From 0329896d49ff20c4868b385b356b711b0de72117 Mon Sep 17 00:00:00 2001 From: Ivan <42812006+ivan-015@users.noreply.github.com> Date: Tue, 9 Aug 2022 22:30:04 -0600 Subject: [PATCH 1/4] Generate ColorSchemes and integrate into ThemeData --- .../global_styling_aggregator.dart | 35 ++++--- .../global_styling/theming_post_gen_task.dart | 97 ++++++++++++++----- 2 files changed, 92 insertions(+), 40 deletions(-) diff --git a/lib/generation/flutter_project_builder/post_gen_tasks/global_styling/global_styling_aggregator.dart b/lib/generation/flutter_project_builder/post_gen_tasks/global_styling/global_styling_aggregator.dart index ae118976..7b425f0a 100644 --- a/lib/generation/flutter_project_builder/post_gen_tasks/global_styling/global_styling_aggregator.dart +++ b/lib/generation/flutter_project_builder/post_gen_tasks/global_styling/global_styling_aggregator.dart @@ -42,39 +42,44 @@ class GlobalStylingAggregator { /// Examines [globalStyles] and adds PostGenTasks to [builder] static void addPostGenTasks( FlutterProjectBuilder builder, PBDLGlobalStyles globalStyles) { - if (globalStyles.colors != null && globalStyles.colors.isNotEmpty) { + /// Check whether there are theme or global colors + if ((globalStyles.colors != null && globalStyles.colors.isNotEmpty) || + (globalStyles.themeColors != null && + globalStyles.themeColors.isNotEmpty)) { + /// Aggregate all colors + final globalColors = globalStyles.colors + ..addAll(globalStyles.themeColors); builder.postGenTasks.add( ColorsPostGenTask( builder.generationConfiguration, - globalStyles.colors, + globalColors, ), ); } - if (globalStyles.textStyles != null && globalStyles.textStyles.isNotEmpty) { + /// Check whether there are theme or global textstyles + if ((globalStyles.textStyles != null && + globalStyles.textStyles.isNotEmpty) || + (globalStyles.themeTextStyles != null && + globalStyles.themeTextStyles.isNotEmpty)) { + final globalTextStyles = globalStyles.textStyles + ..addAll(globalStyles.themeTextStyles); builder.postGenTasks.add( TextStylesPostGenTask( builder.generationConfiguration, - globalStyles.textStyles, + globalTextStyles, ), ); } - var themeTextStyles = []; - - for (var style in globalStyles.textStyles) { - if (_textStyleList.contains(style.name.camelCase)) { - /// Add Text Style to Global theming list - themeTextStyles.add(style); - } - } - - if (themeTextStyles.isNotEmpty) { + if (globalStyles.themeTextStyles.isNotEmpty || + globalStyles.themeColors.isNotEmpty) { /// Add Theme Styles to the Theme task builder.postGenTasks.add( ThemingPostGenTask( builder.generationConfiguration, - themeTextStyles, + globalStyles.themeTextStyles ?? [], + globalStyles.themeColors ?? [], ), ); } diff --git a/lib/generation/flutter_project_builder/post_gen_tasks/global_styling/theming_post_gen_task.dart b/lib/generation/flutter_project_builder/post_gen_tasks/global_styling/theming_post_gen_task.dart index dc60cdcd..6c070d15 100644 --- a/lib/generation/flutter_project_builder/post_gen_tasks/global_styling/theming_post_gen_task.dart +++ b/lib/generation/flutter_project_builder/post_gen_tasks/global_styling/theming_post_gen_task.dart @@ -18,47 +18,94 @@ class ThemingPostGenTask extends PostGenTask { ThemingPostGenTask( this.generationConfiguration, this.textStyles, + this.colors, ); @override void execute() { - final projectName = MainInfo().projectName; + var pathService = GetIt.I.get(); - /// Map the [TextStyle] attributes in the project for [TextTheme] - final textThemeAttributes = textStyles - .map((style) => - '${style.name.camelCase}: ${projectName.pascalCase}TextStyles.${style.name.camelCase},') - .join(); - final textThemeBoilerplate = 'TextTheme($textThemeAttributes)'; + /// Relative path to theming folder for imports + final themingRelativePath = + pathService.themingRelativePath.replaceFirst('lib/', ''); - final textConstant = ConstantHolder( - 'TextTheme', - 'textTheme', - textThemeBoilerplate, - ); + final projectName = MainInfo().projectName; - final themeConstant = ConstantHolder( - 'ThemeData', - 'themeData', - 'ThemeData(textTheme: textTheme,)', - isconst: false, + final constants = []; + final importBuffer = StringBuffer( + 'import \'package:flutter/material.dart\';', ); - var pathService = GetIt.I.get(); + if (textStyles.isNotEmpty) { + importBuffer.writeln( + 'import \'package:${projectName.snakeCase}/$themingRelativePath/${projectName.snakeCase}_text_styles.g.dart\';', + ); + + /// Map the [TextStyle] attributes in the project for [TextTheme] + final textThemeAttributes = textStyles + .map((style) => + '${style.name.camelCase}: ${projectName.pascalCase}TextStyles.${style.name.camelCase},') + .join(); + final textThemeBoilerplate = 'TextTheme($textThemeAttributes)'; + + constants.add(ConstantHolder( + 'TextTheme', + 'textTheme', + textThemeBoilerplate, + )); + + /// Only create a [ThemeData] here if there are no [ColorSchemes]. + /// + /// This is because a [ThemeData] will already be generated for each [ColorSchem] + if (colors.isEmpty) { + constants.add(ConstantHolder( + 'ThemeData', + 'themeData', + 'ThemeData(textTheme: textTheme,)', + isconst: false, + )); + } + } + + if (colors.isNotEmpty) { + importBuffer.writeln( + 'import \'package:${projectName.snakeCase}/$themingRelativePath/${projectName.snakeCase}_colors.g.dart\';', + ); + + /// Map the [ColorSchemes] by name + final colorSchemeMap = >{}; + for (final color in colors) { + final attributeName = color.name.split('/').last; + final colorAttribute = + '$attributeName: ${projectName.pascalCase}Colors.${color.name.camelCase}'; + if (colorSchemeMap.containsKey(color.colorScheme)) { + colorSchemeMap[color.colorScheme].add(colorAttribute); + } else { + colorSchemeMap[color.colorScheme] = [colorAttribute]; + } + } - /// Imports for material and the [TextStyles]. - var imports = ''' -import 'package:flutter/material.dart'; -import 'package:${projectName.snakeCase}/${pathService.themingRelativePath.replaceFirst('lib/', '')}/${projectName.snakeCase}_text_styles.g.dart'; -'''; + /// Create the constants for [ThemeData] and [ColorSchemes] + for (final entry in colorSchemeMap.entries) { + final attributes = entry.value.join(','); + constants.add(ConstantHolder( + 'ColorScheme', entry.key, 'ColorScheme.${entry.key}($attributes)')); + constants.add(ConstantHolder( + 'ThemeData', + 'themeData${entry.key.pascalCase}', + 'ThemeData(${textStyles.isNotEmpty ? 'textTheme: textTheme,' : ''} colorScheme: ${entry.key},)', + isconst: false, + )); + } + } generationConfiguration.fileStructureStrategy.commandCreated( WriteConstantsCommand( Uuid().v4(), - [themeConstant, textConstant], + constants, filename: '${projectName.snakeCase}_theme', ownershipPolicy: FileOwnership.PBC, - imports: imports, + imports: importBuffer.toString(), relativePath: pathService.themingRelativePath, ), ); From 43ff674a3decde005ffc4327fca147950a5e9164 Mon Sep 17 00:00:00 2001 From: Ivan <42812006+ivan-015@users.noreply.github.com> Date: Thu, 11 Aug 2022 16:37:48 -0600 Subject: [PATCH 2/4] Update to version `3.3.0` * Add ColorScheme generation and integration to `ThemeData` --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 9bec921d..b1ab2247 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: parabeac_core description: Continuous Design / Continuous Integration for Figma-to-Flutter -version: 3.2.0 +version: 3.3.0 # homepage: https://www.example.com environment: From ae6f2b215cc00519de8fa99cc3c379d22c7f20c7 Mon Sep 17 00:00:00 2001 From: Ivan <42812006+ivan-015@users.noreply.github.com> Date: Thu, 11 Aug 2022 16:30:01 -0600 Subject: [PATCH 3/4] Update README.md * Add levels of integration to README * Add configurations.json information to README (cherry picked from commit 0a6cc4d60984a050429d38f9694cb6bdda57c29d) --- README.md | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 53046b5c..977df6d8 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,35 @@ Sets the name of the exported project. For instance, if you want to name your pr #### Absolute Path (Optional): -o Specifies the absolute path of the exported Flutter Project to be created. For instance, to export your Flutter project in the Documents folder, set your `-o` flag to `/Users/ParabeacUser/Documents/` Not setting this will export the project in the parabeac_core directory. + +#### Level of Export (Optional): --level + + +Specifies the level of export. At the time of writing, there are three levels: **theming**, **component**, and **screen**. +- **Theming** - will export global styles, such as text styles and global colors to a file in `lib/theme`. +- **Component** - will export theming as well as individual reusable UI components to `lib/widgets`. +- **Screen** [**default**] - will export all of the above and a full UI screen to `lib/views`. +The first two levels, theming and component, export packages that one can import to an existing Flutter project. The third level, screen, exports both of those levels as well as the main screen--essentially, a full running app. + + +### Configurations.json +To avoid repetitively entering the same flags in the command line, you can edit the configurations.json file. Just populate the corresponding fields with the information you would normally enter with the commands listed above. + +The default configurations.json file is pictured below. It can be found in `lib/configurations` + + ![image](https://user-images.githubusercontent.com/42812006/184252654-5fc55f48-502b-4eca-8bc5-029832a23d39.png) + +For example, take the following CLI command: + + +``` +dart parabeac.dart -f AaGNw26baKo91CT0I4B2lJ -k figd_60xGD-VXvoA-ABRdk7VPGq2Zrk_vYj2oSzUPqi6D -o /Users/ivanvigliante/Documents/parabeac/core/debug +``` + +This is the equivalent of the command above in the `configurations.json` file: + + ![image](https://user-images.githubusercontent.com/42812006/184252687-e4cd2e75-a116-4d33-a8a6-b40cac096f52.png) + ### Sketch @@ -161,9 +190,6 @@ Follow or subscribe to our [Twitter](https://twitter.com/parabeac), [Youtube](ht * parabeac_core has support for global theming for **TextStyles** and **Colors**. If detected, parabeac_core will export two files containing the styles ready for internal and external use. * For more information on how to set up Global Styles in your design file, read the following [Global Styling Docs](https://docs.parabeac.com/docs/learn-the-parabeac-way/global-styling). -### Current limitations -* At the moment, we only generate global styling nodes that are actually being used inside a frame of the Figma project. This is because of Figma's API limitations. We are currently working on a way to completely decouple this so that we are able to get the styling information without depending on them being used inside the Figma project. - ### TextStyles * If parabeac_core detects global TextStyles in the design file, it will export a file under `lib/theme/_text_styles.g.dart`. This file will contain all global TextStyles of the design file in the following format: From 76de6c9117509ca0c2937bbd0f707f35da3aa78d Mon Sep 17 00:00:00 2001 From: Ivan <42812006+ivan-015@users.noreply.github.com> Date: Thu, 11 Aug 2022 16:40:37 -0600 Subject: [PATCH 4/4] Update README.md Co-authored-by: Xavier <43008089+xm94@users.noreply.github.com> (cherry picked from commit fa73410be3af7e22507647d5b48428b3d8bd0e28) --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 977df6d8..2675d28c 100644 --- a/README.md +++ b/README.md @@ -97,6 +97,7 @@ Specifies the level of export. At the time of writing, there are three levels: * - **Theming** - will export global styles, such as text styles and global colors to a file in `lib/theme`. - **Component** - will export theming as well as individual reusable UI components to `lib/widgets`. - **Screen** [**default**] - will export all of the above and a full UI screen to `lib/views`. + The first two levels, theming and component, export packages that one can import to an existing Flutter project. The third level, screen, exports both of those levels as well as the main screen--essentially, a full running app.