Commit bb31d839 by Rizal Hermawan

feat (ui component & json schema validator): add textfield component & other…

feat (ui component & json schema validator): add textfield component & other components and add json schema validator on some components. Story #3
parent 5fc6cc71
......@@ -3,7 +3,7 @@
#
# For more info see: https://dart.dev/go/dot-packages-deprecation
#
# Generated by pub on 2021-06-23 16:39:43.392636.
# Generated by pub on 2021-06-28 18:53:09.517451.
args:file:///D:/flutter/2.0.4-stable/.pub-cache/hosted/pub.dartlang.org/args-2.1.1/lib/
async:file:///D:/flutter/2.0.4-stable/.pub-cache/hosted/pub.dartlang.org/async-2.5.0/lib/
boolean_selector:file:///D:/flutter/2.0.4-stable/.pub-cache/hosted/pub.dartlang.org/boolean_selector-2.1.0/lib/
......@@ -34,6 +34,7 @@ rest_client:file:///D:/flutter/2.0.4-stable/.pub-cache/hosted/pub.dartlang.org/r
sky_engine:file:///D:/flutter/2.0.4-stable/bin/cache/pkg/sky_engine/lib/
source_span:file:///D:/flutter/2.0.4-stable/.pub-cache/hosted/pub.dartlang.org/source_span-1.8.0/lib/
stack_trace:file:///D:/flutter/2.0.4-stable/.pub-cache/hosted/pub.dartlang.org/stack_trace-1.10.0/lib/
states_rebuilder:file:///D:/flutter/2.0.4-stable/.pub-cache/hosted/pub.dartlang.org/states_rebuilder-4.3.0/lib/
stream_channel:file:///D:/flutter/2.0.4-stable/.pub-cache/hosted/pub.dartlang.org/stream_channel-2.1.0/lib/
string_scanner:file:///D:/flutter/2.0.4-stable/.pub-cache/hosted/pub.dartlang.org/string_scanner-1.1.0/lib/
term_glyph:file:///D:/flutter/2.0.4-stable/.pub-cache/hosted/pub.dartlang.org/term_glyph-1.2.0/lib/
......
......@@ -2,3 +2,7 @@
### feat (init): create flutter widget parser package for flutter app development.
* add some flutter and lls widgets parser
## 0.0.6 - 2021-06-28
### feat (ui component & json schema validator): add textfield component & other components and add json schema validator on some components
\ No newline at end of file
......@@ -6,7 +6,7 @@ class AppBarWidgetParser extends WidgetParser {
@override
Widget parse(Map<String, dynamic> map, BuildContext buildContext, MethodListener? listener, Map<String, dynamic>? variable) {
var appBarWidget = AppBar(
key: map.containsKey("key") ? createKeyForWidget(map["key"]) : null,
key: map.containsKey("key") ? variable![map["key"]] != null ? variable[map["key"]] : Key(map["key"]) : null,
title: map.containsKey("title")
? WidgetParserBuilder.buildFromMap(
map["title"], buildContext, listener, variable)
......
import 'package:flutter/material.dart';
import 'package:widgetparser/src/utils.dart';
import 'package:widgetparser/widgetparser.dart';
import 'package:flutter/widgets.dart';
class CircularProgressIndicatorWidgetParser extends WidgetParser {
@override
Widget parse(Map<String, dynamic> map, BuildContext buildContext, MethodListener? listener, Map<String, dynamic>? variable) {
return CircularProgressIndicator(
key: map.containsKey("key") ? variable![map["key"]] != null ? variable[map["key"]] : Key(map["key"]) : null,
value: map.containsKey('value') ? map['value'] : null,
backgroundColor: map.containsKey('backgroundColor') ? parseHexColor(map['backgroundColor']) : null,
strokeWidth: map.containsKey('strokeWidth') ? map['strokeWidth'] : 4.0,
semanticsLabel: map.containsKey('semanticsLabel') ? map['semanticsLabel'] : null,
semanticsValue: map.containsKey('semanticsValue') ? map['semanticsValue'] : null
);
}
@override
String get widgetName => "CircularProgressIndicator";
@override
Type get widgetType => CircularProgressIndicator;
}
......@@ -71,9 +71,7 @@ class ContainerWidgetParser extends WidgetParser {
},
"Child": ${SchemaHelper.child},
"Constraints": ${SchemaHelper.constraints},
"Decoration": ${SchemaHelper.decoration},
"BorderRadius": ${SchemaHelper.borderRadius},
"BoxShadow": ${SchemaHelper.boxShadow}
"Decoration": ${SchemaHelper.decoration}
}
}
''';
......@@ -112,12 +110,12 @@ class ContainerWidgetParser extends WidgetParser {
// }
// }
// Map<String, dynamic> jsonSchemaResult = jsonSchemaValidation(containerSchema, map);
// if (!jsonSchemaResult['validates']) {
// return jsonSchemaErrorWidget(jsonSchemaResult['validator']);
// } else {
Map<String, dynamic> jsonSchemaResult = jsonSchemaValidation(containerSchema, map);
if (!jsonSchemaResult['validates']) {
return jsonSchemaErrorWidget(jsonSchemaResult['validator'], widgetName);
} else {
return containerWidget;
//}
}
}
@override
......
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:widgetparser/widgetparser.dart';
import 'package:widgetparser/src/utils.dart';
class GestureDetectorWidgetParser extends WidgetParser {
@override
Widget parse(Map<String, dynamic> map, BuildContext buildContext, MethodListener? listener, Map<String, dynamic>? variable) {
var gestureDetectorWidget = GestureDetector(
key: map.containsKey('key') ? createKeyForWidget(map['key']) : null,
key: map.containsKey("key") ? variable![map["key"]] != null ? variable[map["key"]] : Key(map["key"]) : null,
child: WidgetParserBuilder.buildFromMap(map['child'], buildContext, listener, variable),
onTap: map.containsKey('onTap') ? () => listener!.run(buildContext, map['onTap']) : null,
onTapDown: map.containsKey('onTapDown') ? (TapDownDetails tapDownDetails) {
......
......@@ -3,9 +3,59 @@ import 'package:widgetparser/src/icons_helper.dart';
import 'package:widgetparser/src/utils.dart';
import 'package:flutter/material.dart';
import '../json_schema_helper.dart';
class IconWidgetParser extends WidgetParser {
@override
Widget parse(Map<String, dynamic> map, BuildContext buildContext, MethodListener? listener, Map<String, dynamic>? variable) {
//example JSON for rendering Icon
// {
// "widget": "Icon",
// "data": "data",
// "size": 10.0,
// "color": "color",
// "semanticLabel": "semanticLabel",
// "textDirection": "ltr"
// }
const iconSchema = '''
{
"\$schema\": "$schemaUrl",
"\$ref\": "${refSchema}Icon",
"definitions": {
"Icon": {
"type": "object",
"additionalProperties": false,
"properties": {
"widget": {
"type": "string"
},
"data": {
"type": "string"
},
"size": {
"type": "integer"
},
"color": ${SchemaHelper.color}
"semanticLabel": {
"type": "string"
},
"textDirection": ${SchemaHelper.textDirection}
},
"required": [
"data",
"widget"
],
"title": "Icon"
}
}
}
''';
// Map<String, dynamic> jsonSchemaResult = jsonSchemaValidation(iconSchema, map);
// if (!jsonSchemaResult['validates']) {
// return jsonSchemaErrorWidget(jsonSchemaResult['validator'], widgetName);
// } else {
return Icon(
map.containsKey('data')
? getIconUsingPrefix(name: map['data'])
......@@ -18,6 +68,7 @@ class IconWidgetParser extends WidgetParser {
? parseTextDirection(map['textDirection'])
: null,
);
//}
}
@override
......
......@@ -8,7 +8,7 @@ class IconButtonWidgetParser extends WidgetParser {
EdgeInsets? padding = parseEdgeInsetsGeometry(map['padding']) as EdgeInsets;
return IconButton(
key: map.containsKey("key") ? createKeyForWidget(map["key"]) : null,
key: map.containsKey("key") ? variable![map["key"]] != null ? variable[map["key"]] : Key(map["key"]) : null,
iconSize: map.containsKey('iconSize') ? map['iconSize'] : 24.0,
icon: WidgetParserBuilder.buildFromMap(map['icon'], buildContext, listener, variable)!,
padding: map.containsKey('padding') ? padding : EdgeInsets.all(8.0),
......
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:widgetparser/widgetparser.dart';
import 'package:widgetparser/src/utils.dart';
class InkWellWidgetParser extends WidgetParser {
@override
Widget parse(Map<String, dynamic> map, BuildContext buildContext, MethodListener? listener, Map<String, dynamic>? variable) {
return InkWell(
key: map.containsKey('key') ? createKeyForWidget(map['key']) : null,
key: map.containsKey("key") ? variable![map["key"]] != null ? variable[map["key"]] : Key(map["key"]) : null,
child: WidgetParserBuilder.buildFromMap(map['child'], buildContext, listener, variable),
onTap: map.containsKey('onTap') ? () => listener!.run(buildContext, map['onTap']) : null,
onTapDown: map.containsKey('onTapDown') ? (TapDownDetails tapDownDetails) => listener!.run(buildContext, map['onTapDown']) : null,
......@@ -21,5 +20,4 @@ class InkWellWidgetParser extends WidgetParser {
@override
Type get widgetType => InkWell;
}
\ No newline at end of file
import 'package:widgetparser/widgetparser.dart';
import 'package:widgetparser/src/utils.dart';
import 'package:flutter/widgets.dart';
import '../json_schema_helper.dart';
class PaddingWidgetParser extends WidgetParser {
@override
Widget parse(Map<String, dynamic> map, BuildContext buildContext, MethodListener? listener, Map<String, dynamic>? variable) {
//example JSON for rendering Padding
// {
// "widget": "Padding",
// "padding": "4.0,4.0,4.0,4.0",
// "child": {
// "widget": "SizedBox"
// }
// }
const paddingSchema = '''
{
"\$schema\": "$schemaUrl",
"\$ref\": "${refSchema}Padding",
"definitions": {
"Padding": {
"type": "object",
"additionalProperties": true,
"properties": {
"widget": {
"type": "string"
},
"padding": {
"type": "string"
},
"child": {
"\$ref\": "${refSchema}Child"
}
},
"required": [
"padding",
"widget"
],
"title": "Padding"
},
"Child": ${SchemaHelper.child}
}
}
''';
Map<String, dynamic> jsonSchemaResult = jsonSchemaValidation(paddingSchema, map);
if (!jsonSchemaResult['validates']) {
return jsonSchemaErrorWidget(jsonSchemaResult['validator'], widgetName);
} else {
return Padding(
padding: map.containsKey("padding")
? parseEdgeInsetsGeometry(map["padding"])!
......@@ -13,6 +58,7 @@ class PaddingWidgetParser extends WidgetParser {
map["child"], buildContext, listener, variable),
);
}
}
@override
String get widgetName => "Padding";
......
......@@ -2,6 +2,8 @@ import 'package:widgetparser/widgetparser.dart';
import 'package:widgetparser/src/utils.dart';
import 'package:flutter/widgets.dart';
import '../json_schema_helper.dart';
class RowWidgetParser extends WidgetParser {
@override
Widget parse(Map<String, dynamic> map, BuildContext buildContext, MethodListener? listener, Map<String, dynamic>? variable) {
......@@ -41,6 +43,70 @@ class ColumnWidgetParser extends WidgetParser {
@override
Widget parse(Map<String, dynamic> map, BuildContext buildContext, MethodListener? listener, Map<String, dynamic>? variable) {
//example JSON for rendering Column
// {
// "widget": "Column",
// "crossAxisAlignment": "start",
// "mainAxisAlignment": "start",
// "mainAxisSize": "min",
// "textBaseline": "alphabetic",
// "textDirection": "ltr",
// "verticalDirection": "up",
// "children": [
// {
// "widget": "SizedBox"
// }
// ]
// }
const columnSchema = '''
{
"\$schema\": "$schemaUrl",
"\$ref\": "${refSchema}Column",
"definitions": {
"Column": {
"type": "object",
"additionalProperties": true,
"properties": {
"widget": {
"type": "string"
},
"crossAxisAlignment": {
"type": "string",
"enum": ["start","end","center","stretch","baseline"]
},
"mainAxisAlignment": {
"type": "string",
"enum": ["start","end","center","spaceBetween","spaceAround","spaceEvenly"]
},
"mainAxisSize": {
"type": "string",
"enum": ["min","max"]
},
"textBaseline": ${SchemaHelper.textBaseline},
"textDirection": ${SchemaHelper.textDirection},
"verticalDirection": ${SchemaHelper.verticalDirection},
"children": {
"type": "array",
"items": {
"\$ref\": "${refSchema}Child"
}
}
},
"required": [
"widget"
],
"title": "Column"
},
"Child": ${SchemaHelper.child}
}
}
''';
Map<String, dynamic> jsonSchemaResult = jsonSchemaValidation(columnSchema, map);
if (!jsonSchemaResult['validates']) {
return jsonSchemaErrorWidget(jsonSchemaResult['validator'], widgetName);
} else {
return Column(
crossAxisAlignment: map.containsKey('crossAxisAlignment')
? parseCrossAxisAlignment(map['crossAxisAlignment'])
......@@ -64,6 +130,7 @@ class ColumnWidgetParser extends WidgetParser {
map['children'], buildContext, listener, variable),
);
}
}
@override
String get widgetName => "Column";
......
......@@ -3,11 +3,13 @@ import 'package:widgetparser/src/utils.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import '../json_schema_helper.dart';
class ScaffoldWidgetParser extends WidgetParser {
@override
Widget parse(Map<String, dynamic> map, BuildContext buildContext, MethodListener? listener, Map<String, dynamic>? variable) {
var scaffoldWidget = Scaffold(
key: map.containsKey("key") ? createKeyForWidget(map["key"]) : null,
key: map.containsKey("key") ? variable![map["key"]] != null ? variable[map["key"]] : Key(map["key"]) : null,
appBar: map.containsKey("appBar")
? WidgetParserBuilder.buildFromMap(
map["appBar"], buildContext, listener, variable) as PreferredSizeWidget?
......@@ -29,8 +31,69 @@ class ScaffoldWidgetParser extends WidgetParser {
: null,
);
const scaffoldSchema = '''
{
"\$schema\": "$schemaUrl",
"\$ref\": "${refSchema}Scaffold",
"definitions": {
"Scaffold": {
"type": "object",
"additionalProperties": true,
"properties": {
"widget": {
"type": "string"
},
"appBar": {
"\$ref\": "${refSchema}AppBar"
},
"body": {
"\$ref\": "${refSchema}Child"
},
"floatingActionButton": {
"\$ref\": "${refSchema}Child"
},
"backgroundColor": ${SchemaHelper.color},
"persistentFooterButtons": {
"\$ref\": "${refSchema}Child"
}
},
"required": [
"body",
"widget"
],
"title": "Scaffold"
},
"AppBar": ${SchemaHelper.appBar},
"Child": ${SchemaHelper.child}
}
}
''';
//example JSON for rendering Scaffold
// {
// "widget": "Scaffold",
// "appBar": {
// "widget": "AppBar"
// },
// "body": {
// "widget": "SizedBox"
// },
// "floatingActionButton": {
// "widget": "SizedBox"
// },
// "backgroundColor": "#fff",
// "persistentFooterButtons": {
// "widget": "SizedBox"
// }
// }
Map<String, dynamic> jsonSchemaResult = jsonSchemaValidation(scaffoldSchema, map);
if (!jsonSchemaResult['validates']) {
return jsonSchemaErrorWidget(jsonSchemaResult['validator'], widgetName);
} else {
return scaffoldWidget;
}
}
@override
String get widgetName => "Scaffold";
......
import 'package:widgetparser/widgetparser.dart';
import 'package:flutter/widgets.dart';
import '../json_schema_helper.dart';
import '../utils.dart';
//Creates a box that will become as large as its parent allows.
class ExpandedSizedBoxWidgetParser extends WidgetParser {
@override
......@@ -21,13 +24,60 @@ class ExpandedSizedBoxWidgetParser extends WidgetParser {
class SizedBoxWidgetParser extends WidgetParser {
@override
Widget parse(Map<String, dynamic> map, BuildContext buildContext, MethodListener? listener, Map<String, dynamic>? variable) {
//example JSON for rendering SizedBox
// {
// "widget": "SizedBox",
// "width": 20.0,
// "height": 20.0,
// "child": {
// "widget": "SizedBox"
// }
// }
const sizedBoxSchema = '''
{
"\$schema\": "$schemaUrl",
"\$ref\": "${refSchema}SizedBox",
"definitions": {
"SizedBox": {
"type": "object",
"additionalProperties": true,
"properties": {
"widget": {
"type": "string"
},
"width": {
"type": "integer"
},
"height": {
"type": "integer"
},
"child": {
"\$ref\": "${refSchema}Child"
}
},
"required": [
"widget"
],
"title": "SizedBox"
},
"Child": ${SchemaHelper.child}
}
}
''';
Map<String, dynamic> jsonSchemaResult = jsonSchemaValidation(sizedBoxSchema, map);
if (!jsonSchemaResult['validates']) {
return jsonSchemaErrorWidget(jsonSchemaResult['validator'], widgetName);
} else {
return SizedBox(
width: map["width"],
height: map["height"],
child: WidgetParserBuilder.buildFromMap(
map["child"], buildContext, listener, variable),
child: map.containsKey('child') ? WidgetParserBuilder.buildFromMap(
map["child"], buildContext, listener, variable) : null
);
}
}
@override
String get widgetName => "SizedBox";
......
......@@ -7,7 +7,7 @@ import 'package:flutter/widgets.dart';
class TextWidgetParser implements WidgetParser {
@override
Widget parse(Map<String, dynamic> map, BuildContext buildContext, MethodListener? listener, Map<String, dynamic>? variable) {
String? data = map['data'];
String data = map['data'];
String? textAlignString = map['textAlign'];
String? overflow = map['overflow'];
int? maxLines = map['maxLines'];
......@@ -23,7 +23,7 @@ class TextWidgetParser implements WidgetParser {
if (textSpan == null) {
return Text(
data!,
data,
textAlign: parseTextAlign(textAlignString),
overflow: parseTextOverflow(overflow),
maxLines: maxLines,
......
......@@ -7,7 +7,8 @@ class TextFormFieldWidgetParser extends WidgetParser {
@override
Widget parse(Map<String, dynamic> map, BuildContext buildContext, MethodListener? listener, Map<String, dynamic>? variable) {
return TextFormField(
controller: TextEditingController(),
controller: map.containsKey('controller') ? variable![map['controller']] : null,
focusNode: map.containsKey('focusNode') ? variable![map['focusNode']] : null,
initialValue: map.containsKey('initialValue') ? map['initialValue'] : null,
decoration: map.containsKey('decoration') ? parseInputDecoration(map['decoration'], buildContext, listener, variable) : InputDecoration(),
keyboardType: map.containsKey('keyboardType') ? parseTextInputType(map['keyboardType']) : null,
......
......@@ -14,6 +14,7 @@ IconData? getIconUsingPrefix({required String name}) {
return getCupertinoIcon(name: name);
}
} else {
name = split[0];
return getIconGuessFavorMaterial(name: name);
}
......
......@@ -2,6 +2,299 @@ const schemaUrl = "http://json-schema.org/draft-06/schema#";
const refSchema = "#/definitions/";
class SchemaHelper {
static const brightness = '''
{
"type": "string",
"enum": ["dark","light"]
}
''';
static const toolbarOptions = '''
{
"type": "object",
"additionalProperties": false,
"properties": {
"copy": {
"type": "boolean"
},
"cut": {
"type": "boolean"
},
"paste": {
"type": "boolean"
},
"selectAll": {
"type": "boolean"
}
},
"required": [],
"title": "ToolbarOptions"
}
''';
static const textAlign = '''
{
"type": "string",
"enum": ["left","right","center","justify","start","end"]
}
''';
static const functionObject = '''
{
"type": "object",
"additionalProperties": true,
"properties": {
"function": {
"type": "string",
"description": "function name"
},
"parameters": {
"type": "object",
"additionalProperties": true,
"title": "Parameters"
}
},
"required": [
"function"
],
"title": "Function"
}
''';
static const textCapitalization = '''
{
"type": "string",
"enum": ["words","sentences","characters","none"]
}
''';
static const textInputType = '''
{
"type": "string",
"enum": ["datetime","emailAddress","multiline","name","number","phone","streetAddress","url","text"]
}
''';
static const inputDecoration = '''
{
"type": "object",
"additionalProperties": false,
"properties": {
"icon": $widget,
"labelText": {
"type": "string"
},
"labelStyle": $textStyle,
"helperText": {
"type": "string"
},
"helperStyle": $textStyle,
"helperMaxLines": {
"type": "integer"
},
"hintText": {
"type": "string"
},
"hintStyle": $textStyle,
"hintTextDirection": {
"type": "string"
},
"hintMaxLines": {
"type": "integer"
},
"errorText": {
"type": "string"
},
"errorStyle": $textStyle,
"errorMaxLines": {
"type": "integer"
},
"floatingLabelBehavior": {
"type": "string"
},
"isCollapsed": {
"type": "boolean"
},
"isDense": {
"type": "boolean"
},
"contentPadding": {
"type": "string"
},
"prefixIcon": $widget,
"prefixIconConstraints": $constraints,
"prefix": $widget,
"prefixText": {
"type": "string"
},
"prefixStyle": $textStyle,
"suffixIcon": $widget,
"suffix": $widget,
"suffixText": {
"type": "string"
},
"suffixStyle": $textStyle,
"suffixIconConstraints": $constraints,
"counter": $widget,
"counterText": {
"type": "string"
},
"counterStyle": $textStyle,
"filled": {
"type": "boolean"
},
"fillColor": {
"type": "string"
},
"focusColor": {
"type": "string"
},
"hoverColor": {
"type": "string"
},
"errorBorder": $inputBorder,
"focusedBorder": $inputBorder,
"focusedErrorBorder": $inputBorder,
"disabledBorder": $inputBorder,
"enabledBorder": $inputBorder,
"border": $inputBorder,
"enabled": {
"type": "boolean"
},
"semanticCounterText": {
"type": "string"
},
"alignLabelWithHint": {
"type": "boolean"
}
},
"required": [],
"title": "InputDecoration"
}
''';
static const textStyle = '''
{
"type": "object",
"additionalProperties": false,
"properties": {
"color": $color,
"debugLabel": {
"type": "string"
},
"fontFamily": {
"type": "string"
},
"fontSize": {
"type": "number"
},
"fontWeight": $fontWeight,
"fontStyle": $fontStyle
},
"required": [],
"title": "TextStyle"
}
''';
static const borderSide = '''
{
"type": "object",
"additionalProperties": false,
"properties": {
"color": $color,
"width": {
"type": "integer"
},
"style": $borderStyle
},
"required": [],
"title": "BorderSide"
}
''';
static const inputBorder = '''
{
"type": "object",
"additionalProperties": false,
"properties": {
"inputBorder": $inputBorderType,
"borderRadius": $borderRadius
"borderSide": $borderSide
},
"required": [
"inputBorder"
],
"title": "InputBorder"
}
''';
static const inputBorderType = '''
{
"type": "string",
"enum": ["underline","outline","none"]
}
''';
static const borderStyle = '''
{
"type": "string",
"enum": ["solid","none"]
}
''';
static const floatingLabelBehavior = '''
{
"type": "string",
"enum": ["auto","always","never"]
}
''';
static const fontWeight = '''
{
"type": "string",
"minLength": 3
}
''';
static const fontStyle = '''
{
"type": "string",
"enum": ["italic","normal"]
}
''';
static const textDecoration = '''
{
"type": "string",
"enum": ["lineThrough","overline","underline","none"]
}
''';
static const textDirection = '''
{
"type": "string",
"enum": ["ltr","rtl"]
}
''';
static const textBaseline = '''
{
"type": "string",
"enum": ["alphabetic","ideographic"]
}
''';
static const verticalDirection = '''
{
"type": "string",
"enum": ["up","down"]
}
''';
static const widget = '''
{
"type": "string",
"minLength": 1
}
''';
static const child = '''
{
"type": "object",
......@@ -20,6 +313,20 @@ class SchemaHelper {
}
''';
static const appBar = '''
{
"type": "object",
"additionalProperties": true,
"properties": {
"widget": $widget
},
"required": [
"widget"
],
"title": "AppBar"
}
''';
static const constraints = '''
{
"type": "object",
......@@ -52,15 +359,11 @@ class SchemaHelper {
"type": "object",
"additionalProperties": true,
"properties": {
"borderRadius": {
"\$ref\": "${refSchema}BorderRadius"
},
"borderRadius": $borderRadius,
"color": $color,
"boxShadow": {
"type": "array",
"items": {
"\$ref\": "${refSchema}BoxShadow"
}
"items": $boxShadow
}
},
"required": [],
......
......@@ -7,10 +7,10 @@ class LLSButtonWidgetParser extends WidgetParser {
@override
Widget parse(Map<String, dynamic> map, BuildContext buildContext, MethodListener? listener, Map<String, dynamic>? variable) {
return LLSButton(
key: map.containsKey("key") ? createKeyForWidget(map["key"]) : null,
key: map.containsKey("key") ? variable![map["key"]] != null ? variable[map["key"]] : Key(map["key"]) : null,
onPressed: map.containsKey('onPressed') ? () => listener!.run(buildContext, map['onPressed']) : null,
onHighlightChanged: map.containsKey('onHighlightChanged') ? (bool value) => listener!.run(buildContext, map['onHighlightChanged']) : null,
textStyle: map.containsKey('textStyle') ? parseTextStyle(map['style']) : null,
textStyle: map.containsKey('textStyle') ? parseTextStyle(map['textStyle']) : null,
boxShadow: map.containsKey('boxShadow') ? parseBoxShadow(map['boxShadow']) : null,
buttonBoxShadow: map.containsKey('buttonBoxShadow') ? map['buttonBoxShadow'] : null,
focusColor: map.containsKey('focusColor') ? parseHexColor(map['focusColor']) : null,
......@@ -25,9 +25,9 @@ class LLSButtonWidgetParser extends WidgetParser {
padding: map.containsKey('padding') ? parseEdgeInsetsGeometry(map['padding'])! : EdgeInsets.symmetric(horizontal: 8),
constraints: map.containsKey('constraints') ? parseBoxConstraints(map['constraints']) : null,
clipBehavior: parseClipBehavior(map['clipBehavior']),
focusNode: map.containsKey('focusNode') ? map['focusNode'] : null,
// focusNode: map.containsKey('focusNode') ? variable![map['focusNode']] : null,
autofocus: map.containsKey('autofocus') ? map['autofocus'] as bool : false,
child: map.containsKey('child') ? WidgetParserBuilder.buildFromMap(map["child"], buildContext, listener, variable) : SizedBox(),
child: map.containsKey('child') ? WidgetParserBuilder.buildFromMap(map["child"], buildContext, listener, variable) : null,
type: map.containsKey('type') ? parseLLSButtonType(map['type']) : LLSButtonType.solid,
shape: map.containsKey('shape') ? parseLLSButtonShape(map['shape']) : LLSButtonShape.standard,
color: map.containsKey('color') ? parseHexColor(map['color'])! : LLSColors.PRIMARY,
......
......@@ -9,7 +9,7 @@ class LLSCardWidgetParser extends WidgetParser {
EdgeInsets? margin = parseEdgeInsetsGeometry(map['margin']) as EdgeInsets;
return LLSCard(
key: map.containsKey('key') ? createKeyForWidget(map['key']) : null,
key: map.containsKey("key") ? variable![map["key"]] != null ? variable[map["key"]] : Key(map["key"]) : null,
color: map.containsKey('color') ? parseHexColor(map['color'])! : LLSColors.WHITE,
elevation: map.containsKey('elevation') ? map['elevation'] : 0.0,
borderOnForeground: map['borderOnForeground'],
......
......@@ -7,7 +7,7 @@ class LLSLabelWidgetParser extends WidgetParser {
@override
Widget parse(Map<String, dynamic> map, BuildContext buildContext, MethodListener? listener, Map<String, dynamic>? variable) {
return LLSLabel(
key: map.containsKey('key') ? createKeyForWidget(map['key']) : null,
key: map.containsKey("key") ? variable![map["key"]] != null ? variable[map["key"]] : Key(map["key"]) : null,
type: parseLLSLabelType(map['type']),
child: map.containsKey('child') ? WidgetParserBuilder.buildFromMap(map['child'], buildContext, listener, variable) : null,
text: map.containsKey('text') ? map['text'] : '',
......
......@@ -8,7 +8,7 @@ class LLSListTileWidgetParser extends WidgetParser {
Widget parse(Map<String, dynamic> map, BuildContext buildContext, MethodListener? listener, Map<String, dynamic>? variable) {
return LLSListTile(
key: map.containsKey('key') ? createKeyForWidget(map['key']) : null,
key: map.containsKey("key") ? variable![map["key"]] != null ? variable[map["key"]] : Key(map["key"]) : null,
titleText: map.containsKey('titleText') ? map['titleText'] : null,
subTitleText: map.containsKey('subTitleText') ? map['subTitleText'] : null,
color: map.containsKey('color') ? parseHexColor(map['color'])! : LLSColors.WHITE,
......@@ -25,7 +25,7 @@ class LLSListTileWidgetParser extends WidgetParser {
selected: map.containsKey('selected') ? map['selected'] : false,
focusColor: map.containsKey('focusColor') ? parseHexColor(map['focusColor'])! : LLSColors.PRIMARY,
hoverColor: map.containsKey('hoverColor') ? parseHexColor(map['hoverColor'])! : LLSColors.PRIMARY,
focusNode: map.containsKey('focusNode') ? map['focusNode'] : null,
focusNode: map.containsKey('focusNode') ? variable![map['focusNode']] : null,
autofocus: map.containsKey('autofocus') ? map['autofocus'] as bool : false
);
}
......
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:states_rebuilder/states_rebuilder.dart';
import 'package:widgetparser/widgetparser.dart';
class OnDataParser extends WidgetParser {
@override
parse(Map<String, dynamic> map, BuildContext buildContext, MethodListener? listener, Map<String, dynamic>? variable) {
return On.data(
() => map.containsKey('child') ? (WidgetParserBuilder.buildFromMap(map['child'], buildContext, listener, variable))! : SizedBox()
).listenTo(variable![map['state']]);
}
@override
String get widgetName => "OnData";
@override
Type get widgetType => On;
}
\ No newline at end of file
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:states_rebuilder/states_rebuilder.dart';
import 'package:widgetparser/widgetparser.dart';
import '../json_schema_helper.dart';
import '../utils.dart';
class OnFormParser extends WidgetParser {
@override
parse(Map<String, dynamic> map, BuildContext buildContext, MethodListener? listener, Map<String, dynamic>? variable) {
//example JSON for rendering On.form
// {
// "widget": "Onform",
// "child": {
// "widget": "SizedBox"
// },
// "state": "stateVariable"
// }
const onFormSchema = '''
{
"\$schema\": "$schemaUrl",
"\$ref\": "${refSchema}OnForm",
"definitions": {
"OnForm": {
"type": "object",
"additionalProperties": true,
"properties": {
"widget": {
"type": "string"
},
"child": {
"\$ref\": "${refSchema}Child"
},
"state": {
"type": "string"
}
},
"required": [
"child",
"state",
"widget"
],
"title": "OnForm"
},
"Child": ${SchemaHelper.child}
}
}
''';
Map<String, dynamic> jsonSchemaResult = jsonSchemaValidation(onFormSchema, map);
if (!jsonSchemaResult['validates']) {
return jsonSchemaErrorWidget(jsonSchemaResult['validator'], widgetName);
} else {
return On.form(
() => map.containsKey('child') ? (WidgetParserBuilder.buildFromMap(map['child'], buildContext, listener, variable))! : SizedBox()
).listenTo(variable![map['state']]);
}
}
@override
String get widgetName => "Onform";
@override
Type get widgetType => On;
}
\ No newline at end of file
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:states_rebuilder/states_rebuilder.dart';
import 'package:widgetparser/widgetparser.dart';
import '../json_schema_helper.dart';
import '../utils.dart';
class OnFormSubmissionParser extends WidgetParser {
@override
parse(Map<String, dynamic> map, BuildContext buildContext, MethodListener? listener, Map<String, dynamic>? variable) {
//example JSON for rendering On.formSubmission
// {
// "widget": "OnformSubmission",
// "onSubmitting": {
// "widget": "SizedBox"
// },
// "child": {
// "widget": "SizedBox"
// },
// "onSubmissionError": {
// "function": "function",
// "parameters": {
// "something": "something"
// }
// },
// "state": "stateVariable"
// }
const onFormSubmissionSchema = '''
{
"\$schema\": "$schemaUrl",
"\$ref\": "${refSchema}OnformSubmission",
"definitions": {
"OnformSubmission": {
"type": "object",
"additionalProperties": true,
"properties": {
"widget": {
"type": "string"
},
"onSubmitting": {
"\$ref\": "${refSchema}Child"
},
"child": {
"\$ref\": "${refSchema}Child"
},
"onSubmissionError": ${SchemaHelper.functionObject},
"state": {
"type": "string"
}
},
"required": [
"child",
"onSubmitting",
"state",
"widget"
],
"title": "OnformSubmission"
},
"Child": ${SchemaHelper.child}
}
}
''';
printWrapped(onFormSubmissionSchema);
Map<String, dynamic> jsonSchemaResult = jsonSchemaValidation(onFormSubmissionSchema, map);
if (!jsonSchemaResult['validates']) {
return jsonSchemaErrorWidget(jsonSchemaResult['validator'], widgetName);
} else {
return On.formSubmission(
onSubmitting: () => map.containsKey('onSubmitting') ? (WidgetParserBuilder.buildFromMap(map['onSubmitting'], buildContext, listener, variable))! : SizedBox(),
child: map.containsKey('child') ? (WidgetParserBuilder.buildFromMap(map['child'], buildContext, listener, variable))! : SizedBox(),
onSubmissionError: map.containsKey('onSubmissionError') ? (dynamic error, refresh) {
map['onSubmissionError']['parameters']['error'] = error;
map['onSubmissionError']['parameters']['refresh'] = refresh;
return listener!.run(buildContext, map['onSubmissionError']);
} : null
).listenTo(variable![map['state']]);
}
}
@override
String get widgetName => "OnformSubmission";
@override
Type get widgetType => On;
}
\ No newline at end of file
......@@ -14,6 +14,7 @@ void printWrapped(String text) {
}
Map<String, dynamic> jsonSchemaValidation(widgetSchema, widgetJson) {
try {
JsonSchema schema = JsonSchema.createSchema(widgetSchema);
Validator validator = Validator(schema);
bool validates = validator.validate(widgetJson);
......@@ -21,20 +22,33 @@ Map<String, dynamic> jsonSchemaValidation(widgetSchema, widgetJson) {
'validates': validates,
'validator': validator
};
} catch (e) {
return {
'validates': true,
'validator': e.toString()
};
}
}
Widget jsonSchemaErrorWidget(Validator validator) {
Widget jsonSchemaErrorWidget(Validator validator, String widgetName) {
List<Widget> widget = validator.errors.map((err) => Text(
err,
style: TextStyle(fontSize: 16),
)
).toList();
widget.add(
Text(
"Error parsing widget '$widgetName'",
style: TextStyle(fontSize: 16),
)
);
return Scaffold(
body: Container(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: validator.errors.map((err) => Text(
err,
style: TextStyle(fontSize: 16),
),
).toList()
children: widget
),
)
),
......@@ -134,6 +148,8 @@ FontWeight parseFontWeight(String? textFontWeight) {
fontWeight = FontWeight.w300;
break;
case 'normal':
fontWeight = FontWeight.normal;
break;
case 'w400':
fontWeight = FontWeight.w400;
break;
......@@ -144,6 +160,8 @@ FontWeight parseFontWeight(String? textFontWeight) {
fontWeight = FontWeight.w600;
break;
case 'bold':
fontWeight = FontWeight.bold;
break;
case 'w700':
fontWeight = FontWeight.w700;
break;
......@@ -912,7 +930,7 @@ InputDecoration parseInputDecoration(Map<String, dynamic> map, BuildContext buil
hintStyle: map.containsKey('hintStyle') ? parseTextStyle(map['hintStyle']) : null,
hintTextDirection: map.containsKey('hintTextDirection') ? parseTextDirection(map['hintTextDirection']) : null,
hintMaxLines: map.containsKey('hintMaxLines') ? map['hintMaxLines'] : null,
errorText: map.containsKey('errorText') ? map['errorText'] : null,
errorText: map.containsKey('errorText') ? variable![map['errorText']] != null ? variable[map['errorText']] : map['errorText'] : null,
errorStyle: map.containsKey('errorStyle') ? parseTextStyle(map['errorStyle']) : null,
errorMaxLines: map.containsKey('errorMaxLines') ? map['errorMaxLines'] : null,
floatingLabelBehavior: map.containsKey('floatingLabelBehavior') ? parseFloatingLabelBehavior(map['floatingLabelBehavior']) : null,
......@@ -942,7 +960,7 @@ InputDecoration parseInputDecoration(Map<String, dynamic> map, BuildContext buil
disabledBorder: map.containsKey('disabledBorder') ? parseInputBorder(map['disabledBorder']) : null,
enabledBorder: map.containsKey('enabledBorder') ? parseInputBorder(map['enabledBorder']) : null,
border: map.containsKey('border') ? parseInputBorder(map['border']) : null,
enabled: (map.containsKey('enabled') ? map['enabled'] as bool : null)!,
enabled: map.containsKey('enabled') ? map['enabled'] as bool : true,
semanticCounterText: map.containsKey('semanticCounterText') ? map['semanticCounterText'] : null,
alignLabelWithHint: map.containsKey('alignLabelWithHint') ? map['alignLabelWithHint'] as bool : null
);
......@@ -961,20 +979,20 @@ FloatingLabelBehavior parseFloatingLabelBehavior(String floatingLabelBehavior) {
InputBorder parseInputBorder(Map<String, dynamic> map) {
// example
// {
// "typeInputOrder": 'outline',
// "inputBorder": 'outline',
// "borderRadius": {
// "borderRadiusMethod": "vertical",
// "radius": [1.4,1.4]
// },
// "borderSide": {"color": "lls_primary", "width": 1.0, "style": {}}
// }
if (map.containsKey('typeInputOrder')) {
if (map['typeInputOrder'] == 'underline') {
if (map.containsKey('inputBorder')) {
if (map['inputBorder'] == 'underline') {
return UnderlineInputBorder(
borderRadius: (map.containsKey('borderRadius') ? parseBorderRadius(map['borderRadius']) : BorderRadius.only(topLeft: Radius.circular(4.0), topRight: Radius.circular(4.0)))!,
borderSide: map.containsKey('borderSide') ? parseBorderSide(map['borderSide']) : BorderSide()
);
} else if (map['typeInputOrder'] == 'outline') {
} else if (map['inputBorder'] == 'outline') {
return OutlineInputBorder(
borderRadius: (map.containsKey('borderRadius') ? parseBorderRadius(map['borderRadius']) : BorderRadius.all(Radius.circular(4.0)))!,
borderSide: map.containsKey('borderSide') ? parseBorderSide(map['borderSide']) : BorderSide(),
......
......@@ -6,6 +6,7 @@ library widgetparser;
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:states_rebuilder/states_rebuilder.dart';
//exports flutter widget parser
import 'package:widgetparser/src/flutter_widget/align_widget_parser.dart';
......@@ -42,11 +43,17 @@ import 'package:widgetparser/src/flutter_widget/inkwell_widget_parser.dart';
import 'package:widgetparser/src/flutter_widget/gesturedetector_widget_parser.dart';
import 'package:widgetparser/src/flutter_widget/form_widget_parser.dart';
import 'package:widgetparser/src/flutter_widget/textformfield_widget_parser.dart';
import 'package:widgetparser/src/flutter_widget/textfield_widget_parser.dart';
import 'package:widgetparser/src/flutter_widget/circularprogressindicator_widget_parser.dart';
//exports llswidget parser
import 'package:widgetparser/src/llswidget/llsbutton_widget_parser.dart';
import 'package:widgetparser/src/llswidget/llslisttile_widget_parser.dart';
import 'package:widgetparser/src/llswidget/llscard_widget_parser.dart';
import 'package:widgetparser/src/llswidget/llslabel_widget_parser.dart';
//exports state listener
import 'package:widgetparser/src/state_listener/onform_parser.dart';
import 'package:widgetparser/src/state_listener/ondata_parser.dart';
import 'package:widgetparser/src/state_listener/onform_submission_parser.dart';
class WidgetParserBuilder {
......@@ -89,11 +96,17 @@ class WidgetParserBuilder {
GestureDetectorWidgetParser(),
FormWidgetParser(),
TextFormFieldWidgetParser(),
TextFieldWidgetParser(),
CircularProgressIndicatorWidgetParser(),
//llswidget
LLSButtonWidgetParser(),
LLSListTileWidgetParser(),
LLSCardWidgetParser(),
LLSLabelWidgetParser()
LLSLabelWidgetParser(),
//state listener
OnFormParser(),
OnDataParser(),
OnFormSubmissionParser()
];
static final _widgetNameParserMap = <String, WidgetParser>{};
......@@ -117,12 +130,9 @@ class WidgetParserBuilder {
return widget;
}
static Widget? buildFromMap(Map<String, dynamic>? map, BuildContext buildContext, MethodListener? listener, Map<String, dynamic>? variable) {
static Widget? buildFromMap(Map<String, dynamic> map, BuildContext buildContext, MethodListener? listener, Map<String, dynamic>? variable) {
initDefaultParsersIfNess();
if (map == null) {
return null;
}
String? widgetName = map['widget'];
String? widgetName = map.containsKey("widget") ? map['widget'] : null;
var parser = _widgetNameParserMap[widgetName];
if (parser != null) {
try {
......@@ -150,7 +160,7 @@ class WidgetParserBuilder {
}
abstract class WidgetParser {
Widget parse(Map<String, dynamic> map, BuildContext buildContext, MethodListener? listener, Map<String, dynamic>? variable);
parse(Map<String, dynamic> map, BuildContext buildContext, MethodListener? listener, Map<String, dynamic>? variable);
String get widgetName;
......
......@@ -138,7 +138,7 @@ packages:
path: "../llswidget"
relative: true
source: path
version: "0.0.5"
version: "0.0.8"
logging:
dependency: transitive
description:
......@@ -207,6 +207,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.10.0"
states_rebuilder:
dependency: "direct main"
description:
name: states_rebuilder
url: "https://pub.dartlang.org"
source: hosted
version: "4.3.0"
stream_channel:
dependency: transitive
description:
......
name: widgetparser
description: this package to dynamically render widgets from JSON
version: 0.0.4
version: 0.0.6
author: Rizal Hermawan
homepage: https://locatorlogic.com
......@@ -18,6 +18,7 @@ dependencies:
path: ../llswidget
cupertino_icons: ^1.0.2
json_schema2: 2.0.0+2
states_rebuilder: 4.3.0
dev_dependencies:
flutter_test:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment