content_foundry 1.0.0-alpha.1
content_foundry: ^1.0.0-alpha.1 copied to clipboard
Customizable GUI editor for content with user-defined schema
example/main.dart
import 'dart:convert';
import 'package:content_foundry/content_foundry.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Content Foundry Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const ContentFoundryPage(),
);
}
}
class ContentFoundryPage extends StatefulWidget {
const ContentFoundryPage({super.key});
@override
State<ContentFoundryPage> createState() => _ContentFoundryPageState();
}
class _ContentFoundryPageState extends State<ContentFoundryPage> {
late Field _field;
late String _formattedValue;
final _encoder = JsonEncoder.withIndent(' ' * 2);
@override
void initState() {
super.initState();
_field = StructureField(
properties: [
StructureFieldProperty(
name: 'Outer list',
field: ListField(
fieldFactory: (initialValue) {
return PolymorphicField(
typeFieldName: 'type',
valueFieldName: 'value',
initialValue: initialValue is Map<String, dynamic> ? initialValue : const {},
types: [
PolymorphicFieldType(
type: 'text',
displayName: 'Text',
description: 'Multi-line text with optional alignment.',
fieldFactory: (defaultData) => StructureField.fromFieldMap(
fieldByName: {
'text': StringField(maxLines: null),
'align': EnumField(
choices: ['left', 'center', 'right', 'justify'],
).nullable(isNull: true),
},
),
),
PolymorphicFieldType(
type: 'image',
displayName: 'Image',
description: 'Image from internet with optional aspect ratio.',
fieldFactory: (defaultData) => StructureField.fromFieldMap(
fieldByName: {
'url': StringField(),
'aspect_ratio': DoubleField().nullable(),
},
),
),
PolymorphicFieldType(
type: 'button',
displayName: 'Button',
description: 'Button with configurable emphasis.',
fieldFactory: (defaultData) => StructureField.fromFieldMap(
fieldByName: {
'title': StringField(),
'link': StringField().nullable(),
'emphasis': EnumField(
choices: ['primary', 'secondary', 'warning'],
value: 'primary',
),
},
),
),
],
);
},
),
),
StructureFieldProperty(
name: 'Another outer list',
field: ListField(
fieldFactory: (initialValue) {
return ListField(
fieldFactory: (initialValue) => StringField(),
);
},
),
),
StructureFieldProperty(
displayName: 'Floating-point number',
name: 'double',
field: DoubleField(),
),
StructureFieldProperty(
name: 'string',
description: 'Multi-line text',
field: StringField(
value: 'Initial string value',
maxLines: null,
),
),
StructureFieldProperty(
displayName: 'Nullable enum',
name: 'enum',
field: EnumField(
choices: ['left', 'center', 'right', 'justify'],
).nullable(isNull: true),
),
StructureFieldProperty(
displayName: 'Polymorphic',
description: 'This field can contain values of different types',
name: 'polymorphic',
field: PolymorphicField(
typeFieldName: 'type',
valueFieldName: 'value',
types: [
PolymorphicFieldType(
type: 'text',
displayName: 'Text',
description: 'Multi-line text with optional alignment.',
fieldFactory: (defaultData) => StructureField.fromFieldMap(
fieldByName: {
'text': StringField(maxLines: null),
'align': EnumField(
choices: ['left', 'center', 'right', 'justify'],
).nullable(isNull: true),
},
),
),
PolymorphicFieldType(
type: 'image',
displayName: 'Image',
description: 'Image from internet with optional aspect ratio.',
fieldFactory: (defaultData) => StructureField.fromFieldMap(
fieldByName: {
'url': StringField(),
'aspect_ratio': DoubleField().nullable(),
},
),
),
PolymorphicFieldType(
type: 'button',
displayName: 'Button',
description: 'Button with configurable emphasis.',
fieldFactory: (defaultData) => StructureField.fromFieldMap(
fieldByName: {
'title': StringField(),
'link': StringField().nullable(),
'emphasis': EnumField(
choices: ['primary', 'secondary', 'warning'],
value: 'primary',
),
},
),
),
],
),
),
],
);
_updateValue();
_field.addListener(_onChange);
}
@override
void dispose() {
_field.dispose();
super.dispose();
}
void _onChange() {
_updateValue();
setState(() {});
}
void _updateValue() =>
_formattedValue = _field.isValid() ? _encoder.convert(_field.getValue()) : 'Invalid';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Content Foundry'),
),
body: Center(
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Flexible(
child: SingleChildScrollView(
child: ContentFoundryEditor(
field: _field,
),
),
),
Flexible(
child: Text(_formattedValue),
),
],
),
),
);
}
}