Skip to content

Commit 9849689

Browse files
committed
feat: implement flutter_json_render with streaming, examples, and publish prep
0 parents  commit 9849689

152 files changed

Lines changed: 8601 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Miscellaneous
2+
*.class
3+
*.log
4+
*.pyc
5+
*.swp
6+
.DS_Store
7+
.atom/
8+
.buildlog/
9+
.history
10+
.svn/
11+
migrate_working_dir/
12+
13+
# IntelliJ related
14+
*.iml
15+
*.ipr
16+
*.iws
17+
.idea/
18+
19+
# The .vscode folder contains launch configuration and tasks you configure in
20+
# VS Code which you may wish to be included in version control, so this line
21+
# is commented out by default.
22+
#.vscode/
23+
24+
# Flutter/Dart/Pub related
25+
# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
26+
/pubspec.lock
27+
**/doc/api/
28+
.dart_tool/
29+
.flutter-plugins
30+
.flutter-plugins-dependencies
31+
build/

.metadata

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# This file tracks properties of this Flutter project.
2+
# Used by Flutter tool to assess capabilities and perform upgrades etc.
3+
#
4+
# This file should be version controlled and should not be manually edited.
5+
6+
version:
7+
revision: "b25305a8832cfc6ba632a7f87ad455e319dccce8"
8+
channel: "stable"
9+
10+
project_type: package

CHANGELOG.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
## 0.2.0
2+
3+
- Added JSON Patch support with `JsonPatchOperation`, `JsonPatchOp`, and `applyJsonPatch`
4+
- Added streaming compiler API `JsonSpecStreamCompiler` for JSONL full specs and incremental patch lines
5+
- Expanded `JsonCatalog.prompt()` with richer schema metadata (`JsonPropDefinition`, `JsonPromptOptions`)
6+
- Enhanced standard component catalog definitions with prop schemas for stronger prompt generation
7+
- Added a full multi-case `/example` app (counter, repeat/item scope, dynamic cond props, async actions, stream simulation)
8+
- Expanded test coverage for patching, streaming, and prompt generation
9+
- Updated README with streaming and example usage docs
10+
- Updated package metadata for publishing readiness
11+
12+
## 0.1.0
13+
14+
- Initial Flutter/Dart library implementation inspired by `vercel-labs/json-render`
15+
- Added flat spec model (`JsonRenderSpec`, `JsonElement`, actions/repeat support)
16+
- Added guarded catalog and registry APIs (`JsonCatalog`, `JsonRegistry`)
17+
- Added `JsonRenderer` with visibility, repeat, dynamic value resolution, and event-action dispatch
18+
- Added built-in standard component set for Material widgets
19+
- Added spec validation API (`validateSpec`)
20+
- Added widget and unit tests for rendering, action execution, visibility, and repeat

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 Youngbeom Lee
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
# flutter_json_render
2+
3+
A Flutter-first implementation of the [vercel-labs/json-render](https://github.com/vercel-labs/json-render) concept.
4+
5+
`flutter_json_render` renders flat JSON specs into Flutter widgets through an explicit registry and catalog.
6+
7+
- Guardrailed component/action model
8+
- Flat and model-friendly spec shape (`root + elements`)
9+
- Dynamic prop resolution (`$state`, `$item`, `$index`, `$cond`)
10+
- Visibility and repeat support
11+
- JSONL streaming patch compiler for progressive UI updates
12+
13+
## Install
14+
15+
```bash
16+
flutter pub add flutter_json_render
17+
```
18+
19+
## Core Concepts
20+
21+
- `JsonCatalog`: declares what components/actions are allowed
22+
- `JsonRegistry`: maps component type -> Flutter widget builder, action -> handler
23+
- `JsonRenderer`: renders `JsonRenderSpec` safely
24+
- `JsonSpecStreamCompiler`: compiles streamed JSONL specs/patches
25+
26+
## Quick Start
27+
28+
```dart
29+
import 'package:flutter/material.dart';
30+
import 'package:flutter_json_render/flutter_json_render.dart';
31+
32+
final catalog = JsonCatalog(
33+
components: {
34+
...standardComponentDefinitions,
35+
'Panel': const JsonComponentDefinition(
36+
description: 'Simple card container',
37+
props: {
38+
'title': JsonPropDefinition(type: 'string', required: true),
39+
},
40+
),
41+
},
42+
actions: {
43+
...standardActionDefinitions,
44+
'increment': const JsonActionDefinition(description: 'Increase count'),
45+
},
46+
);
47+
48+
final registry = defineRegistry(
49+
components: {
50+
...standardComponentBuilders(),
51+
'Panel': (ctx) => Card(
52+
child: Padding(
53+
padding: const EdgeInsets.all(12),
54+
child: Column(
55+
crossAxisAlignment: CrossAxisAlignment.start,
56+
children: [
57+
Text(ctx.props['title']?.toString() ?? 'Panel'),
58+
const SizedBox(height: 8),
59+
...ctx.children,
60+
],
61+
),
62+
),
63+
),
64+
},
65+
actions: {
66+
'increment': (ctx) {
67+
ctx.setStateModel((prev) {
68+
final next = <String, dynamic>{...prev};
69+
next['count'] = ((prev['count'] as num?) ?? 0) + 1;
70+
return next;
71+
});
72+
},
73+
},
74+
);
75+
76+
final spec = JsonRenderSpec.fromJson({
77+
'root': 'panel',
78+
'state': {'count': 1},
79+
'elements': {
80+
'panel': {
81+
'type': 'Panel',
82+
'props': {'title': 'Counter'},
83+
'children': ['value', 'button'],
84+
},
85+
'value': {
86+
'type': 'Text',
87+
'props': {'text': {'$state': '/count'}},
88+
},
89+
'button': {
90+
'type': 'Button',
91+
'props': {'label': 'Increment'},
92+
'on': {
93+
'press': {'action': 'increment'}
94+
}
95+
}
96+
}
97+
});
98+
99+
Widget app() {
100+
return MaterialApp(
101+
home: Scaffold(
102+
body: Center(
103+
child: JsonRenderer(spec: spec, registry: registry),
104+
),
105+
),
106+
);
107+
}
108+
```
109+
110+
## Stream JSONL Patches
111+
112+
```dart
113+
final compiler = JsonSpecStreamCompiler();
114+
115+
compiler.push('{"root":"root","elements":{"root":{"type":"Text","props":{"text":"loading"}}}}\n');
116+
compiler.push('{"op":"replace","path":"/elements/root/props/text","value":"ready"}\n');
117+
118+
final spec = compiler.getResult();
119+
```
120+
121+
Supported stream line shapes:
122+
123+
- full spec object
124+
- single patch op object
125+
- patch op array
126+
- wrapped patch object: `{ "patch": [ ... ] }`
127+
128+
## Validate Specs
129+
130+
```dart
131+
final result = validateSpec(spec, catalog: catalog, strictCatalog: false);
132+
if (!result.isValid) {
133+
for (final issue in result.issues) {
134+
debugPrint('[${issue.severity}] ${issue.message}');
135+
}
136+
}
137+
```
138+
139+
## Built-In Components
140+
141+
- `Text`
142+
- `Column`
143+
- `Row`
144+
- `Container`
145+
- `Center`
146+
- `SizedBox`
147+
- `Button`
148+
- `Image`
149+
150+
## Example App
151+
152+
A full multi-scenario showcase app is included in `/example`:
153+
154+
```bash
155+
cd example
156+
flutter run
157+
```
158+
159+
Included scenarios:
160+
161+
- Counter + visibility conditions
162+
- Repeat + `$item`/`$index` actions
163+
- Dynamic props via `$cond`
164+
- Async action flow
165+
- Streamed JSONL patch simulation
166+
167+
## pub.dev Release Checklist
168+
169+
```bash
170+
flutter analyze
171+
flutter test
172+
dart pub publish --dry-run
173+
```
174+
175+
## License
176+
177+
MIT

analysis_options.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
include: package:flutter_lints/flutter.yaml
2+
3+
# Additional information about this file can be found at
4+
# https://dart.dev/guides/language/analysis-options

example/.gitignore

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Miscellaneous
2+
*.class
3+
*.log
4+
*.pyc
5+
*.swp
6+
.DS_Store
7+
.atom/
8+
.build/
9+
.buildlog/
10+
.history
11+
.svn/
12+
.swiftpm/
13+
migrate_working_dir/
14+
15+
# IntelliJ related
16+
*.iml
17+
*.ipr
18+
*.iws
19+
.idea/
20+
21+
# The .vscode folder contains launch configuration and tasks you configure in
22+
# VS Code which you may wish to be included in version control, so this line
23+
# is commented out by default.
24+
#.vscode/
25+
26+
# Flutter/Dart/Pub related
27+
**/doc/api/
28+
**/ios/Flutter/.last_build_id
29+
.dart_tool/
30+
.flutter-plugins
31+
.flutter-plugins-dependencies
32+
.pub-cache/
33+
.pub/
34+
/build/
35+
36+
# Symbolication related
37+
app.*.symbols
38+
39+
# Obfuscation related
40+
app.*.map.json
41+
42+
# Android Studio will place build artifacts here
43+
/android/app/debug
44+
/android/app/profile
45+
/android/app/release

example/.metadata

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# This file tracks properties of this Flutter project.
2+
# Used by Flutter tool to assess capabilities and perform upgrades etc.
3+
#
4+
# This file should be version controlled and should not be manually edited.
5+
6+
version:
7+
revision: "b25305a8832cfc6ba632a7f87ad455e319dccce8"
8+
channel: "stable"
9+
10+
project_type: app
11+
12+
# Tracks metadata for the flutter migrate command
13+
migration:
14+
platforms:
15+
- platform: root
16+
create_revision: b25305a8832cfc6ba632a7f87ad455e319dccce8
17+
base_revision: b25305a8832cfc6ba632a7f87ad455e319dccce8
18+
- platform: android
19+
create_revision: b25305a8832cfc6ba632a7f87ad455e319dccce8
20+
base_revision: b25305a8832cfc6ba632a7f87ad455e319dccce8
21+
- platform: ios
22+
create_revision: b25305a8832cfc6ba632a7f87ad455e319dccce8
23+
base_revision: b25305a8832cfc6ba632a7f87ad455e319dccce8
24+
- platform: linux
25+
create_revision: b25305a8832cfc6ba632a7f87ad455e319dccce8
26+
base_revision: b25305a8832cfc6ba632a7f87ad455e319dccce8
27+
- platform: macos
28+
create_revision: b25305a8832cfc6ba632a7f87ad455e319dccce8
29+
base_revision: b25305a8832cfc6ba632a7f87ad455e319dccce8
30+
- platform: web
31+
create_revision: b25305a8832cfc6ba632a7f87ad455e319dccce8
32+
base_revision: b25305a8832cfc6ba632a7f87ad455e319dccce8
33+
- platform: windows
34+
create_revision: b25305a8832cfc6ba632a7f87ad455e319dccce8
35+
base_revision: b25305a8832cfc6ba632a7f87ad455e319dccce8
36+
37+
# User provided section
38+
39+
# List of Local paths (relative to this file) that should be
40+
# ignored by the migrate tool.
41+
#
42+
# Files that are not part of the templates will be ignored by default.
43+
unmanaged_files:
44+
- 'lib/main.dart'
45+
- 'ios/Runner.xcodeproj/project.pbxproj'

example/README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# flutter_json_render example
2+
3+
Showcase app for the package with practical scenarios:
4+
5+
1. Counter + visibility conditions
6+
2. Repeat + `$item`/`$index` actions
7+
3. Dynamic props with `$cond`
8+
4. Async action flow
9+
5. Streamed JSONL patch simulation
10+
11+
Run:
12+
13+
```bash
14+
flutter pub get
15+
flutter run
16+
```

0 commit comments

Comments
 (0)