├── .DS_Store ├── .github └── FUNDING.yml ├── .gitignore ├── .npmignore ├── README.md ├── img └── flutterlogo.png ├── package-lock.json ├── package.json └── src └── index.js /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robertodevs/zeplin-flutter-extended/d353818f53d2395c8d94f079e501b8f085cd2a6d/.DS_Store -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | custom: 'https://www.buymeacoffee.com/SaNhE76x9' 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .vscode 3 | node_modules 4 | .DS_Store 5 | Thumbs.db 6 | npm-debug.log* 7 | /dist 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | Flutter Logo 3 |

4 | 5 |

6 | Buy Me A Coffee 7 |

8 | 9 | # Flutter Extended Zeplin Extension 💻 10 | 11 | This is a new Flutter Extended version of the actual extension to help a lot of people who need more components than TextStyles and Colors and RichTexts. With this new one you have the opportunity to have more info about Widgets, for example, generate Container elements, BoxDecoration Widget with Shadows, Linear Gradients, Fills, Borders, Opacity and several components more. Coming soon RadialGradient and SweapGradient and also Components as buttons and others. 12 | 13 | ## Getting started 14 | 15 | Add the extension to your project from [extensions.zeplin.io](https://extensions.zeplin.io), then test the extension and give me your comments about possible improvements. I will try giving frequently support to this extension. 16 | 17 | ## Output 18 | 19 | #### Sample colors output 20 | ``` 21 | const Color black = const Color(0xff000000); 22 | const Color white = const Color(0xffffffff); 23 | const Color cloudyBlue = const Color(0xffbec4cd); 24 | const Color black = const Color(0xff333333); 25 | const Color blushPink = const Color(0xffff8993); 26 | 27 | ``` 28 | 29 | #### Sample text style output: 30 | ``` 31 | const TextStyle title = const TextStyle( 32 | fontFamily: 'Montserrat', 33 | color: Color(0xff000000), 34 | fontSize: 14, 35 | fontWeight: FontWeight.w500, 36 | fontStyle: FontStyle.normal, 37 | ); 38 | const TextStyle PingFangSC—14pt = const TextStyle( 39 | fontFamily: 'PingFangSC', 40 | color: Color(0xff000000), 41 | fontSize: 14, 42 | fontWeight: FontWeight.w400, 43 | fontStyle: FontStyle.normal, 44 | ); 45 | 46 | ``` 47 | #### Sample layer output - `(Text with Shadows)` 48 | 49 | ``` 50 | new Text("Color", 51 | style: TextStyle( 52 | fontFamily: 'Montserrat', 53 | color: Color(0xfffefefe), 54 | fontSize: 10, 55 | fontWeight: FontWeight.w500, 56 | fontStyle: FontStyle.normal, 57 | 58 | shadows: [BoxShadow( 59 | color: Color(0x29646464), 60 | offset: Offset(0,3), 61 | blurRadius: 6, 62 | spreadRadius: 0 63 | 64 | )], 65 | ) 66 | ) 67 | ``` 68 | 69 | #### Sample layer output - `(Text with multiple Styles)` 70 | 71 | ``` 72 | RichText( 73 | text: new TextSpan( 74 | children: [ 75 | new TextSpan( 76 | text: "EN | ", 77 | style: TextStyle( 78 | fontFamily: 'Segoe UI', 79 | color: Color(0xfff4b326), 80 | fontSize: 12, 81 | fontWeight: FontWeight.w400, 82 | fontStyle: FontStyle.normal, 83 | ) 84 | ), 85 | new TextSpan( 86 | text: "CH", 87 | style: TextStyle( 88 | fontFamily: 'Segoe UI', 89 | color: Color(0xff444242), 90 | fontSize: 12, 91 | fontWeight: FontWeight.w400, 92 | fontStyle: FontStyle.normal, 93 | ) 94 | ), 95 | ] 96 | ) 97 | ) 98 | ``` 99 | 100 | #### Sample layer output - `(Container with Borders and Shadows)` 101 | 102 | ``` 103 | new Container( 104 | width: 128, 105 | height: 172, 106 | decoration: new BoxDecoration( 107 | color: Color(0xff1b1b1b), 108 | border: Border.all( 109 | color: Color(0xfff19528), 110 | width: 1 111 | ), 112 | boxShadow: [BoxShadow( 113 | color: Color(0x29000000), 114 | offset: Offset(0,3), 115 | blurRadius: 6, 116 | spreadRadius: 0 117 | 118 | ) ], 119 | 120 | ) 121 | ) 122 | ``` 123 | 124 | #### Sample layer output - `Container with Circular Borders` 125 | ``` 126 | new Container( 127 | width: 103, 128 | height: 36, 129 | decoration: new BoxDecoration( 130 | color: Color(0xffd7d6d6), 131 | borderRadius: BorderRadius.circular(25), 132 | boxShadow: [ 133 | BoxShadow( 134 | color: Color(0x29000000), 135 | offset: Offset(0,3), 136 | blurRadius: 6, 137 | spreadRadius: 0 138 | 139 | ) ], 140 | 141 | ) 142 | ) 143 | ``` 144 | 145 | #### Sample layer output - `Container with Fill with Opacity` 146 | ``` 147 | new Container( 148 | width: 169, 149 | height: 269, 150 | decoration: new BoxDecoration( 151 | color: Color(0xfffbd085).withOpacity(0.46) 152 | ) 153 | ) 154 | ``` 155 | 156 | #### Sample layer output - `Container with LinearGradient` 157 | 158 | ``` 159 | new Container( 160 | width: 30.492919921875, 161 | height: 30.4931640625, 162 | decoration: new BoxDecoration( 163 | gradient: LinearGradient( 164 | colors: [ 165 | Color(0xfff8362d), 166 | Color(0xff801c18), 167 | Color(0xff7c1b17) ], 168 | stops: [ 169 | 0, 170 | 0.7395932078361511, 171 | 1 172 | ] 173 | ) 174 | ) 175 | ) 176 | ``` 177 | 178 | ## Options 179 | 180 | There are several features to modify in the future, first of them will be add more options to Gradients, Radial and Sweap Gradients. If this is extension is useful for you and you want to support me [buy me a coffe!](https://www.buymeacoffee.com/SaNhE76x9) 181 | 182 | 183 | ## Developmentß 184 | 185 | This extension is developed using [zem](https://github.com/zeplin/zem), Zeplin Extension Manager. zem is a command line tool that lets you quickly create, test and publish extensions. 186 | 187 | To learn more about creating Zeplin extensions, [see documentation](https://github.com/zeplin/zeplin-extension-documentation). 188 | ß 189 | -------------------------------------------------------------------------------- /img/flutterlogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robertodevs/zeplin-flutter-extended/d353818f53d2395c8d94f079e501b8f085cd2a6d/img/flutterlogo.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "zeplin-flutter-extended", 3 | "version": "0.1.3", 4 | "description": "Flutter Extended version extension to generate smart code snippets like Containers, RichTexts, BoxDecoration with their properties: Shadows, Borders, Gradients, etc.", 5 | "scripts": { 6 | "start": "zem start", 7 | "build": "zem build", 8 | "clean": "zem clean", 9 | "exec": "zem exec", 10 | "publish": "zem publish" 11 | }, 12 | "author": { 13 | "name": "Roberto Juarez", 14 | "email": "juarez.roberto77@gmail.com", 15 | "url": "https://lnk.bio/9dQ4" 16 | }, 17 | "repository": { 18 | "type": "git", 19 | "url": "https://github.com/robertodevs/zeplin-flutter-extended" 20 | }, 21 | "zeplin": { 22 | "displayName": "Flutter Extended", 23 | "platforms": [ 24 | "web", 25 | "android", 26 | "ios" 27 | ] 28 | }, 29 | "dependencies": { 30 | "zem": "^0.4.4" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | function layer(context, selectedLayer) { 2 | switch(selectedLayer.type) { 3 | case 'text': 4 | // Getting text information for one specific TextStyle 5 | var body = getTextElement(context, selectedLayer); 6 | 7 | return { 8 | code: `${body}`, 9 | language: "dart" 10 | }; 11 | break; 12 | case 'shape': 13 | // Getting shape information 14 | var container = getContainer(context, selectedLayer); 15 | 16 | return { 17 | code: convertContainerToDart(container, context), 18 | language: 'dart' 19 | } 20 | break; 21 | 22 | case 'group': 23 | // Missing to implement, it will in future versions 24 | return { 25 | code: `group`, 26 | language: 'dart' 27 | } 28 | break; 29 | 30 | default: 31 | 32 | 33 | } 34 | } 35 | 36 | function colors(context) { 37 | // Mapping colors from context.project 38 | var body = convertColorsListToDart(context).join("\n"); 39 | return { 40 | code: body, 41 | language: "dart" 42 | } 43 | 44 | } 45 | 46 | function textStyles(context) { 47 | // Mapping textStyles from context.project 48 | return { 49 | code: convertTextStylesListToDart(context).join("\n"), 50 | language: "dart" 51 | } 52 | } 53 | 54 | function exportColors(context) { 55 | // Exporting color to DART file 56 | var dartCode = `import 'package:flutter/material.dart';\n 57 | ${convertColorsListToDart(context).join("\n")}`; 58 | 59 | return{ 60 | code: dartCode, 61 | filename: `${context.project.name}Colors.dart`, 62 | language: "dart" 63 | } 64 | 65 | } 66 | 67 | function exportTextStyles(context) { 68 | // Exporting textStyle to DART file 69 | var dartCode = `import 'package:flutter/material.dart';\n 70 | ${convertTextStylesListToDart(context).join("\n")}`; 71 | 72 | return{ 73 | code: dartCode, 74 | filename: `${context.project.name}TextStyles.dart`, 75 | language: "dart" 76 | } 77 | } 78 | 79 | function screen(context, selectedVersion, selectedScreen) { 80 | return{ 81 | code: 'Cooming soon', 82 | filename: `${context.project.name}TextStyles.dart`, 83 | language: "dart" 84 | } 85 | } 86 | 87 | function component(context, selectedVersion, selectedComponent) { 88 | return{ 89 | code: 'Cooming soon...', 90 | filename: `${context.project.name}TextStyles.dart`, 91 | language: "dart" 92 | } 93 | } 94 | 95 | 96 | 97 | // /** 98 | // * The following functions will be deprecated. Your extensions can export them to support old versions of Zeplin's macOS app. 99 | // * See Zeplin Extensions migration guide for details: 100 | // * https://zpl.io/shared-styleguides-extensions-migration-guide 101 | // */ 102 | 103 | // function styleguideColors(context, colors) { 104 | 105 | // } 106 | 107 | // function styleguideTextStyles(context, textStyles) { 108 | 109 | // } 110 | 111 | // function exportStyleguideColors(context, colors) { 112 | 113 | // } 114 | 115 | // function exportStyleguideTextStyles(context, textStyles) { 116 | 117 | // } 118 | 119 | // function comment(context, text) { 120 | 121 | // } 122 | 123 | 124 | /* 125 | The functions below are used for generate Flutter Widgets, 126 | Container, BoxDecoration, Shadows, etc. 127 | */ 128 | 129 | /** 130 | * 131 | * @param {*} context 132 | * @param {*} layer 133 | */ 134 | function buildingBoxDecoration(context, layer){ 135 | // Getting a new decoration Box 136 | var decoration = new BoxDecoration(); 137 | 138 | // Evaluating if the selected layer has Fills 139 | 140 | if (layer.fills.length>0) 141 | { 142 | // Getting gradient 143 | decoration.gradient = getGradient(context, layer); 144 | 145 | // Without gradient 146 | if (decoration.gradient == null){ 147 | // Without Gradient 148 | decoration.color = new Color( 149 | layer.fills[layer.fills.length -1].color.toHex().r, 150 | layer.fills[layer.fills.length -1].color.toHex().g, 151 | layer.fills[layer.fills.length -1].color.toHex().b, 152 | layer.fills[layer.fills.length -1].color.toHex().a 153 | ); 154 | } 155 | } 156 | 157 | // Getting Border 158 | decoration.border = getBorder(context, layer); 159 | 160 | // Assigning borderRadius 161 | if (layer.borderRadius != 0) 162 | { 163 | decoration.borderRadius = layer.borderRadius; 164 | } 165 | 166 | // Getting Shadows 167 | decoration.shadows = getShadows(context, layer.shadows); 168 | 169 | 170 | // Adding Opacity to the Layer 171 | decoration.opacity = layer.opacity; 172 | return decoration; 173 | 174 | } 175 | 176 | /** 177 | * 178 | * @param {*} context 179 | * @param {*} layer 180 | */ 181 | function getTextElement(context, layer){ 182 | var body; 183 | if (layer.textStyles.length > 1){ 184 | // List of TextSpans 185 | var textSpans = []; 186 | layer.textStyles.map( 187 | textSpan => { 188 | textSpans.push( 189 | new Text( 190 | layer.content.substring(textSpan.range.start, textSpan.range.end), 191 | null, 192 | new TextStyle( 193 | textSpan.textStyle.fontFamily, 194 | new Color( 195 | textSpan.textStyle.color.toHex().r, 196 | textSpan.textStyle.color.toHex().g, 197 | textSpan.textStyle.color.toHex().b, 198 | textSpan.textStyle.color.toHex().a), 199 | textSpan.textStyle.fontSize, 200 | textSpan.textStyle.fontWeight, 201 | textSpan.textStyle.fontStyle, 202 | textSpan.textStyle.letterSpacing, 203 | textSpan.textStyle.lineHeight , 204 | getShadows(context, layer.shadows) 205 | ) 206 | ) 207 | ) 208 | } 209 | ); 210 | 211 | body = convertRichTextToDart(textSpans, layer.textStyles[0].textStyle.textAlign, context); 212 | 213 | } 214 | else if (layer.textStyles.length == 1) 215 | { 216 | body = convertTextToDart(new Text(layer.content, 217 | layer.textStyles[0].textStyle.textAlign, 218 | new TextStyle( 219 | layer.textStyles[0].textStyle.fontFamily, 220 | new Color( 221 | layer.textStyles[0].textStyle.color.toHex().r, 222 | layer.textStyles[0].textStyle.color.toHex().g, 223 | layer.textStyles[0].textStyle.color.toHex().b, 224 | layer.textStyles[0].textStyle.color.toHex().a), 225 | layer.textStyles[0].textStyle.fontSize, 226 | layer.textStyles[0].textStyle.fontWeight, 227 | layer.textStyles[0].textStyle.fontStyle, 228 | layer.textStyles[0].textStyle.letterSpacing, 229 | layer.textStyles[0].textStyle.lineHeight , 230 | getShadows(context, layer.shadows) 231 | ) 232 | ), context 233 | ) 234 | } 235 | 236 | return body; 237 | } 238 | 239 | /** 240 | * 241 | * @param {*} context has all elements from the entire project 242 | * @param {*} color to evaluate if exists on the project 243 | */ 244 | function getColorNameFromProject(context, color){ 245 | // The color must be the object from Zepli Model not DART 246 | colors = []; 247 | var colorName = ''; 248 | // It is important to evaluate before map the colors 249 | // if the context is not null 250 | if(context != null){ 251 | context.project.colors.map( 252 | colorMap => { 253 | // Evaluating if the color exists for the project 254 | var dartColor = new Color(colorMap.toHex().r, colorMap.toHex().g,colorMap.toHex().b, colorMap.toHex().a) 255 | // Both colors must be object dart colors model 256 | if (equalsColor(dartColor, color)){ 257 | // The name of the color will show instead of hex code 258 | colorName = colorMap.name; 259 | } 260 | } 261 | ); 262 | } 263 | return colorName; 264 | } 265 | 266 | /** 267 | * 268 | * @param {*} context 269 | * @param {*} layer 270 | */ 271 | function getContainer(context, layer){ 272 | var container = new Container(layer.rect.width, layer.rect.height); 273 | container.decoration = buildingBoxDecoration(context, layer); 274 | 275 | return container; 276 | 277 | } 278 | 279 | /** 280 | * 281 | * @param {*} context 282 | * @param {*} layer 283 | */ 284 | function getGradient(context, layer){ 285 | if(layerHasGradient(context, layer)) 286 | { 287 | // Building the Gradient 288 | return new Gradient( 289 | layer.fills[layer.fills.length -1].gradient.type, 290 | // List of Colors 291 | layer.fills[layer.fills.length -1].gradient.colorStops.map( 292 | colorMap => { 293 | return new Color(colorMap.color.toHex().r, colorMap.color.toHex().g,colorMap.color.toHex().b, colorMap.color.toHex().a); 294 | } 295 | ), 296 | // List of Stops 297 | layer.fills[layer.fills.length -1].gradient.colorStops.map( 298 | colorMap => { 299 | return colorMap.position; 300 | } 301 | ), 302 | layer.fills[layer.fills.length -1].gradient.angle, 303 | 304 | ); 305 | 306 | 307 | } 308 | return null; 309 | 310 | } 311 | /** 312 | * 313 | * @param {*} context 314 | * @param {*} layer 315 | */ 316 | function getBorder(context, layer){ 317 | 318 | // Adding Shadows to the Layer 319 | if(layer.borders.length > 0){ 320 | const lastBorder = layer.borders[layer.borders.length -1]; 321 | if (lastBorder.fill == "color") { 322 | return new Border( 323 | new Color( 324 | lastBorder.fill.color.toHex().r, 325 | lastBorder.fill.color.toHex().g, 326 | lastBorder.fill.color.toHex().b, 327 | lastBorder.fill.color.toHex().a 328 | ), 329 | lastBorder.thickness, 330 | ); 331 | } else { 332 | return null; 333 | } 334 | } 335 | 336 | else{ 337 | return null; 338 | } 339 | 340 | } 341 | 342 | /** 343 | * 344 | * @param {*} context 345 | * @param {*} shadows 346 | */ 347 | function getShadows(context, shadows){ 348 | // Adding Shadows to the Layer 349 | if(shadows.length > 0){ 350 | return shadows.map( shadow => { 351 | return new BoxShadow(new Color( 352 | shadow.color.toHex().r, shadow.color.toHex().g,shadow.color.toHex().b, shadow.color.toHex().a), 353 | shadow.offsetX, 354 | shadow.offsetY, 355 | shadow.blurRadius, 356 | shadow.spread 357 | ); 358 | } 359 | ); 360 | } 361 | 362 | else{ 363 | return null 364 | } 365 | 366 | } 367 | 368 | 369 | /* 370 | The functions below are used to generate Flutter Widgets Objects to DART CODE, 371 | */ 372 | 373 | /** 374 | * 375 | * @param {*} container 376 | */ 377 | function convertContainerToDart(container, context){ 378 | var decorationElements = []; 379 | 380 | if (container.decoration != null){ 381 | if (container.decoration.color != null) 382 | { 383 | decorationElements.push(`color: ${convertColorToDart(container.decoration.color, 1, false, context)}`); 384 | } 385 | if (container.decoration.border != null) 386 | { 387 | decorationElements.push(`border: ${convertBorderToDart(container.decoration.border, context)}`); 388 | } 389 | if (container.decoration.borderRadius != null) 390 | { 391 | decorationElements.push(`\t\tborderRadius: BorderRadius.circular(${container.decoration.borderRadius})`); 392 | } 393 | 394 | if (container.decoration.gradient != null){ 395 | decorationElements.push(`\t\tgradient: ${convertGradientToDart(container.decoration.gradient, context)}`); 396 | } 397 | 398 | if(container.decoration.shadows != null){ 399 | decorationElements.push(`\t\tboxShadow: ${convertShadowsToDart(container.decoration.shadows, context)}`); 400 | 401 | } 402 | } 403 | 404 | let containerCode = `new Container( 405 | width: ${container.width}, 406 | height: ${container.height}, 407 | decoration: new BoxDecoration( 408 | ${decorationElements.join(",\n")} 409 | ) 410 | )`; 411 | 412 | // opacity is applied to the whole container, this way it affects its gradient (or color), border and shadows 413 | if (container.decoration.opacity != null && container.decoration.opacity < 1.0) { 414 | // we wrap the Opacity in a stack for the purpose of enabling the developer putting a widget inside 415 | // that is not affected by the opacity (the empty Container() inside Positioned.fill) 416 | containerCode = `Stack( 417 | children: [ 418 | Opacity( 419 | opacity: ${container.decoration.opacity}, 420 | child: ${containerCode}, 421 | ), 422 | Positioned.fill( 423 | child: Container(), 424 | ), 425 | ], 426 | )`; 427 | } 428 | 429 | return containerCode; 430 | } 431 | 432 | /** 433 | * 434 | * @param {*} color 435 | * @param {*} opacity 436 | * @param {*} multipleColors 437 | * @param {*} context 438 | */ 439 | function convertColorToDart(color, opacity, multipleColors, context){ 440 | 441 | var space; 442 | if (multipleColors){ 443 | space = "\n "; 444 | } 445 | else{ 446 | space= ""; 447 | } 448 | if (opacity < 1){ 449 | return `${space}Color(0x${color.a}${color.r}${color.g}${color.b}).withOpacity(${opacity})`; 450 | } 451 | // Evaluating if the color exists 452 | // If '' is returned the color does not exist 453 | var colorName = getColorNameFromProject(context, color); 454 | // Assigning the new color name 455 | if(colorName != ''){ 456 | return `${space}${colorName}`; 457 | } 458 | return `${space}Color(0x${color.a}${color.r}${color.g}${color.b})`; 459 | 460 | } 461 | 462 | /** 463 | * 464 | * @param {*} textSelected 465 | */ 466 | function convertTextToDart(textSelected, context){ 467 | const textAlign = (textSelected.textAlign == null) ? "" : 468 | "\n textAlign: TextAlign." + textSelected.textAlign + ","; 469 | return `new Text(${JSON.stringify(textSelected.text)},${textAlign} 470 | style: ${convertTextStyleToDart(textSelected.textStyle, context)} 471 | )`; 472 | 473 | } 474 | /** 475 | * 476 | * @param {*} textSelected 477 | */ 478 | function convertTextSpanToDart(textSelected, context){ 479 | 480 | return `\n\tnew TextSpan( 481 | text: ${JSON.stringify(textSelected.text)}, 482 | style: ${convertTextStyleToDart(textSelected.textStyle, context)} 483 | )`; 484 | 485 | } 486 | /** 487 | * 488 | * @param {*} textStyle 489 | * @param {*} context 490 | */ 491 | function convertTextStyleToDart(textStyle, context){ 492 | var shadowElements; 493 | var letterSpacingElement; 494 | 495 | // Evaluating if shadow exists 496 | if (textStyle.shadows != null) 497 | { 498 | shadowElements = `shadows: ${convertShadowsToDart(textStyle.shadows)}`; 499 | } 500 | else{ 501 | shadowElements = ""; 502 | } 503 | 504 | // Evaluating if shadow exists 505 | if (textStyle.letterSpacing != null) 506 | { 507 | letterSpacingElement = `letterSpacing: ${textStyle.letterSpacing},`; 508 | } 509 | else{ 510 | letterSpacingElement = ""; 511 | } 512 | 513 | return `TextStyle( 514 | fontFamily: '${textStyle.fontFamily}', 515 | color: ${convertColorToDart(textStyle.color, 1, false, context)}, 516 | fontSize: ${textStyle.fontSize}, 517 | fontWeight: FontWeight.w${textStyle.fontWeight}, 518 | fontStyle: FontStyle.${textStyle.fontStyle}, 519 | ${letterSpacingElement} 520 | ${shadowElements} 521 | )`; 522 | 523 | } 524 | 525 | function angleToPoint(degrees) { 526 | return { 527 | x: Math.sin(degrees / 180.0 * Math.PI), 528 | y: -1.0 * Math.cos(degrees / 180.0 * Math.PI), 529 | }; 530 | } 531 | 532 | /** 533 | * 534 | * @param {*} gradient 535 | * @param {*} context 536 | */ 537 | function convertGradientToDart(gradient, context){ 538 | 539 | if (gradient.type === 'linear'){ 540 | const angle = gradient.angle || 90; 541 | const end = angleToPoint(angle); 542 | const begin = { 543 | x : -end.x, 544 | y : -end.y, 545 | }; 546 | 547 | return `LinearGradient( 548 | colors: [${gradient.colors.map( 549 | colorHex => { 550 | return convertColorToDart(colorHex,1, true, context) 551 | } 552 | )} ], 553 | stops: [ 554 | ${gradient.stops.join(",\n\t\t\t\t")} 555 | ], 556 | begin: Alignment(${begin.x.toFixed(2)}, ${begin.y.toFixed(2)}), 557 | end: Alignment(${end.x.toFixed(2)}, ${end.y.toFixed(2)}), 558 | // angle: ${gradient.angle}, 559 | // scale: ${gradient.scale}, 560 | )`; 561 | } 562 | 563 | else if (gradient.type === 'radial'){ 564 | return `RadialGradient(colors: [${gradient.colors.map( 565 | colorHex => { 566 | return convertColorToDart(colorHex,1, true, context) 567 | } 568 | )} ], 569 | stops: [ 570 | ${gradient.stops.join(",\n\t\t\t\t")} 571 | ] 572 | )`; 573 | } 574 | 575 | return ``; 576 | 577 | } 578 | 579 | /** 580 | * 581 | * @param {*} shadows 582 | * @param {*} context 583 | */ 584 | function convertShadowsToDart(shadows, context){ 585 | 586 | return `[${shadows.map( 587 | shadow => { 588 | return convertBoxShadowToDart(shadow, context) 589 | } 590 | )} ], 591 | `; 592 | } 593 | 594 | /** 595 | * 596 | * @param {*} shadow 597 | * @param {*} context 598 | */ 599 | function convertBoxShadowToDart(shadow, context){ 600 | return `BoxShadow( 601 | color: ${convertColorToDart(shadow.color,1, false, context)}, 602 | offset: Offset(${shadow.offsetx},${shadow.offsety}), 603 | blurRadius: ${shadow.blurRadius}, 604 | spreadRadius: ${shadow.spreadRadius} 605 | 606 | )`; 607 | 608 | } 609 | /** 610 | * 611 | * @param {*} border 612 | * @param {*} context 613 | */ 614 | function convertBorderToDart(border, context){ 615 | return `Border.all( 616 | color: ${convertColorToDart(border.color,1, false, context)}, 617 | width: ${border.width} 618 | )`; 619 | 620 | } 621 | /** 622 | * 623 | * @param {*} context 624 | */ 625 | function convertColorsListToDart(context){ 626 | colors = []; 627 | context.project.colors.map( 628 | colorMap => { 629 | colors.push(`const Color ${colorMap.name} = const ${convertColorToDart(new Color(colorMap.toHex().r, colorMap.toHex().g,colorMap.toHex().b, colorMap.toHex().a), 1, false)};`) 630 | 631 | } 632 | ); 633 | return colors; 634 | } 635 | /** 636 | * 637 | * @param {*} context 638 | */ 639 | function convertTextStylesListToDart(context){ 640 | textStyles = []; 641 | context.project.textStyles.map( 642 | textStyleMap => { 643 | textStyles.push(`const TextStyle ${textStyleMap.name.replace(/\s/g, '')} = const ${convertTextStyleToDart( 644 | new TextStyle( 645 | textStyleMap.fontFamily, 646 | new Color(textStyleMap.color.toHex().r, textStyleMap.color.toHex().g,textStyleMap.color.toHex().b, textStyleMap.color.toHex().a), 647 | textStyleMap.fontSize, 648 | textStyleMap.fontWeight, 649 | textStyleMap.fontStyle, 650 | textStyleMap.letterSpacing, 651 | textStyleMap.lineHeight , 652 | getShadows(context, []) 653 | ), context 654 | )};`) 655 | 656 | } 657 | ); 658 | return textStyles; 659 | } 660 | 661 | /** 662 | * 663 | * @param {*} textSpans 664 | */ 665 | function convertRichTextToDart(textSpans, textAlign, context){ 666 | 667 | textAlign = (textAlign == null) ? "" : 668 | "\n textAlign: TextAlign." + textAlign + ","; 669 | 670 | return `RichText(${textAlign} 671 | text: new TextSpan( 672 | children: [ 673 | ${textSpans.map( textSpan => 674 | {return convertTextSpanToDart(textSpan, context)} 675 | )}, 676 | ] 677 | ) 678 | )`; 679 | } 680 | 681 | 682 | /* 683 | The functions below are used to create all 684 | the Widget Objects from Flutter, this part try organize 685 | better the final code 686 | */ 687 | 688 | /** 689 | * 690 | * @param {*} color 691 | * @param {*} offsetx 692 | * @param {*} offsety 693 | * @param {*} blurRadius 694 | * @param {*} spreadRadius 695 | */ 696 | function BoxShadow(color, offsetx, offsety, blurRadius, spreadRadius){ 697 | this.color = color; 698 | this.offsetx = offsetx; 699 | this.offsety = offsety; 700 | this.blurRadius = blurRadius; 701 | this.spreadRadius = spreadRadius; 702 | 703 | } 704 | 705 | /** 706 | * 707 | * @param {*} type 708 | * @param {*} colors 709 | * @param {*} stops 710 | * @param {*} angle 711 | * @param {*} scale 712 | */ 713 | function Gradient(type, colors, stops, angle, scale){ 714 | this.type = type; 715 | this.colors = colors; 716 | this.stops = stops; 717 | this.angle = angle; 718 | this.scale = scale; 719 | } 720 | 721 | /** 722 | * 723 | * @param {*} color 724 | * @param {*} width 725 | */ 726 | // Border Flutter 727 | function Border(color, width){ 728 | this.color = color; 729 | this.width = width; 730 | } 731 | // This is a function to model Color from DART object 732 | function Color(r,g,b,a){ 733 | this.r = r; 734 | this.g = g; 735 | this.b = b; 736 | this.a = a; 737 | } 738 | 739 | function equalsColor(color1, color2){ 740 | if (color1.r == color2.r && 741 | color1.g == color2.g && 742 | color1.b == color2.b && 743 | color1.a == color2.a ) 744 | return true; 745 | return false; 746 | } 747 | 748 | /** 749 | * 750 | * @param {*} width 751 | * @param {*} height 752 | * @param {*} decoration 753 | */ 754 | // This is a function to model Shape as DART Container Flutter 755 | function Container(width, height, decoration) { 756 | this.width = width; 757 | this.height = height; 758 | this.decoration = decoration; 759 | } 760 | 761 | /** 762 | * 763 | * @param {*} color 764 | * @param {*} border 765 | * @param {*} borderRadius 766 | * @param {*} shadows 767 | * @param {*} gradient 768 | * @param {*} opacity 769 | */ 770 | // This is a function to model BoxDecoration in Flutter 771 | function BoxDecoration(color, border, borderRadius, shadows, gradient, opacity){ 772 | this.color = color; 773 | this.border = border; 774 | this.borderRadius = borderRadius; 775 | this.shadows = shadows; 776 | this.gradient = gradient; 777 | this.opacity = opacity; 778 | } 779 | 780 | /** 781 | * 782 | * @param {*} text 783 | * @param {*} textAlign 784 | * @param {*} textStyle 785 | */ 786 | // This is a funtion to model Text in Flutter 787 | function Text(text, textAlign, textStyle){ 788 | this.text = text; 789 | this.textAlign = textAlign; 790 | this.textStyle = textStyle; 791 | } 792 | /** 793 | * 794 | * @param {*} fontFamily 795 | * @param {*} color 796 | * @param {*} fontSize 797 | * @param {*} fontWeight 798 | * @param {*} fontStyle 799 | * @param {*} letterSpacing 800 | * @param {*} height 801 | * @param {*} shadows 802 | */ 803 | // This is a function to model TextStyle in Flutter 804 | function TextStyle(fontFamily, color, fontSize, fontWeight, fontStyle, letterSpacing, height, shadows){ 805 | 806 | this.fontFamily = fontFamily; 807 | this.color = color; 808 | this.fontSize = fontSize; 809 | this.fontWeight = fontWeight; 810 | this.fontStyle = fontStyle; 811 | this.letterSpacing = letterSpacing; 812 | this.height = height; 813 | this.shadows = shadows; 814 | } 815 | 816 | /* 817 | The functions below are used as common functions 818 | */ 819 | /** 820 | * 821 | * @param {*} context 822 | * @param {*} layer 823 | */ 824 | function layerHasGradient(context, layer) { 825 | return layer.fills.some(f => f.type === "gradient"); 826 | } 827 | 828 | 829 | export default { 830 | layer, 831 | screen, 832 | component, 833 | colors, 834 | textStyles, 835 | exportColors, 836 | exportTextStyles, 837 | // styleguideColors, 838 | // styleguideTextStyles, 839 | // exportStyleguideColors, 840 | // exportStyleguideTextStyles, 841 | // comment 842 | }; --------------------------------------------------------------------------------