Code generator for Flutter's theme extension classes.

Overview

Theme Tailor

Welcome to Theme Tailor, a code generator and theming utility for supercharging Flutter ThemeExtension classes introduced in Flutter 3.0! The generator helps to minimize the required boilerplate code.

Table of contents

Motivation

Flutter 3.0 provides a new way of theming applications via ThemeData's theme extensions. To declare theme extension, we need to:

  • define a class that extends ThemeData,
  • define a constructor and fields,
  • implement "copyWith",
  • implement "lerp",
  • (optional) override "hashCode",
  • (optional) override "==" operator
  • (optional) implement "debugFillProperties" method
  • (optional) add serialization code

In addition to generating themes, we may want to declare utility extensions to access theme properties via an extension on BuildContext or ThemeData that requires additional work. Implementing this requires lots of additional lines of code and time.

Before After
before after

How to use

Install

ThemeTailor is a code generator and requires build_runner to run. Make sure to add these packages to the project dependencies:

flutter pub add --dev build_runner
flutter pub add --dev theme_tailor
flutter pub add theme_tailor_annotation

Add imports and part directive

ThemeTailor is a generator for annotation that generates code in a part file that needs to be specified. Make sure to add the following imports and part directive in the file where you use the annotation.

Make sure to specify the correct file name in a part directive. In the example below, replace "name" with the file name.

name.dart
import 'package:theme_tailor_annotation/theme_tailor_annotation.dart';

part 'name.tailor.dart';

Run the code generator

To run the code generator, run the following commands:

flutter run build_runner build --delete-conflicting-outputs

Create Theme class

ThemeTailor will generate ThemeExtension class based on the configuration class you are required to annotate with theme_tailor_annotation. Please make sure to name class and theme properties appropriately according to the following rules:

  • class name starts with _$ or $_ (Recommendation is to use the former, as it ensures that the configuration class is private). If the class name does not contain the required prefix, then the generated class name will append an additional suffix,
  • class contains static List<T> fields (e.g. static List<Color> surface = []). If no fields exist in the config class, the generator will create an empty ThemeExtension class.

Example

my_theme.dart
import 'package:flutter/material.dart';
import 'package:theme_tailor_annotation/theme_tailor_annotation.dart';

part 'my_theme.tailor.dart';

@tailor
class _$MyTheme {
  static List<Color> background = [Colors.white, Colors.black];
}

The following code snippet defines the "MyTheme" theme extension class.

  • "MyTheme" extends ThemeExtension<MyTheme>
  • defined class is immutable with final fields with const constructor
  • there is one field "background" of type Color
  • "light" and "dark" static fields matching the default theme names supplied by theme_tailor_annotation
  • "copyWith" method is created (override of ThemeExtension) with a nullable argument "background" of type "Color"
  • "lerp" method is created (override of ThemeExtension) with the default lerping method for the "Color" type.
  • "hashCode" method && "==" operator are created

Additionally theme_tailor_annotation by default generates extension on BuildContext

  • "MyThemeBuildContextProps" extension on "BuildContext" is generated
  • getter on "background" of type "Color" is added directly to "BuildContext"

Change themes quantity and names

By default, "@tailor" will generate two themes: "light" and "dark"; To control the names and quantity of the themes, edit the "themes" property on the "@Tailor" annotation.

@Tailor(themes: ['baseTheme'])
class _$MyTheme {}

Access generated themes list

The generator will create a static getter with a list of the generated themes:

final allThemes = MyTailorGeneratedTheme.themes;

If themes property is already used in the tailor class, the generator will use another name and print a warning.

Change generated extensions

By default, "@tailor" will generate an extension on "BuildContext" and expand theme properties as getters. If this is an undesired behavior, you can disable it by changing the "themeGetter" property in the "@Tailor" or use "@TailorComponent" annotation.

@Tailor(themeGetter: ThemeGetter.none)
// OR
@TailorComponent()

"ThemeGetter" has several variants for generating common extensions to ease access to the declared themes.

Nesting generated ThemeExtensions, Modular themes && DesignSystems

It might be beneficial to split them into smaller parts, where each part is responsible for the theme of one component. You can think about it as modularization of the theme. ThemeExtensions allow easier custom theme integration with Flutter ThemeData without creating additional Inherited widgets handling theme changes. It is especially beneficial when

  • Creating design systems,
  • Modularization of the application per feature and components,
  • Create a package that supplies widgets and needs more or additional properties not found in ThemeData.
Structure of the application's theme data and its extensions. "chatComponentsTheme" has nested properties.
ThemeData: [] # Flutter's material widgets props
ThemeDataExtensions:
  - ChatComponentsTheme: 
    - MsgBubble: 
      - Bubble: myBubble
      - Bubble: friendsBubble
    - MsgList: [foo, bar, baz]

Use "@tailor" and "@Tailor" annotations if you may need additional extensions on ThemeData or ThemeContext.

Use "@tailorComponent" or "@TailorComponent" if you intend to nest the theme extension class and do not need additional extensions. Use this annotation for generated themes to allow generator to recognize the type correctly.

/// Use generated "ChatComponentsTheme" in ThemeData
@tailor
class _$ChatComponentsTheme {
  @themeExtension
  static List<MsgBubble> msgBubble = MsgBubble.themes;

  @themeExtension
  static List<MsgList> msgList = MsgList.themes;

  /// "NotGeneratedExtension" is a theme extension that is not created using code generator. It is not necessary to mark it with "@themeExtension" annotation
  static List<NotGeneratedExtension> = [/*custom themes*/];
}

@tailorComponent
class _$MsgBubble {
  // Keep in mind that Bubble type used here may be another Tailor component, and its generated themes can be selectively 
  // assigned to proper fields. (By default tailor will generate two themes: "light" and "dark")

  /// Lets say that my message bubble in 
  /// light mode is darkBlue
  /// dark mode is lightBlue
  static List<Bubble> myBubble = [Bubble.darkBlue, Bubble.lightBlue];

  /// Lets say that my message bubble in 
  /// light mode is darkOrange
  /// dark mode is lightOrange
  static List<Bubble> friendsBubble = [Bubble.darkOrange, Bubble.lightOrange];
}

@TailorComponent(themes: ['darkBlue', 'lightBlue', 'darkOrange', 'lightOrange'])
class _$Bubble {
  static List<Color> background = [/*Corresponding 'default' values for 'darkBlue', 'lightBlue', 'darkOrange', 'lightOrange'*/];
  static List<Color> textStyle = [/*Corresponding 'default' values for 'darkBlue', 'lightBlue', 'darkOrange', 'lightOrange'*/];
}

/// You can also nest classes marked with @tailor (not recommended)
@tailor
class _$MsgList {
  /// implementation
  /// foo
  /// bar 
  /// baz
}

class NotGeneratedExtension extends ThemeExtension<NotGeneratedExtension> {
  /// implementation
}

To see examle implementation of nested theme, head out to: [example:nested_themes][example: nested_themes]

Custom types encoding

ThemeTailor will attempt to provide lerp method for types like:

  • Color
  • Color?
  • TextStyle
  • TextStyle?

In the case of an unrecognized or unsupported type, the generator provides a default lerping function (That does not interpolate values linearly but switches between them). You can specify a custom the lerp function for the given type (Color/TextStyle, etc.) or property by extending "ThemeEncoder" class from theme_tailor_annotation

Example of adding custom encoder for an int.

my_theme.dart
import 'dart:ui';

class IntEncoder extends ThemeEncoder<int> {
  const IntEncoder();

  @override
  int lerp(int a, int b, double t) {
    return lerpDouble(a, b, t)!.toInt();
  }
}

Use it in different ways:

/// 1 Add it to the encoders list in the @Tailor() annotation
@Tailor(encoders: [IntEncoder()])
class _$Theme1 {}

/// 2 Add it as a separate annotation below @Tailor() or @tailor annotation
@tailor
@IntEncoder()
class _$Theme2 {}

/// 3 Add it below your custom tailor annotation
const appTailor = Tailor(themes: ['superLight']);

@appTailor
@IntEncoder()
class _$Theme3 {}

/// 4 Add it on the property
@tailor
class _$Theme4 {
    @IntEncoder()
    static const List<int> someValues = [1,2];
}

/// 5 IntEncoder() can be assigned to a variable and used as an annotation
/// It works for any of the previous examples
const intEncoder = IntEncoder();

@tailor
@intEncoder
class _$Theme5 {}

Generator chooses proper lerp function for the given field based on the order:

  • annotation on the field
  • annotation on top of the class
  • property from encoders list in the "@Tailor" annotation.

Custom supplied encoders override default ones provided by the code generator. Unrecognized or unsupported types will use the default lerp function.

To see more examples of custom theme encoders implementation, head out to: example: theme encoders

Flutter diagnosticable / debugFillProperties

To add support for Flutter diagnosticable to the generated ThemeExtension class, import Flutter foundation. Then create the ThemeTailor config class as usual.

import 'package:flutter/foundation.dart';

To see an example how to ensure debugFillProperties are generated, head out to: example: debugFillProperties

Json serialization

The generator will copy all the annotations on the class and the static fields, including: "@JsonSerializable", "@JsonKey", custom JsonConverter(s), and generate the "fromJson" factory. If you wish to add support for the "toJson" method, you can add it in the class extension:

@tailor
@JsonSerializable()
class _$SerializableTheme {

  /// This is a custom converter (it will be copied to the generated class)
  @JsonColorConverter()
  static List<Color> foo = [Colors.red, Colors.pink];
}

/// Extension for generated class to support toJson (JsonSerializable does not have to generate this method)
extension SerializableThemeExtension on SerializableTheme {
  Map<String, dynamic> toJson() => _$SerializableThemeToJson(this);
}

To see an example implementation of "@JsonColorConverter" check out example: json serializable

To serialize nested themes, declare your config classes as presented in the Nesting generated theme extensions, modular themes, design systems. Make sure to use proper json_serializable config either in the annotation on the class or your config "build.yaml" or "pubspec.yaml". For more information about customizing build config for json_serializable head to the json_serializable documentation.

@JsonSerializable(explicitToJson: true)

Ignore fields

Fields other than static List<T> are ignored by default by the generator, but if you still want to ignore these, you can use @ignore annotation.

@tailor
class _$IgnoreExample {
  static List<Color> background = [AppColors.white, Colors.grey.shade900];
  @ignore
  static List<Color> iconColor = [AppColors.orange, AppColors.blue];
  @ignore
  static List<int> numbers = [1, 2, 3];
}

Build configuration

You can also configure the generator by setting values in the build.yaml.

targets:
  $default:
    builders:
      theme_tailor:
        options:
          themes: ["light", "dark", "superDark"]
Comments
  • Nested theme is getting generated of dynamic type

    Nested theme is getting generated of dynamic type

    As you can see below final dynamic buttonTheme; of dynamic type is being generated.

    // ignore_for_file: unused_element, unused_field
    
    import 'package:client_flutter/barrel.dart';
    
    part 'button_theme.tailor.dart';
    
    @TailorComponent(themes: [])
    class _$ButtonTheme {
      static const List<TextStyle> textStyle = [];
      static const List<Color> color = [];
      static const List<double> height = [];
    }
    
    // ignore_for_file: unused_element, unused_field
    
    import 'package:client_flutter/barrel.dart';
    
    part 'theme.tailor.dart';
    
    @TailorComponent(themes: [])
    class _$GluTheme {
      static const List<GluButtonTheme> buttonTheme = [];
    }
    
    
    class GluTheme extends ThemeExtension<GluTheme> with DiagnosticableTreeMixin {
      const GluTheme({
        required this.buttonTheme,
      });
    
      final dynamic buttonTheme;
    
      @override
      GluTheme copyWith({
        dynamic buttonTheme,
      }) {
        return GluTheme(
          buttonTheme: buttonTheme ?? this.buttonTheme,
        );
      }
    
    opened by jascodes 3
  • theme_tailor fails with flutter 3.3.0 (stable)

    theme_tailor fails with flutter 3.3.0 (stable)

    Hi, thanks for this great package!

    I'm getting an exception from theme_tailor when running the usual flutter packages pub run build_runner build --delete-conflicting-outputs, after upgrading to the latest flutter stable release (3.3.0). Downgrading to flutter 3.0.5 (without any other code changes) fixes the issue and build_runner again completes successfully.

    I have a more complex theme template, but from the stacktrace it doesn't seem to be related to any particular thing in the template. Also, for me it is reproducible even with very simple template, e.g.

    @Tailor(themes: ["light"], themeGetter: ThemeGetter.onBuildContext)
    class _$AppColors {
      static List<Color> background = const [Color(0xFFFFFFFF)];
      static List<Color> onBackground = const [Color(0xFF3C3C3B)];
    }
    

    This is the error (obtained with appending --verbose to the mentioned build_runner command)

    [SEVERE] theme_tailor:theme_tailor on lib/common/resources/tailor_theme_extensions.dart (cached):
    
    Stack Overflow
    dart:core                                                                    new _GrowableList.of
    package:analyzer/src/dart/element/element.dart 4374:10                       LibraryElementImpl._partUnits
    package:analyzer/src/dart/element/element.dart 4364:10                       LibraryElementImpl.units
    package:analyzer/src/dart/element/element.dart 4348:22                       LibraryElementImpl.topLevelElements
    dart:collection                                                              ListMixin.any
    .                                                                            ...
    .                                                                            ...
    dart:collection                                                              ListMixin.any
    package:theme_tailor/src/util/import_finder.dart 51:34                       ImportFinder._isExportedRecursivaly
    dart:collection                                                              ListMixin.any
    package:theme_tailor/src/util/import_finder.dart 51:34                       ImportFinder._isExportedRecursivaly
    dart:collection                                                              ListMixin.any
    package:theme_tailor/src/util/import_finder.dart 51:34                       ImportFinder._isExportedRecursivaly
    dart:collection                                                              ListMixin.any
    package:theme_tailor/src/util/import_finder.dart 51:34                       ImportFinder._isExportedRecursivaly
    dart:collection                                                              ListMixin.any
    package:theme_tailor/src/util/import_finder.dart 51:34                       ImportFinder._isExportedRecursivaly
    dart:collection                                                              ListMixin.any
    package:theme_tailor/src/util/import_finder.dart 51:34                       ImportFinder._isExportedRecursivaly
    dart:collection                                                              SetMixin.any
    package:theme_tailor/src/util/import_finder.dart 41:22                       ImportFinder.recursiveSearch
    package:theme_tailor/src/util/extension/library_element_extension.dart 10:7  LibraryElementExtension.hasFlutterDiagnosticableImport
    package:theme_tailor/src/generator/theme_tailor_generator.dart 48:36         ThemeTailorGenerator.generateForAnnotatedElement
    package:source_gen/src/generator_for_annotation.dart 53:30                   GeneratorForAnnotation.generate
    package:source_gen/src/builder.dart 352:33                                   _generate
    
    [SEVERE] Build:
    Failed after 132ms
    [+4382 ms] "flutter pub" took 4,449ms.
    [   +2 ms] pub finished with exit code 1
    [        ] 
               #0      throwToolExit (package:flutter_tools/src/base/common.dart:10:3)
               #1      _DefaultPub.interactively (package:flutter_tools/src/dart/pub.dart:418:7)
               <asynchronous suspension>
               #2      PackagesPassthroughCommand.runCommand (package:flutter_tools/src/commands/packages.dart:274:5)
               <asynchronous suspension>
               #3      FlutterCommand.run.<anonymous closure> (package:flutter_tools/src/runner/flutter_command.dart:1209:27)
               <asynchronous suspension>
               #4      AppContext.run.<anonymous closure> (package:flutter_tools/src/base/context.dart:150:19)
               <asynchronous suspension>
               #5      CommandRunner.runCommand (package:args/command_runner.dart:209:13)
               <asynchronous suspension>
               #6      FlutterCommandRunner.runCommand.<anonymous closure> (package:flutter_tools/src/runner/flutter_command_runner.dart:281:9)
               <asynchronous suspension>
               #7      AppContext.run.<anonymous closure> (package:flutter_tools/src/base/context.dart:150:19)
               <asynchronous suspension>
               #8      FlutterCommandRunner.runCommand (package:flutter_tools/src/runner/flutter_command_runner.dart:229:5)
               <asynchronous suspension>
               #9      run.<anonymous closure>.<anonymous closure> (package:flutter_tools/runner.dart:62:9)
               <asynchronous suspension>
               #10     AppContext.run.<anonymous closure> (package:flutter_tools/src/base/context.dart:150:19)
               <asynchronous suspension>
               #11     main (package:flutter_tools/executable.dart:91:3)
               <asynchronous suspension>
    
    bug 
    opened by jvincek 3
  • How to add operator==, hashCode and debugFillProperties.

    How to add operator==, hashCode and debugFillProperties.

    flutter 3.0.2 theme_tailor_annotation 1.0.0 theme_tailor 1.0.1

    Example code:

    import 'package:flutter/foundation.dart';
    import 'package:flutter/material.dart';
    import 'package:theme_tailor_annotation/theme_tailor_annotation.dart';
    
    part 'ng_theme.tailor.dart';
    
    @Tailor(
      themes: ['light'],
      themeGetter: ThemeGetter.onBuildContext,
    )
    class _$NgTheme {
      static const List<Color> test = [Colors.black];
    }
    

    Generated code:

    // coverage:ignore-file
    // GENERATED CODE - DO NOT MODIFY BY HAND
    // ignore_for_file: type=lint, unused_element
    
    part of 'ng_theme.dart';
    
    // **************************************************************************
    // ThemeTailorGenerator
    // **************************************************************************
    
    class NgTheme extends ThemeExtension<NgTheme> {
      NgTheme({
        required this.test,
      });
    
      final Color test;
    
      static final NgTheme light = NgTheme(
        test: _$NgTheme.test[0],
      );
    
      @override
      NgTheme copyWith({
        Color? test,
      }) {
        return NgTheme(
          test: test ?? this.test,
        );
      }
    
      @override
      NgTheme lerp(ThemeExtension<NgTheme>? other, double t) {
        if (other is! NgTheme) return this;
        return NgTheme(
          test: Color.lerp(test, other.test, t)!,
        );
      }
    }
    
    extension NgThemeBuildContext on BuildContext {
      NgTheme get ngTheme => Theme.of(this).extension<NgTheme>()!;
    }
    
    

    Expected result: debugFillProperties must be generated operator == must be generated hashCode must be generated

    opened by InAnadea 3
  • Add support for other theme extensions in class fields

    Add support for other theme extensions in class fields

    Example:

    This three themes:

    @tailor
    class $_SomeTheme {
      static List<Color> appBackground = [AppColors.white, AppColors.black];
      @themeExtension
      static List<AnotherThemePart> anotherThemePart = [AnotherThemePart.light, AnotherThemePart.dark];
      static List<OtherThemeExtension> otherThemeExtension = [OtherThemeExtension(), OtherThemeExtension()];
    }
    
    @tailorComponent
    class $_AnotherThemePart {
      static List<Color> navBarBackground = [AppColors.white, AppColors.black];
    }
    
    class OtherThemeExtension extends ThemeExtension<OtherThemeExtension> {
      OtherThemeExtension({
        this.floatingActionButtonColor = Colors.white,
      });
    
      final Color floatingActionButtonColor;
      
      // ...
    }
    

    Will result in following lerp method

      @override
      SomeTheme lerp(ThemeExtension<SomeTheme>? other, double t) {
        if (other is! SomeTheme) return this;
        return SomeTheme(
          appBackground: Color.lerp(appBackground, other.appBackground, t)!,
          anotherThemePart: anotherThemePart.lerp(other.anotherThemePart, t),
          otherThemeExtension:
              otherThemeExtension.lerp(other.otherThemeExtension, t),
        );
      }
    

    This PR also adds generated lists of themes, example:

    @tailor
    class $_SomeTheme {
      @themeExtension
      static List<AnotherThemePart> anotherThemePartGeneratedConstructor = AnotherThemePart.themes;
    }
    
    @tailorComponent
    class $_AnotherThemePart {
      static List<Color> navBarBackground = [AppColors.white, AppColors.black];
    }
    

    Generated code:

    class AnotherThemePart extends ThemeExtension<AnotherThemePart> {
      static final themes = [
        dark,
        light,
      ];
    }
    
    opened by jakubtiteo 3
  • themes property default value not working, error received instead

    themes property default value not working, error received instead

    Hi,

    if u not set the themes property: @Tailor(themes: ['light', 'dark']) just type this: @Tailor you will receive the following error message and the tailor file not generated: type 'Null' is not a subtype of type 'List<dynamic>' in type cast

    regards

    opened by mrnusa 2
  • Feature/extensions

    Feature/extensions

    Add extensions to access theme/theme properties to ThemeData / BuildContext

    ThemeGetter.onBuildContextProps is selected as a default option, this is a subject to change. Also we may allow to generate few of these at once.

    Generated extensions examples:

    /// ThemeGetter.onBuildContext
    extension SimpleThemeBuildContextExtension on BuildContext {
      SimpleTheme get simpleTheme => Theme.of(this).extension<SimpleTheme>()!;
    }
    
    /// ThemeGetter.onBuildContextProps
    extension SimpleThemeBuildContextExtension on BuildContext {
      SimpleTheme get _simpleTheme => Theme.of(this).extension<SimpleTheme>()!;
      Color get background => _simpleTheme.background;
      Color get surface => _simpleTheme.surface;
      Color get appBar => _simpleTheme.appBar;
      TextStyle get h1 => _simpleTheme.h1;
      TextStyle get h2 => _simpleTheme.h2;
    }
    
    /// ThemeGetter.onThemeData
    extension SimpleThemeThemeDataExtension on ThemeData {
      SimpleTheme get simpleTheme => extension<SimpleTheme>()!;
    }
    
    /// ThemeGetter.onThemeDataProps
    extension SimpleThemeThemeDataExtension on ThemeData {
      SimpleTheme get _simpleTheme => extension<SimpleTheme>()!;
      Color get background => _simpleTheme.background;
      Color get surface => _simpleTheme.surface;
      Color get appBar => _simpleTheme.appBar;
      TextStyle get h1 => _simpleTheme.h1;
      TextStyle get h2 => _simpleTheme.h2;
    }
    
    opened by Rongix 2
  • Feat: Add documentation to generated props

    Feat: Add documentation to generated props

    Is it possible to document the properties in the generated .tailor file?

    For example

    @tailor
    class _$BoxTheme {
      /// Some documentation foo bar
      static List<Color> backgroundColor = [
        Colors.red,
        Colors.blue,
      ];
    }
    

    should lead to

    class BoxTheme extends ThemeExtension<BoxTheme> {
      const BoxTheme({
        required this.backgroundColor,
      });
    
      /// Some documentation foo bar
      final Color backgroundColor;
    
      /// ...
    }
    
    opened by jtdLab 1
  • Analyzer version

    Analyzer version

    Hi,

    theme_tailor depends on analyzer >=3.0.0 <5.0.0

    More packages depends on analyzer >=5.1.0 <5.2.0.

    Could you please up version for analyzer?

    Thanks!

    opened by pro100andrey 1
  • Add type from ast if appears to be dynamic

    Add type from ast if appears to be dynamic

    After upgrading to newer versions of analyzer (e.g. 5.2) Color is recognized as a dynamic type. (We get it from the FieldElement.type).

    Changes:

    • This PR adds a workaround to get type name from AST node if returned type is dynamic.
    • Fix generation of debugFillProperties
    opened by Rongix 0
  • support latest analyser (5.1.0)

    support latest analyser (5.1.0)

    otherwize it generates the following:

    flutter packages pub run build_runner watch --delete-conflicting-outputs
    [INFO] Generating build script...
    [INFO] Generating build script completed, took 186ms
    
    [INFO] Setting up file watchers...
    [INFO] Setting up file watchers completed, took 4ms
    
    [INFO] Waiting for all file watchers to be ready...
    [INFO] Waiting for all file watchers to be ready completed, took 200ms
    
    [INFO] Initializing inputs
    [INFO] Reading cached asset graph...
    [WARNING] Throwing away cached asset graph because the language version of some package(s) changed. This would most commonly happen when updating dependencies or changing your min sdk constraint.
    [INFO] Cleaning up outputs from previous builds....
    [INFO] Cleaning up outputs from previous builds. completed, took 5ms
    
    [INFO] Terminating. No further builds will be scheduled
    
    [INFO] Builds finished. Safe to exit
    
    [INFO] Generating build script...
    [INFO] Generating build script completed, took 54ms
    
    [WARNING] Invalidated precompiled build script due to missing asset graph.
    [INFO] Precompiling build script......
    [WARNING] ../../../flutter/.pub-cache/hosted/pub.dartlang.org/theme_tailor-1.0.7/lib/src/util/extension/element_annotation_extension.dart:13:57: Error: The getter 'element' isn't defined for the class 'DartType'.
     - 'DartType' is from 'package:analyzer/dart/element/type.dart' ('../../../flutter/.pub-cache/hosted/pub.dartlang.org/analyzer-5.1.0/lib/dart/element/type.dart').
    Try correcting the name to the name of an existing getter, or defining a getter or field named 'element'.
            .isAssignableFrom(computeConstantValue()!.type!.element!);
                                                            ^^^^^^^
    ../../../flutter/.pub-cache/hosted/pub.dartlang.org/theme_tailor-1.0.7/lib/src/util/extension/field_declaration_extension.dart:4:50: Error: The getter 'name' isn't defined for the class 'Token'.
     - 'Token' is from 'package:_fe_analyzer_shared/src/scanner/token.dart' ('../../../flutter/.pub-cache/hosted/pub.dartlang.org/_fe_analyzer_shared-49.0.0/lib/src/scanner/token.dart').
    Try correcting the name to the name of an existing getter, or defining a getter or field named 'name'.
      String get name => fields.variables.first.name.name;
                                                     ^^^^
    ../../../flutter/.pub-cache/hosted/pub.dartlang.org/theme_tailor-1.0.7/lib/src/util/theme_encoder_helper.dart:13:51: Error: The getter 'element' isn't defined for the class 'DartType'.
     - 'DartType' is from 'package:analyzer/dart/element/type.dart' ('../../../flutter/.pub-cache/hosted/pub.dartlang.org/analyzer-5.1.0/lib/dart/element/type.dart').
    Try correcting the name to the name of an existing getter, or defining a getter or field named 'element'.
      final encoderClassElement = constantValue.type!.element as ClassElement;
                                                      ^^^^^^^
    ../../../flutter/.pub-cache/hosted/pub.dartlang.org/theme_tailor-1.0.7/lib/src/util/theme_encoder_helper.dart:29:41: Error: The getter 'enclosingElement' isn't defined for the class 'PropertyAccessorElement'.
     - 'PropertyAccessorElement' is from 'package:analyzer/dart/element/element.dart' ('../../../flutter/.pub-cache/hosted/pub.dartlang.org/analyzer-5.1.0/lib/dart/element/element.dart').
    Try correcting the name to the name of an existing getter, or defining a getter or field named 'enclosingElement'.
        final enclosing = annotationElement.enclosingElement;
                                            ^^^^^^^^^^^^^^^^
    ../../../flutter/.pub-cache/hosted/pub.dartlang.org/theme_tailor-1.0.7/lib/src/util/theme_encoder_helper.dart:55:25: Error: The getter 'element' isn't defined for the class 'DartType'.
     - 'DartType' is from 'package:analyzer/dart/element/type.dart' ('../../../flutter/.pub-cache/hosted/pub.dartlang.org/analyzer-5.1.0/lib/dart/element/type.dart').
    Try correcting the name to the name of an existing getter, or defining a getter or field named 'element'.
        constantValue.type!.element!.name!,
                            ^^^^^^^
    ../../../flutter/.pub-cache/hosted/pub.dartlang.org/theme_tailor-1.0.7/lib/src/util/import_finder.dart:31:30: Error: The getter 'imports' isn't defined for the class 'LibraryElement'.
     - 'LibraryElement' is from 'package:analyzer/dart/element/element.dart' ('../../../flutter/.pub-cache/hosted/pub.dartlang.org/analyzer-5.1.0/lib/dart/element/element.dart').
    Try correcting the name to the name of an existing getter, or defining a getter or field named 'imports'.
        for (final import in lib.imports) {
                                 ^^^^^^^
    ../../../flutter/.pub-cache/hosted/pub.dartlang.org/theme_tailor-1.0.7/lib/src/util/import_finder.dart:103:30: Error: The getter 'exports' isn't defined for the class 'LibraryElement'.
     - 'LibraryElement' is from 'package:analyzer/dart/element/element.dart' ('../../../flutter/.pub-cache/hosted/pub.dartlang.org/analyzer-5.1.0/lib/dart/element/element.dart').
    Try correcting the name to the name of an existing getter, or defining a getter or field named 'exports'.
        for (final export in lib.exports) {
                                 ^^^^^^^
    [INFO] Precompiling build script... completed, took 538ms
    
    [SEVERE] Failed to precompile build script .dart_tool/build/entrypoint/build.dart.
    This is likely caused by a misconfigured builder definition.
    
    opened by cgestes 0
  • #35 Fix default theme names

    #35 Fix default theme names

    Fixes https://github.com/Iteo/theme_tailor/issues/35 No build.yaml config caused the generator to crash. In the example folder build.config is used and it obscured the problem (Additional package without build.config can be created later)

    Additional changes:

    • Cleanup example folder (Wrong annotations that caused to generate dynamic theme instead)
    opened by Rongix 0
  • Fields are dynamic in generated code.

    Fields are dynamic in generated code.

    In code, in theme_tailor->pubspec.yaml, its saying that analyzer: ">=4.6.0 <6.0.0" is supported, but when you use anaylzer version 5.3.1, then Color becomes dynamic.

    opened by aarajput 1
  • Nullable params are required in generated ThemeExtension constructor

    Nullable params are required in generated ThemeExtension constructor

    Given

    @tailor
    class _$BoxStyle {
      static List<Color?> background = [
        TOfflineColors.lightGrey,
        TOfflineColorsDark.lightBlack,
      ];
    }
    

    leads to

    class BoxStyle extends ThemeExtension<BoxStyle> {
      const BoxStyle({
        required this.background, // this is required but nullable
      });
    
      final Color? background;
    
      // ...
    }
    

    Is it possible to make background not beeing required?

    opened by jtdLab 0
  • Copy documentation comments to generated class

    Copy documentation comments to generated class

    I'm not sure if this would be possible, but it would be cool if documentation comments added to the properties in the class annotated with @tailor were copied to the generated class. For example:

    @tailor
    class _$MyTheme{
      /// A documentation comment.
      static List<Color> customColor = [Colors.red, Colors.blue];
    }
    

    generates:

    class MyTheme extends ThemeExtension<Colors> {
      ...
      /// A documentation comnent.
      final Color customColor;
      ...
    }
    
    enhancement 
    opened by Hannnes1 0
  • Rework Arrays to Theme classes

    Rework Arrays to Theme classes

    Could be nice to rework Arrays to Theme classes. Currently it is not obvious to find certain color for the certain theme to change for example.

    
    @tailor
    class _$MyTheme {
      static List<Color> background = [darkColor, lightColor, orangeColor, greenColor, ...];
      static List<Color> iconColor = [darkColor, lightColor, orangeColor, greenColor, ...];
      static List<TextStyle> h1 = [darkStyle, lightStyle, orangeStyle, greenStyle, ...];
      static List<TextStyle> h2 = [darkStyle, lightStyle, orangeStyle, greenStyle, ...];
    }
    
    

    into

    
    @tailor
    class _$MyThemeOrangeColors {
      static Color background = orangeColor;
      static Color iconColor = orangeColor;
    }
    
    @tailor
    class _$MyThemeOrangeTextStyles {
      static TextStyle h1 = orangeStyle;
      static TextStyle h2 = orangeStyle;
    }
    

    and etc

    documentation enhancement question 
    opened by zs-dima 5
A generator for fhir dart classes with json artifacts.

A generator for fhir dart classes with json artifacts. Thie generator uses the freezed package to generate the data classes. It also uses all the primitive_types from the fhir package.

Joel Staubach 2 Jun 14, 2022
Flutter App Change Theme With Getx and Save Theme Stage with Hive

Flutter Change app Theme With GetX Flutter App Change Theme With Getx. Theme Stage saved using Hive. instead of hive you can use get-storage or shared

Azraf Al Monzim 12 Oct 22, 2022
A flutter plugin about qr code or bar code scan , it can scan from file、url、memory and camera qr code or bar code .Welcome to feedback your issue.

r_scan A flutter plugin about qr code or bar code scan , it can scan from file、url、memory and camera qr code or bar code .Welcome to feedback your iss

PengHui Li 112 Nov 11, 2022
Enum extendable - Dart code generator. Generates enum extensions code.

Generates code for the extension on an enum. Overview Being able to add fields and methods to an enum. Let's say we have the following enum: enum Math

null 0 Jan 10, 2022
Startup-Name-Generator-App-in-Flutter - Business Startup Name Generator App in Flutter

Business Startup Name Generator App #About APP: A simple mobile app that generat

AHSAN SIDDZ 0 Jan 30, 2022
Create dart data classes easily, fast and without writing boilerplate or running code generation.

Dart Data Class Generator Create dart data classes easily, fast and without writing boilerplate or running code generation. Features The generator can

null 186 Feb 28, 2022
Simple Dart package with build-in code generation. It simplifies and speedup creation of cache mechanism for dart classes.

Simple Dart package with build-in code generation. It simplifies and speedup creation of cache mechanism for dart classes.

iteo 37 Jan 2, 2023
Flutter code extension that provides MediaQuery sizing info directly on the BuildContext instance

Flutter code extension that provides MediaQuery sizing info directly on the BuildContext instance. Also adds some helper methods for sizing and layout.

gskinner team 87 Dec 6, 2022
A convenient code generator for app styleguide, gallery, wireframes and/or storyboard.

Framy A convenient code generator for app styleguide, gallery, wireframes and/or storyboard. ?? Official documentation ?? Packages In order to use Fra

Fidev 145 Dec 19, 2022
Dart code generator for helping with (firebase) analytics.

analytics_events_gen An easy generator for tracking firebase analytics events via type safe methods. Add to pubspec.yaml Check pub for the latest vers

Herbert Poul 2 Nov 16, 2022
The Swift code generator for your assets, storyboards, Localizable.strings, … — Get rid of all String-based APIs!

SwiftGen SwiftGen is a tool to automatically generate Swift code for resources of your projects (like images, localised strings, etc), to make them ty

null 8.3k Dec 31, 2022
bq Scanner : An QR Code and Barcode Scanner and Generator.

bq Scanner A Barcode Scanner. A QR Code Scanner. A Barcode Generator. A QR Code Generator. Visit bq Scanner at https://ritikpatle.github.io/bqscanner/

Ritik Patle 4 Jun 5, 2022
Adobe XD Flutter Code Generator - Plugin

Adobe XD Flutter Code Generator - Plugin

Giovani Lobato 337 Dec 28, 2022
Flutter shareable package of object-oriented classes for local caching of user data in json

json_cache Json Cache is an object-oriented package to serve as a layer on top of local storage packages - packages that persist data locally on the u

Dartoos 10 Dec 19, 2022
Immutable value types, enum classes, and serialization.

Built Values for Dart Introduction Built Value provides: Immutable value types; EnumClass, classes that behave like enums; JSON serialization. Immutab

Google 816 Dec 23, 2022
Awesome Flutter Snippets is a collection snippets and shortcuts for commonly used Flutter functions and classes

Awesome Flutter Snippets Awesome Flutter Snippets is a collection of commonly used Flutter classes and methods. It increases your speed of development

Neevash Ramdial (Nash) 139 Dec 9, 2022
DoItEverywhere fitnessApp - DIE - A project created in flutter for the needs of classes

DIE - DoItEverywhere DIE is a project created in flutter for the needs of classe

Grzegorz Kucharski 0 Jan 31, 2022
Zooper flutter encoding utf16 - Helper classes to encode and decode UTF16 string to List

zooper_flutter_encoding_utf16 Helper classes to encode and decode UTF16 string t

Zooper 0 Feb 10, 2022
Flutter UI Travel app for completing tasks in mobile development classes 📱

cti3i3-app-travel-ui Flutter UI Travel app for completing tasks in mobile development classes. Setup Run the following commands to install the depende

Sultan Kautsar 1 May 14, 2022