From ec854b5adfa748e91af6c92fd431f51c4bed9382 Mon Sep 17 00:00:00 2001 From: Jeff Peiffer Date: Wed, 16 Jul 2025 13:23:37 -0400 Subject: [PATCH 1/6] Removed lock file --- .../example/macos/Podfile.lock | 22 ------------------- .../xcshareddata/xcschemes/Runner.xcscheme | 1 + 2 files changed, 1 insertion(+), 22 deletions(-) delete mode 100644 packages/json_dynamic_widget/example/macos/Podfile.lock diff --git a/packages/json_dynamic_widget/example/macos/Podfile.lock b/packages/json_dynamic_widget/example/macos/Podfile.lock deleted file mode 100644 index d8488a0e..00000000 --- a/packages/json_dynamic_widget/example/macos/Podfile.lock +++ /dev/null @@ -1,22 +0,0 @@ -PODS: - - desktop_window (0.0.1): - - FlutterMacOS - - FlutterMacOS (1.0.0) - -DEPENDENCIES: - - desktop_window (from `Flutter/ephemeral/.symlinks/plugins/desktop_window/macos`) - - FlutterMacOS (from `Flutter/ephemeral`) - -EXTERNAL SOURCES: - desktop_window: - :path: Flutter/ephemeral/.symlinks/plugins/desktop_window/macos - FlutterMacOS: - :path: Flutter/ephemeral - -SPEC CHECKSUMS: - desktop_window: fb7c4f12c1129f947ac482296b6f14059d57a3c3 - FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 - -PODFILE CHECKSUM: 6fdb9d81903b459721e9b46c3a326c64ed2e24b8 - -COCOAPODS: 1.15.2 diff --git a/packages/json_dynamic_widget/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/packages/json_dynamic_widget/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index 1e76471a..9bb12151 100644 --- a/packages/json_dynamic_widget/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/packages/json_dynamic_widget/example/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -58,6 +58,7 @@ ignoresPersistentStateOnLaunch = "NO" debugDocumentVersioning = "YES" debugServiceExtension = "internal" + enableGPUValidationMode = "1" allowLocationSimulation = "YES"> From c2a7296ed797de4d503fb042d1cc57b7ca9af9ad Mon Sep 17 00:00:00 2001 From: Jeff Peiffer Date: Thu, 17 Jul 2025 20:57:21 -0400 Subject: [PATCH 2/6] mild refactor --- packages/json_dynamic_widget/example/.gitignore | 1 + packages/json_dynamic_widget/pubspec.yaml | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/json_dynamic_widget/example/.gitignore b/packages/json_dynamic_widget/example/.gitignore index b36b7db0..18702f5e 100644 --- a/packages/json_dynamic_widget/example/.gitignore +++ b/packages/json_dynamic_widget/example/.gitignore @@ -29,6 +29,7 @@ .pub-cache/ .pub/ /build/ +Podfile.lock # Web related diff --git a/packages/json_dynamic_widget/pubspec.yaml b/packages/json_dynamic_widget/pubspec.yaml index 8189f53f..376f3058 100644 --- a/packages/json_dynamic_widget/pubspec.yaml +++ b/packages/json_dynamic_widget/pubspec.yaml @@ -4,7 +4,7 @@ repository: 'https://github.com/peiffer-innovations/json_dynamic_widget' version: '10.0.2' environment: - sdk: '^3.7.0' + sdk: '^3.8.0' resolution: 'workspace' analyzer: @@ -23,7 +23,7 @@ dependencies: json_class: '^3.0.1' json_conditional: '^3.0.1+17' json_schema: '^5.2.1' - json_theme: '^9.0.0+1' + json_theme: '^9.0.1+2' logging: '^1.3.0' meta: '^1.16.0' template_expressions: '^3.3.1+2' From 5a9936c24dbf9405208a62a835d926a52891b785 Mon Sep 17 00:00:00 2001 From: Jeff Peiffer Date: Sun, 9 Nov 2025 15:16:26 -0400 Subject: [PATCH 3/6] codegen! --- packages/annotation/CHANGELOG.md | 5 + .../lib/dynamic_widget_annotation.dart | 20 +- packages/annotation/pubspec.yaml | 6 +- packages/codegen/CHANGELOG.md | 7 + .../lib/json_dynamic_widget_codegen.dart | 2 +- .../builder/json_widget_library_builder.dart | 1142 ++++++++++------- .../json_widget_registrar_builder.dart | 184 +-- .../codegen/lib/src/decoder/decoders.dart | 358 +++--- .../lib/src/decoder/schema_decoders.dart | 12 +- .../codegen/lib/src/encoder/encoders.dart | 100 +- .../src/extension/dart_type_extension.dart | 16 - packages/codegen/lib/src/model/param.dart | 36 + packages/codegen/pubspec.yaml | 14 +- packages/json_dynamic_widget/CHANGELOG.md | 8 + packages/json_dynamic_widget/README.md | 12 +- .../example/assets/pages/card.json | 2 +- .../example/assets/pages/checkbox.json | 4 + .../assets/pages/cupertino_switch.yaml | 105 +- .../example/assets/pages/dynamic.json | 12 +- .../example/assets/pages/form.json | 18 +- .../assets/pages/null_value_passing.json | 1 + .../example/assets/pages/radio.json | 85 +- .../example/assets/pages/switch.json | 3 + .../example/assets/pages/theme.json | 46 +- .../custom_schemas/dotted_border_schema.dart | 2 +- .../lib/src/custom_schemas/svg_schema.dart | 2 +- .../macos/Runner.xcodeproj/project.pbxproj | 6 +- .../json_dynamic_widget/example/pubspec.yaml | 21 +- .../json_dynamic_widget/lib/builders.dart | 1 + .../lib/json_dynamic_widget.dart | 2 +- .../json_animated_container_builder.dart | 12 +- .../builders/json_animated_theme_builder.dart | 2 +- .../src/builders/json_checkbox_builder.dart | 112 +- ...n_circular_progress_indicator_builder.dart | 15 +- .../src/builders/json_container_builder.dart | 12 +- .../json_cupertino_switch_builder.dart | 91 +- .../builders/json_decorated_box_builder.dart | 4 +- ...on_dropdown_button_form_field_builder.dart | 238 ++-- .../builders/json_layout_builder_builder.dart | 2 +- ...son_linear_progress_indicator_builder.dart | 15 +- .../src/builders/json_measured_builder.dart | 2 +- .../lib/src/builders/json_radio_builder.dart | 170 +-- .../builders/json_radio_group_builder.dart | 83 ++ .../src/builders/json_rich_text_builder.dart | 2 +- .../src/builders/json_scaffold_builder.dart | 31 + .../src/builders/json_semantics_builder.dart | 13 +- .../lib/src/builders/json_switch_builder.dart | 134 +- .../json_text_form_field_builder.dart | 76 +- .../lib/src/builders/json_widget_builder.dart | 6 +- .../decoders/input_decoration_decoder.dart | 51 +- .../src/models/deferred_json_widget_data.dart | 4 + .../lib/src/models/json_widget_data.dart | 31 +- packages/json_dynamic_widget/pubspec.yaml | 21 +- pubspec.yaml | 3 +- 54 files changed, 1745 insertions(+), 1617 deletions(-) delete mode 100644 packages/codegen/lib/src/extension/dart_type_extension.dart create mode 100644 packages/codegen/lib/src/model/param.dart create mode 100644 packages/json_dynamic_widget/lib/src/builders/json_radio_group_builder.dart diff --git a/packages/annotation/CHANGELOG.md b/packages/annotation/CHANGELOG.md index 7df69add..9ff1706a 100644 --- a/packages/annotation/CHANGELOG.md +++ b/packages/annotation/CHANGELOG.md @@ -1,3 +1,8 @@ +## [3.0.1] - October 29th, 2025 + +* Flutter 3.35 + + ## [3.0.0] - June 17th, 2025 * Upgraded `flutter_lints` to `^6.0.0`. diff --git a/packages/annotation/lib/dynamic_widget_annotation.dart b/packages/annotation/lib/dynamic_widget_annotation.dart index da32a4b2..1e165127 100644 --- a/packages/annotation/lib/dynamic_widget_annotation.dart +++ b/packages/annotation/lib/dynamic_widget_annotation.dart @@ -2,9 +2,7 @@ import 'dart:convert'; import 'package:meta/meta_meta.dart'; -const jsonWidget = JsonWidget( - autoRegister: true, -); +const jsonWidget = JsonWidget(autoRegister: true, requiresId: false); const jsonWidgetRegistrar = JsonWidgetRegistrar(); /// An annotation to be placed on the building `buildCustom` function that can @@ -14,10 +12,7 @@ const jsonWidgetRegistrar = JsonWidgetRegistrar(); /// [SliverGrid] for consistency). @Target({TargetKind.method}) class JsonArgAlias { - const JsonArgAlias({ - required this.alias, - required this.name, - }); + const JsonArgAlias({required this.alias, required this.name}); final String alias; final String name; @@ -94,10 +89,7 @@ class JsonBuilder { /// [String]. @Target({TargetKind.method}) class JsonDefaultParam { - const JsonDefaultParam( - this.name, - this.code, - ); + const JsonDefaultParam(this.name, this.code); final String code; final String name; @@ -135,6 +127,10 @@ class JsonSchemaName { /// The [autoRegister] can be set to `false` to skip adding the widget to the /// default registrar. /// +/// When the [requiresId] is true, that informs the code generator that this +/// particular widget needs a provided id to function correctly or else an error +/// or unexpected behavior may be encountered. +/// /// The [type] can override the widget JSON type that is generated for the /// widget. By default the type is a snake_case'd version of the Widget. For /// example, `ListView` becomes `list_view`. However, there may be times where @@ -149,12 +145,14 @@ class JsonWidget { const JsonWidget({ this.autoRegister = true, this.jsonWidget, + this.requiresId = false, this.type, this.widget, }); final bool autoRegister; final String? jsonWidget; + final bool requiresId; final String? type; final String? widget; } diff --git a/packages/annotation/pubspec.yaml b/packages/annotation/pubspec.yaml index 713fd041..862cc5b7 100644 --- a/packages/annotation/pubspec.yaml +++ b/packages/annotation/pubspec.yaml @@ -1,10 +1,10 @@ name: 'dynamic_widget_annotation' description: 'Annotations for the json_dynamic_widget library.' homepage: 'https://github.com/peiffer-innovations/json_dynamic_widget' -version: '3.0.0' +version: '3.0.1' environment: - sdk: '^3.8.1' + sdk: '^3.9.0' resolution: workspace analyzer: @@ -17,7 +17,7 @@ dependencies: dev_dependencies: flutter_lints: '^6.0.0' - test: '^1.25.0' + test: ^1.26.3 permittedLicenses: - 'Apache-2.0' diff --git a/packages/codegen/CHANGELOG.md b/packages/codegen/CHANGELOG.md index ba14b26c..1d39d1da 100644 --- a/packages/codegen/CHANGELOG.md +++ b/packages/codegen/CHANGELOG.md @@ -1,3 +1,9 @@ +## [4.0.0] - October 29th, 2025 + +* Updated generaters to the latest version +* Flutter 3.35 + + ## [3.0.0] - June 17th, 2025 * Updated `flutter_lints` to `^6.0.0`. @@ -9,6 +15,7 @@ * Pegged [analyzer depenendency to be <7.4](https://pub.dev/packages/analyzer/changelog#740) because Dart is preparing a breaking change (via deprecation) but hasn't bothered to update the [source_gen](https://pub.dev/packages/source_gen) package to absorb said breaking change yet so it breaks generators with no good way to fix the break, or ignore the warnings; which is rarely a great idea either. + ## [2.1.0+3] - March 11, 2025 * Automated dependency updates diff --git a/packages/codegen/lib/json_dynamic_widget_codegen.dart b/packages/codegen/lib/json_dynamic_widget_codegen.dart index 0797fb0f..934fef38 100644 --- a/packages/codegen/lib/json_dynamic_widget_codegen.dart +++ b/packages/codegen/lib/json_dynamic_widget_codegen.dart @@ -8,6 +8,6 @@ export 'src/builder/json_widget_registrar_builder.dart'; export 'src/decoder/decoders.dart'; export 'src/decoder/schema_decoders.dart'; // -export 'src/extension/dart_type_extension.dart'; +export 'src/model/param.dart'; // export 'src/util/widget_metadata.dart'; diff --git a/packages/codegen/lib/src/builder/json_widget_library_builder.dart b/packages/codegen/lib/src/builder/json_widget_library_builder.dart index 660b00b0..ce7e17ca 100644 --- a/packages/codegen/lib/src/builder/json_widget_library_builder.dart +++ b/packages/codegen/lib/src/builder/json_widget_library_builder.dart @@ -1,3 +1,5 @@ +// ignore_for_file: avoid_print + import 'dart:io'; import 'package:analyzer/dart/element/element.dart'; @@ -13,382 +15,524 @@ import 'package:yaon/yaon.dart'; class JsonWidgetLibraryBuilder extends GeneratorForAnnotation { static const kChildNames = {'child', 'children'}; + bool _isDebugMode = false; + @override String generateForAnnotatedElement( Element element, ConstantReader annotation, BuildStep buildStep, ) { - var constBuilder = false; - final autoRegister = annotation.read('autoRegister').boolValue; - String? jsonWidgetName; + assert(() { + _isDebugMode = true; + return true; + }()); + + var builderCode = ''; + var jsonWidgetCode = ''; + var modelCode = ''; + var schemaCode = ''; String? widgetName; - String? typeName; - try { - jsonWidgetName = annotation.read('jsonWidget').stringValue; - } catch (_) { - // no-op; use the default name - } - try { - typeName = annotation.read('type').stringValue; - } catch (_) { - // no-op; use the default name - } + try { - widgetName = annotation.read('widget').stringValue; - } catch (_) { - // no-op; use the default name - } - final pubspec = yaon.parse(File('pubspec.yaml').readAsStringSync()); - final packageName = pubspec['name'].toString(); - final schemaBaseUrl = - pubspec['schema_url'] ?? - 'https://peiffer-innovations.github.io/flutter_json_schemas/schemas'; - final name = element.name; - if (name == null) { - throw Exception('Annotation found on unnamed location, cannot continue.'); - } - if (!name.startsWith('_')) { - throw Exception('Class must be private, but [$name] is not private.'); - } + var constBuilder = false; + final autoRegister = annotation.read('autoRegister').boolValue; + final requiresId = annotation.read('requiresId').boolValue; + String? jsonWidgetName; + String? typeName; + + try { + jsonWidgetName = annotation.read('jsonWidget').stringValue; + } catch (_) { + // no-op; use the default name + } + try { + typeName = annotation.read('type').stringValue; + } catch (_) { + // no-op; use the default name + } + try { + widgetName = annotation.read('widget').stringValue; + } catch (_) { + // no-op; use the default name + } + final pubspec = yaon.parse(File('pubspec.yaml').readAsStringSync()); + final packageName = pubspec['name'].toString(); + final schemaBaseUrl = + pubspec['schema_url'] ?? + 'https://peiffer-innovations.github.io/flutter_json_schemas/schemas'; + final name = element.name; + if (name == null) { + throw Exception( + 'Annotation found on unnamed location, cannot continue.', + ); + } + if (!name.startsWith('_')) { + throw Exception('Class must be private, but [$name] is not private.'); + } - if (element is! ClassElement) { - throw Exception('Annotation found but is not associated with a class.'); - } + if (element is! ClassElement) { + throw Exception('Annotation found but is not associated with a class.'); + } - final positionedParams = []; - MethodElement? method; - const aliasChecker = TypeChecker.fromRuntime(JsonArgAlias); - const builderParamChecker = TypeChecker.fromRuntime(JsonBuildArg); - const builderChecker = TypeChecker.fromRuntime(JsonBuilder); - const defaultChecker = TypeChecker.fromRuntime(JsonDefaultParam); - const positionedChecker = TypeChecker.fromRuntime(JsonPositionedParam); - const schemaNameChecker = TypeChecker.fromRuntime(JsonSchemaName); - - var conHasRegistry = false; - - ConstructorElement? eCon; - for (var c in element.constructors) { - if (c.name == '') { - eCon = c; - for (var p in c.parameters) { - if (p.name == 'registry') { - conHasRegistry = true; + final positionedParams = []; + MethodElement? method; + const aliasChecker = TypeChecker.typeNamed(JsonArgAlias); + const builderParamChecker = TypeChecker.typeNamed(JsonBuildArg); + const builderChecker = TypeChecker.typeNamed(JsonBuilder); + const defaultChecker = TypeChecker.typeNamed(JsonDefaultParam); + const positionedChecker = TypeChecker.typeNamed(JsonPositionedParam); + const schemaNameChecker = TypeChecker.typeNamed(JsonSchemaName); + + var conHasRegistry = false; + + ConstructorElement? eCon; + for (var c in element.constructors) { + if (!c.isFactory && !c.displayName.contains('.')) { + eCon = c; + for (var p in c.formalParameters) { + if (p.name == 'registry') { + conHasRegistry = true; + } } } } - } - if (eCon == null) { - throw Exception('Unable to locate a default constructor.'); - } - - final methodsList = []; - methodsList.addAll(element.methods); - List interfaceVisitor(List interfaces) { - final list = []; - for (final interface in interfaces) { - list.addAll(interface.methods); - list.addAll(interfaceVisitor(interface.interfaces)); + if (eCon == null) { + throw Exception('Unable to locate a default constructor.'); } - return list; - } - for (final mixin in element.mixins) { - methodsList.addAll(mixin.methods); - methodsList.addAll(interfaceVisitor(mixin.interfaces)); - } + final methodsList = []; + methodsList.addAll(element.methods); + List interfaceVisitor(List interfaces) { + final list = []; + for (final interface in interfaces) { + list.addAll(interface.methods); + list.addAll(interfaceVisitor(interface.interfaces)); + } + return list; + } - for (var m in methodsList) { - final annotation = builderChecker.firstAnnotationOf(m); - if (annotation != null) { - method = m; - break; + for (final mixin in element.mixins) { + methodsList.addAll(mixin.methods); + methodsList.addAll(interfaceVisitor(mixin.interfaces)); } - } - if (method == null) { + for (var m in methodsList) { - if (m.name == 'buildCustom') { + final annotation = builderChecker.firstAnnotationOf(m); + if (annotation != null) { method = m; break; } } - } + if (method == null) { + for (var m in methodsList) { + if (m.name == 'buildCustom') { + method = m; + break; + } + } + } - if (method == null) { - throw Exception('No [buildCustom] or [_buildCustom] function found.'); - } + if (method == null) { + throw Exception('No [buildCustom] or [_buildCustom] function found.'); + } - String? schemaName; - final schemaNameAnnotation = schemaNameChecker.firstAnnotationOf(method); - if (schemaNameAnnotation != null) { - schemaName = ConstantReader( - schemaNameAnnotation, - ).read('name').stringValue; - } + String? schemaName; + final schemaNameAnnotation = schemaNameChecker.firstAnnotationOf(method); + if (schemaNameAnnotation != null) { + schemaName = ConstantReader( + schemaNameAnnotation, + ).read('name').stringValue; + } - final positionedAnnotations = positionedChecker.annotationsOf(method); - for (var annotation in positionedAnnotations) { - final name = ConstantReader(annotation).read('name').stringValue; - positionedParams.add(name); - } + final positionedAnnotations = positionedChecker.annotationsOf(method); + for (var annotation in positionedAnnotations) { + final name = ConstantReader(annotation).read('name').stringValue; + positionedParams.add(name); + } - final paramDefaults = {}; - final defaultAnnotations = defaultChecker.annotationsOf(method); - for (var annotation in defaultAnnotations) { - final name = ConstantReader(annotation).read('name').stringValue; - final code = ConstantReader(annotation).read('code').stringValue; - paramDefaults[name] = code; - } + final paramDefaults = {}; + final defaultAnnotations = defaultChecker.annotationsOf(method); + for (var annotation in defaultAnnotations) { + final name = ConstantReader(annotation).read('name').stringValue; + final code = ConstantReader(annotation).read('code').stringValue; + paramDefaults[name] = code; + } - final aliasAnnotations = aliasChecker.annotationsOf(method); - final aliases = {}; - for (var annotation in aliasAnnotations) { - final name = ConstantReader(annotation).read('name').stringValue; - final alias = ConstantReader(annotation).read('alias').stringValue; - aliases[name] = alias; - } + final aliasAnnotations = aliasChecker.annotationsOf(method); + final aliases = {}; + for (var annotation in aliasAnnotations) { + final name = ConstantReader(annotation).read('name').stringValue; + final alias = ConstantReader(annotation).read('alias').stringValue; + aliases[name] = alias; + } + + final paramDecoders = {}; + final paramEncoders = {}; + final schemaDecoders = {}; + const paramEncoderChecker = TypeChecker.typeNamed(JsonArgEncoder); + const paramDecoderChecker = TypeChecker.typeNamed(JsonArgDecoder); + const paramSchemaChecker = TypeChecker.typeNamed(JsonArgSchema); + for (var m in methodsList) { + final paramEncoderAnnotation = paramEncoderChecker.firstAnnotationOf(m); + final paramDecoderAnnotation = paramDecoderChecker.firstAnnotationOf(m); + final schemaAnnotation = paramSchemaChecker.firstAnnotationOf(m); + if (paramDecoderAnnotation != null) { + final param = ConstantReader( + paramDecoderAnnotation, + ).read('param').stringValue; + paramDecoders[param] = m; + } + if (paramEncoderAnnotation != null) { + final param = ConstantReader( + paramEncoderAnnotation, + ).read('param').stringValue; + paramEncoders[param] = m; + } + + if (schemaAnnotation != null) { + if (!m.isStatic) { + throw Exception( + 'Encountered [JsonArgSchema] annotation on a non-static method named: [${m.displayName}].', + ); + } + final param = ConstantReader( + schemaAnnotation, + ).read('param').stringValue; + schemaDecoders[param] = m; + } + } - final paramDecoders = {}; - final paramEncoders = {}; - final schemaDecoders = {}; - const paramEncoderChecker = TypeChecker.fromRuntime(JsonArgEncoder); - const paramDecoderChecker = TypeChecker.fromRuntime(JsonArgDecoder); - const paramSchemaChecker = TypeChecker.fromRuntime(JsonArgSchema); - for (var m in methodsList) { - final paramEncoderAnnotation = paramEncoderChecker.firstAnnotationOf(m); - final paramDecoderAnnotation = paramDecoderChecker.firstAnnotationOf(m); - final schemaAnnotation = paramSchemaChecker.firstAnnotationOf(m); - if (paramDecoderAnnotation != null) { - final param = ConstantReader( - paramDecoderAnnotation, - ).read('param').stringValue; - paramDecoders[param] = m; + final widget = method.returnType; + if (widget is! InterfaceType) { + throw Exception( + 'Unknown type [${widget.runtimeType}] found on the return from [buildCustom].', + ); } - if (paramEncoderAnnotation != null) { - final param = ConstantReader( - paramEncoderAnnotation, - ).read('param').stringValue; - paramEncoders[param] = m; + final widgetElement = widget.element; + if (widgetElement is! ClassElement) { + throw Exception( + 'Unknown type [${widgetElement.runtimeType}] found on the return from [buildCustom].', + ); } - if (schemaAnnotation != null) { - if (!m.isStatic) { - throw Exception( - 'Encountered [JsonArgSchema] annotation on a non-static method named: [${m.displayName}].', - ); + final widgetFieldDocs = {}; + for (var f in widgetElement.fields) { + final docs = f.documentationComment; + + if (docs != null) { + widgetFieldDocs[f.displayName] = docs; } - final param = ConstantReader( - schemaAnnotation, - ).read('param').stringValue; - schemaDecoders[param] = m; } - } - final widget = method.returnType; - if (widget is! InterfaceType) { - throw Exception( - 'Unknown type [${widget.runtimeType}] found on the return from [buildCustom].', + widgetName ??= _withoutNullability(widget.getDisplayString()); + widgetName = widgetName.replaceAll(RegExp(r'\<.*\>'), ''); + jsonWidgetName ??= + 'Json${widgetName.startsWith('_') ? widgetName.substring(1) : widgetName}'; + + ConstructorElement? wCon; + for (var c in widget.constructors) { + if (!c.isFactory && !c.displayName.contains('.')) { + wCon = c; + } + } + + if (wCon == null) { + throw Exception( + 'Cannot find unnamed constructor in [${_withoutNullability(widget.getDisplayString())}]', + ); + } + + final wConstructor = wCon; + + final formelParams = wConstructor.formalParameters; + + final params = []; + for (var p in formelParams) { + params.add( + Param.fromFormalParameter( + p, + builderParamChecker: builderParamChecker, + ), + ); + } + final generated = Class( + (c) => _generateClass( + c, + aliases: aliases, + conHasRegistry: conHasRegistry, + constBuilder: (c) => constBuilder = c, + eCon: eCon, + method: method, + name: name, + paramDecoders: paramDecoders, + params: params, + positionedParams: positionedParams, + requiresId: requiresId, + typeName: typeName, + widget: widget, + widgetName: widgetName!, + ), ); - } - final widgetElement = widget.element; - if (widgetElement is! ClassElement) { - throw Exception( - 'Unknown type [${widgetElement.runtimeType}] found on the return from [buildCustom].', + + final emitter = DartEmitter(useNullSafetySyntax: true); + builderCode = generated.accept(emitter).toString(); + + final jsonWidget = Class( + (c) => _generateWidgetClass( + c, + aliases: aliases, + name: name, + jsonWidgetName: jsonWidgetName!, + paramDecoders: paramDecoders, + paramDefaults: paramDefaults, + params: params, + positionedParams: positionedParams, + widget: widget, + widgetFieldDocs: widgetFieldDocs, + ), + ); + jsonWidgetCode = jsonWidget.accept(emitter).toString(); + + final model = Class( + (c) => _generateModel( + c, + aliases: aliases, + element: element, + name: name, + paramDecoders: paramDecoders, + paramDefaults: paramDefaults, + paramEncoders: paramEncoders, + params: params, + wConstructor: wConstructor, + widget: widget, + widgetFieldDocs: widgetFieldDocs, + ), ); - } - final widgetFieldDocs = {}; - for (var f in widgetElement.fields) { - final docs = f.documentationComment; + modelCode = model.accept(emitter).toString(); + + final schema = Class( + (c) => _generateSchema( + c, + aliases: aliases, + packageName: packageName, + params: params, + schemaBaseUrl: schemaBaseUrl, + schemaDecoders: schemaDecoders, + schemaName: schemaName, + schemaNameCallback: (s) => schemaName = s, + widgetName: widgetName!, + ), + ); - if (docs != null) { - widgetFieldDocs[f.name] = docs; + schemaCode = schema.accept(emitter).toString(); + + if (schemaName == null) { + throw Exception('Unexpected error, [schemaName] is null.'); } - } - widgetName ??= _withoutNullability(widget.getDisplayString()); - widgetName = widgetName.replaceAll(RegExp(r'\<.*\>'), ''); - jsonWidgetName ??= - 'Json${widgetName.startsWith('_') ? widgetName.substring(1) : widgetName}'; + WidgetMetadata.instance.add( + autoRegister: autoRegister, + builder: name.substring(1), + constBuilder: constBuilder, + schema: schemaName!, + widget: widgetName, + ); + + return _prepareCode( + builderCode: builderCode, + jsonWidgetCode: jsonWidgetCode, + modelCode: modelCode, + schemaCode: schemaCode, + widgetName: widgetName, + ); + } catch (e, stack) { + print('$e\n$stack\n'); - ConstructorElement? wCon; - for (var c in widget.constructors) { - if (c.name == '') { - wCon = c; + if (!_isDebugMode) { + rethrow; } - } - if (wCon == null) { - throw Exception( - 'Cannot find unnamed constructor in [${_withoutNullability(widget.getDisplayString())}]', - ); - } + return ''' +/* - final wConstructor = wCon; +${_prepareCode(builderCode: builderCode, jsonWidgetCode: jsonWidgetCode, modelCode: modelCode, schemaCode: schemaCode, widgetName: widgetName)} - final params = wConstructor.parameters; +*/ - final generated = Class((c) { - c.name = name.substring(1); - c.extend = Reference(name); - params.sort((a, b) { - var result = a.name.compareTo(b.name); +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- +// ----------------------------------------------------------------------------- - if (kChildNames.contains(a.name)) { - if (!kChildNames.contains(b.name)) { - result = 1; - } +/* + +$e +$stack + +*/ +'''; + } + } + + void _generateClass( + ClassBuilder c, { + required Map aliases, + required bool conHasRegistry, + required void Function(bool) constBuilder, + required ConstructorElement? eCon, + required MethodElement? method, + required String name, + required Map paramDecoders, + required List params, + required List positionedParams, + required bool requiresId, + required String? typeName, + required InterfaceType widget, + required String widgetName, + }) { + final typeStr = + typeName ?? + ReCase(widgetName).snakeCase.replaceAll(RegExp(r'\<.*\>'), ''); + c.name = name.substring(1); + c.extend = Reference(name); + params.sort((a, b) { + var result = a.displayName.compareTo(b.displayName); + + if (kChildNames.contains(a.displayName)) { + if (!kChildNames.contains(b.displayName)) { + result = 1; } - if (kChildNames.contains(b.name)) { - if (!kChildNames.contains(a.name)) { - result = -1; - } + } + if (kChildNames.contains(b.displayName)) { + if (!kChildNames.contains(a.displayName)) { + result = -1; } + } - return result; - }); - - c.fields.add( - Field((f) { - f.name = 'kType'; - f.static = true; - f.modifier = FieldModifier.constant; - f.assignment = Code( - "'${typeName ?? ReCase(widgetName!).snakeCase.replaceAll(RegExp(r'\<.*\>'), '')}'", - ); - }), - ); + return result; + }); - // c.fields.add(Field((f) { - // f.name = 'args'; - // f.type = const Reference('dynamic'); - // f.modifier = FieldModifier.final$; - // })); + c.fields.add( + Field((f) { + f.name = 'kType'; + f.static = true; + f.modifier = FieldModifier.constant; + f.assignment = Code("'$typeStr'"); + }), + ); - c.constructors.add( - Constructor((con) { - con.constant = eCon != null && eCon.isConst; - constBuilder = con.constant; + c.constructors.add( + Constructor((con) { + con.constant = eCon != null && eCon.isConst; + constBuilder(con.constant); + + con.optionalParameters.add( + Parameter((param) { + param.name = 'args'; + param.named = true; + param.required = true; + param.toSuper = true; + }), + ); + if (conHasRegistry) { con.optionalParameters.add( Parameter((param) { - param.name = 'args'; + param.name = 'registry'; param.named = true; param.required = true; param.toSuper = true; }), ); + } + }), + ); - if (conHasRegistry) { - con.optionalParameters.add( - Parameter((param) { - param.name = 'registry'; - param.named = true; - param.required = true; - param.toSuper = true; - }), - ); - } - }), - ); - - c.methods.add( - Method((m) { - m.docs.add(''' + c.methods.add( + Method((m) { + m.docs.add(''' /// Constant that can be referenced for the builder's type.'''); - m.name = 'type'; - m.annotations.add(const CodeExpression(Code('override'))); - m.lambda = true; - m.type = MethodType.getter; - m.returns = const Reference('String'); - m.body = const Code('kType'); - }), - ); + m.name = 'type'; + m.annotations.add(const CodeExpression(Code('override'))); + m.lambda = true; + m.type = MethodType.getter; + m.returns = const Reference('String'); + m.body = const Code('kType'); + }), + ); - c.methods.add( - Method((m) { - m.docs.add(''' + c.methods.add( + Method((m) { + m.docs.add(''' /// Static function that is capable of decoding the widget from a dynamic JSON /// or YAML set of values.'''); - m.name = 'fromDynamic'; - m.static = true; - m.requiredParameters.add( - Parameter((p) { - p.name = 'map'; - p.type = const Reference('dynamic'); - }), - ); - m.optionalParameters.add( - Parameter((p) { - p.name = 'registry'; - p.type = const Reference('JsonWidgetRegistry?'); - p.named = true; - p.required = false; - }), - ); + m.name = 'fromDynamic'; + m.static = true; + m.requiredParameters.add( + Parameter((p) { + p.name = 'map'; + p.type = const Reference('dynamic'); + }), + ); + m.optionalParameters.add( + Parameter((p) { + p.name = 'registry'; + p.type = const Reference('JsonWidgetRegistry?'); + p.named = true; + p.required = false; + }), + ); - m.returns = Reference(c.name); - m.lambda = true; + m.returns = Reference(c.name); + m.lambda = true; - m.body = Code(''' + m.body = Code(''' ${c.name}( args: map, ${conHasRegistry ? 'registry: registry,' : ''} ) '''); - }), - ); - - // c.methods.add(Method((m) { - // m.name = 'toJson'; - // m.body = const Code('Map.from(args)'); - // m.returns = const Reference('Map'); - // m.annotations.add(const CodeExpression(Code('override'))); - // m.lambda = true; - // })); - - // c.methods.add(Method((m) { - // m.name = 'fromModel'; - // m.static = true; - // m.docs.add(''' - // /// Static function that will take a manually build model and build the widget - // /// for display.'''); + }), + ); - // m.returns = Reference('${c.name}'); - // m.requiredParameters.add(Parameter((p) { - // p.type = Reference('${name.substring(1)}Model'); - // p.name = 'model'; - // })); - // m.body = Code(''' - // ${c.name}(args: model) - // '''); - // m.lambda = true; - // })); + c.methods.add( + Method((m) { + m.name = 'createModel'; + m.annotations.add(const CodeExpression(Code('override'))); + m.returns = Reference('${name.substring(1)}Model'); + m.optionalParameters.add( + Parameter((p) { + p.name = 'childBuilder'; + p.named = true; + p.required = false; + p.type = const Reference('ChildWidgetBuilder?'); + }), + ); + m.optionalParameters.add( + Parameter((p) { + p.name = 'data'; + p.named = true; + p.required = true; + p.type = const Reference('JsonWidgetData'); + }), + ); - c.methods.add( - Method((m) { - m.name = 'createModel'; - m.annotations.add(const CodeExpression(Code('override'))); - m.returns = Reference('${name.substring(1)}Model'); - m.optionalParameters.add( - Parameter((p) { - p.name = 'childBuilder'; - p.named = true; - p.required = false; - p.type = const Reference('ChildWidgetBuilder?'); - }), - ); - m.optionalParameters.add( - Parameter((p) { - p.name = 'data'; - p.named = true; - p.required = true; - p.type = const Reference('JsonWidgetData'); - }), - ); + final idBuf = StringBuffer(); + if (requiresId) { + assert(false, ''); + idBuf.writeln(""" +assert(data.hasProvidedId, ''' +The $typeStr requires an id to be provided within the JSON but no provided +id was found. This may lead to errors or unexpected results when running in +release mode. +'''); +"""); + } - m.body = Code(''' + m.body = Code(''' +$idBuf final model = ${c.name}Model.fromDynamic( args, registry: data.jsonWidgetRegistry, @@ -396,79 +540,76 @@ final model = ${c.name}Model.fromDynamic( return model; '''); - }), - ); + }), + ); - c.methods.add( - Method((m) { - m.name = method!.name; - m.annotations.add(const CodeExpression(Code('override'))); - m.returns = Reference(widget.getDisplayString()); + c.methods.add( + Method((m) { + m.name = method!.name; + m.annotations.add(const CodeExpression(Code('override'))); + m.returns = Reference(widget.getDisplayString()); + + m.optionalParameters.add( + Parameter((p) { + p.name = 'childBuilder'; + p.named = true; + p.required = false; + p.type = const Reference('ChildWidgetBuilder?'); + }), + ); + m.optionalParameters.add( + Parameter((p) { + p.name = 'context'; + p.named = true; + p.required = true; + p.type = const Reference('BuildContext'); + }), + ); + m.optionalParameters.add( + Parameter((p) { + p.name = 'data'; + p.named = true; + p.required = true; + p.type = const Reference('JsonWidgetData'); + }), + ); + m.optionalParameters.add( + Parameter((p) { + p.name = 'key'; + p.named = true; + p.required = false; + p.type = const Reference('Key?'); + }), + ); - m.optionalParameters.add( - Parameter((p) { - p.name = 'childBuilder'; - p.named = true; - p.required = false; - p.type = const Reference('ChildWidgetBuilder?'); - }), - ); - m.optionalParameters.add( - Parameter((p) { - p.name = 'context'; - p.named = true; - p.required = true; - p.type = const Reference('BuildContext'); - }), - ); - m.optionalParameters.add( - Parameter((p) { - p.name = 'data'; - p.named = true; - p.required = true; - p.type = const Reference('JsonWidgetData'); - }), - ); - m.optionalParameters.add( - Parameter((p) { - p.name = 'key'; - p.named = true; - p.required = false; - p.type = const Reference('Key?'); - }), + final lines = []; + final buf = StringBuffer(); + for (var pos in positionedParams) { + _buildCustomParamBuilder( + aliases: aliases, + buf: buf, + positioned: true, + lines: lines, + param: params.firstWhere((p) => p.displayName == pos), + paramDecoders: paramDecoders, + positionedParams: positionedParams, ); - - final lines = []; - final buf = StringBuffer(); - for (var pos in positionedParams) { - // lines.add('model.$pos'); + } + for (var param in params) { + if (!positionedParams.contains(param.displayName)) { _buildCustomParamBuilder( aliases: aliases, buf: buf, - builderParamChecker: builderParamChecker, - positioned: true, + positioned: false, lines: lines, - param: params.firstWhere((p) => p.name == pos), + param: param, paramDecoders: paramDecoders, positionedParams: positionedParams, ); } - for (var param in params) { - if (!positionedParams.contains(param.name)) { - _buildCustomParamBuilder( - aliases: aliases, - buf: buf, - builderParamChecker: builderParamChecker, - positioned: false, - lines: lines, - param: param, - paramDecoders: paramDecoders, - positionedParams: positionedParams, - ); - } - } + } - m.body = Code(''' + m.body = Code(''' final model = createModel( childBuilder: childBuilder, data: data, @@ -479,14 +620,23 @@ return ${_withoutNullability(widget.getDisplayString())}( ${lines.join(',')}${lines.isNotEmpty ? ',' : ''} ); '''); - }), - ); - }); - - final emitter = DartEmitter(useNullSafetySyntax: true); - final builderCode = generated.accept(emitter).toString(); + }), + ); + } - final jsonWidget = Class((c) { + void _generateWidgetClass( + ClassBuilder c, { + required Map aliases, + required String name, + required String jsonWidgetName, + required Map paramDecoders, + required Map paramDefaults, + required List params, + required List? positionedParams, + required InterfaceType widget, + required Map widgetFieldDocs, + }) { + try { c.name = jsonWidgetName; c.extend = const Reference('JsonWidgetData'); c.constructors.add( @@ -510,7 +660,6 @@ return ${_withoutNullability(widget.getDisplayString())}( ); _buildConstructorParams( aliases: aliases, - builderParamChecker: builderParamChecker, con: con, paramDecoders: paramDecoders, paramDefaults: paramDefaults, @@ -523,9 +672,10 @@ return ${_withoutNullability(widget.getDisplayString())}( final modelLines = StringBuffer(); for (var p in params) { - final annotation = builderParamChecker.firstAnnotationOf(p); - if (annotation == null && p.name != 'key') { - modelLines.writeln("'${aliases[p.name] ?? p.name}': ${p.name},"); + if (!p.isBuilderParam && p.displayName != 'key') { + modelLines.writeln( + "'${aliases[p.displayName] ?? p.displayName}': ${p.displayName},", + ); } } @@ -557,7 +707,6 @@ super( _buildClassFields( aliases: aliases, - builderParamChecker: builderParamChecker, c: c, paramDecoders: paramDecoders, params: params, @@ -591,10 +740,25 @@ super( // ),).build(context: context,) // '''); // })); - }); - final jsonWidgetCode = jsonWidget.accept(emitter).toString(); + } catch (e, stack) { + print('$e\n$stack\n'); + } + } - final model = Class((c) { + void _generateModel( + ClassBuilder c, { + required Map aliases, + required ClassElement element, + required String name, + required Map paramDecoders, + required Map paramDefaults, + required Map paramEncoders, + required List params, + required ConstructorElement wConstructor, + required InterfaceType widget, + required Map widgetFieldDocs, + }) { + try { final docs = wConstructor.documentationComment; if (docs != null) { c.docs.add( @@ -618,7 +782,6 @@ super( _buildConstructorParams( aliases: aliases, - builderParamChecker: builderParamChecker, con: con, paramDecoders: paramDecoders, paramDefaults: paramDefaults, @@ -629,7 +792,6 @@ super( _buildClassFields( aliases: aliases, - builderParamChecker: builderParamChecker, c: c, paramDecoders: paramDecoders, params: params, @@ -705,14 +867,13 @@ return result; ); final lines = []; for (var param in params) { - final annotation = builderParamChecker.firstAnnotationOf(param); - if (annotation != null) { + if (param.isBuilderParam) { // comes from the build method, not the data map. continue; } - if (param.name != 'key') { + if (param.displayName != 'key') { lines.add( - '${param.name}: ${decode(element, param, aliases: aliases, defaults: paramDefaults, paramDecoders: paramDecoders.keys)}', + '${param.displayName}: ${decode(element, param, aliases: aliases, defaults: paramDefaults, paramDecoders: paramDecoders.keys)}', ); } } @@ -752,13 +913,12 @@ return result; final buf = StringBuffer(); for (var param in params) { - final annotation = builderParamChecker.firstAnnotationOf(param); - if (annotation != null) { + if (param.isBuilderParam) { // comes from the build method, not the data map. continue; } if (param.displayName != 'key') { - final name = aliases[param.name] ?? param.name; + final name = aliases[param.displayName] ?? param.displayName; final encoder = paramEncoders[name]; var defaultValueCode = @@ -768,7 +928,7 @@ return result; } if (encoder != null) { customEncoders.write(''' -final ${name}Encoded = ${encoder.enclosingElement3.name}.${encoder.name}(${param.name}); +final ${name}Encoded = ${encoder.enclosingElement?.displayName}.${encoder.name}(${param.displayName}); '''); buf.write(''' @@ -797,65 +957,77 @@ ${buf.toString()} } }), ); - }); - - final modelCode = model.accept(emitter).toString(); + } catch (e, stack) { + print('$e\n$stack\n'); + if (!_isDebugMode) { + rethrow; + } + } + } + void _generateSchema( + ClassBuilder c, { + required Map aliases, + required String packageName, + required List params, + required String schemaBaseUrl, + required Map schemaDecoders, + required String? schemaName, + required void Function(String) schemaNameCallback, + required String widgetName, + }) { final properties = StringBuffer(); - final requiredProperties = StringBuffer(); - final schema = Class((c) { - final id = - '$schemaBaseUrl/$packageName/${ReCase(widgetName!).snakeCase}.json'; - - var name = widgetName; - name = name.replaceAll(RegExp(r'\<.*\>'), ''); - if (name.startsWith('_')) { - name = name.substring(1); - } - schemaName ??= '${name}Schema'; - c.name = schemaName; + final id = + '$schemaBaseUrl/$packageName/${ReCase(widgetName).snakeCase}.json'; - for (var param in params) { - final annotation = builderParamChecker.firstAnnotationOf(param); - if (annotation != null) { - // comes from the build method, not the data map. - continue; - } - final name = aliases[param.displayName] ?? param.displayName; - if (param.isRequired) { - requiredProperties.write("'$name',"); - } - if (param.displayName != 'key') { - final type = _withoutNullability(param.type.getDisplayString()); - - final sMethod = schemaDecoders[name]; - if (sMethod == null) { - final fun = kSchemaDecoders[type]; - - final schema = fun == null ? 'SchemaHelper.anySchema' : fun(param); - properties.write("'$name': $schema,\n"); - } else { - if (!sMethod.isStatic) throw 'Schema only supports static methods'; - properties.write( - "'$name': ${sMethod.enclosingElement3.name}.${sMethod.displayName}(),", - ); + var name = widgetName; + name = name.replaceAll(RegExp(r'\<.*\>'), ''); + if (name.startsWith('_')) { + name = name.substring(1); + } + schemaName ??= '${name}Schema'; + schemaNameCallback(schemaName); + c.name = schemaName; + + for (var param in params) { + if (param.isBuilderParam) { + // comes from the build method, not the data map. + continue; + } + final name = aliases[param.displayName] ?? param.displayName; + if (param.displayName != 'key') { + final type = _withoutNullability(param.typeName); + + final sMethod = schemaDecoders[name]; + if (sMethod == null) { + final fun = kSchemaDecoders[type]; + + final schema = fun == null ? 'SchemaHelper.anySchema' : fun(param); + properties.write("'$name': $schema,\n"); + } else { + if (!sMethod.isStatic) { + throw 'Schema only supports static methods'; } + properties.write( + "'$name': ${sMethod.enclosingElement?.displayName}.${sMethod.displayName}(),", + ); } } - c.fields.add( - Field((f) { - f.name = 'id'; - f.modifier = FieldModifier.constant; - f.static = true; - f.assignment = Code("'$id'"); - }), - ); - c.fields.add( - Field((f) { - f.name = 'schema'; - f.modifier = FieldModifier.final$; - f.static = true; - f.assignment = Code(''' + } + c.fields.add( + Field((f) { + f.name = 'id'; + f.modifier = FieldModifier.constant; + f.static = true; + f.assignment = Code("'$id'"); + }), + ); + c.fields.add( + Field((f) { + f.name = 'schema'; + f.modifier = FieldModifier.final$; + f.static = true; + f.assignment = Code(''' { r'\$schema': 'http://json-schema.org/draft-07/schema#', r'\$id': id, @@ -865,33 +1037,23 @@ ${buf.toString()} 'properties': { ${properties.toString()} }, - 'required': [ - ${requiredProperties.toString()} - ], } '''); - }), - ); - }); - - final schemaCode = schema.accept(emitter).toString(); - - if (schemaName == null) { - throw Exception('Unexpected error, [schemaName] is null.'); - } - - WidgetMetadata.instance.add( - autoRegister: autoRegister, - builder: name.substring(1), - constBuilder: constBuilder, - schema: schemaName!, - widget: widgetName, + }), ); + } - return ''' + String _prepareCode({ + required String builderCode, + required String jsonWidgetCode, + required String modelCode, + required String schemaCode, + required String? widgetName, + }) => + ''' // ignore_for_file: avoid_init_to_null // ignore_for_file: deprecated_member_use -${widgetName.startsWith('_') ? '// ignore_for_file: library_private_types_in_public_api' : ''} +${widgetName?.startsWith('_') == true ? '// ignore_for_file: library_private_types_in_public_api' : ''} // ignore_for_file: prefer_const_constructors // ignore_for_file: prefer_const_constructors_in_immutables // ignore_for_file: prefer_final_locals @@ -907,27 +1069,24 @@ $modelCode $schemaCode '''; - } } void _buildClassFields({ required Map aliases, - required TypeChecker builderParamChecker, required ClassBuilder c, required Map paramDecoders, - required List params, + required List params, required InterfaceType widget, required Map widgetFieldDocs, }) { for (var p in params) { - final annotation = builderParamChecker.firstAnnotationOf(p); - if (annotation != null) { + if (p.isBuilderParam) { // comes from the build method, not the data map. continue; } - if ( /*!kChildNames.containsKey(p.name) &&*/ p.name != 'key') { - final method = paramDecoders[aliases[p.name] ?? p.name]; - var type = p.type.getDisplayString(); + if ( /*!kChildNames.containsKey(p.name) &&*/ p.displayName != 'key') { + final method = paramDecoders[aliases[p.displayName] ?? p.displayName]; + var type = p.typeName; if (type == 'Widget' || type == 'PreferredSizeWidget') { type = 'JsonWidgetData'; @@ -943,15 +1102,16 @@ void _buildClassFields({ c.fields.add( Field((f) { - final docs = widgetFieldDocs[p.name]; + final docs = widgetFieldDocs[p.displayName]; if (docs != null) { f.docs.add( - ' /* AUTOGENERATED FROM [${_withoutNullability(widget.getDisplayString())}.${p.name}]*/', + ' /* AUTOGENERATED FROM [${_withoutNullability(widget.getDisplayString())}.${p.displayName}]*/', ); f.docs.add(docs); } + f.modifier = FieldModifier.final$; - f.name = p.name; + f.name = p.displayName; f.type = Reference(method == null ? type : 'dynamic'); }), ); @@ -961,11 +1121,10 @@ void _buildClassFields({ void _buildConstructorParams({ required Map aliases, - required TypeChecker builderParamChecker, required ConstructorBuilder con, required Map paramDecoders, required Map paramDefaults, - required List params, + required List params, List? positionedParams, }) { positionedParams?.forEach((paramName) { @@ -973,7 +1132,7 @@ void _buildConstructorParams({ con.requiredParameters.add( Parameter((param) { final name = aliases[paramName] ?? paramName; - final p = params.firstWhere((p) => p.name == paramName); + final p = params.firstWhere((p) => p.displayName == paramName); param.name = paramName; param.named = false; @@ -995,15 +1154,14 @@ void _buildConstructorParams({ }); for (var p in params) { - final annotation = builderParamChecker.firstAnnotationOf(p); - if (annotation != null || positionedParams?.contains(p.name) == true) { + if (p.isBuilderParam || positionedParams?.contains(p.displayName) == true) { continue; } - if ( /*!kChildNames.containsKey(p.name) && */ p.name != 'key') { + if (p.displayName != 'key') { con.optionalParameters.add( Parameter((param) { - final name = aliases[p.name] ?? p.name; + final name = aliases[p.displayName] ?? p.displayName; final decoder = paramDecoders[name]; var defaultValueCode = paramDefaults[name] ?? p.defaultValueCode; if (defaultValueCode == 'const []') { @@ -1012,14 +1170,14 @@ void _buildConstructorParams({ bool hasAnyRequiredParameter(MethodElement? me) { if (me == null) return false; - return me.parameters.any((pe) { + return me.formalParameters.any((pe) { return pe.isPositional || pe.isRequiredPositional || pe.isRequiredNamed; }); } - param.name = p.name; + param.name = p.displayName; param.named = true; param.defaultTo = defaultValueCode == null || @@ -1040,23 +1198,23 @@ void _buildConstructorParams({ void _buildCustomParamBuilder({ required Map aliases, required StringBuffer buf, - required TypeChecker builderParamChecker, required List lines, - required ParameterElement param, + required Param param, required Map paramDecoders, required bool positioned, required List positionedParams, }) { - final method = paramDecoders[aliases[param.name] ?? param.name]; - final annotation = builderParamChecker.firstAnnotationOf(param); + final method = paramDecoders[aliases[param.displayName] ?? param.displayName]; - final name = param.name; - final prefix = positioned ? '' : '${param.name}: '; + final name = param.displayName; + final prefix = positioned ? '' : '${param.displayName}: '; - if (annotation != null || param.name == 'key' || param.name == 'context') { - lines.add('$prefix${param.name}'); + if (param.isBuilderParam || + param.displayName == 'key' || + param.displayName == 'context') { + lines.add('$prefix${param.displayName}'); } else if (method == null) { - final type = param.type.getDisplayString(); + final type = param.typeName; if (type == 'Widget') { lines.add(''' ${prefix}model.$name.build( @@ -1117,7 +1275,7 @@ $prefix[ '''); } else if (type == 'List?') { lines.add(''' -${prefix}model.${param.name} == null ? null : [ +${prefix}model.${param.displayName} == null ? null : [ for (var d in model.$name!) d.build( childBuilder: childBuilder, @@ -1133,7 +1291,7 @@ ${prefix}model.${param.name} == null ? null : [ lines.add('$pPrefix${name}Decoded'); final decoderParams = []; - for (var field in method.parameters) { + for (var field in method.formalParameters) { if (field.name == 'childBuilder') { decoderParams.add('childBuilder: childBuilder,'); } else if (field.name == 'context') { @@ -1145,7 +1303,7 @@ ${prefix}model.${param.name} == null ? null : [ } else if (field.name == 'registry') { decoderParams.add('registry: data.jsonWidgetRegistry,'); } else if (field.name == 'value') { - decoderParams.add('value: model.${param.name},'); + decoderParams.add('value: model.${param.displayName},'); } } diff --git a/packages/codegen/lib/src/builder/json_widget_registrar_builder.dart b/packages/codegen/lib/src/builder/json_widget_registrar_builder.dart index f287c2db..0fd87111 100644 --- a/packages/codegen/lib/src/builder/json_widget_registrar_builder.dart +++ b/packages/codegen/lib/src/builder/json_widget_registrar_builder.dart @@ -22,7 +22,7 @@ class JsonWidgetRegistrarBuilder final emitter = DartEmitter(useNullSafetySyntax: true); final widgets = WidgetMetadata().data; - const registrationChecker = TypeChecker.fromRuntime(JsonWidgetRegistration); + const registrationChecker = TypeChecker.typeNamed(JsonWidgetRegistration); final manualRegistrations = {}; MethodElement? registerMethod; @@ -32,7 +32,7 @@ class JsonWidgetRegistrarBuilder registerMethod = m; } if (annotation != null) { - manualRegistrations[m.name] = WidgetInfo( + manualRegistrations[m.displayName] = WidgetInfo( autoRegister: true, builder: ConstantReader(annotation).read('builder').stringValue, constBuilder: false, @@ -46,74 +46,87 @@ class JsonWidgetRegistrarBuilder c.name = name.substring(1); c.extend = Reference(name); - c.fields.add(Field((f) { - f.name = '_builders'; - f.type = const Reference('Map'); - f.assignment = const Code('{}'); - f.modifier = FieldModifier.final$; - })); - c.fields.add(Field((f) { - f.name = '_schemas'; - f.type = const Reference('Map>'); - f.assignment = const Code('>{}'); - f.modifier = FieldModifier.final$; - })); - - c.methods.add(Method((m) { - m.name = 'registerDefaults'; - m.optionalParameters.add(Parameter((p) { - p.name = 'registry'; - p.type = const Reference('JsonWidgetRegistry?'); - p.named = true; - p.required = false; - })); - m.static = true; - m.returns = Reference(c.name); - - final buf = StringBuffer(); - - buf.writeln('registry ??= JsonWidgetRegistry.instance;'); - - buf.writeln('return ${c.name}()'); - final registrations = []; - for (var entry in manualRegistrations.entries) { - registrations.add('..${entry.key}()'); - } - for (var w in widgets) { - if (w.autoRegister) { - registrations.add('..with${w.widget}()'); + c.fields.add( + Field((f) { + f.name = '_builders'; + f.type = const Reference('Map'); + f.assignment = const Code('{}'); + f.modifier = FieldModifier.final$; + }), + ); + c.fields.add( + Field((f) { + f.name = '_schemas'; + f.type = const Reference('Map>'); + f.assignment = const Code('>{}'); + f.modifier = FieldModifier.final$; + }), + ); + + c.methods.add( + Method((m) { + m.name = 'registerDefaults'; + m.optionalParameters.add( + Parameter((p) { + p.name = 'registry'; + p.type = const Reference('JsonWidgetRegistry?'); + p.named = true; + p.required = false; + }), + ); + m.static = true; + m.returns = Reference(c.name); + + final buf = StringBuffer(); + + buf.writeln('registry ??= JsonWidgetRegistry.instance;'); + + buf.writeln('return ${c.name}()'); + final registrations = []; + for (var entry in manualRegistrations.entries) { + registrations.add('..${entry.key}()'); } - } - - registrations.sort(); - buf.write(registrations.join('\n')); - buf.write('..register(registry);'); - - m.body = Code(buf.toString()); - })); - - c.methods.add(Method((m) { - m.name = 'schemas'; - m.type = MethodType.getter; - m.returns = const Reference('Map>'); - m.lambda = true; - m.body = const Code('Map>.from(_schemas)'); - })); - - c.methods.add(Method((m) { - m.name = 'register'; - m.requiredParameters.add( - Parameter((p) { - p.name = 'registry'; - p.type = const Reference('JsonWidgetRegistry'); - p.named = false; - }), - ); - m.returns = const Reference('void'); - if (registerMethod != null) { - m.annotations.add(const CodeExpression(Code('override'))); - } - m.body = Code(''' + for (var w in widgets) { + if (w.autoRegister) { + registrations.add('..with${w.widget}()'); + } + } + + registrations.sort(); + buf.write(registrations.join('\n')); + buf.write('..register(registry);'); + + m.body = Code(buf.toString()); + }), + ); + + c.methods.add( + Method((m) { + m.name = 'schemas'; + m.type = MethodType.getter; + m.returns = const Reference('Map>'); + m.lambda = true; + m.body = const Code( + 'Map>.from(_schemas)', + ); + }), + ); + + c.methods.add( + Method((m) { + m.name = 'register'; + m.requiredParameters.add( + Parameter((p) { + p.name = 'registry'; + p.type = const Reference('JsonWidgetRegistry'); + p.named = false; + }), + ); + m.returns = const Reference('void'); + if (registerMethod != null) { + m.annotations.add(const CodeExpression(Code('override'))); + } + m.body = Code(''' ${registerMethod == null ? '' : 'super.register(registry);'} for (var b in _builders.entries) { registry.registerCustomBuilder(b.key, b.value); @@ -124,13 +137,15 @@ for (var s in _schemas.entries) { schemaCache.addSchema(s.key, s.value); } '''); - })); + }), + ); for (var w in widgets) { - c.methods.add(Method((m) { - m.name = 'with${w.widget}'; - m.returns = const Reference('void'); - m.body = Code(''' + c.methods.add( + Method((m) { + m.name = 'with${w.widget}'; + m.returns = const Reference('void'); + m.body = Code(''' _builders[${w.builder}.kType] = const JsonWidgetBuilderContainer( builder: ${w.builder}.fromDynamic, @@ -138,17 +153,19 @@ _builders[${w.builder}.kType] = ); _schemas[${w.schema}.id] = ${w.schema}.schema; '''); - })); + }), + ); } for (var entry in manualRegistrations.entries) { - c.methods.add(Method((m) { - m.name = entry.key; - m.annotations.add(const CodeExpression(Code('override'))); - m.returns = const Reference('void'); - - final w = entry.value; - m.body = Code(''' + c.methods.add( + Method((m) { + m.name = entry.key; + m.annotations.add(const CodeExpression(Code('override'))); + m.returns = const Reference('void'); + + final w = entry.value; + m.body = Code(''' _builders[${w.builder}.kType] = const JsonWidgetBuilderContainer( builder: ${w.builder}.fromDynamic, @@ -156,7 +173,8 @@ _builders[${w.builder}.kType] = ); _schemas[${w.schema}.id] = ${w.schema}.schema; '''); - })); + }), + ); } }); diff --git a/packages/codegen/lib/src/decoder/decoders.dart b/packages/codegen/lib/src/decoder/decoders.dart index 77b35f10..212320b1 100644 --- a/packages/codegen/lib/src/decoder/decoders.dart +++ b/packages/codegen/lib/src/decoder/decoders.dart @@ -1,224 +1,172 @@ import 'package:analyzer/dart/element/element.dart'; -import 'package:json_dynamic_widget_codegen/src/extension/dart_type_extension.dart'; +import 'package:json_dynamic_widget_codegen/src/model/param.dart'; import 'package:json_theme/codegen.dart'; -typedef ParameterDecoder = String Function( - ParameterElement element, { - required String? defaultValueCode, - required String name, -}); +typedef ParameterDecoder = + String Function( + Param element, { + required String? defaultValueCode, + required String name, + }); final kDecoders = { - 'bool': ( - ParameterElement element, { - required String? defaultValueCode, - required String name, - }) => - element.type.nullable - ? "JsonClass.maybeParseBool(map['$name'],)" - : "JsonClass.parseBool(map['$name'], whenNull: ${defaultValueCode ?? false},)", - 'double': ( - element, { - required String? defaultValueCode, - required String name, - }) => - _defaultDecoder( - element, - name, - (element.type.nullable || element.defaultValueCode != null) - ? 'JsonClass.maybeParseDouble' - : 'JsonClass.parseDouble', - defaultValueCode, - ), - 'int': ( - element, { - required String? defaultValueCode, - required String name, - }) => + 'bool': (element, {String? defaultValueCode, required String name}) => + element.typeNullable + ? "JsonClass.maybeParseBool(map['$name'],)" + : "JsonClass.parseBool(map['$name'], whenNull: ${defaultValueCode ?? false},)", + 'double': + (element, {required String? defaultValueCode, required String name}) => + _defaultDecoder( + element, + name, + (element.typeNullable || element.defaultValueCode != null) + ? 'JsonClass.maybeParseDouble' + : 'JsonClass.parseDouble', + defaultValueCode, + ), + 'int': (element, {required String? defaultValueCode, required String name}) => _defaultDecoder( element, name, - (element.type.nullable || element.defaultValueCode != null) + (element.typeNullable || element.defaultValueCode != null) ? 'JsonClass.maybeParseInt' : 'JsonClass.parseInt', defaultValueCode, ), - 'Curve': ( - element, { - required String? defaultValueCode, - required String name, - }) => - _defaultDecoder( - element, - name, - 'CurvesValues.lookup', - defaultValueCode, - ), - 'DateTime': ( - element, { - required String? defaultValueCode, - required String name, - }) => - _defaultDecoder( - element, - name, - (element.type.nullable || element.defaultValueCode != null) - ? 'JsonClass.maybeParseDateTime' - : 'JsonClass.parseDateTime', - defaultValueCode, - ), - 'Duration': ( - element, { - required String? defaultValueCode, - required String name, - }) => - _defaultDecoder( - element, - name, - (element.type.nullable || element.defaultValueCode != null) - ? 'JsonClass.maybeParseDurationFromMillis' - : 'JsonClass.parseDurationFromMillis', - defaultValueCode, - ), - 'List': ( - element, { - required String? defaultValueCode, - required String name, - }) => - _defaultDecoder( - element, - name, - (element.type.nullable || element.defaultValueCode != null) - ? 'JsonClass.maybeParseDoubleList' - : 'JsonClass.parseDoubleList', - defaultValueCode, - ), - 'List': ( - element, { - required String? defaultValueCode, - required String name, - }) => - _defaultDecoder( - element, - name, - (element.type.nullable || element.defaultValueCode != null) - ? 'JsonClass.maybeParseIntList' - : 'JsonClass.parseIntList', - defaultValueCode, - ), - 'List': ( - element, { - required String? defaultValueCode, - required String name, - }) => - _widgetDecoder( - element, - name, - (element.type.nullable || element.defaultValueCode != null) - ? 'JsonWidgetData.maybeFromDynamicList' - : 'JsonWidgetData.fromDynamicList', - defaultValueCode, - ), - 'List': ( - element, { - required String? defaultValueCode, - required String name, - }) => - _widgetDecoder( - element, - name, - (element.type.nullable || element.defaultValueCode != null) - ? 'JsonWidgetData.maybeFromDynamicList' - : 'JsonWidgetData.fromDynamicList', - defaultValueCode, - ), - 'List': ( - element, { - required String? defaultValueCode, - required String name, - }) => - _widgetDecoder( - element, - name, - (element.type.nullable || element.defaultValueCode != null) - ? 'JsonWidgetData.maybeFromDynamicList' - : 'JsonWidgetData.fromDynamicList', - defaultValueCode, - ), - 'JsonWidgetData': ( - element, { - required String? defaultValueCode, - required String name, - }) => - _widgetDecoder( - element, - name, - (element.type.nullable || element.defaultValueCode != null) - ? 'JsonWidgetData.maybeFromDynamic' - : 'JsonWidgetData.fromDynamic', - defaultValueCode, - ), - 'PreferredSizeWidget': ( - element, { - required String? defaultValueCode, - required String name, - }) => - _widgetDecoder( - element, - name, - (element.type.nullable || element.defaultValueCode != null) - ? 'JsonWidgetData.maybeFromDynamic' - : 'JsonWidgetData.fromDynamic', - defaultValueCode, - ), - 'String': ( - element, { - required String? defaultValueCode, - required String name, - }) => + 'Curve': + (element, {required String? defaultValueCode, required String name}) => + _defaultDecoder( + element, + name, + 'CurvesValues.lookup', + defaultValueCode, + ), + 'DateTime': + (element, {required String? defaultValueCode, required String name}) => + _defaultDecoder( + element, + name, + (element.typeNullable || element.defaultValueCode != null) + ? 'JsonClass.maybeParseDateTime' + : 'JsonClass.parseDateTime', + defaultValueCode, + ), + 'Duration': + (element, {required String? defaultValueCode, required String name}) => + _defaultDecoder( + element, + name, + (element.typeNullable || element.defaultValueCode != null) + ? 'JsonClass.maybeParseDurationFromMillis' + : 'JsonClass.parseDurationFromMillis', + defaultValueCode, + ), + 'List': + (element, {required String? defaultValueCode, required String name}) => + _defaultDecoder( + element, + name, + (element.typeNullable || element.defaultValueCode != null) + ? 'JsonClass.maybeParseDoubleList' + : 'JsonClass.parseDoubleList', + defaultValueCode, + ), + 'List': + (element, {required String? defaultValueCode, required String name}) => + _defaultDecoder( + element, + name, + (element.typeNullable || element.defaultValueCode != null) + ? 'JsonClass.maybeParseIntList' + : 'JsonClass.parseIntList', + defaultValueCode, + ), + 'List': + (element, {required String? defaultValueCode, required String name}) => + _widgetDecoder( + element, + name, + (element.typeNullable || element.defaultValueCode != null) + ? 'JsonWidgetData.maybeFromDynamicList' + : 'JsonWidgetData.fromDynamicList', + defaultValueCode, + ), + 'List': + (element, {required String? defaultValueCode, required String name}) => + _widgetDecoder( + element, + name, + (element.typeNullable || element.defaultValueCode != null) + ? 'JsonWidgetData.maybeFromDynamicList' + : 'JsonWidgetData.fromDynamicList', + defaultValueCode, + ), + 'List': + (element, {required String? defaultValueCode, required String name}) => + _widgetDecoder( + element, + name, + (element.typeNullable || element.defaultValueCode != null) + ? 'JsonWidgetData.maybeFromDynamicList' + : 'JsonWidgetData.fromDynamicList', + defaultValueCode, + ), + 'JsonWidgetData': + (element, {required String? defaultValueCode, required String name}) => + _widgetDecoder( + element, + name, + (element.typeNullable || element.defaultValueCode != null) + ? 'JsonWidgetData.maybeFromDynamic' + : 'JsonWidgetData.fromDynamic', + defaultValueCode, + ), + 'PreferredSizeWidget': + (element, {required String? defaultValueCode, required String name}) => + _widgetDecoder( + element, + name, + (element.typeNullable || element.defaultValueCode != null) + ? 'JsonWidgetData.maybeFromDynamic' + : 'JsonWidgetData.fromDynamic', + defaultValueCode, + ), + 'String': (element, {required String? defaultValueCode, required String name}) => "map['$name'] ${defaultValueCode == null ? '' : ' ?? $defaultValueCode'}", - 'Widget': ( - element, { - required String? defaultValueCode, - required String name, - }) => - _widgetDecoder( - element, - name, - (element.type.nullable || element.defaultValueCode != null) - ? 'JsonWidgetData.maybeFromDynamic' - : 'JsonWidgetData.fromDynamic', - defaultValueCode, - ), - ...kThemeDecoders.map((key, value) => MapEntry( - key, - ( - element, { - required String? defaultValueCode, - required String name, - }) => - _themeDecoder( + 'Widget': + (element, {required String? defaultValueCode, required String name}) => + _widgetDecoder( element, name, - value, + (element.typeNullable || element.defaultValueCode != null) + ? 'JsonWidgetData.maybeFromDynamic' + : 'JsonWidgetData.fromDynamic', defaultValueCode, - ))), + ), + ...kThemeDecoders.map( + (key, value) => MapEntry( + key, + (element, {required String? defaultValueCode, required String name}) => + _themeDecoder(element, name, value, defaultValueCode), + ), + ), }; String decode( ClassElement classElement, - ParameterElement element, { + Param element, { required Map aliases, required Map defaults, required Iterable paramDecoders, }) { - final name = aliases[element.name] ?? element.name; - var defaultValueCode = defaults[name] ?? + final name = aliases[element.displayName] ?? element.displayName; + var defaultValueCode = + defaults[name] ?? (paramDecoders.contains(name) ? null : element.defaultValueCode); if (defaultValueCode != null) { if (defaultValueCode == 'null') { defaultValueCode = null; - } else if (element.type.toNonNullableString() == 'double') { + } else if (element.typeName.replaceAll('?', '') == 'double') { if (int.tryParse(defaultValueCode) != null) { defaultValueCode = '$defaultValueCode.0'; } @@ -227,7 +175,7 @@ String decode( var result = "map['$name']${defaultValueCode == null ? '' : '?? $defaultValueCode'}"; - final typeStr = element.type.toNonNullableString(); + final typeStr = element.typeName.replaceAll('?', ''); var decoded = false; if (paramDecoders.contains(name)) { @@ -238,11 +186,7 @@ String decode( final decoder = kDecoders[typeStr]; if (decoder != null) { - result = decoder( - element, - defaultValueCode: defaultValueCode, - name: name, - ); + result = decoder(element, defaultValueCode: defaultValueCode, name: name); } } @@ -250,7 +194,7 @@ String decode( } String _defaultDecoder( - ParameterElement element, + Param element, String name, String funName, String? defaultValueCode, @@ -259,21 +203,21 @@ String _defaultDecoder( () { dynamic parsed = $funName(map['$name']); - ${element.type.nullable && defaultValueCode != null ? ''' + ${element.typeNullable && defaultValueCode != null ? ''' if (!map.containsKey('$name')) { parsed ??= $defaultValueCode; } ''' : ''' ${defaultValueCode == null ? '' : 'parsed ??= $defaultValueCode;'} '''} - ${!element.type.nullable && defaultValueCode == null ? "if (parsed == null) { throw Exception('Null value encountered for required parameter: [$name].',); }" : ''} + ${!element.typeNullable && defaultValueCode == null ? "if (parsed == null) { throw Exception('Null value encountered for required parameter: [$name].',); }" : ''} return parsed; }() '''; } String _themeDecoder( - ParameterElement element, + Param element, String name, String funName, String? defaultValueCode, @@ -281,21 +225,21 @@ String _themeDecoder( return ''' () { dynamic parsed = $funName(map['$name'], validate: false,); - ${element.type.nullable && defaultValueCode != null ? ''' + ${element.typeNullable && defaultValueCode != null ? ''' if (!map.containsKey('$name')) { parsed ??= $defaultValueCode; } ''' : ''' ${defaultValueCode == null ? '' : 'parsed ??= $defaultValueCode;'} '''} - ${!element.type.nullable && defaultValueCode == null ? "if (parsed == null) { throw Exception('Null value encountered for required parameter: [$name].',); }" : ''} + ${!element.typeNullable && defaultValueCode == null ? "if (parsed == null) { throw Exception('Null value encountered for required parameter: [$name].',); }" : ''} return parsed; }() '''; } String _widgetDecoder( - ParameterElement element, + Param element, String name, String funName, String? defaultValueCode, @@ -306,7 +250,7 @@ String _widgetDecoder( ${defaultValueCode == null ? '' : 'parsed ??= ${defaultValueCode.replaceAll('PreferredSizeWidget', 'JsonWidgetData').replaceAll('Widget', 'JsonWidgetData')};'} - ${!element.type.nullable && element.defaultValueCode == null ? "if (parsed == null) { throw Exception('Null value encountered for required parameter: [$name].'); }" : ''} + ${!element.typeNullable && element.defaultValueCode == null ? "if (parsed == null) { throw Exception('Null value encountered for required parameter: [$name].'); }" : ''} return parsed; }() '''; diff --git a/packages/codegen/lib/src/decoder/schema_decoders.dart b/packages/codegen/lib/src/decoder/schema_decoders.dart index 5c057b27..176cfd6d 100644 --- a/packages/codegen/lib/src/decoder/schema_decoders.dart +++ b/packages/codegen/lib/src/decoder/schema_decoders.dart @@ -1,15 +1,13 @@ import 'dart:convert'; -import 'package:analyzer/dart/element/element.dart'; +import 'package:json_dynamic_widget_codegen/src/model/param.dart'; import 'package:json_theme/codegen.dart'; -typedef ParameterSchemaDecoder = String Function(ParameterElement element); +typedef ParameterSchemaDecoder = String Function(Param element); const _kNumberArraySchema = { 'anyOf': [ - { - 'type': 'string', - }, + {'type': 'string'}, { 'type': 'array', 'items': {'type': 'number'}, @@ -18,7 +16,7 @@ const _kNumberArraySchema = { }; final kSchemaDecoders = { - 'bool': (ParameterElement element) => 'SchemaHelper.boolSchema', + 'bool': (element) => 'SchemaHelper.boolSchema', 'double': (element) => 'SchemaHelper.numberSchema', 'int': (element) => 'SchemaHelper.numberSchema', 'List': (element) => json.encode(_kNumberArraySchema), @@ -41,5 +39,5 @@ final kSchemaDecoders = { (element) => 'SchemaHelper.objectSchema(${key.replaceAll('<', '').replaceAll('>', '')}Schema.id)', ), - ) + ), }; diff --git a/packages/codegen/lib/src/encoder/encoders.dart b/packages/codegen/lib/src/encoder/encoders.dart index 38714e17..b9bb8e3b 100644 --- a/packages/codegen/lib/src/encoder/encoders.dart +++ b/packages/codegen/lib/src/encoder/encoders.dart @@ -1,104 +1,64 @@ import 'package:analyzer/dart/element/element.dart'; -import 'package:json_dynamic_widget_codegen/json_dynamic_widget_codegen.dart'; +import 'package:json_dynamic_widget_codegen/src/model/param.dart'; import 'package:json_theme/codegen.dart'; -typedef ParameterEncoder = String Function( - ParameterElement element, { - required String name, -}); +typedef ParameterEncoder = + String Function(Param element, {required String name}); final kEncoders = { - 'bool': ( - ParameterElement element, { - required String name, - }) => - name, - 'double': ( - element, { - required String name, - }) => - name, - 'int': ( - element, { - required String name, - }) => - name, - 'Curve': ( - element, { - required String name, - }) => - 'CurvesValues.encode($name)', - 'DateTime': ( - element, { - required String name, - }) => - element.type.nullable - ? '$name?.millisecondsSinceEpoch' - : '$name.millisecondsSinceEpoch', - 'Duration': ( - element, { - required String name, - }) => - element.type.nullable ? '$name?.inMilliseconds' : '$name.inMilliseconds', - 'List': ( - element, { - required String name, - }) => - name, - 'List': ( - element, { - required String name, - }) => - name, + 'bool': (element, {required String name}) => name, + 'double': (element, {required String name}) => name, + 'int': (element, {required String name}) => name, + 'Curve': (element, {required String name}) => 'CurvesValues.encode($name)', + 'DateTime': (element, {required String name}) => element.typeNullable + ? '$name?.millisecondsSinceEpoch' + : '$name.millisecondsSinceEpoch', + 'Duration': (element, {required String name}) => + element.typeNullable ? '$name?.inMilliseconds' : '$name.inMilliseconds', + 'List': (element, {required String name}) => name, + 'List': (element, {required String name}) => name, 'List': (element, {required String name}) => - element.type.nullable - ? 'JsonClass.maybeToJsonList($name)' - : 'JsonClass.toJsonList($name)', + element.typeNullable + ? 'JsonClass.maybeToJsonList($name)' + : 'JsonClass.toJsonList($name)', 'List': (element, {required String name}) => - element.type.nullable - ? 'JsonClass.maybeToJsonList($name)' - : 'JsonClass.toJsonList($name)', - 'List': (element, {required String name}) => element.type.nullable + element.typeNullable + ? 'JsonClass.maybeToJsonList($name)' + : 'JsonClass.toJsonList($name)', + 'List': (element, {required String name}) => element.typeNullable ? 'JsonClass.maybeToJsonList($name)' : 'JsonClass.toJsonList($name)', 'JsonWidgetData': (element, {required String name}) => - element.type.nullable ? '$name?.toJson()' : '$name.toJson()', + element.typeNullable ? '$name?.toJson()' : '$name.toJson()', 'PreferredSizeWidget': (element, {required String name}) => - element.type.nullable ? '$name?.toJson()' : '$name.toJson()', + element.typeNullable ? '$name?.toJson()' : '$name.toJson()', 'String': (element, {required String name}) => name, 'Widget': (element, {required String name}) => - element.type.nullable ? '$name?.toJson()' : '$name.toJson()', + element.typeNullable ? '$name?.toJson()' : '$name.toJson()', ...kThemeEncoders.map( (key, value) => MapEntry( key, - ( - element, { - required String name, - }) => - '$value($name,)', + (element, {required String name}) => '$value($name,)', ), ), }; String encode( ClassElement classElement, - ParameterElement element, { + Param element, { required Map aliases, required Map defaults, }) { - final displayName = element.name; - final name = aliases[element.name] ?? element.name; + final displayName = element.displayName; + final name = aliases[displayName] ?? displayName; - final typeStr = element.type.toNonNullableString(); + final typeStr = element.typeName.replaceAll('?', ''); final encoder = kEncoders[typeStr]; var result = displayName; if (encoder != null) { - result = encoder( - element, - name: displayName, - ); + result = encoder(element, name: displayName); } var defaultValueCode = defaults[name] ?? element.defaultValueCode; diff --git a/packages/codegen/lib/src/extension/dart_type_extension.dart b/packages/codegen/lib/src/extension/dart_type_extension.dart deleted file mode 100644 index 04d891f1..00000000 --- a/packages/codegen/lib/src/extension/dart_type_extension.dart +++ /dev/null @@ -1,16 +0,0 @@ -import 'package:analyzer/dart/element/nullability_suffix.dart'; -import 'package:analyzer/dart/element/type.dart'; - -extension DartTypeNullability on DartType { - bool get nullable => nullabilitySuffix == NullabilitySuffix.question; - - String toNonNullableString() { - var result = getDisplayString(); - - if (nullabilitySuffix == NullabilitySuffix.question) { - result = result.substring(0, result.length - 1); - } - - return result; - } -} diff --git a/packages/codegen/lib/src/model/param.dart b/packages/codegen/lib/src/model/param.dart new file mode 100644 index 00000000..a615d938 --- /dev/null +++ b/packages/codegen/lib/src/model/param.dart @@ -0,0 +1,36 @@ +import 'package:analyzer/dart/element/element.dart'; +import 'package:analyzer/dart/element/nullability_suffix.dart'; +import 'package:source_gen/source_gen.dart'; + +class Param { + const Param({ + this.custom = true, + this.defaultValueCode, + required this.displayName, + this.isBuilderParam = false, + required this.isRequired, + required this.typeName, + this.typeNullable = false, + }); + + factory Param.fromFormalParameter( + FormalParameterElement param, { + required TypeChecker builderParamChecker, + }) => Param( + custom: false, + defaultValueCode: param.defaultValueCode, + displayName: param.name!, + isBuilderParam: builderParamChecker.annotationsOf(param).isNotEmpty, + isRequired: param.isRequired, + typeName: param.type.getDisplayString(), + typeNullable: param.type.nullabilitySuffix == NullabilitySuffix.question, + ); + + final bool custom; + final String? defaultValueCode; + final String displayName; + final bool isBuilderParam; + final bool isRequired; + final String typeName; + final bool typeNullable; +} diff --git a/packages/codegen/pubspec.yaml b/packages/codegen/pubspec.yaml index b36e1219..ba008c73 100644 --- a/packages/codegen/pubspec.yaml +++ b/packages/codegen/pubspec.yaml @@ -1,10 +1,10 @@ name: 'json_dynamic_widget_codegen' description: 'A library autogenerate JSON widget builders.' homepage: 'https://github.com/peiffer-innovations/json_dynamic_widget' -version: '3.0.0' +version: '4.0.0' environment: - sdk: '^3.8.1' + sdk: '^3.9.0' resolution: 'workspace' analyzer: @@ -13,21 +13,21 @@ analyzer: - 'lib/**/*.g.dart' dependencies: - analyzer: '>=6.2.0 <7.4.0' - build: '^2.4.2' + analyzer: '^8.4.0' + build: '^4.0.0' code_builder: '^4.10.1' dynamic_widget_annotation: '^3.0.0' json_class: '^3.0.1' - json_theme: '^9.0.0+1' + json_theme: '^10.0.0' recase: '^4.1.0' - source_gen: '^2.0.0' + source_gen: '^4.0.2' template_expressions: '^3.3.1+2' yaml_writer: '^2.1.0' yaon: '^1.1.4+10' dev_dependencies: flutter_lints: '^6.0.0' - test: '^1.25.2' + test: ^1.26.3 permittedLicenses: - 'Apache-2.0' diff --git a/packages/json_dynamic_widget/CHANGELOG.md b/packages/json_dynamic_widget/CHANGELOG.md index e2a0a0c7..04f4735c 100644 --- a/packages/json_dynamic_widget/CHANGELOG.md +++ b/packages/json_dynamic_widget/CHANGELOG.md @@ -1,3 +1,11 @@ +## [11.0.0] - October 29th, 2025 + +* Flutter 3.35 +* Removed custom coded versions of the following widgets and replaced them with an autogenerated versions: + * `Radio` + + + ## [10.0.2] - July 14th, 2025 * Fix for TextFormField.autofillHints typing diff --git a/packages/json_dynamic_widget/README.md b/packages/json_dynamic_widget/README.md index 23a0d759..4ba2fde5 100644 --- a/packages/json_dynamic_widget/README.md +++ b/packages/json_dynamic_widget/README.md @@ -128,30 +128,30 @@ class JsonColumnBuilder extends JsonWidgetBuilder { if (map != null) { result = JsonColumnBuilder( - crossAxisAlignment: ThemeDecoder.decodeCrossAxisAlignment( + crossAxisAlignment: ThemeDecoder.instance.decodeCrossAxisAlignment( map['crossAxisAlignment'], validate: false, ) ?? CrossAxisAlignment.center, - mainAxisAlignment: ThemeDecoder.decodeMainAxisAlignment( + mainAxisAlignment: ThemeDecoder.instance.decodeMainAxisAlignment( map['mainAxisAlignment'], validate: false, ) ?? MainAxisAlignment.start, - mainAxisSize: ThemeDecoder.decodeMainAxisSize( + mainAxisSize: ThemeDecoder.instance.decodeMainAxisSize( map['mainAxisSize'], validate: false, ) ?? MainAxisSize.max, - textBaseline: ThemeDecoder.decodeTextBaseline( + textBaseline: ThemeDecoder.instance.decodeTextBaseline( map['textBaseline'], validate: false, ), - textDirection: ThemeDecoder.decodeTextDirection( + textDirection: ThemeDecoder.instance.decodeTextDirection( map['textDirection'], validate: false, ), - verticalDirection: ThemeDecoder.decodeVerticalDirection( + verticalDirection: ThemeDecoder.instance.decodeVerticalDirection( map['verticalDirection'], validate: false, ) ?? diff --git a/packages/json_dynamic_widget/example/assets/pages/card.json b/packages/json_dynamic_widget/example/assets/pages/card.json index 6af5f91f..5a016430 100644 --- a/packages/json_dynamic_widget/example/assets/pages/card.json +++ b/packages/json_dynamic_widget/example/assets/pages/card.json @@ -73,7 +73,7 @@ } }, { - "type": "button_bar", + "type": "overflow_bar", "args": { "children": [ { diff --git a/packages/json_dynamic_widget/example/assets/pages/checkbox.json b/packages/json_dynamic_widget/example/assets/pages/checkbox.json index 36a21ad7..6c55f193 100644 --- a/packages/json_dynamic_widget/example/assets/pages/checkbox.json +++ b/packages/json_dynamic_widget/example/assets/pages/checkbox.json @@ -27,6 +27,7 @@ "children": [ { "type": "checkbox", + "id": "checked", "args": { "label": "Checked", "value": true @@ -48,6 +49,7 @@ "children": [ { "type": "checkbox", + "id": "not_checked", "args": { "label": "Not Checked", "value": false @@ -69,6 +71,7 @@ "children": [ { "type": "checkbox", + "id": "disabled", "args": { "enabled": false, "label": "Disabled" @@ -90,6 +93,7 @@ "children": [ { "type": "checkbox", + "id": "on_changed", "args": { "label": "OnChanged example", "onChanged": "${setBooleanValue('changedValue')}" diff --git a/packages/json_dynamic_widget/example/assets/pages/cupertino_switch.yaml b/packages/json_dynamic_widget/example/assets/pages/cupertino_switch.yaml index 490b7b94..6cf0f875 100644 --- a/packages/json_dynamic_widget/example/assets/pages/cupertino_switch.yaml +++ b/packages/json_dynamic_widget/example/assets/pages/cupertino_switch.yaml @@ -1,90 +1,77 @@ type: scaffold -args: - appBar: +args: + appBar: type: 'app_bar' - args: - title: + args: + title: type: text - args: + args: text: CupertinoSwitch - body: + body: type: center - args: - child: + args: + child: type: column - args: + args: mainAxisSize: min - children: - - - type: row - args: + children: + - type: row + args: mainAxisSize: min - children: - - - type: 'cupertino_switch' - args: + children: + - type: 'cupertino_switch' + id: checked + args: label: Checked value: true - - - type: text - args: + - type: text + args: text: Checked - - - type: row - args: + - type: row + args: mainAxisSize: min - children: - - - type: 'cupertino_switch' - args: + children: + - type: 'cupertino_switch' + id: not_checked + args: label: Not Checked value: false - - - type: text - args: + - type: text + args: text: Not Checked - - - type: row - args: + - type: row + args: mainAxisSize: min - children: - - - type: 'cupertino_switch' - args: + children: + - type: 'cupertino_switch' + id: disabled + args: enabled: false label: Disabled - - - type: text - args: + - type: text + args: text: Disabled - - - type: column - args: + - type: column + args: mainAxisSize: min - children: - - - type: 'cupertino_switch' + children: + - type: 'cupertino_switch' id: 'example_switch' - - - type: conditional - args: - conditional: - values: + - type: conditional + args: + conditional: + values: example_switch: true - onFalse: + onFalse: type: text - args: + args: text: Not Checked - onTrue: + onTrue: type: text - args: + args: text: 'Checked!' - - - - diff --git a/packages/json_dynamic_widget/example/assets/pages/dynamic.json b/packages/json_dynamic_widget/example/assets/pages/dynamic.json index c1489b20..7df27505 100644 --- a/packages/json_dynamic_widget/example/assets/pages/dynamic.json +++ b/packages/json_dynamic_widget/example/assets/pages/dynamic.json @@ -125,9 +125,9 @@ "args": { "icon": { "codePoint": 61912, - "fontFamily": "MaterialIcons", - "size": 50 - } + "fontFamily": "MaterialIcons" + }, + "size": 50 } }, "onPressed": "${show_dialog('dialogContext', 'editDialogData{id}')}" @@ -237,9 +237,9 @@ "args": { "icon": { "codePoint": 57704, - "fontFamily": "MaterialIcons", - "size": 50 - } + "fontFamily": "MaterialIcons" + }, + "size": 50 } }, "onPressed": "${set_value('form_message','')}" diff --git a/packages/json_dynamic_widget/example/assets/pages/form.json b/packages/json_dynamic_widget/example/assets/pages/form.json index 9482e6a8..ebfc84e2 100644 --- a/packages/json_dynamic_widget/example/assets/pages/form.json +++ b/packages/json_dynamic_widget/example/assets/pages/form.json @@ -103,9 +103,9 @@ "args": { "icon": { "codePoint": 57704, - "fontFamily": "MaterialIcons", - "size": 50 - } + "fontFamily": "MaterialIcons" + }, + "size": 20 } }, "onPressed": "${set_value('first_name','')}" @@ -152,9 +152,9 @@ "args": { "icon": { "codePoint": 57704, - "fontFamily": "MaterialIcons", - "size": 50 - } + "fontFamily": "MaterialIcons" + }, + "size": 20 } }, "onPressed": "${set_value('last_name','')}" @@ -196,9 +196,9 @@ "args": { "icon": { "codePoint": 57704, - "fontFamily": "MaterialIcons", - "size": 50 - } + "fontFamily": "MaterialIcons" + }, + "size": 20 } }, "onPressed": "${set_value('email_address','')}" diff --git a/packages/json_dynamic_widget/example/assets/pages/null_value_passing.json b/packages/json_dynamic_widget/example/assets/pages/null_value_passing.json index 079f32f4..d6bbf88a 100644 --- a/packages/json_dynamic_widget/example/assets/pages/null_value_passing.json +++ b/packages/json_dynamic_widget/example/assets/pages/null_value_passing.json @@ -17,6 +17,7 @@ "args": { "child": { "type": "text_form_field", + "id": "text_field", "args": { "expands": true, "maxLines": "${null}", diff --git a/packages/json_dynamic_widget/example/assets/pages/radio.json b/packages/json_dynamic_widget/example/assets/pages/radio.json index 7c21730f..427d7758 100644 --- a/packages/json_dynamic_widget/example/assets/pages/radio.json +++ b/packages/json_dynamic_widget/example/assets/pages/radio.json @@ -19,53 +19,48 @@ "radioGroupValue": "radioValue1" }, "child": { - "type": "column", + "type": "radio_group", + "id": "radioGroupValue", "args": { - "crossAxisAlignment": "start", - "children": [ - { - "type": "text", - "listen": [ - "radioGroupValue" - ], - "args": { - "text": "${'Selected radio group value: ' + radioGroupValue ?? ''}" - } - }, - { - "type": "radio", - "listen": [ - "radioGroupValue" - ], - "args": { - "groupValue": "${radioGroupValue}", - "id": "radioGroupValue", - "value": "radioValue1" - } - }, - { - "type": "radio", - "listen": [ - "radioGroupValue" - ], - "args": { - "groupValue": "${radioGroupValue}", - "id": "radioGroupValue", - "value": "radioValue2" - } - }, - { - "type": "radio", - "listen": [ - "radioGroupValue" - ], - "args": { - "groupValue": "${radioGroupValue}", - "id": "radioGroupValue", - "value": "radioValue3" - } + "groupValue": "${radioGroupValue}", + "child": { + "type": "column", + "args": { + "crossAxisAlignment": "start", + "children": [ + { + "type": "text", + "listen": [ + "radioGroupValue" + ], + "args": { + "text": "${'Selected radio group value: ' + radioGroupValue ?? ''}" + } + }, + { + "type": "radio", + "id": "radioValue1", + "args": { + "value": "radioValue1" + } + }, + { + "type": "radio", + "id": "radioValue2", + "args": { + "value": "radioValue2" + } + }, + { + "type": "radio", + "id": "radioValue3", + "args": { + "value": "radioValue3" + } + } + ] } - ] + } } } } diff --git a/packages/json_dynamic_widget/example/assets/pages/switch.json b/packages/json_dynamic_widget/example/assets/pages/switch.json index ca2efa9c..a7fc20c8 100644 --- a/packages/json_dynamic_widget/example/assets/pages/switch.json +++ b/packages/json_dynamic_widget/example/assets/pages/switch.json @@ -27,6 +27,7 @@ "children": [ { "type": "switch", + "id": "checked", "args": { "label": "Checked", "value": true @@ -48,6 +49,7 @@ "children": [ { "type": "switch", + "id": "not_checked", "args": { "label": "Not Checked", "value": false @@ -69,6 +71,7 @@ "children": [ { "type": "switch", + "id": "disabled", "args": { "enabled": false, "label": "Disabled" diff --git a/packages/json_dynamic_widget/example/assets/pages/theme.json b/packages/json_dynamic_widget/example/assets/pages/theme.json index 94c3e94e..705bcdc9 100644 --- a/packages/json_dynamic_widget/example/assets/pages/theme.json +++ b/packages/json_dynamic_widget/example/assets/pages/theme.json @@ -85,7 +85,8 @@ "mainAxisSize": "min", "children": [ { - "type": "checkbox" + "type": "checkbox", + "id": "checkbox" }, { "type": "sized_box", @@ -94,27 +95,32 @@ } }, { - "type": "row", + "type": "radio_group", + "id": "radioGroupValue", "args": { - "mainAxisAlignment": "spaceEvenly", - "children": [ - { - "type": "radio", - "args": { - "groupValue": "false", - "id": "radio", - "value": true - } - }, - { - "type": "radio", - "args": { - "groupValue": "false", - "id": "radio", - "value": false - } + "groupValue": "${radioGroupValue}", + "child": { + "type": "row", + "args": { + "mainAxisAlignment": "spaceEvenly", + "children": [ + { + "type": "radio", + "id": "radio1", + "args": { + "value": true + } + }, + { + "type": "radio", + "id": "radio2", + "args": { + "value": false + } + } + ] } - ] + } } }, { diff --git a/packages/json_dynamic_widget/example/lib/src/custom_schemas/dotted_border_schema.dart b/packages/json_dynamic_widget/example/lib/src/custom_schemas/dotted_border_schema.dart index dfb3605d..c2bdca48 100644 --- a/packages/json_dynamic_widget/example/lib/src/custom_schemas/dotted_border_schema.dart +++ b/packages/json_dynamic_widget/example/lib/src/custom_schemas/dotted_border_schema.dart @@ -1,4 +1,4 @@ -import 'package:json_theme/json_theme_schemas.dart'; +import 'package:json_theme/json_theme.dart'; class DottedBorderSchema { static const id = 'https://your-url-here.com/schemas/dotted_border'; diff --git a/packages/json_dynamic_widget/example/lib/src/custom_schemas/svg_schema.dart b/packages/json_dynamic_widget/example/lib/src/custom_schemas/svg_schema.dart index 9fa441cf..94133a82 100644 --- a/packages/json_dynamic_widget/example/lib/src/custom_schemas/svg_schema.dart +++ b/packages/json_dynamic_widget/example/lib/src/custom_schemas/svg_schema.dart @@ -1,4 +1,4 @@ -import 'package:json_theme/json_theme_schemas.dart'; +import 'package:json_theme/json_theme.dart'; class SvgSchema { static const id = 'https://your-url-here.com/schemas/svg'; diff --git a/packages/json_dynamic_widget/example/macos/Runner.xcodeproj/project.pbxproj b/packages/json_dynamic_widget/example/macos/Runner.xcodeproj/project.pbxproj index 28551da0..430fe058 100644 --- a/packages/json_dynamic_widget/example/macos/Runner.xcodeproj/project.pbxproj +++ b/packages/json_dynamic_widget/example/macos/Runner.xcodeproj/project.pbxproj @@ -407,7 +407,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.14; + MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; @@ -491,7 +491,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.14; + MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; @@ -538,7 +538,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.14; + MACOSX_DEPLOYMENT_TARGET = 10.15; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; SWIFT_COMPILATION_MODE = wholemodule; diff --git a/packages/json_dynamic_widget/example/pubspec.yaml b/packages/json_dynamic_widget/example/pubspec.yaml index 82dc3452..cdb6b54c 100644 --- a/packages/json_dynamic_widget/example/pubspec.yaml +++ b/packages/json_dynamic_widget/example/pubspec.yaml @@ -4,8 +4,7 @@ publish_to: 'none' version: '1.0.0+90' environment: - sdk: '^3.8.1' -resolution: 'workspace' + sdk: '^3.9.0' dependencies: child_builder: '^2.0.2' @@ -18,19 +17,31 @@ dependencies: json_class: '^3.0.1' json_dynamic_widget: path: '../' - json_theme: '^9.0.0+1' + json_theme: '^10.0.0' logging: '^1.3.0' yaon: '^1.1.4+10' dev_dependencies: - build_runner: '^2.4.15' + build_runner: '^2.10.1' flutter_lints: '^6.0.0' flutter_test: sdk: 'flutter' icons_launcher: '^3.0.1' - json_dynamic_widget_codegen: '^3.0.0' + json_dynamic_widget_codegen: '^4.0.0' yaml_writer: '^2.1.0' +dependency_overrides: + dynamic_widget_annotation: + path: ../../annotation + json_dynamic_widget_codegen: + path: ../../codegen + json_theme_annotation: + path: ../../../../json_theme/packages/annotation + json_theme_codegen: + path: ../../../../json_theme/packages/codegen + json_theme: + path: ../../../../json_theme/packages/json_theme + icons_launcher: image_path: 'assets-src/icon.png' platforms: diff --git a/packages/json_dynamic_widget/lib/builders.dart b/packages/json_dynamic_widget/lib/builders.dart index 9d57e438..e7f012c5 100644 --- a/packages/json_dynamic_widget/lib/builders.dart +++ b/packages/json_dynamic_widget/lib/builders.dart @@ -86,6 +86,7 @@ export 'src/builders/json_popup_menu_button_builder.dart'; export 'src/builders/json_positioned_builder.dart'; export 'src/builders/json_primary_scroll_controller_builder.dart'; export 'src/builders/json_radio_builder.dart'; +export 'src/builders/json_radio_group_builder.dart'; export 'src/builders/json_rich_text_builder.dart'; export 'src/builders/json_row_builder.dart'; export 'src/builders/json_safe_area_builder.dart'; diff --git a/packages/json_dynamic_widget/lib/json_dynamic_widget.dart b/packages/json_dynamic_widget/lib/json_dynamic_widget.dart index c6689a9b..6768265c 100644 --- a/packages/json_dynamic_widget/lib/json_dynamic_widget.dart +++ b/packages/json_dynamic_widget/lib/json_dynamic_widget.dart @@ -10,7 +10,7 @@ export 'package:json_theme/json_theme.dart' hide CardThemeDataSchema, DialogThemeDataSchema, - InputDecorationThemeSchema, + // InputDecorationThemeSchema, TabBarThemeDataSchema; export 'package:uuid/uuid.dart'; export 'package:yaon/yaon.dart'; diff --git a/packages/json_dynamic_widget/lib/src/builders/json_animated_container_builder.dart b/packages/json_dynamic_widget/lib/src/builders/json_animated_container_builder.dart index 0c64911e..d7c78770 100644 --- a/packages/json_dynamic_widget/lib/src/builders/json_animated_container_builder.dart +++ b/packages/json_dynamic_widget/lib/src/builders/json_animated_container_builder.dart @@ -16,19 +16,23 @@ abstract class _JsonAnimatedContainerBuilder extends JsonWidgetBuilder { @JsonArgEncoder('decoration') static Map? _encodeDecoration(dynamic value) => - value is BoxDecoration ? ThemeEncoder.encodeBoxDecoration(value) : null; + value is BoxDecoration + ? ThemeEncoder.instance.encodeBoxDecoration(value) + : null; @JsonArgEncoder('foregroundDecoration') static Map? _encodeForegroundDecoration(dynamic value) => - value is BoxDecoration ? ThemeEncoder.encodeBoxDecoration(value) : null; + value is BoxDecoration + ? ThemeEncoder.instance.encodeBoxDecoration(value) + : null; @JsonArgDecoder('decoration') Decoration? _decodeDecoration({required dynamic value}) => - ThemeDecoder.decodeBoxDecoration(value, validate: false); + ThemeDecoder.instance.decodeBoxDecoration(value, validate: false); @JsonArgDecoder('foregroundDecoration') Decoration? _decodeForegroundDecoration({required dynamic value}) => - ThemeDecoder.decodeBoxDecoration(value, validate: false); + ThemeDecoder.instance.decodeBoxDecoration(value, validate: false); @override AnimatedContainer buildCustom({ diff --git a/packages/json_dynamic_widget/lib/src/builders/json_animated_theme_builder.dart b/packages/json_dynamic_widget/lib/src/builders/json_animated_theme_builder.dart index 93ef38cb..b98f9748 100644 --- a/packages/json_dynamic_widget/lib/src/builders/json_animated_theme_builder.dart +++ b/packages/json_dynamic_widget/lib/src/builders/json_animated_theme_builder.dart @@ -3,7 +3,7 @@ import 'package:json_dynamic_widget/json_dynamic_widget.dart'; part 'json_animated_theme_builder.g.dart'; /// Builder that can build an [AnimatedTheme] widget. -@jsonWidget +@JsonWidget(requiresId: true) abstract class _JsonAnimatedThemeBuilder extends JsonWidgetBuilder { const _JsonAnimatedThemeBuilder({required super.args}); diff --git a/packages/json_dynamic_widget/lib/src/builders/json_checkbox_builder.dart b/packages/json_dynamic_widget/lib/src/builders/json_checkbox_builder.dart index 8f7a1ce6..e8048da7 100644 --- a/packages/json_dynamic_widget/lib/src/builders/json_checkbox_builder.dart +++ b/packages/json_dynamic_widget/lib/src/builders/json_checkbox_builder.dart @@ -3,15 +3,14 @@ import 'package:json_dynamic_widget/json_dynamic_widget.dart'; part 'json_checkbox_builder.g.dart'; -@jsonWidget +@JsonWidget(requiresId: true) abstract class _JsonCheckboxBuilder extends JsonWidgetBuilder { const _JsonCheckboxBuilder({required super.args}); @JsonArgDecoder('validator') - Validator? _decodeValidator({dynamic value}) => - value is Map - ? Validator.fromDynamic({'validators': value['validators']}) - : null; + Validator? _decodeValidator({dynamic value}) => value is Map + ? Validator.fromDynamic({'validators': value['validators']}) + : null; @override _Checkbox buildCustom({ @@ -106,64 +105,61 @@ class _CheckboxState extends State<_Checkbox> { enabled: widget.enabled, initialValue: initialValue, onSaved: widget.onSaved, - validator: - widget.validator == null - ? null - : (value) { - final error = widget.validator!.validate( - label: widget.label ?? '', - value: value?.toString(), - ); + validator: widget.validator == null + ? null + : (value) { + final error = widget.validator!.validate( + label: widget.label ?? '', + value: value?.toString(), + ); - widget.data.jsonWidgetRegistry.setValue( - '${widget.data.jsonWidgetId}.error', - error ?? '', - originator: widget.data.jsonWidgetId, - ); + widget.data.jsonWidgetRegistry.setValue( + '${widget.data.jsonWidgetId}.error', + error ?? '', + originator: widget.data.jsonWidgetId, + ); - return error; - }, - builder: - (FormFieldState state) => MergeSemantics( - child: Semantics( - label: widget.label ?? '', - child: Checkbox( - activeColor: widget.activeColor, - autofocus: widget.autofocus, - checkColor: widget.checkColor, - fillColor: widget.fillColor, - focusColor: widget.focusColor, - focusNode: widget.focusNode, - hoverColor: widget.hoverColor, - isError: widget.isError, - materialTapTargetSize: widget.materialTapTargetSize, - mouseCursor: widget.mouseCursor, - onChanged: - widget.enabled != true - ? null - : (value) { - if (widget.onChanged != null) { - widget.onChanged!(value); - } + return error; + }, + builder: (FormFieldState state) => MergeSemantics( + child: Semantics( + label: widget.label ?? '', + child: Checkbox( + activeColor: widget.activeColor, + autofocus: widget.autofocus, + checkColor: widget.checkColor, + fillColor: widget.fillColor, + focusColor: widget.focusColor, + focusNode: widget.focusNode, + hoverColor: widget.hoverColor, + isError: widget.isError, + materialTapTargetSize: widget.materialTapTargetSize, + mouseCursor: widget.mouseCursor, + onChanged: widget.enabled != true + ? null + : (value) { + if (widget.onChanged != null) { + widget.onChanged!(value); + } - state.didChange(value); + state.didChange(value); - widget.data.jsonWidgetRegistry.setValue( - widget.data.jsonWidgetId, - value, - originator: widget.data.jsonWidgetId, - ); - }, - overlayColor: widget.overlayColor, - shape: widget.shape, - side: widget.side, - splashRadius: widget.splashRadius, - tristate: widget.tristate, - value: state.value, - visualDensity: widget.visualDensity, - ), - ), + widget.data.jsonWidgetRegistry.setValue( + widget.data.jsonWidgetId, + value, + originator: widget.data.jsonWidgetId, + ); + }, + overlayColor: widget.overlayColor, + shape: widget.shape, + side: widget.side, + splashRadius: widget.splashRadius, + tristate: widget.tristate, + value: state.value, + visualDensity: widget.visualDensity, ), + ), + ), ); } } diff --git a/packages/json_dynamic_widget/lib/src/builders/json_circular_progress_indicator_builder.dart b/packages/json_dynamic_widget/lib/src/builders/json_circular_progress_indicator_builder.dart index 2554636f..73c33378 100644 --- a/packages/json_dynamic_widget/lib/src/builders/json_circular_progress_indicator_builder.dart +++ b/packages/json_dynamic_widget/lib/src/builders/json_circular_progress_indicator_builder.dart @@ -13,14 +13,13 @@ abstract class _JsonCircularProgressIndicatorBuilder extends JsonWidgetBuilder { CircularProgressIndicator.strokeAlignCenter; @JsonArgDecoder('valueColor') - Animation? _decodeValueColor({required dynamic value}) => - value == null - ? null - : value is Animation - ? value - : AlwaysStoppedAnimation( - ThemeDecoder.decodeColor(value, validate: false)!, - ); + Animation? _decodeValueColor({required dynamic value}) => value == null + ? null + : value is Animation + ? value + : AlwaysStoppedAnimation( + ThemeDecoder.instance.decodeColor(value, validate: false)!, + ); @JsonDefaultParam( 'strokeAlign', diff --git a/packages/json_dynamic_widget/lib/src/builders/json_container_builder.dart b/packages/json_dynamic_widget/lib/src/builders/json_container_builder.dart index 6c5d6290..944f04ef 100644 --- a/packages/json_dynamic_widget/lib/src/builders/json_container_builder.dart +++ b/packages/json_dynamic_widget/lib/src/builders/json_container_builder.dart @@ -16,19 +16,23 @@ abstract class _JsonContainerBuilder extends JsonWidgetBuilder { @JsonArgEncoder('decoration') static Map? _encodeDecoration(dynamic value) => - value is BoxDecoration ? ThemeEncoder.encodeBoxDecoration(value) : null; + value is BoxDecoration + ? ThemeEncoder.instance.encodeBoxDecoration(value) + : null; @JsonArgEncoder('foregroundDecoration') static Map? _encodeForegroundDecoration(dynamic value) => - value is BoxDecoration ? ThemeEncoder.encodeBoxDecoration(value) : null; + value is BoxDecoration + ? ThemeEncoder.instance.encodeBoxDecoration(value) + : null; @JsonArgDecoder('decoration') Decoration? _decodeDecoration({required dynamic value}) => - ThemeDecoder.decodeBoxDecoration(value, validate: false); + ThemeDecoder.instance.decodeBoxDecoration(value, validate: false); @JsonArgDecoder('foregroundDecoration') Decoration? _decodeForegroundDecoration({required dynamic value}) => - ThemeDecoder.decodeBoxDecoration(value, validate: false); + ThemeDecoder.instance.decodeBoxDecoration(value, validate: false); @override Container buildCustom({ diff --git a/packages/json_dynamic_widget/lib/src/builders/json_cupertino_switch_builder.dart b/packages/json_dynamic_widget/lib/src/builders/json_cupertino_switch_builder.dart index 2a5f3637..725b3ece 100644 --- a/packages/json_dynamic_widget/lib/src/builders/json_cupertino_switch_builder.dart +++ b/packages/json_dynamic_widget/lib/src/builders/json_cupertino_switch_builder.dart @@ -7,7 +7,7 @@ import 'package:json_dynamic_widget/json_dynamic_widget.dart'; part 'json_cupertino_switch_builder.g.dart'; /// Builder that can build an [CupertinoSwitch] widget. -@jsonWidget +@JsonWidget(requiresId: true) abstract class _JsonCupertinoSwitchBuilder extends JsonWidgetBuilder { const _JsonCupertinoSwitchBuilder({required super.args}); @@ -86,57 +86,54 @@ class _CupertinoSwitchState extends State<_CupertinoSwitch> { initialValue: widget.value, onSaved: widget.onSaved, restorationId: widget.restorationId, - validator: - widget.validators == null - ? null - : (value) { - final error = widget.validators!.validate( - label: widget.label ?? '', - value: value?.toString(), - ); + validator: widget.validators == null + ? null + : (value) { + final error = widget.validators!.validate( + label: widget.label ?? '', + value: value?.toString(), + ); - if (widget.data.jsonWidgetId.isNotEmpty == true) { - widget.data.jsonWidgetRegistry.setValue( - '${widget.data.jsonWidgetId}.error', - error ?? '', - originator: widget.data.jsonWidgetId, - ); - } + if (widget.data.jsonWidgetId.isNotEmpty == true) { + widget.data.jsonWidgetRegistry.setValue( + '${widget.data.jsonWidgetId}.error', + error ?? '', + originator: widget.data.jsonWidgetId, + ); + } - return error; - }, - builder: - (FormFieldState state) => MergeSemantics( - child: Semantics( - label: widget.label ?? '', - child: CupertinoSwitch( - activeTrackColor: widget.activeColor, - dragStartBehavior: - widget.dragStartBehavior ?? DragStartBehavior.start, - onChanged: - widget.enabled != true - ? null - : (value) { - if (widget.onChanged != null) { - widget.onChanged!(value); - } + return error; + }, + builder: (FormFieldState state) => MergeSemantics( + child: Semantics( + label: widget.label ?? '', + child: CupertinoSwitch( + activeTrackColor: widget.activeColor, + dragStartBehavior: + widget.dragStartBehavior ?? DragStartBehavior.start, + onChanged: widget.enabled != true + ? null + : (value) { + if (widget.onChanged != null) { + widget.onChanged!(value); + } - state.didChange(value); + state.didChange(value); - if (widget.data.jsonWidgetId.isNotEmpty == true) { - widget.data.jsonWidgetRegistry.setValue( - widget.data.jsonWidgetId, - value, - originator: widget.data.jsonWidgetId, - ); - } - }, - thumbColor: widget.thumbColor, - inactiveTrackColor: widget.trackColor, - value: state.value, - ), - ), + if (widget.data.jsonWidgetId.isNotEmpty == true) { + widget.data.jsonWidgetRegistry.setValue( + widget.data.jsonWidgetId, + value, + originator: widget.data.jsonWidgetId, + ); + } + }, + thumbColor: widget.thumbColor, + inactiveTrackColor: widget.trackColor, + value: state.value, ), + ), + ), ); } } diff --git a/packages/json_dynamic_widget/lib/src/builders/json_decorated_box_builder.dart b/packages/json_dynamic_widget/lib/src/builders/json_decorated_box_builder.dart index 58de6545..39dff27a 100644 --- a/packages/json_dynamic_widget/lib/src/builders/json_decorated_box_builder.dart +++ b/packages/json_dynamic_widget/lib/src/builders/json_decorated_box_builder.dart @@ -9,11 +9,11 @@ abstract class _JsonDecoratedBoxBuilder extends JsonWidgetBuilder { @JsonArgDecoder('decoration') Decoration _decodeDecoration({required dynamic value}) => - ThemeDecoder.decodeBoxDecoration(value, validate: false)!; + ThemeDecoder.instance.decodeBoxDecoration(value, validate: false)!; @JsonArgDecoder('position') DecorationPosition _decodePosition({required dynamic value}) => - ThemeDecoder.decodeDecorationPosition(value, validate: false) ?? + ThemeDecoder.instance.decodeDecorationPosition(value, validate: false) ?? DecorationPosition.background; @override diff --git a/packages/json_dynamic_widget/lib/src/builders/json_dropdown_button_form_field_builder.dart b/packages/json_dynamic_widget/lib/src/builders/json_dropdown_button_form_field_builder.dart index d7ad661c..2a99cf46 100644 --- a/packages/json_dynamic_widget/lib/src/builders/json_dropdown_button_form_field_builder.dart +++ b/packages/json_dynamic_widget/lib/src/builders/json_dropdown_button_form_field_builder.dart @@ -1,5 +1,3 @@ -import 'dart:async'; - import 'package:form_validation/form_validation.dart'; import 'package:json_dynamic_widget/json_dynamic_widget.dart'; @@ -64,6 +62,7 @@ class JsonDropdownButtonFormFieldBuilderModel extends JsonWidgetBuilderModel { this.alignment, this.autofocus, this.autovalidateMode, + this.barrierDismissable = true, this.borderRadius, this.decoration, this.disabledHint, @@ -71,25 +70,28 @@ class JsonDropdownButtonFormFieldBuilderModel extends JsonWidgetBuilderModel { this.elevation, this.enableFeedback, this.enabled, + this.errorBuilder, this.focusColor, this.focusNode, + this.forceErrorText, this.hint, this.icon, this.iconSize, - this.items, this.iconDisabledColor, this.iconEnabledColor, + this.initialValue, this.isDense, this.isExpanded, this.itemHeight, + this.items, this.menuMaxHeight, this.onChanged, this.onSaved, this.onTap, + this.padding, this.selectedItemBuilder, this.validator, this.style, - this.value, }); static const kType = 'dropdown_button_form_field'; @@ -97,6 +99,7 @@ class JsonDropdownButtonFormFieldBuilderModel extends JsonWidgetBuilderModel { final Alignment? alignment; final bool? autofocus; final AutovalidateMode? autovalidateMode; + final bool barrierDismissable; final BorderRadius? borderRadius; final dynamic decoration; final JsonWidgetData? disabledHint; @@ -104,25 +107,28 @@ class JsonDropdownButtonFormFieldBuilderModel extends JsonWidgetBuilderModel { final int? elevation; final bool? enableFeedback; final bool? enabled; + final FormFieldErrorBuilder? errorBuilder; final Color? focusColor; final FocusNode? focusNode; + final String? forceErrorText; final JsonWidgetData? hint; final JsonWidgetData? icon; - final dynamic items; final Color? iconDisabledColor; final double? iconSize; final Color? iconEnabledColor; + final dynamic initialValue; final bool? isDense; final bool? isExpanded; final double? itemHeight; + final dynamic items; final double? menuMaxHeight; final ValueChanged? onChanged; final FormFieldSetter? onSaved; final VoidCallback? onTap; + final EdgeInsetsGeometry? padding; final dynamic selectedItemBuilder; final Validator? validator; final TextStyle? style; - final dynamic value; /// Builds the builder from a Map-like dynamic structure. This expects the /// JSON format to be of the following structure: @@ -133,13 +139,16 @@ class JsonDropdownButtonFormFieldBuilderModel extends JsonWidgetBuilderModel { /// "autofocus": "", /// "autovalidateMode": "", /// "borderRadius": "", + /// "barrierDismissable": "", /// "decoration": "", /// "disabledHint": "", /// "dropdownColor": "", /// "elevation": "", /// "enabled": "", + /// "errorBuilder": "", /// "focusColor": "", /// "focusNode": "", + /// "forceErrorText": "", /// "hint": "", /// "icon": "", /// "items": "> || >", @@ -152,6 +161,7 @@ class JsonDropdownButtonFormFieldBuilderModel extends JsonWidgetBuilderModel { /// "onChanged": "", /// "onSaved": "", /// "onTap": "", + /// "padding": "", /// "selectedItemBuilder": " || ", /// "validators": ">", /// "style": "", @@ -176,15 +186,6 @@ class JsonDropdownButtonFormFieldBuilderModel extends JsonWidgetBuilderModel { /// both the display and the value or a map of strings to values where the key /// will be used as the display and the value will be the internal dropdown /// value. - /// - /// See also: - /// * [buildCustom] - /// * [InputDecorationDecoder.fromDynamic] - /// * [JsonWidgetData.fromDynamic] - /// * [ThemeDecoder.decodeAutovalidateMode] - /// * [ThemeDecoder.decodeColor] - /// * [ThemeDecoder.decodeTextStyle] - /// * [Validator] static JsonDropdownButtonFormFieldBuilderModel fromDynamic( dynamic map, { Map args = const {}, @@ -209,30 +210,34 @@ class JsonDropdownButtonFormFieldBuilderModel extends JsonWidgetBuilderModel { /// "alignment": "", /// "autofocus": "", /// "autovalidateMode": "", + /// "barrierDismissable": "", /// "borderRadius": "", /// "decoration": "", /// "disabledHint": "", /// "dropdownColor": "", /// "elevation": "", /// "enabled": "", + /// "errorBuilder": "", /// "focusColor": "", + /// "forceErrorText": "", /// "focusNode": "", /// "hint": "", /// "icon": "", - /// "items": "> || >", + /// "initialValue": "" /// "iconDisabledColor": "", /// "iconEnabledColor": "", /// "iconSize": "", /// "isDense": "", /// "isExpanded": "", /// "itemHeight": "", + /// "items": "> || >", /// "onChanged": "", /// "onSaved": "", /// "onTap": "", + /// "padding": "", /// "selectedItemBuilder": " || ", /// "validators": ">", - /// "style": "", - /// "value": "" + /// "style": "" /// } /// ``` /// @@ -255,15 +260,6 @@ class JsonDropdownButtonFormFieldBuilderModel extends JsonWidgetBuilderModel { /// value. /// /// If the [map] is `null` then `null` will be returned. - /// - /// See also: - /// * [buildCustom] - /// * [InputDecorationDecoder.fromDynamic] - /// * [JsonWidgetData.fromDynamic] - /// * [ThemeDecoder.decodeAutovalidateMode] - /// * [ThemeDecoder.decodeColor] - /// * [ThemeDecoder.decodeTextStyle] - /// * [Validator] static JsonDropdownButtonFormFieldBuilderModel? maybeFromDynamic( dynamic map, { Map args = const {}, @@ -281,27 +277,30 @@ class JsonDropdownButtonFormFieldBuilderModel extends JsonWidgetBuilderModel { result = JsonDropdownButtonFormFieldBuilderModel( args, - alignment: ThemeDecoder.decodeAlignment( + alignment: ThemeDecoder.instance.decodeAlignment( map['alignment'], validate: false, ), autofocus: JsonClass.maybeParseBool(map['autofocus']), - autovalidateMode: - map['autovalidate'] == null - ? ThemeDecoder.decodeAutovalidateMode( - map['autovalidateMode'], - validate: false, - ) - : JsonClass.maybeParseBool(map['autovalidate']) == true - ? AutovalidateMode.always - : AutovalidateMode.disabled, - borderRadius: ThemeDecoder.decodeBorderRadius( + autovalidateMode: map['autovalidate'] == null + ? ThemeDecoder.instance.decodeAutovalidateMode( + map['autovalidateMode'], + validate: false, + ) + : JsonClass.maybeParseBool(map['autovalidate']) == true + ? AutovalidateMode.always + : AutovalidateMode.disabled, + barrierDismissable: JsonClass.parseBool( + map['barrierDismissable'], + whenNull: true, + ), + borderRadius: ThemeDecoder.instance.decodeBorderRadius( map['borderRadius'], validate: false, ), decoration: map['decoration'], disabledHint: JsonWidgetData.maybeFromDynamic(map['disabledHint']), - dropdownColor: ThemeDecoder.decodeColor( + dropdownColor: ThemeDecoder.instance.decodeColor( map['dropdownColor'], validate: false, ), @@ -310,22 +309,24 @@ class JsonDropdownButtonFormFieldBuilderModel extends JsonWidgetBuilderModel { map['enableFeedback'], whenNull: true, ), - enabled: - map['enabled'] == null - ? true - : JsonClass.maybeParseBool(map['enabled']), + errorBuilder: map['errorBuilder'], + enabled: map['enabled'] == null + ? true + : JsonClass.maybeParseBool(map['enabled']), + forceErrorText: map['forceErrorText'], hint: JsonWidgetData.maybeFromDynamic(map['hint']), icon: JsonWidgetData.maybeFromDynamic(map['icon']), items: map['items'], - iconDisabledColor: ThemeDecoder.decodeColor( + iconDisabledColor: ThemeDecoder.instance.decodeColor( map['iconDisabledColor'], validate: false, ), - iconEnabledColor: ThemeDecoder.decodeColor( + iconEnabledColor: ThemeDecoder.instance.decodeColor( map['iconEnabledColor'], validate: false, ), iconSize: JsonClass.maybeParseDouble(map['iconSize'], 24.0), + initialValue: map['initialValue'] ?? map['value'], isDense: JsonClass.parseBool(map['isDense'], whenNull: true), isExpanded: JsonClass.maybeParseBool(map['isExpanded']), itemHeight: JsonClass.maybeParseDouble(map['itemHeight']), @@ -333,13 +334,18 @@ class JsonDropdownButtonFormFieldBuilderModel extends JsonWidgetBuilderModel { onChanged: map['onChanged'], onSaved: map['onSaved'], onTap: map['onTap'], + padding: ThemeDecoder.instance.decodeEdgeInsetsGeometry( + map['padding'], + validate: false, + ), selectedItemBuilder: map['selectedItemBuilder'], - style: ThemeDecoder.decodeTextStyle(map['style'], validate: false), - validator: - map['validators'] == null - ? null - : Validator.fromDynamic({'validators': map['validators']}), - value: map['value'], + style: ThemeDecoder.instance.decodeTextStyle( + map['style'], + validate: false, + ), + validator: map['validators'] == null + ? null + : Validator.fromDynamic({'validators': map['validators']}), ); } @@ -348,22 +354,28 @@ class JsonDropdownButtonFormFieldBuilderModel extends JsonWidgetBuilderModel { @override Map toJson() => { - 'alignment': ThemeEncoder.encodeAlignment(alignment), + 'alignment': ThemeEncoder.instance.encodeAlignment(alignment), 'autofocus': autofocus, - 'autovalidateMode': ThemeEncoder.encodeAutovalidateMode(autovalidateMode), - 'borderRadius': ThemeEncoder.encodeBorderRadius(borderRadius), + 'autovalidateMode': ThemeEncoder.instance.encodeAutovalidateMode( + autovalidateMode, + ), + 'barrierDismissable': barrierDismissable, + 'borderRadius': ThemeEncoder.instance.encodeBorderRadius(borderRadius), 'decoration': decoration, 'disabledHint': disabledHint, - 'dropdownColor': ThemeEncoder.encodeColor(dropdownColor), + 'dropdownColor': ThemeEncoder.instance.encodeColor(dropdownColor), 'elevation': elevation, 'enableFeedback': enableFeedback, 'enabled': enabled, + 'errorBuilder': errorBuilder, + 'forceErrorText': forceErrorText, 'hint': hint?.toJson(), 'icon': icon?.toJson(), 'items': JsonClass.toJsonList(items), - 'iconDisabledColor': ThemeEncoder.encodeColor(iconDisabledColor), - 'iconEnabledColor': ThemeEncoder.encodeColor(iconEnabledColor), + 'iconDisabledColor': ThemeEncoder.instance.encodeColor(iconDisabledColor), + 'iconEnabledColor': ThemeEncoder.instance.encodeColor(iconEnabledColor), 'iconSize': iconSize, + 'initialValue': initialValue, 'isDense': isDense, 'isExpanded': isExpanded, 'itemHeight': itemHeight, @@ -371,10 +383,10 @@ class JsonDropdownButtonFormFieldBuilderModel extends JsonWidgetBuilderModel { 'onChanged': onChanged, 'onSaved': onSaved, 'onTap': onTap, + 'padding': padding, 'selectedItemBuilder': selectedItemBuilder, - 'style': ThemeEncoder.encodeTextStyle(style), + 'style': ThemeEncoder.instance.encodeTextStyle(style), 'validator': validator == null ? null : {'validators': validator!.toJson()}, - 'value': value, ...args, }; } @@ -397,6 +409,7 @@ class DropdownButtonFormFieldSchema { 'autofocus': SchemaHelper.boolSchema, 'autovalidate': SchemaHelper.boolSchema, 'autovalidateMode': SchemaHelper.objectSchema(AutovalidateModeSchema.id), + 'barrierDismissable': SchemaHelper.boolSchema, 'borderRadius': SchemaHelper.objectSchema(BorderRadiusSchema.id), 'decoration': SchemaHelper.anySchema, 'disabledHint': SchemaHelper.objectSchema(JsonWidgetDataSchema.id), @@ -404,14 +417,17 @@ class DropdownButtonFormFieldSchema { 'elevation': SchemaHelper.numberSchema, 'enableFeedback': SchemaHelper.boolSchema, 'enabled': SchemaHelper.boolSchema, + 'errorBuilder': SchemaHelper.stringSchema, 'focusColor': SchemaHelper.objectSchema(ColorSchema.id), 'focusNode': SchemaHelper.stringSchema, + 'forceErrorText': SchemaHelper.stringSchema, 'hint': SchemaHelper.objectSchema(JsonWidgetDataSchema.id), 'icon': SchemaHelper.objectSchema(JsonWidgetDataSchema.id), 'items': SchemaHelper.anySchema, 'iconDisabledColor': SchemaHelper.objectSchema(ColorSchema.id), 'iconEnabledColor': SchemaHelper.objectSchema(ColorSchema.id), 'iconSize': SchemaHelper.numberSchema, + 'initialValue': SchemaHelper.anySchema, 'isDense': SchemaHelper.boolSchema, 'isExpanded': SchemaHelper.boolSchema, 'itemHeight': SchemaHelper.numberSchema, @@ -419,11 +435,11 @@ class DropdownButtonFormFieldSchema { 'onChanged': SchemaHelper.stringSchema, 'onSaved': SchemaHelper.stringSchema, 'onTap': SchemaHelper.stringSchema, + 'padding': SchemaHelper.objectSchema(EdgeInsetsGeometrySchema.id), 'selectedItemBuilder': SchemaHelper.anySchema, 'shadows': SchemaHelper.arraySchema(ShadowSchema.id), 'validators': SchemaHelper.anySchema, 'style': SchemaHelper.objectSchema(TextStyleSchema.id), - 'value': SchemaHelper.anySchema, }, }; } @@ -451,8 +467,6 @@ class _JsonDropdownButtonFormFieldWidgetState List? _items; late JsonDropdownButtonFormFieldBuilderModel _model; DropdownButtonBuilder? _selectedItemBuilder; - late StreamSubscription _subscription; - dynamic _value; @override void initState() { @@ -465,15 +479,6 @@ class _JsonDropdownButtonFormFieldWidgetState _items = _getItems(); _selectedItemBuilder = _getSelectedItemBuilder(); _decoration = _getDecoration(); - _value = _model.value; - _subscription = widget.data.jsonWidgetRegistry.valueStream - .where((e) => !e.isSelfTriggered && e.id == widget.data.jsonWidgetId) - .listen((event) { - _value = event.value; - if (mounted) { - setState(() {}); - } - }); } @override @@ -485,12 +490,10 @@ class _JsonDropdownButtonFormFieldWidgetState _items = _getItems(); _selectedItemBuilder = _getSelectedItemBuilder(); _decoration = _getDecoration(); - _value = _model.value; } @override void dispose() { - _subscription.cancel(); if (widget.data.jsonWidgetId.isNotEmpty == true) { widget.data.jsonWidgetRegistry.removeValue( widget.data.jsonWidgetId, @@ -503,11 +506,11 @@ class _JsonDropdownButtonFormFieldWidgetState InputDecoration? _getDecoration() { return _model.decoration != null ? InputDecorationDecoder.fromDynamic( - _model.decoration, - childBuilder: widget.childBuilder, - context: context, - registry: widget.data.jsonWidgetRegistry, - ) + _model.decoration, + childBuilder: widget.childBuilder, + context: context, + registry: widget.data.jsonWidgetRegistry, + ) : null; } @@ -578,6 +581,7 @@ class _JsonDropdownButtonFormFieldWidgetState alignment: _model.alignment ?? AlignmentDirectional.centerStart, autofocus: _model.autofocus ?? false, autovalidateMode: _model.autovalidateMode, + barrierDismissible: _model.barrierDismissable, borderRadius: _model.borderRadius, decoration: _decoration ?? const InputDecoration(), disabledHint: _model.disabledHint?.build( @@ -586,10 +590,12 @@ class _JsonDropdownButtonFormFieldWidgetState registry: widget.data.jsonWidgetRegistry, ), dropdownColor: _model.dropdownColor, + errorBuilder: _model.errorBuilder, elevation: _model.elevation ?? 8, enableFeedback: _model.enableFeedback, focusColor: _model.focusColor, focusNode: _model.focusNode, + forceErrorText: _model.forceErrorText, hint: _model.hint?.build( childBuilder: widget.childBuilder, context: context, @@ -600,57 +606,55 @@ class _JsonDropdownButtonFormFieldWidgetState context: context, registry: widget.data.jsonWidgetRegistry, ), - items: _items, iconDisabledColor: _model.iconDisabledColor, iconEnabledColor: _model.iconEnabledColor, iconSize: _model.iconSize ?? 24, + initialValue: _model.initialValue, isDense: _model.isDense ?? true, isExpanded: _model.isExpanded ?? false, itemHeight: _model.itemHeight, + items: _items, menuMaxHeight: _model.menuMaxHeight, - onChanged: - _model.enabled != true - ? null - : (dynamic value) { - if (_model.onChanged != null) { - _model.onChanged!(value); - } - _value = value; - if (mounted == true) { - setState(() {}); - } - - if (widget.data.jsonWidgetId.isNotEmpty == true) { - widget.data.jsonWidgetRegistry.setValue( - widget.data.jsonWidgetId, - value, - originator: widget.data.jsonWidgetId, - ); - } - }, + onChanged: _model.enabled != true + ? null + : (dynamic value) { + if (_model.onChanged != null) { + _model.onChanged!(value); + } + if (mounted == true) { + setState(() {}); + } + + if (widget.data.jsonWidgetId.isNotEmpty == true) { + widget.data.jsonWidgetRegistry.setValue( + widget.data.jsonWidgetId, + value, + originator: widget.data.jsonWidgetId, + ); + } + }, + padding: _model.padding, onSaved: _model.onSaved, onTap: _model.onTap, selectedItemBuilder: _selectedItemBuilder, - validator: - _model.validator == null - ? null - : (dynamic value) { - final error = _model.validator!.validate( - label: _decoration?.labelText ?? '', - value: value?.toString(), - ); + validator: _model.validator == null + ? null + : (dynamic value) { + final error = _model.validator!.validate( + label: _decoration?.labelText ?? '', + value: value?.toString(), + ); - if (widget.data.jsonWidgetId.isNotEmpty == true) { - widget.data.jsonWidgetRegistry.setValue( - '${widget.data.jsonWidgetId}.error', - error ?? '', - originator: widget.data.jsonWidgetId, - ); - } + if (widget.data.jsonWidgetId.isNotEmpty == true) { + widget.data.jsonWidgetRegistry.setValue( + '${widget.data.jsonWidgetId}.error', + error ?? '', + originator: widget.data.jsonWidgetId, + ); + } - return error; - }, + return error; + }, style: _model.style, - value: _value, ); } diff --git a/packages/json_dynamic_widget/lib/src/builders/json_layout_builder_builder.dart b/packages/json_dynamic_widget/lib/src/builders/json_layout_builder_builder.dart index 5bb877a2..21f3257e 100644 --- a/packages/json_dynamic_widget/lib/src/builders/json_layout_builder_builder.dart +++ b/packages/json_dynamic_widget/lib/src/builders/json_layout_builder_builder.dart @@ -3,7 +3,7 @@ import 'package:json_dynamic_widget/json_dynamic_widget.dart'; part 'json_layout_builder_builder.g.dart'; /// Builder that can build an [LayoutBuilder] widget. -@jsonWidget +@JsonWidget(requiresId: true) abstract class _JsonLayoutBuilderBuilder extends JsonWidgetBuilder { const _JsonLayoutBuilderBuilder({required super.args}); diff --git a/packages/json_dynamic_widget/lib/src/builders/json_linear_progress_indicator_builder.dart b/packages/json_dynamic_widget/lib/src/builders/json_linear_progress_indicator_builder.dart index 90c42e90..a2044693 100644 --- a/packages/json_dynamic_widget/lib/src/builders/json_linear_progress_indicator_builder.dart +++ b/packages/json_dynamic_widget/lib/src/builders/json_linear_progress_indicator_builder.dart @@ -8,14 +8,13 @@ abstract class _JsonLinearProgressIndicatorBuilder extends JsonWidgetBuilder { const _JsonLinearProgressIndicatorBuilder({required super.args}); @JsonArgDecoder('valueColor') - Animation? _decodeValueColor({required dynamic value}) => - value == null - ? null - : value is Animation - ? value - : AlwaysStoppedAnimation( - ThemeDecoder.decodeColor(value, validate: false)!, - ); + Animation? _decodeValueColor({required dynamic value}) => value == null + ? null + : value is Animation + ? value + : AlwaysStoppedAnimation( + ThemeDecoder.instance.decodeColor(value, validate: false)!, + ); @override LinearProgressIndicator buildCustom({ diff --git a/packages/json_dynamic_widget/lib/src/builders/json_measured_builder.dart b/packages/json_dynamic_widget/lib/src/builders/json_measured_builder.dart index 9cc90dea..a99b70d7 100644 --- a/packages/json_dynamic_widget/lib/src/builders/json_measured_builder.dart +++ b/packages/json_dynamic_widget/lib/src/builders/json_measured_builder.dart @@ -5,7 +5,7 @@ part 'json_measured_builder.g.dart'; /// Builder that can build a widget that measures itself and writes the /// measurements to the [JsonWidgetRegistry]'s values. -@jsonWidget +@JsonWidget(requiresId: true) abstract class _JsonMeasuredBuilder extends JsonWidgetBuilder { const _JsonMeasuredBuilder({required super.args}); diff --git a/packages/json_dynamic_widget/lib/src/builders/json_radio_builder.dart b/packages/json_dynamic_widget/lib/src/builders/json_radio_builder.dart index d0ab0075..5bdf9b19 100644 --- a/packages/json_dynamic_widget/lib/src/builders/json_radio_builder.dart +++ b/packages/json_dynamic_widget/lib/src/builders/json_radio_builder.dart @@ -1,182 +1,16 @@ -import 'dart:async'; - -import 'package:form_validation/form_validation.dart'; import 'package:json_dynamic_widget/json_dynamic_widget.dart'; part 'json_radio_builder.g.dart'; -/// Builder that can build an [Radio] Unlike other form fields, this requires -/// the `id` for the radio variable to be inside of the `args`. This is because -/// no two widgets can share the same overall id. -@jsonWidget +@JsonWidget(requiresId: true) abstract class _JsonRadioBuilder extends JsonWidgetBuilder { const _JsonRadioBuilder({required super.args}); @override - _Radio buildCustom({ + Radio buildCustom({ ChildWidgetBuilder? childBuilder, required BuildContext context, required JsonWidgetData data, Key? key, }); } - -class _Radio extends StatefulWidget { - _Radio({ - this.activeColor, - required this.autofocus, - this.autovalidateMode, - @JsonBuildArg() required this.data, - this.enabled = true, - this.fillColor, - this.focusColor, - this.focusNode, - this.groupValue, - this.hoverColor, - this.id, - this.label, - this.materialTapTargetSize, - this.mouseCursor, - this.onChanged, - this.onSaved, - this.overlayColor, - this.splashRadius, - required this.toggleable, - this.validator, - this.value, - this.visualDensity, - }) : assert(id?.isNotEmpty == true); - - final Color? activeColor; - final bool autofocus; - final AutovalidateMode? autovalidateMode; - final JsonWidgetData data; - final bool enabled; - final WidgetStateProperty? fillColor; - final Color? focusColor; - final FocusNode? focusNode; - final dynamic groupValue; - final Color? hoverColor; - final String? id; - final String? label; - final MaterialTapTargetSize? materialTapTargetSize; - final MouseCursor? mouseCursor; - final ValueChanged? onChanged; - final ValueChanged? onSaved; - final WidgetStateProperty? overlayColor; - final bool toggleable; - final double? splashRadius; - final Validator? validator; - final dynamic value; - final VisualDensity? visualDensity; - - @override - State createState() => _RadioState(); -} - -class _RadioState extends State<_Radio> { - final List _subscriptions = []; - final GlobalKey _globalKey = GlobalKey(); - - @override - void initState() { - super.initState(); - - _subscriptions.add( - widget.data.jsonWidgetRegistry.valueStream - .where((event) => event.id == widget.id) - .listen((event) { - if (mounted == true) { - _globalKey.currentState!.didChange( - widget.data.jsonWidgetRegistry.getValue(widget.id), - ); - } - }), - ); - } - - @override - void dispose() { - final id = widget.data.jsonWidgetArgs?['id']?.toString(); - - if (id != null && id.isNotEmpty == true) { - widget.data.jsonWidgetRegistry.removeValue(id, originator: id); - } - for (var sub in _subscriptions) { - sub.cancel(); - } - _subscriptions.clear(); - - super.dispose(); - } - - @override - Widget build(BuildContext context) { - return FormField( - autovalidateMode: widget.autovalidateMode, - enabled: widget.enabled, - initialValue: widget.groupValue, - key: _globalKey, - onSaved: widget.onSaved, - validator: - widget.validator == null - ? null - : (value) { - final error = widget.validator!.validate( - label: widget.label ?? '', - value: value?.toString(), - ); - - if (widget.data.jsonWidgetId.isNotEmpty == true) { - widget.data.jsonWidgetRegistry.setValue( - '${widget.id}.error', - error ?? '', - originator: '${widget.id}.error', - ); - } - - return error; - }, - builder: - (FormFieldState state) => MergeSemantics( - child: Semantics( - label: widget.label ?? '', - child: Radio( - activeColor: widget.activeColor, - autofocus: widget.autofocus, - fillColor: widget.fillColor, - focusColor: widget.focusColor, - focusNode: widget.focusNode, - groupValue: state.value, - hoverColor: widget.hoverColor, - materialTapTargetSize: widget.materialTapTargetSize, - mouseCursor: widget.mouseCursor, - onChanged: - widget.enabled != true - ? null - : (value) { - if (widget.onChanged != null) { - widget.onChanged!(value); - } - - state.didChange(value); - - if (widget.id?.isNotEmpty == true) { - widget.data.jsonWidgetRegistry.setValue( - widget.id!, - value, - originator: widget.id!, - ); - } - }, - overlayColor: widget.overlayColor, - splashRadius: widget.splashRadius, - toggleable: widget.toggleable, - value: widget.value, - visualDensity: widget.visualDensity, - ), - ), - ), - ); - } -} diff --git a/packages/json_dynamic_widget/lib/src/builders/json_radio_group_builder.dart b/packages/json_dynamic_widget/lib/src/builders/json_radio_group_builder.dart new file mode 100644 index 00000000..d8e892f6 --- /dev/null +++ b/packages/json_dynamic_widget/lib/src/builders/json_radio_group_builder.dart @@ -0,0 +1,83 @@ +import 'package:json_dynamic_widget/json_dynamic_widget.dart'; + +part 'json_radio_group_builder.g.dart'; + +/// Builder that can build an [RadioGroup] widget. +@JsonWidget(requiresId: true) +abstract class _JsonRadioGroupBuilder extends JsonWidgetBuilder { + const _JsonRadioGroupBuilder({required super.args}); + + @override + _RadioGroup buildCustom({ + ChildWidgetBuilder? childBuilder, + required BuildContext context, + required JsonWidgetData data, + Key? key, + }); +} + +class _RadioGroup extends StatefulWidget { + const _RadioGroup({ + @JsonBuildArg() this.childBuilder, + @JsonBuildArg() required this.data, + required this.groupValue, + required this.onChanged, + this.child, + }); + + final ChildWidgetBuilder? childBuilder; + final JsonWidgetData? child; + final JsonWidgetData data; + final dynamic groupValue; + final ValueChanged? onChanged; + + @override + State createState() => _RadioGroupState(); +} + +class _RadioGroupState extends State<_RadioGroup> { + dynamic _groupValue; + + @override + void initState() { + super.initState(); + _groupValue = widget.groupValue; + + widget.data.jsonWidgetRegistry.setValue( + widget.data.jsonWidgetId, + _groupValue, + originator: widget.data.jsonWidgetId, + ); + } + + @override + Widget build(BuildContext context) { + return RadioGroup( + groupValue: widget.data.jsonWidgetRegistry.getValue( + widget.data.jsonWidgetId, + ), + onChanged: (value) { + if (widget.onChanged != null) { + widget.onChanged!(value); + } + _groupValue = value; + widget.data.jsonWidgetRegistry.setValue( + widget.data.jsonWidgetId, + value, + originator: widget.data.jsonWidgetId, + ); + if (mounted) { + setState(() {}); + } + }, + + child: + widget.child?.build( + childBuilder: widget.childBuilder, + context: context, + registry: widget.data.jsonWidgetRegistry, + ) ?? + const SizedBox(), + ); + } +} diff --git a/packages/json_dynamic_widget/lib/src/builders/json_rich_text_builder.dart b/packages/json_dynamic_widget/lib/src/builders/json_rich_text_builder.dart index 848e26da..fd882781 100644 --- a/packages/json_dynamic_widget/lib/src/builders/json_rich_text_builder.dart +++ b/packages/json_dynamic_widget/lib/src/builders/json_rich_text_builder.dart @@ -9,7 +9,7 @@ abstract class _JsonRichTextBuilder extends JsonWidgetBuilder { @JsonArgDecoder('text') InlineSpan _decodeText({required dynamic value}) => - ThemeDecoder.decodeTextSpan(value, validate: false)!; + ThemeDecoder.instance.decodeTextSpan(value, validate: false)!; @override RichText buildCustom({ diff --git a/packages/json_dynamic_widget/lib/src/builders/json_scaffold_builder.dart b/packages/json_dynamic_widget/lib/src/builders/json_scaffold_builder.dart index 8514ad41..e1899e69 100644 --- a/packages/json_dynamic_widget/lib/src/builders/json_scaffold_builder.dart +++ b/packages/json_dynamic_widget/lib/src/builders/json_scaffold_builder.dart @@ -1,9 +1,15 @@ // ignore: unused_import +import 'dart:math' as math; + import 'package:flutter/gestures.dart'; import 'package:json_dynamic_widget/json_dynamic_widget.dart'; part 'json_scaffold_builder.g.dart'; +const double _kBottomSheetDominatesPercentage = 0.3; +const double _kMinBottomSheetScrimOpacity = 0.1; +const double _kMaxBottomSheetScrimOpacity = 0.6; + /// Builder that can build an [Scaffold] widget. @jsonWidget abstract class _JsonScaffoldBuilder extends JsonWidgetBuilder { @@ -17,3 +23,28 @@ abstract class _JsonScaffoldBuilder extends JsonWidgetBuilder { Key? key, }); } + +Widget _defaultBottomSheetScrimBuilder( + BuildContext context, + Animation animation, +) { + return AnimatedBuilder( + animation: animation, + builder: (BuildContext context, Widget? child) { + final extentRemaining = + _kBottomSheetDominatesPercentage * (1.0 - animation.value); + final floatingButtonVisibilityValue = + extentRemaining * _kBottomSheetDominatesPercentage * 10; + + final double opacity = math.max( + _kMinBottomSheetScrimOpacity, + _kMaxBottomSheetScrimOpacity - floatingButtonVisibilityValue, + ); + + return ModalBarrier( + dismissible: false, + color: Colors.black.withValues(alpha: opacity), + ); + }, + ); +} diff --git a/packages/json_dynamic_widget/lib/src/builders/json_semantics_builder.dart b/packages/json_dynamic_widget/lib/src/builders/json_semantics_builder.dart index 94319f38..7ee3fdf8 100644 --- a/packages/json_dynamic_widget/lib/src/builders/json_semantics_builder.dart +++ b/packages/json_dynamic_widget/lib/src/builders/json_semantics_builder.dart @@ -11,18 +11,13 @@ abstract class _JsonSemanticsBuilder extends JsonWidgetBuilder { @JsonArgEncoder('sortKey') static Map? _encodeSortKey(SemanticsSortKey? value) => - value is OrdinalSortKey ? ThemeEncoder.encodeOrdinalSortKey(value) : null; - - @JsonArgSchema('sortKey') - static Map _inputDecorationSchema() { - final schema = OrdinalSortKeySchema.schema; - SchemaCache().addSchema(OrdinalSortKeySchema.id, schema); - return SchemaHelper.objectSchema(OrdinalSortKeySchema.id); - } + value is OrdinalSortKey + ? ThemeEncoder.instance.encodeOrdinalSortKey(value) + : null; @JsonArgDecoder('sortKey') OrdinalSortKey? _decodeSortKey({required dynamic value}) => - ThemeDecoder.decodeOrdinalSortKey(value, validate: false); + ThemeDecoder.instance.decodeOrdinalSortKey(value, validate: false); @JsonDefaultParam('sortKey', 'null') @override diff --git a/packages/json_dynamic_widget/lib/src/builders/json_switch_builder.dart b/packages/json_dynamic_widget/lib/src/builders/json_switch_builder.dart index e4a12df5..47c73828 100644 --- a/packages/json_dynamic_widget/lib/src/builders/json_switch_builder.dart +++ b/packages/json_dynamic_widget/lib/src/builders/json_switch_builder.dart @@ -5,7 +5,7 @@ import 'package:json_dynamic_widget/json_dynamic_widget.dart'; part 'json_switch_builder.g.dart'; /// Builder that can build an [Switch] widget. -@jsonWidget +@JsonWidget(requiresId: true) abstract class _JsonSwitchBuilder extends JsonWidgetBuilder { const _JsonSwitchBuilder({required super.args}); @@ -27,7 +27,7 @@ abstract class _JsonSwitchBuilder extends JsonWidgetBuilder { class _Switch extends StatefulWidget { const _Switch({ - this.activeColor, + this.activeThumbColor, this.activeThumbImage, this.activeTrackColor, this.autofocus = false, @@ -46,6 +46,7 @@ class _Switch extends StatefulWidget { this.mouseCursor, this.onActiveThumbImageError, this.onChanged, + this.onFocusChanged, this.onInactiveThumbImageError, this.onSaved, this.overlayColor, @@ -53,12 +54,14 @@ class _Switch extends StatefulWidget { this.thumbColor, this.thumbIcon, this.trackColor, + this.trackOutlineColor, + this.trackOutlineWidth, this.validator, this.value = false, this.visualDensity, }); - final Color? activeColor; + final Color? activeThumbColor; final ImageProvider? activeThumbImage; final Color? activeTrackColor; final bool autofocus; @@ -77,6 +80,7 @@ class _Switch extends StatefulWidget { final MouseCursor? mouseCursor; final ImageErrorListener? onActiveThumbImageError; final ValueChanged? onChanged; + final ValueChanged? onFocusChanged; final ImageErrorListener? onInactiveThumbImageError; final ValueChanged? onSaved; final WidgetStateProperty? overlayColor; @@ -84,6 +88,8 @@ class _Switch extends StatefulWidget { final WidgetStateProperty? thumbColor; final WidgetStateProperty? thumbIcon; final WidgetStateProperty? trackColor; + final WidgetStateProperty? trackOutlineColor; + final WidgetStateProperty? trackOutlineWidth; final Validator? validator; final bool value; final VisualDensity? visualDensity; @@ -112,73 +118,73 @@ class _SwitchState extends State<_Switch> { enabled: widget.enabled, initialValue: widget.value, key: widget.key, - validator: - widget.validator == null - ? null - : (value) { - final error = widget.validator!.validate( - label: widget.label ?? '', - value: value?.toString(), - ); + validator: widget.validator == null + ? null + : (value) { + final error = widget.validator!.validate( + label: widget.label ?? '', + value: value?.toString(), + ); - if (widget.data.jsonWidgetId.isNotEmpty == true) { - widget.data.jsonWidgetRegistry.setValue( - '${widget.data.jsonWidgetId}.error', - error ?? '', - originator: '${widget.data.jsonWidgetId}.error', - ); - } + if (widget.data.jsonWidgetId.isNotEmpty == true) { + widget.data.jsonWidgetRegistry.setValue( + '${widget.data.jsonWidgetId}.error', + error ?? '', + originator: '${widget.data.jsonWidgetId}.error', + ); + } - return error; - }, + return error; + }, onSaved: widget.onSaved, - builder: - (FormFieldState state) => MergeSemantics( - child: Semantics( - label: widget.label ?? '', - child: Switch( - activeColor: widget.activeColor, - activeThumbImage: widget.activeThumbImage, - activeTrackColor: widget.activeTrackColor, - autofocus: widget.autofocus, - dragStartBehavior: widget.dragStartBehavior, - focusColor: widget.focusColor, - focusNode: widget.focusNode, - hoverColor: widget.hoverColor, - inactiveThumbColor: widget.inactiveThumbColor, - inactiveThumbImage: widget.inactiveThumbImage, - inactiveTrackColor: widget.inactiveTrackColor, - materialTapTargetSize: widget.materialTapTargetSize, - mouseCursor: widget.mouseCursor, - onActiveThumbImageError: widget.onActiveThumbImageError, - onChanged: - widget.enabled != true - ? null - : (value) { - if (widget.onChanged != null) { - widget.onChanged!(value); - } + builder: (FormFieldState state) => MergeSemantics( + child: Semantics( + label: widget.label ?? '', + child: Switch( + activeThumbColor: widget.activeThumbColor, + activeThumbImage: widget.activeThumbImage, + activeTrackColor: widget.activeTrackColor, + autofocus: widget.autofocus, + dragStartBehavior: widget.dragStartBehavior, + focusColor: widget.focusColor, + focusNode: widget.focusNode, + hoverColor: widget.hoverColor, + inactiveThumbColor: widget.inactiveThumbColor, + inactiveThumbImage: widget.inactiveThumbImage, + inactiveTrackColor: widget.inactiveTrackColor, + materialTapTargetSize: widget.materialTapTargetSize, + mouseCursor: widget.mouseCursor, + onActiveThumbImageError: widget.onActiveThumbImageError, + onChanged: widget.enabled != true + ? null + : (value) { + if (widget.onChanged != null) { + widget.onChanged!(value); + } - state.didChange(value); + state.didChange(value); - if (widget.data.jsonWidgetId.isNotEmpty == true) { - widget.data.jsonWidgetRegistry.setValue( - widget.data.jsonWidgetId, - value, - originator: widget.data.jsonWidgetId, - ); - } - }, - onInactiveThumbImageError: widget.onInactiveThumbImageError, - overlayColor: widget.overlayColor, - splashRadius: widget.splashRadius, - thumbColor: widget.thumbColor, - thumbIcon: widget.thumbIcon, - trackColor: widget.trackColor, - value: state.value, - ), - ), + if (widget.data.jsonWidgetId.isNotEmpty == true) { + widget.data.jsonWidgetRegistry.setValue( + widget.data.jsonWidgetId, + value, + originator: widget.data.jsonWidgetId, + ); + } + }, + onFocusChange: widget.onFocusChanged, + onInactiveThumbImageError: widget.onInactiveThumbImageError, + overlayColor: widget.overlayColor, + splashRadius: widget.splashRadius, + thumbColor: widget.thumbColor, + thumbIcon: widget.thumbIcon, + trackColor: widget.trackColor, + trackOutlineColor: widget.trackOutlineColor, + trackOutlineWidth: widget.trackOutlineWidth, + value: state.value, ), + ), + ), ); } } diff --git a/packages/json_dynamic_widget/lib/src/builders/json_text_form_field_builder.dart b/packages/json_dynamic_widget/lib/src/builders/json_text_form_field_builder.dart index 77c59161..e7560e19 100644 --- a/packages/json_dynamic_widget/lib/src/builders/json_text_form_field_builder.dart +++ b/packages/json_dynamic_widget/lib/src/builders/json_text_form_field_builder.dart @@ -6,7 +6,7 @@ import 'package:json_dynamic_widget/json_dynamic_widget.dart'; part 'json_text_form_field_builder.g.dart'; -@jsonWidget +@JsonWidget(requiresId: true) abstract class _JsonTextFormFieldBuilder extends JsonWidgetBuilder { const _JsonTextFormFieldBuilder({required super.args}); @@ -66,6 +66,7 @@ class _TextFormField extends StatefulWidget { this.contextMenuBuilder, required this.controller, this.cursorColor, + this.cursorErrorColor, this.cursorHeight, this.cursorOpacityAnimates, this.cursorRadius, @@ -78,6 +79,11 @@ class _TextFormField extends StatefulWidget { this.enableSuggestions = true, this.enabled, this.expands = false, + this.errorBuilder, + this.forceErrorText, + this.groupId = EditableText, + this.hintLocales, + this.ignorePointers, this.focusNode, this.initialValue, this.inputFormatters, @@ -97,12 +103,16 @@ class _TextFormField extends StatefulWidget { this.onFieldSubmitted, this.onSaved, this.onTap, + this.onTapAlwaysCalled = false, this.onTapOutside, + this.onTapUpOutside, this.readOnly = false, this.restorationId, this.scrollController, this.scrollPadding = const EdgeInsets.all(20.0), this.scrollPhysics, + this.selectAllOnFocus, + this.statesController, this.selectionControls, this.selectionHeightStyle = BoxHeightStyle.tight, this.selectionWidthStyle = BoxWidthStyle.tight, @@ -133,6 +143,7 @@ class _TextFormField extends StatefulWidget { final EditableTextContextMenuBuilder? contextMenuBuilder; final TextEditingController? controller; final Color? cursorColor; + final Color? cursorErrorColor; final double? cursorHeight; final bool? cursorOpacityAnimates; final Radius? cursorRadius; @@ -144,8 +155,13 @@ class _TextFormField extends StatefulWidget { final bool? enableInteractiveSelection; final bool enableSuggestions; final bool? enabled; + final Widget Function(BuildContext, String)? errorBuilder; final bool expands; final FocusNode? focusNode; + final String? forceErrorText; + final Object groupId; + final List? hintLocales; + final bool? ignorePointers; final String? initialValue; final List? inputFormatters; final Brightness? keyboardAppearance; @@ -164,12 +180,15 @@ class _TextFormField extends StatefulWidget { final ValueChanged? onFieldSubmitted; final FormFieldSetter? onSaved; final VoidCallback? onTap; + final bool onTapAlwaysCalled; final TapRegionCallback? onTapOutside; + final void Function(PointerUpEvent)? onTapUpOutside; final bool readOnly; final String? restorationId; final ScrollController? scrollController; final EdgeInsets scrollPadding; final ScrollPhysics? scrollPhysics; + final bool? selectAllOnFocus; final TextSelectionControls? selectionControls; final BoxHeightStyle selectionHeightStyle; final BoxWidthStyle selectionWidthStyle; @@ -177,6 +196,7 @@ class _TextFormField extends StatefulWidget { final SmartDashesType? smartDashesType; final SmartQuotesType? smartQuotesType; final SpellCheckConfiguration? spellCheckConfiguration; + final WidgetStatesController? statesController; final StrutStyle? strutStyle; final TextStyle? style; final bool stylusHandwritingEnabled; @@ -260,6 +280,7 @@ class _TextFormFieldState extends State<_TextFormField> { contextMenuBuilder: widget.contextMenuBuilder, controller: _controller, cursorColor: widget.cursorColor, + cursorErrorColor: widget.cursorErrorColor, cursorHeight: widget.cursorHeight, cursorOpacityAnimates: widget.cursorOpacityAnimates, cursorRadius: widget.cursorRadius, @@ -270,8 +291,13 @@ class _TextFormFieldState extends State<_TextFormField> { enableInteractiveSelection: widget.enableInteractiveSelection, enableSuggestions: widget.enableSuggestions, enabled: widget.enabled, + errorBuilder: widget.errorBuilder, expands: widget.expands, focusNode: widget.focusNode, + forceErrorText: widget.forceErrorText, + groupId: widget.groupId, + hintLocales: widget.hintLocales, + ignorePointers: widget.ignorePointers, // initialValue: , inputFormatters: widget.inputFormatters, keyboardAppearance: widget.keyboardAppearance, @@ -285,24 +311,26 @@ class _TextFormFieldState extends State<_TextFormField> { obscuringCharacter: widget.obscuringCharacter, obscureText: widget.obscureText, onAppPrivateCommand: widget.onAppPrivateCommand, - onChanged: - widget.enabled != true - ? null - : (value) { - if (widget.onChanged != null) { - widget.onChanged!(value); - } - }, + onChanged: widget.enabled != true + ? null + : (value) { + if (widget.onChanged != null) { + widget.onChanged!(value); + } + }, onEditingComplete: widget.onEditingComplete, onFieldSubmitted: widget.onFieldSubmitted, onSaved: widget.onSaved, onTap: widget.onTap, + onTapAlwaysCalled: widget.onTapAlwaysCalled, onTapOutside: widget.onTapOutside, + onTapUpOutside: widget.onTapUpOutside, readOnly: widget.readOnly, restorationId: widget.restorationId, scrollController: widget.scrollController, scrollPadding: widget.scrollPadding, scrollPhysics: widget.scrollPhysics, + selectAllOnFocus: widget.selectAllOnFocus, selectionControls: widget.selectionControls, selectionHeightStyle: widget.selectionHeightStyle, selectionWidthStyle: widget.selectionWidthStyle, @@ -310,6 +338,7 @@ class _TextFormFieldState extends State<_TextFormField> { smartDashesType: widget.smartDashesType, smartQuotesType: widget.smartQuotesType, spellCheckConfiguration: widget.spellCheckConfiguration, + statesController: widget.statesController, strutStyle: widget.strutStyle, style: widget.style, stylusHandwritingEnabled: widget.stylusHandwritingEnabled, @@ -320,22 +349,21 @@ class _TextFormFieldState extends State<_TextFormField> { textInputAction: widget.textInputAction, // @deprecated toolbarOptions undoController: widget.undoController, - validator: - widget.validators == null - ? null - : (value) { - final error = widget.validators!.validate( - label: widget.decoration?.labelText ?? '', - value: value?.toString(), - ); + validator: widget.validators == null + ? null + : (value) { + final error = widget.validators!.validate( + label: widget.decoration?.labelText ?? '', + value: value?.toString(), + ); - widget.data.jsonWidgetRegistry.setValue( - '${widget.data.jsonWidgetId}.error', - error ?? '', - originator: widget.data.jsonWidgetId, - ); + widget.data.jsonWidgetRegistry.setValue( + '${widget.data.jsonWidgetId}.error', + error ?? '', + originator: widget.data.jsonWidgetId, + ); - return error; - }, + return error; + }, ); } diff --git a/packages/json_dynamic_widget/lib/src/builders/json_widget_builder.dart b/packages/json_dynamic_widget/lib/src/builders/json_widget_builder.dart index ab34a0dc..deff06e4 100644 --- a/packages/json_dynamic_widget/lib/src/builders/json_widget_builder.dart +++ b/packages/json_dynamic_widget/lib/src/builders/json_widget_builder.dart @@ -162,7 +162,8 @@ class _JsonWidgetStatefulState extends State<_JsonWidgetStateful> { _data = widget.data; _subscription = widget.data.jsonWidgetRegistry.valueStream.listen((event) { - if (_data.jsonWidgetListenVariables.contains(event.id) == true) { + if (_data.jsonWidgetListenVariables.contains(event.id) == true && + event.originator != _data.jsonWidgetId) { // _data = _data.recreate(); if (mounted == true) { setState(() {}); @@ -196,7 +197,8 @@ class _JsonWidgetStatefulState extends State<_JsonWidgetStateful> { } catch (e, stack) { result = SingleChildScrollView( child: ErrorWidget.withDetails( - message: ''' + message: + ''' $e $stack ''', diff --git a/packages/json_dynamic_widget/lib/src/decoders/input_decoration_decoder.dart b/packages/json_dynamic_widget/lib/src/decoders/input_decoration_decoder.dart index 1ba947bb..dda22fe8 100644 --- a/packages/json_dynamic_widget/lib/src/decoders/input_decoration_decoder.dart +++ b/packages/json_dynamic_widget/lib/src/decoders/input_decoration_decoder.dart @@ -73,8 +73,11 @@ class InputDecorationDecoder { if (map != null) { result = InputDecoration( alignLabelWithHint: JsonClass.maybeParseBool(map['alignLabelWithHint']), - border: ThemeDecoder.decodeInputBorder(map['border'], validate: false), - contentPadding: ThemeDecoder.decodeEdgeInsetsGeometry( + border: ThemeDecoder.instance.decodeInputBorder( + map['border'], + validate: false, + ), + contentPadding: ThemeDecoder.instance.decodeEdgeInsetsGeometry( map['contentPadding'], validate: false, ), @@ -82,61 +85,65 @@ class InputDecorationDecoder { map['counter'], registry: registry, )?.build(childBuilder: childBuilder, context: context), - counterStyle: ThemeDecoder.decodeTextStyle( + counterStyle: ThemeDecoder.instance.decodeTextStyle( map['counterStyle'], validate: false, ), counterText: map['counterText'], - disabledBorder: ThemeDecoder.decodeInputBorder( + disabledBorder: ThemeDecoder.instance.decodeInputBorder( map['disabledBorder'], validate: false, ), enabled: JsonClass.parseBool(map['enabled'], whenNull: true), - enabledBorder: ThemeDecoder.decodeInputBorder( + enabledBorder: ThemeDecoder.instance.decodeInputBorder( map['enabledBorder'], validate: false, ), - errorBorder: ThemeDecoder.decodeInputBorder( + errorBorder: ThemeDecoder.instance.decodeInputBorder( map['errorBorder'], validate: false, ), errorMaxLines: JsonClass.maybeParseInt(map['errorMaxLines']), - errorStyle: ThemeDecoder.decodeTextStyle( + errorStyle: ThemeDecoder.instance.decodeTextStyle( map['errorStyle'], validate: false, ), errorText: map['errorText'], - fillColor: ThemeDecoder.decodeColor(map['fillColor'], validate: false), - filled: JsonClass.maybeParseBool(map['filled']), - floatingLabelBehavior: ThemeDecoder.decodeFloatingLabelBehavior( - map['floatingLabelBehavior'], + fillColor: ThemeDecoder.instance.decodeColor( + map['fillColor'], validate: false, ), - focusColor: ThemeDecoder.decodeColor( + filled: JsonClass.maybeParseBool(map['filled']), + floatingLabelBehavior: ThemeDecoder.instance + .decodeFloatingLabelBehavior( + map['floatingLabelBehavior'], + validate: false, + ), + focusColor: ThemeDecoder.instance.decodeColor( map['focusColor'], validate: false, ), - focusedBorder: ThemeDecoder.decodeInputBorder( + focusedBorder: ThemeDecoder.instance.decodeInputBorder( map['focusedBorder'], validate: false, ), - focusedErrorBorder: ThemeDecoder.decodeInputBorder( + focusedErrorBorder: ThemeDecoder.instance.decodeInputBorder( map['focusedErrorBorder'], validate: false, ), helperMaxLines: JsonClass.maybeParseInt(map['helperMaxLines']), - helperStyle: ThemeDecoder.decodeTextStyle( + helperStyle: ThemeDecoder.instance.decodeTextStyle( map['helperStyle'], validate: false, ), helperText: map['helperText'], hintMaxLines: JsonClass.maybeParseInt(map['hintMaxLines']), - hintStyle: ThemeDecoder.decodeTextStyle( + hintStyle: ThemeDecoder.instance.decodeTextStyle( map['hintStyle'], validate: false, ), hintText: map['hintText'], - hoverColor: ThemeDecoder.decodeColor( + hoverColor: ThemeDecoder.instance.decodeColor( map['hoverColor'], validate: false, ), @@ -145,7 +152,7 @@ class InputDecorationDecoder { registry: registry, )?.build(childBuilder: childBuilder, context: context), isDense: JsonClass.maybeParseBool(map['isDense']), - labelStyle: ThemeDecoder.decodeTextStyle( + labelStyle: ThemeDecoder.instance.decodeTextStyle( map['labelStyle'], validate: false, ), @@ -158,11 +165,11 @@ class InputDecorationDecoder { map['prefixIcon'], registry: registry, )?.build(childBuilder: childBuilder, context: context), - prefixIconConstraints: ThemeDecoder.decodeBoxConstraints( + prefixIconConstraints: ThemeDecoder.instance.decodeBoxConstraints( map['prefixIconConstraints'], validate: false, ), - prefixStyle: ThemeDecoder.decodeTextStyle( + prefixStyle: ThemeDecoder.instance.decodeTextStyle( map['prefixStyle'], validate: false, ), @@ -176,11 +183,11 @@ class InputDecorationDecoder { map['suffixIcon'], registry: registry, )?.build(childBuilder: childBuilder, context: context), - suffixIconConstraints: ThemeDecoder.decodeBoxConstraints( + suffixIconConstraints: ThemeDecoder.instance.decodeBoxConstraints( map['suffixIconConstraints'], validate: false, ), - suffixStyle: ThemeDecoder.decodeTextStyle( + suffixStyle: ThemeDecoder.instance.decodeTextStyle( map['suffixStyle'], validate: false, ), diff --git a/packages/json_dynamic_widget/lib/src/models/deferred_json_widget_data.dart b/packages/json_dynamic_widget/lib/src/models/deferred_json_widget_data.dart index ee84c3e0..102cd13b 100644 --- a/packages/json_dynamic_widget/lib/src/models/deferred_json_widget_data.dart +++ b/packages/json_dynamic_widget/lib/src/models/deferred_json_widget_data.dart @@ -16,6 +16,9 @@ class DeferredJsonWidgetData implements JsonWidgetData { JsonWidgetData? _data; + @override + bool get hasProvidedId => data.hasProvidedId; + @override JsonWidgetBuilder? get jsonWidgetArgs => data.jsonWidgetArgs; @@ -74,6 +77,7 @@ class DeferredJsonWidgetData implements JsonWidgetData { JsonWidgetRegistry? jsonWidgetRegistry, String? jsonWidgetType, }) => JsonWidgetData( + hasProvidedId: hasProvidedId, jsonWidgetArgs: jsonWidgetArgs ?? this.jsonWidgetArgs, jsonWidgetBuilder: jsonWidgetBuilder as JsonWidgetBuilder Function()? ?? diff --git a/packages/json_dynamic_widget/lib/src/models/json_widget_data.dart b/packages/json_dynamic_widget/lib/src/models/json_widget_data.dart index 1afa4ace..da255a16 100644 --- a/packages/json_dynamic_widget/lib/src/models/json_widget_data.dart +++ b/packages/json_dynamic_widget/lib/src/models/json_widget_data.dart @@ -7,18 +7,21 @@ import 'package:logging/logging.dart'; class JsonWidgetData extends JsonClass { JsonWidgetData({ + bool? hasProvidedId, this.jsonWidgetArgs, required this.jsonWidgetBuilder, Set? jsonWidgetListenVariables, String? jsonWidgetId, JsonWidgetRegistry? jsonWidgetRegistry, required this.jsonWidgetType, - }) : jsonWidgetListenVariables = jsonWidgetListenVariables ?? {}, + }) : hasProvidedId = hasProvidedId ?? jsonWidgetId != null, + jsonWidgetListenVariables = jsonWidgetListenVariables ?? {}, jsonWidgetId = jsonWidgetId ?? const Uuid().v4(), jsonWidgetRegistry = jsonWidgetRegistry ?? JsonWidgetRegistry.instance; static final Logger _logger = Logger('JsonWidgetData'); + final bool hasProvidedId; final dynamic jsonWidgetArgs; final JsonWidgetBuilder Function() jsonWidgetBuilder; final String jsonWidgetType; @@ -94,12 +97,11 @@ class JsonWidgetData extends JsonClass { } else if (map != null) { try { final type = map['type']; - final timer = - ExecutionWatch( - group: 'JsonWidgetData.fromDynamic', - name: type, - precision: TimerPrecision.microsecond, - ).start(); + final timer = ExecutionWatch( + group: 'JsonWidgetData.fromDynamic', + name: type, + precision: TimerPrecision.microsecond, + ).start(); try { if (type is! String) { throw HandledJsonWidgetException( @@ -227,6 +229,7 @@ $errorValue JsonWidgetRegistry? jsonWidgetRegistry, String? jsonWidgetType, }) => JsonWidgetData( + hasProvidedId: hasProvidedId, jsonWidgetArgs: jsonWidgetArgs ?? this.jsonWidgetArgs, jsonWidgetBuilder: jsonWidgetBuilder as JsonWidgetBuilder Function()? ?? @@ -247,14 +250,12 @@ $errorValue // Skips the id if it's a valid (auto generated) UUID to avoid spamming // the emitted JSON 'id': Uuid.isValidUUID(fromString: jsonWidgetId) ? null : jsonWidgetId, - 'listen': - jsonWidgetListenVariables.isEmpty - ? null - : List.from(jsonWidgetListenVariables), - 'args': - jsonWidgetArgs is JsonClass - ? jsonWidgetArgs.toJson() - : jsonWidgetArgs, + 'listen': jsonWidgetListenVariables.isEmpty + ? null + : List.from(jsonWidgetListenVariables), + 'args': jsonWidgetArgs is JsonClass + ? jsonWidgetArgs.toJson() + : jsonWidgetArgs, }); } } diff --git a/packages/json_dynamic_widget/pubspec.yaml b/packages/json_dynamic_widget/pubspec.yaml index 376f3058..ab43af54 100644 --- a/packages/json_dynamic_widget/pubspec.yaml +++ b/packages/json_dynamic_widget/pubspec.yaml @@ -1,10 +1,10 @@ name: 'json_dynamic_widget' description: 'A library to dynamically generate widgets within Flutter from JSON or other Map-like structures.' repository: 'https://github.com/peiffer-innovations/json_dynamic_widget' -version: '10.0.2' +version: '11.0.0' environment: - sdk: '^3.8.0' + sdk: '^3.9.0' resolution: 'workspace' analyzer: @@ -23,7 +23,7 @@ dependencies: json_class: '^3.0.1' json_conditional: '^3.0.1+17' json_schema: '^5.2.1' - json_theme: '^9.0.1+2' + json_theme: '^10.0.0' logging: '^1.3.0' meta: '^1.16.0' template_expressions: '^3.3.1+2' @@ -32,11 +32,22 @@ dependencies: yaon: '^1.1.4+10' dev_dependencies: - build_runner: '^2.4.15' + build_runner: '2.7.2' + # build_runner: '^2.10.1' + code_builder: '^4.10.1' flutter_lints: '^6.0.0' flutter_test: sdk: 'flutter' - json_dynamic_widget_codegen: '^3.0.0' + json_dynamic_widget_codegen: '^4.0.0' + +dependency_overrides: + json_theme: + path: ../../../json_theme/packages/json_theme + json_theme_annotation: + path: ../../../json_theme/packages/annotation + json_theme_codegen: + path: ../../../json_theme/packages/codegen + test_api: '^0.7.6' permittedLicenses: - 'Apache-2.0' diff --git a/pubspec.yaml b/pubspec.yaml index 46a7c4b0..99a7604e 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,10 +2,9 @@ name: json_dynamic_widget_workspace publish_to: none environment: - sdk: '^3.7.0' + sdk: '^3.9.0' workspace: - packages/annotation - packages/codegen - packages/json_dynamic_widget - - packages/json_dynamic_widget/example From 656f20a0b24c22bdbfa9f396de0f50326aaca17c Mon Sep 17 00:00:00 2001 From: Jeff Peiffer Date: Sun, 9 Nov 2025 15:21:57 -0400 Subject: [PATCH 4/6] updates --- packages/json_dynamic_widget/example/pubspec.yaml | 6 ------ packages/json_dynamic_widget/pubspec.yaml | 11 +++-------- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/packages/json_dynamic_widget/example/pubspec.yaml b/packages/json_dynamic_widget/example/pubspec.yaml index cdb6b54c..4f23642d 100644 --- a/packages/json_dynamic_widget/example/pubspec.yaml +++ b/packages/json_dynamic_widget/example/pubspec.yaml @@ -35,12 +35,6 @@ dependency_overrides: path: ../../annotation json_dynamic_widget_codegen: path: ../../codegen - json_theme_annotation: - path: ../../../../json_theme/packages/annotation - json_theme_codegen: - path: ../../../../json_theme/packages/codegen - json_theme: - path: ../../../../json_theme/packages/json_theme icons_launcher: image_path: 'assets-src/icon.png' diff --git a/packages/json_dynamic_widget/pubspec.yaml b/packages/json_dynamic_widget/pubspec.yaml index ab43af54..c20eb976 100644 --- a/packages/json_dynamic_widget/pubspec.yaml +++ b/packages/json_dynamic_widget/pubspec.yaml @@ -32,8 +32,9 @@ dependencies: yaon: '^1.1.4+10' dev_dependencies: - build_runner: '2.7.2' - # build_runner: '^2.10.1' + # When debugging is needed + # build_runner: '2.7.2' + build_runner: '^2.10.1' code_builder: '^4.10.1' flutter_lints: '^6.0.0' flutter_test: @@ -41,12 +42,6 @@ dev_dependencies: json_dynamic_widget_codegen: '^4.0.0' dependency_overrides: - json_theme: - path: ../../../json_theme/packages/json_theme - json_theme_annotation: - path: ../../../json_theme/packages/annotation - json_theme_codegen: - path: ../../../json_theme/packages/codegen test_api: '^0.7.6' permittedLicenses: From 2aea5cb9bf30084fcf3c1442c2398e0b56a62263 Mon Sep 17 00:00:00 2001 From: Jeff Peiffer Date: Sun, 9 Nov 2025 15:30:28 -0400 Subject: [PATCH 5/6] updates --- .github/workflows/pull_request.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 1125e1bb..36e4d159 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -4,6 +4,7 @@ on: workflow_dispatch: pull_request: branches: [main] + types: [opened, reopened, synchronize] jobs: build: @@ -29,4 +30,3 @@ jobs: with: generate_code: true path: packages/json_dynamic_widget - From c66adcfb4507615168a5ddf460937f14b809d944 Mon Sep 17 00:00:00 2001 From: Jeff Peiffer Date: Sun, 9 Nov 2025 15:36:22 -0400 Subject: [PATCH 6/6] manual publish, catch up changelog --- packages/annotation/CHANGELOG.md | 2 +- packages/codegen/CHANGELOG.md | 2 +- packages/json_dynamic_widget/CHANGELOG.md | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/annotation/CHANGELOG.md b/packages/annotation/CHANGELOG.md index 9ff1706a..41e68b18 100644 --- a/packages/annotation/CHANGELOG.md +++ b/packages/annotation/CHANGELOG.md @@ -1,4 +1,4 @@ -## [3.0.1] - October 29th, 2025 +## [3.0.1] - November 9th, 2025 * Flutter 3.35 diff --git a/packages/codegen/CHANGELOG.md b/packages/codegen/CHANGELOG.md index 1d39d1da..9bd73efb 100644 --- a/packages/codegen/CHANGELOG.md +++ b/packages/codegen/CHANGELOG.md @@ -1,4 +1,4 @@ -## [4.0.0] - October 29th, 2025 +## [4.0.0] - November 9th, 2025 * Updated generaters to the latest version * Flutter 3.35 diff --git a/packages/json_dynamic_widget/CHANGELOG.md b/packages/json_dynamic_widget/CHANGELOG.md index 04f4735c..047a52f4 100644 --- a/packages/json_dynamic_widget/CHANGELOG.md +++ b/packages/json_dynamic_widget/CHANGELOG.md @@ -1,9 +1,9 @@ -## [11.0.0] - October 29th, 2025 +## [11.0.0] - November 9th, 2025 * Flutter 3.35 * Removed custom coded versions of the following widgets and replaced them with an autogenerated versions: * `Radio` - +* Added `RadioGroup` ## [10.0.2] - July 14th, 2025