diff --git a/docs/flutter-svg-support.md b/docs/flutter-svg-support.md
new file mode 100644
index 00000000..ffe44def
--- /dev/null
+++ b/docs/flutter-svg-support.md
@@ -0,0 +1,17 @@
+# Flutter does not have a SVG support.
+
+**Use `flutter_svg`**
+
+> Can't run on dartpad.
+
+```dart
+
+```
+
+**Use `Image.network()`**
+
+> Can run on dartpad, requires hosting within svg to png conversion.
+
+```dart
+
+```
diff --git a/editor/components/app-runner/app-runner.tsx b/editor/components/app-runner/app-runner.tsx
index 2ff35610..5611a557 100644
--- a/editor/components/app-runner/app-runner.tsx
+++ b/editor/components/app-runner/app-runner.tsx
@@ -77,15 +77,12 @@ function DedicatedFrameworkRunner({
switch (platform) {
case "flutter":
return (
-
-
+
+
);
case "react":
diff --git a/editor/pages/figma/to-flutter.tsx b/editor/pages/figma/to-flutter.tsx
index 144ce575..c46bf71e 100644
--- a/editor/pages/figma/to-flutter.tsx
+++ b/editor/pages/figma/to-flutter.tsx
@@ -1,5 +1,13 @@
import React, { useEffect, useState } from "react";
import { designTo } from "@designto/code";
+import styled from "@emotion/styled";
+import { RemoteImageRepositories } from "@design-sdk/figma-remote/lib/asset-repository/image-repository";
+import {
+ ImageRepository,
+ MainImageRepository,
+} from "@design-sdk/core/assets-repository";
+import { output } from "@designto/config";
+import { tokenize } from "@designto/token";
import { utils_dart } from "../../utils";
import { DefaultEditorWorkspaceLayout } from "../../layout/default-editor-workspace-layout";
import { LayerHierarchy } from "../../components/editor-hierarchy";
@@ -8,15 +16,8 @@ import {
WorkspaceContentPanelGridLayout,
} from "../../layout/panel";
import { PreviewAndRunPanel } from "../../components/preview-and-run";
-import styled from "@emotion/styled";
import { useDesign } from "../../query-hooks";
import { MonacoEditor } from "../../components/code-editor";
-import { RemoteImageRepositories } from "@design-sdk/figma-remote/lib/asset-repository/image-repository";
-import {
- ImageRepository,
- MainImageRepository,
-} from "@design-sdk/core/assets-repository";
-import { output } from "@designto/config";
import LoadingLayout from "../../layout/loading-overlay";
export default function FigmaToFlutterPage() {
@@ -26,7 +27,6 @@ export default function FigmaToFlutterPage() {
useEffect(() => {
if (design) {
const { reflect, url, node, file } = design;
- const { id, name } = reflect;
// ------------------------------------------------------------
// other platforms are not supported yet
@@ -39,13 +39,10 @@ export default function FigmaToFlutterPage() {
)
);
// ------------------------------------------------------------
-
designTo
.flutter({
input: {
- id: id,
- name: name,
- design: reflect,
+ widget: tokenize(reflect),
},
asset_config: { asset_repository: MainImageRepository.instance },
})
diff --git a/editor/pages/to-code/index.tsx b/editor/pages/to-code/index.tsx
index d42be1fa..82dc9486 100644
--- a/editor/pages/to-code/index.tsx
+++ b/editor/pages/to-code/index.tsx
@@ -65,7 +65,7 @@ export default function DesignToCodeUniversalPage() {
return
;
}
- const { code, name: componentName } = result;
+ const { code, scaffold, name: componentName } = result;
const runner_platform = get_runner_platform(framework_config);
return (
@@ -84,7 +84,7 @@ export default function DesignToCodeUniversalPage() {
{
const token = tokenize(input.design);
-
+ const _tokenized_widget_input = { widget: token };
switch (framework.framework) {
case "vanilla":
- return designToVanilla({ input: { widget: token }, asset_config });
+ return designToVanilla({ input: _tokenized_widget_input, asset_config });
case "react":
- return designToReact({ input: { widget: token }, asset_config });
+ return designToReact({ input: _tokenized_widget_input, asset_config });
case "flutter":
- return designToFlutter({ input, asset_config });
+ return designToFlutter({ input: _tokenized_widget_input, asset_config });
}
throw `The framework "${framework}" is not supported at this point.`;
return;
@@ -78,38 +77,31 @@ export async function designToFlutter({
input,
asset_config,
}: {
- input: input.IDesignInput;
+ input: { widget: Widget };
asset_config?: AssetsConfig;
}): Promise {
await Promise.resolve();
- const flutterAppBuild = toflutter.buildApp(input.design);
- const widget = flutterAppBuild?.widget;
- const app =
- widget &&
- toflutter.makeApp({
- widget: widget,
- scrollable: flutterAppBuild.scrollable,
- });
+ const flutterwidget = toflutter.buildFlutterWidget(input.widget);
+ const flutterapp = toflutter.buildFlutterApp(flutterwidget);
- let widgetCode = widget?.build()?.finalize();
- let rootAppCode = composeAppWithHome(app);
// ------------------------------------------------------------------------
// finilize temporary assets
// this should be placed somewhere else
if (asset_config?.asset_repository && !asset_config.skip_asset_replacement) {
const assets = await fetch_all_assets(asset_config?.asset_repository);
- rootAppCode = dangerous_temporary_asset_replacer(rootAppCode, assets);
- widgetCode = dangerous_temporary_asset_replacer(widgetCode, assets);
+ flutterapp.scaffold.raw = dangerous_temporary_asset_replacer(
+ flutterapp.scaffold.raw,
+ assets
+ );
+ flutterapp.code.raw = dangerous_temporary_asset_replacer(
+ flutterapp.code.raw,
+ assets
+ );
}
// ------------------------------------------------------------------------
- return {
- code: { raw: widgetCode },
- scaffold: { raw: rootAppCode },
- id: input.id,
- name: input.name,
- };
+ return flutterapp;
}
export function designToVue(input: input.IDesignInput): output.ICodeOutput {
diff --git a/packages/designto-flutter/utils/make-as-safe-single.ts b/packages/designto-flutter/_utils/array-utils.ts
similarity index 68%
rename from packages/designto-flutter/utils/make-as-safe-single.ts
rename to packages/designto-flutter/_utils/array-utils.ts
index 9c982817..3db65500 100644
--- a/packages/designto-flutter/utils/make-as-safe-single.ts
+++ b/packages/designto-flutter/_utils/array-utils.ts
@@ -1,4 +1,11 @@
import * as flutter from "@flutter-builder/flutter";
+export function makeSafelyAsList(maybeList: Array | T): Array {
+ if (Array.isArray(maybeList)) {
+ return maybeList;
+ } else {
+ return [maybeList];
+ }
+}
export function makeSaflyAsSingle(
maybeWidget: Array | flutter.Widget
diff --git a/packages/designto-flutter/_utils/index.ts b/packages/designto-flutter/_utils/index.ts
new file mode 100644
index 00000000..2b4722cf
--- /dev/null
+++ b/packages/designto-flutter/_utils/index.ts
@@ -0,0 +1,3 @@
+export * from "./round-double";
+export * from "./array-utils";
+export * from "./size-utils";
diff --git a/packages/designto-flutter/convert/double.convert.ts b/packages/designto-flutter/_utils/round-double.ts
similarity index 100%
rename from packages/designto-flutter/convert/double.convert.ts
rename to packages/designto-flutter/_utils/round-double.ts
diff --git a/packages/designto-flutter/convert/size.convert.ts b/packages/designto-flutter/_utils/size-utils.ts
old mode 100755
new mode 100644
similarity index 100%
rename from packages/designto-flutter/convert/size.convert.ts
rename to packages/designto-flutter/_utils/size-utils.ts
diff --git a/packages/designto-flutter/case-handling/handle-flutter-data-image/README.md b/packages/designto-flutter/case-handling/handle-flutter-data-image/README.md
new file mode 100644
index 00000000..9278b933
--- /dev/null
+++ b/packages/designto-flutter/case-handling/handle-flutter-data-image/README.md
@@ -0,0 +1,14 @@
+# Image.memory handling
+
+Unlike web, using base64 encoded image string requires extra steps on flutter
+
+```dart
+import 'dart:convert';
+import 'package:flutter/widgets.dart';
+
+Image.memory(base64Decode(base64String));
+```
+
+### References
+
+- https://stackoverflow.com/questions/46145472/how-to-convert-base64-string-into-image-with-flutter
diff --git a/packages/designto-flutter/case-handling/handle-flutter-svg-as-image/README.md b/packages/designto-flutter/case-handling/handle-flutter-svg-as-image/README.md
new file mode 100644
index 00000000..bb6ab235
--- /dev/null
+++ b/packages/designto-flutter/case-handling/handle-flutter-svg-as-image/README.md
@@ -0,0 +1,3 @@
+# Flutter svg support - [Learn more at docs](../../../../docs/flutter-svg-support.md)
+
+- https://github.com/lovell/sharp
diff --git a/packages/designto-flutter/case-handling/handle-flutter-svg-as-image/index.ts b/packages/designto-flutter/case-handling/handle-flutter-svg-as-image/index.ts
new file mode 100644
index 00000000..e43d4f51
--- /dev/null
+++ b/packages/designto-flutter/case-handling/handle-flutter-svg-as-image/index.ts
@@ -0,0 +1,12 @@
+import { VectorWidget } from "@reflect-ui/core";
+import * as flutter from "@flutter-builder/flutter";
+
+/**
+ * @deprecated - not implemented
+ * @param vector
+ */
+export function flutter_handle_svg_vector_as_bitmap_converted(
+ vector: VectorWidget
+): flutter.Widget {
+ throw `svg to png conversion is not supported yet.`;
+}
diff --git a/packages/designto-flutter/case-handling/handle-nested-stack/README.md b/packages/designto-flutter/case-handling/handle-nested-stack/README.md
new file mode 100644
index 00000000..21a5b29f
--- /dev/null
+++ b/packages/designto-flutter/case-handling/handle-nested-stack/README.md
@@ -0,0 +1,126 @@
+# Nested stack in flutter
+
+Nested stack (stack under positioned under stack) requires width and height.
+This,
+
+```dart
+Stack(
+ children: [
+ Positioned(
+ left: 795,
+ top: 163,
+ child: Stack(
+ children: [
+ Positioned(
+ left: 0,
+ top: 83,
+ child: Text(
+ "BeoPlay S3 draws heavily on geometry as a design reference. But also, it is reminiscent from the lines of two shapes embracing each other.",
+ style: TextStyle(
+ fontSize: 18,
+ fontWeight: FontWeight.w400,
+ fontFamily: "Roboto",
+ ),
+ ),
+ ),
+ Positioned(
+ left: 0,
+ top: 23,
+ child: Text(
+ "B.play Homeaaaa Speaker ",
+ style: TextStyle(
+ fontSize: 36,
+ fontWeight: FontWeight.w700,
+ fontFamily: "Poppins",
+ ),
+ ),
+ ),
+ Positioned(
+ left: 0,
+ top: 0,
+ child: Text(
+ "SPEAKERS",
+ style: TextStyle(
+ fontSize: 14,
+ fontWeight: FontWeight.w500,
+ fontFamily: "Poppins",
+ ),
+ ),
+ ),
+
+ /// stack requires empty non positioned widget to work properly. refer: https://github.com/flutter/flutter/issues/49631#issuecomment-582090992
+ Container(),
+ ],
+ ),
+ ),
+
+ /// stack requires empty non positioned widget to work properly. refer: https://github.com/flutter/flutter/issues/49631#issuecomment-582090992
+ Container(),
+ ],
+);
+```
+
+Tobe
+
+```dart
+Stack(
+ children: [
+ Positioned(
+ left: 795,
+ top: 163,
+ child: Container(
+ width: MediaQuery.of(context).width, /// <-----------
+ height: MediaQuery.of(context).height, /// <-----------
+ child: Stack(
+ children: [
+ Positioned(
+ left: 0,
+ top: 83,
+ child: Text(
+ "BeoPlay S3 draws heavily on geometry as a design reference. But also, it is reminiscent from the lines of two shapes embracing each other.",
+ style: TextStyle(
+ fontSize: 18,
+ fontWeight: FontWeight.w400,
+ fontFamily: "Roboto",
+ ),
+ ),
+ ),
+ Positioned(
+ left: 0,
+ top: 23,
+ child: Text(
+ "B.play Homeaaaa Speaker ",
+ style: TextStyle(
+ fontSize: 36,
+ fontWeight: FontWeight.w700,
+ fontFamily: "Poppins",
+ ),
+ ),
+ ),
+ Positioned(
+ left: 0,
+ top: 0,
+ child: Text(
+ "SPEAKERS",
+ style: TextStyle(
+ fontSize: 14,
+ fontWeight: FontWeight.w500,
+ fontFamily: "Poppins",
+ ),
+ ),
+ ),
+
+ /// stack requires empty non positioned widget to work properly. refer: https://github.com/flutter/flutter/issues/49631#issuecomment-582090992
+ Container(),
+ ],
+ ),
+ ),
+ ),
+
+ /// stack requires empty non positioned widget to work properly. refer: https://github.com/flutter/flutter/issues/49631#issuecomment-582090992
+ Container(),
+ ],
+);
+```
+
+- https://stackoverflow.com/a/52936983/5463235
diff --git a/packages/designto-flutter/case-handling/handle-nested-stack/index.ts b/packages/designto-flutter/case-handling/handle-nested-stack/index.ts
new file mode 100644
index 00000000..404e1326
--- /dev/null
+++ b/packages/designto-flutter/case-handling/handle-nested-stack/index.ts
@@ -0,0 +1,11 @@
+import * as flutter from "@flutter-builder/flutter";
+
+export function handle_flutter_case_nested_positioned_stack(
+ stack: flutter.Stack
+): flutter.Container {
+ return new flutter.Container({
+ width: flutter.MediaQuery.of().size.width,
+ height: flutter.MediaQuery.of().size.height,
+ child: stack,
+ });
+}
diff --git a/packages/designto-flutter/case-handling/handle-no-size-stack-children/README.md b/packages/designto-flutter/case-handling/handle-no-size-stack-children/README.md
new file mode 100644
index 00000000..3c01d032
--- /dev/null
+++ b/packages/designto-flutter/case-handling/handle-no-size-stack-children/README.md
@@ -0,0 +1,3 @@
+# Flutter requires empty container if stack has no size specified or children is only positioned widgets.
+
+- https://github.com/flutter/flutter/issues/49631#issuecomment-582090992
diff --git a/packages/designto-flutter/utils/make-as-safe-list.ts b/packages/designto-flutter/case-handling/handle-no-size-stack-children/index.ts
similarity index 61%
rename from packages/designto-flutter/utils/make-as-safe-list.ts
rename to packages/designto-flutter/case-handling/handle-no-size-stack-children/index.ts
index 9000dcc9..1024070b 100644
--- a/packages/designto-flutter/utils/make-as-safe-list.ts
+++ b/packages/designto-flutter/case-handling/handle-no-size-stack-children/index.ts
@@ -1,15 +1,12 @@
import * as flutter from "@flutter-builder/flutter";
+import { makeSafelyAsList } from "../../_utils";
-export function makeSafelyAsList(maybeList: Array | T): Array {
- if (Array.isArray(maybeList)) {
- return maybeList;
- } else {
- return [maybeList];
- }
-}
-
-// https://github.com/flutter/flutter/issues/49631#issuecomment-582090992
-export function makeSafelyAsStackList(
+/**
+ * https://github.com/flutter/flutter/issues/49631#issuecomment-582090992
+ * @param maybeWidgets
+ * @returns
+ */
+export function handle_flutter_case_no_size_stack_children(
maybeWidgets: Array | flutter.Widget
): Array {
const list = makeSafelyAsList(maybeWidgets);
diff --git a/packages/designto-flutter/case-handling/index.ts b/packages/designto-flutter/case-handling/index.ts
new file mode 100644
index 00000000..0de995da
--- /dev/null
+++ b/packages/designto-flutter/case-handling/index.ts
@@ -0,0 +1,3 @@
+export * from "./handle-nested-stack";
+export * from "./handle-no-size-stack-children";
+export * from "./handle-flutter-svg-as-image";
diff --git a/packages/designto-flutter/convert/index.ts b/packages/designto-flutter/convert/index.ts
deleted file mode 100644
index a29d978f..00000000
--- a/packages/designto-flutter/convert/index.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-import { convertToSize } from "./size.convert";
-export { convertToSize };
-// ----
-export * from "./double.convert";
diff --git a/packages/designto-flutter/core-type-mappers/README.md b/packages/designto-flutter/core-type-mappers/README.md
deleted file mode 100644
index 3d6067b9..00000000
--- a/packages/designto-flutter/core-type-mappers/README.md
+++ /dev/null
@@ -1,3 +0,0 @@
-# Core type mappers
-
-> reflect core types to flutter types (simple mappers, without logics)
diff --git a/packages/designto-flutter/core-type-mappers/index.ts b/packages/designto-flutter/core-type-mappers/index.ts
deleted file mode 100644
index 90fbf38e..00000000
--- a/packages/designto-flutter/core-type-mappers/index.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export * from "./alignment.mapper";
-export * from "./cross-axis-alignment.mapper";
-export * from "./text-align.mapper";
-export * from "./main-axis-alignment.mapper";
-export * from "./main-axis-size.mapper";
-export * from "./radius.mapper";
diff --git a/packages/designto-flutter/core-type-mappers/main-axis-size.mapper.ts b/packages/designto-flutter/core-type-mappers/main-axis-size.mapper.ts
deleted file mode 100644
index 63d2cace..00000000
--- a/packages/designto-flutter/core-type-mappers/main-axis-size.mapper.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-import { MainAxisSize } from "@flutter-builder/flutter";
-import { FigmaLayoutGrow } from "@design-sdk/figma-types";
-
-export function mapMainAxisSize(layoutGrow: FigmaLayoutGrow): MainAxisSize {
- if (layoutGrow === 0) {
- return MainAxisSize.min;
- } else {
- return MainAxisSize.max;
- }
-}
diff --git a/packages/designto-flutter/dart-ui/dart-ui-color.ts b/packages/designto-flutter/dart-ui/dart-ui-color.ts
new file mode 100644
index 00000000..b36a7bf0
--- /dev/null
+++ b/packages/designto-flutter/dart-ui/dart-ui-color.ts
@@ -0,0 +1,16 @@
+import { Color } from "@reflect-ui/core";
+import * as flutter from "@flutter-builder/flutter";
+import { ColorFormat, converters } from "@reflect-ui/core";
+
+/**
+ * this does not support named colors yet.
+ * @param color : Reflect#Color;
+ * @returns
+ */
+export function color(color: Color): flutter.Color {
+ const hex = converters.color.convertReflectColorToUniversal(
+ color,
+ ColorFormat.hex
+ );
+ return flutter.Color.fromHex(hex);
+}
diff --git a/packages/designto-flutter/dart-ui/dart-ui-offset.ts b/packages/designto-flutter/dart-ui/dart-ui-offset.ts
new file mode 100644
index 00000000..512432f2
--- /dev/null
+++ b/packages/designto-flutter/dart-ui/dart-ui-offset.ts
@@ -0,0 +1,19 @@
+import { Offset } from "@reflect-ui/core";
+import * as flutter from "@flutter-builder/flutter";
+
+export function offset(o: Offset): flutter.Offset {
+ const { dx, dy } = o;
+ if (requiredOffset(o)) {
+ return new flutter.Offset(dx, dy);
+ }
+}
+
+/**
+ * returns undefined, if offset is redundant.
+ */
+function requiredOffset(offset: Offset): Offset {
+ if (offset.dx == 0 && offset.dy == 0) {
+ return undefined;
+ }
+ return offset;
+}
diff --git a/packages/designto-flutter/core-type-mappers/radius.mapper.ts b/packages/designto-flutter/dart-ui/dart-ui-radius.ts
similarity index 85%
rename from packages/designto-flutter/core-type-mappers/radius.mapper.ts
rename to packages/designto-flutter/dart-ui/dart-ui-radius.ts
index 03047c4a..4acbaa19 100644
--- a/packages/designto-flutter/core-type-mappers/radius.mapper.ts
+++ b/packages/designto-flutter/dart-ui/dart-ui-radius.ts
@@ -2,7 +2,7 @@ import * as flutter from "@flutter-builder/flutter";
import { IRadius } from "@reflect-ui/core";
import { roundNumber } from "@reflect-ui/uiutils";
-export function mapRadius(radius: IRadius): flutter.Radius {
+export function radius(radius: IRadius): flutter.Radius {
if (typeof radius == "number") {
return flutter.Radius.circular(roundNumber(radius));
} else {
diff --git a/packages/designto-flutter/core-type-mappers/text-align.mapper.ts b/packages/designto-flutter/dart-ui/dart-ui-text-align.ts
similarity index 91%
rename from packages/designto-flutter/core-type-mappers/text-align.mapper.ts
rename to packages/designto-flutter/dart-ui/dart-ui-text-align.ts
index 3e55920e..7c421dc0 100644
--- a/packages/designto-flutter/core-type-mappers/text-align.mapper.ts
+++ b/packages/designto-flutter/dart-ui/dart-ui-text-align.ts
@@ -1,7 +1,7 @@
import * as core from "@reflect-ui/core";
import * as flutter from "@flutter-builder/flutter";
-export function mapTextAlign(textalign: core.TextAlign): flutter.TextAlign {
+export function textAlign(textalign: core.TextAlign): flutter.TextAlign {
// only undefined in testing
// we are not handling "left" align, because it will be set by default.
diff --git a/packages/designto-flutter/dart-ui/index.ts b/packages/designto-flutter/dart-ui/index.ts
new file mode 100644
index 00000000..fdc4535f
--- /dev/null
+++ b/packages/designto-flutter/dart-ui/index.ts
@@ -0,0 +1,4 @@
+export * from "./dart-ui-offset";
+export * from "./dart-ui-radius";
+export * from "./dart-ui-text-align";
+export * from "./dart-ui-color";
diff --git a/packages/designto-flutter/index.ts b/packages/designto-flutter/index.ts
old mode 100755
new mode 100644
index f133acd6..e4763d10
--- a/packages/designto-flutter/index.ts
+++ b/packages/designto-flutter/index.ts
@@ -1,285 +1,35 @@
-import { nodes } from "@design-sdk/core";
-import { TextBuilder, WidgetBuilder } from "./widget-builders";
+import { Widget } from "@reflect-ui/core";
+import { buildFlutterWidgetFromTokens } from "./tokens-to-flutter-widget";
+import { flutter as config } from "@designto/config";
import * as flutter from "@flutter-builder/flutter";
-import { makeSafelyAsStackList } from "./utils/make-as-safe-list";
-import { makeFlutterDivider } from "./make/make-flutter-divider";
-import { detectIf } from "@reflect-ui/detection";
-import { makeFlatButton } from "./make/make-flutter-flat-button";
-import { makeDetectedIcon } from "./make/make-flutter-icon";
-import { makeIllustImage } from "./make/make-flutter-image";
-import { makeRowColumn } from "./make/make-flutter-column-row";
-import { makeStack } from "./make/make-flutter-stack";
-import { Axis as ReflectAxis } from "@reflect-ui/core/lib";
-import { makeChip } from "./make/make-flutter-chip";
-import { array, roundNumber } from "@reflect-ui/uiutils";
-import { output } from "@designto/config";
-import { tokenizeDivider } from "@designto/token";
-
-type FlutterScreenOutput = output.ScreenOutput;
+import { composeAppWithHome } from "@flutter-builder/flutter";
+import { makeApp } from "./make/make-flutter-material-app";
+import { formatCode as dartformat } from "dart-style";
+
+export function buildFlutterApp(
+ widget: flutter.Widget
+): config.FlutterComponentOutput {
+ const app =
+ widget &&
+ makeApp({
+ widget: widget,
+ scrollable: true,
+ });
-let parentId = "";
+ let widgetCode = dartformat(widget?.build()?.finalize()).code;
+ let rootAppCode = composeAppWithHome(app);
-// the target root widget tree
-let targetId: string;
-let scrollable: boolean;
-export function buildApp(
- sceneNode: nodes.ReflectSceneNode
-): FlutterScreenOutput {
- scrollable = true; // init to true.
- targetId = sceneNode.id;
- const rootWidget = generateRootWidget(sceneNode);
- console.log("flutter widget build result is..", rootWidget);
return {
- widget: rootWidget,
- scrollable: scrollable,
+ id: "flutterapp",
+ name: "flutterapp",
+ code: { raw: widgetCode },
+ scaffold: { raw: rootAppCode },
};
}
-function generateRootWidget(
- sceneNode: nodes.ReflectSceneNode,
- parentIdSrc: string = ""
-): flutter.Widget {
- parentId = parentIdSrc;
- _log_current_node(sceneNode);
- let result = flutterWidgetGenerator(sceneNode);
-
- if (Array.isArray(result)) {
- // this won't happen
- throw "result cannot be in array form.";
- }
-
- return result;
-}
-
-function flutterWidgetGenerator(
- sceneNode: ReadonlyArray | nodes.ReflectSceneNode
-): Array | flutter.Widget {
- console.log(`flutterWidgetGenerator handling scene node -`, sceneNode);
- if (Array.isArray(sceneNode) && sceneNode.length > 0) {
- // explicit type casting
- sceneNode = sceneNode as ReadonlyArray;
-
- // count of input nodes
- const sceneLen = sceneNode.length;
-
- // initialize output widgets array
- let widgets: Array = [];
-
- console.log(
- `widget generator::
- targetting list of nodes children of parent:{${sceneNode[0].parent?.toString()}}.
- total count of ${sceneLen}`
- );
-
- sceneNode.forEach((node, index) => {
- _log_current_node(node);
- widgets.push(handleNode(node));
-
- // if the parent is an AutoLayout, and itemSpacing is set, add a SizedBox between items.
- widgets.push(addSpacingIfNeeded(node, index, sceneLen));
- });
-
- // filter empty widgets
- widgets = widgets.filter((w) => array.filters.notEmpty(w));
- if (widgets.length == 1) {
- // TODO - inspect this logic - is it safe?
- // console.log("flutterWidgetGenerator complete", widgets[0])
- return widgets[0];
- }
- // console.log("flutterWidgetGenerator complete", widgets)
- return widgets;
- } else {
- // explicit type casting
- sceneNode = sceneNode as nodes.ReflectSceneNode;
- console.log(
- `widget generator::
- targetting single node ${sceneNode.toString()}
- this is child of ${sceneNode.parent?.toString()}`
- );
-
- return handleNode(sceneNode);
- }
-
- function handleNode(node: nodes.ReflectSceneNode): flutter.Widget {
- _log_current_node(node);
- console.log(
- `starting handling node ${node.toString()} type of ${node.type}`
- );
-
- const chipDetectionResult = detectIf.chip(node);
- if (chipDetectionResult.result) {
- console.log("detected:: this node is detected as Chip", node.name);
- return makeChip(chipDetectionResult.data);
- }
-
- const buttonDetectionResult = detectIf.button(node);
- if (buttonDetectionResult.result) {
- console.log("detected:: this node is detected as button.", node.name);
- return makeFlatButton(buttonDetectionResult.data);
- }
-
- const iconDetectionResult = detectIf.icon(node);
- if (iconDetectionResult.result) {
- console.log("detected:: this node is detected as an icon.", node.name);
- return makeDetectedIcon(iconDetectionResult.data);
- }
-
- const illustDetectionResult = detectIf.illust(node);
- if (illustDetectionResult.result) {
- console.log("detected:: this node is detected as an illust.", node.name);
- return makeIllustImage(node);
- }
-
- if (
- node instanceof nodes.ReflectRectangleNode ||
- node instanceof nodes.ReflectEllipseNode
- ) {
- console.log(
- `this node ${node.toString()} is a rect || ellipse. making it as a empty container`
- );
- return flutterContainer(node, undefined);
- } else if (node instanceof nodes.ReflectLineNode) {
- const _divider_detection_result = detectIf.divider(node);
- if (_divider_detection_result.result) {
- console.log(
- `this node ${node.toString()} is a line. making it as a divider`
- );
- const dividerwidget = tokenizeDivider.fromManifest(
- node,
- _divider_detection_result.data
- );
- return makeFlutterDivider(dividerwidget);
- }
- } else if (node instanceof nodes.ReflectGroupNode) {
- console.log(
- `this node ${node.toString()} is a group. handling with group handler`
- );
- return flutterGroupHandler(node);
- } else if (node instanceof nodes.ReflectFrameNode) {
- return flutterFrame(node);
- } else if (node instanceof nodes.ReflectTextNode) {
- return flutterText(node);
- }
- }
-}
-
-function _log_current_node(node: { id: string }) {
- // console.log(
- // `
- // ----------
- // flutter app generation: targetting current processing node to ${node.id}
- // ----------
- // `
- // );
-}
-
-function flutterGroupHandler(node: nodes.ReflectGroupNode): flutter.Widget {
- // console.log(
- // `group handler :: making ${node} as a stack with its children count of ${node.childrenCount}`
- // );
-
- return flutterContainer(
- node,
- makeStack(flutterWidgetGenerator(node.children) as [])
- );
-}
-
-function flutterContainer(
- node:
- | nodes.ReflectFrameNode
- | nodes.ReflectGroupNode
- | nodes.ReflectRectangleNode
- | nodes.ReflectEllipseNode,
- child?: flutter.Widget
-): flutter.Widget {
- const builder = new WidgetBuilder({ child: child, node: node });
-
- const isBuildRoot = targetId === node.id;
- const sizeOptions = isBuildRoot
- ? {
- size: new flutter.Size(
- flutter.MediaQuery.of().size.width,
- undefined
- ).addComment(
- 'container building for target root node. making the width with "MediaQuery.of().size.width"'
- ),
- }
- : undefined;
-
- builder
- .wrapWithContainer(sizeOptions)
- .blendWithAttributes()
- .positionInParent(parentId);
- return builder.child;
-}
-
-function flutterText(node: nodes.ReflectTextNode): flutter.Widget {
- const builder = new TextBuilder({
- child: undefined,
- node: node,
- });
-
- builder.createText().blendWithAttributes().positionInParent(parentId);
-
- return builder.child;
-}
-
-function flutterFrame(node: nodes.ReflectFrameNode): flutter.Widget {
- // console.log(`start handling frame node ${node.toString()} and its children`);
-
- const children = flutterWidgetGenerator(node.children);
-
- if (node.children.length === 1) {
- // if there is only one child, there is no need for Container or Row. Padding works indepdently of them.
- return flutterContainer(node, children as flutter.Widget);
- } else if (node.layoutMode !== undefined) {
- const rowColumn = makeRowColumn(node, children as Array);
- return flutterContainer(node, rowColumn);
- } else {
- // node.layoutMode === "NONE" && node.children.length > 1
- // children needs to be absolute
-
- // region
- // if currently handled node is root node, and it's outcome is stack, then make it not scrollable. (singlechildscrollview with stack usage is not resolved, remaining as issue.)
- if (node.id == targetId) {
- scrollable = false;
- }
- // endregion
-
- return flutterContainer(
- node,
- new flutter.Stack({
- children: makeSafelyAsStackList(children),
- })
- );
+export function buildFlutterWidget(widget: Widget) {
+ if (!widget) {
+ throw "A valid reflect widget manifest should be passed as an input. none was passed.";
}
+ return buildFlutterWidgetFromTokens(widget);
}
-
-function addSpacingIfNeeded(
- node: nodes.ReflectSceneNode,
- index: number,
- length: number
-): flutter.Widget | undefined {
- if (
- node.parent instanceof nodes.ReflectFrameNode &&
- node.parent.layoutMode !== undefined
- ) {
- // check if itemSpacing is set and if it isn't the last value.
- // Don't add the SizedBox at last value. In Figma, itemSpacing CAN be negative; here it can't.
- if (node.parent.itemSpacing > 0 && index < length - 1) {
- if (node.parent.layoutMode === ReflectAxis.horizontal) {
- return new flutter.SizedBox({
- width: roundNumber(node.parent.itemSpacing),
- });
- } else {
- // node.parent.layoutMode === "VERTICAL"
- return new flutter.SizedBox({
- height: roundNumber(node.parent.itemSpacing),
- });
- }
- }
- }
- return undefined;
-}
-
-export * from "./make/make-flutter-material-app";
diff --git a/packages/designto-flutter/legacy-archives/iterative-builder.ts b/packages/designto-flutter/legacy-archives/iterative-builder.ts
new file mode 100755
index 00000000..b316c9f3
--- /dev/null
+++ b/packages/designto-flutter/legacy-archives/iterative-builder.ts
@@ -0,0 +1,285 @@
+import { nodes } from "@design-sdk/core";
+import { TextBuilder, WidgetBuilder } from "../widget-builders";
+import * as flutter from "@flutter-builder/flutter";
+import { makeSafelyAsStackList } from "../utils/make-as-safe-list";
+import { makeFlutterDivider } from "../make/make-flutter-divider";
+import { detectIf } from "@reflect-ui/detection";
+import { makeFlatButton } from "../make/make-flutter-flat-button";
+import { makeDetectedIcon } from "../make/make-flutter-icon";
+import { makeIllustImage } from "../make/make-flutter-image";
+import { makeRowColumn } from "../make/make-flutter-column-row";
+import { makeStack } from "../make/make-flutter-stack";
+import { Axis as ReflectAxis } from "@reflect-ui/core/lib";
+import { makeChip } from "../make/make-flutter-chip";
+import { array, roundNumber } from "@reflect-ui/uiutils";
+import { output } from "@designto/config";
+import { tokenizeDivider } from "@designto/token";
+
+type FlutterScreenOutput = output.ScreenOutput;
+
+let parentId = "";
+
+// the target root widget tree
+let targetId: string;
+let scrollable: boolean;
+export function buildApp(
+ sceneNode: nodes.ReflectSceneNode
+): FlutterScreenOutput {
+ scrollable = true; // init to true.
+ targetId = sceneNode.id;
+ const rootWidget = generateRootWidget(sceneNode);
+ console.log("flutter widget build result is..", rootWidget);
+ return {
+ widget: rootWidget,
+ scrollable: scrollable,
+ };
+}
+
+function generateRootWidget(
+ sceneNode: nodes.ReflectSceneNode,
+ parentIdSrc: string = ""
+): flutter.Widget {
+ parentId = parentIdSrc;
+ _log_current_node(sceneNode);
+ let result = flutterWidgetGenerator(sceneNode);
+
+ if (Array.isArray(result)) {
+ // this won't happen
+ throw "result cannot be in array form.";
+ }
+
+ return result;
+}
+
+function flutterWidgetGenerator(
+ sceneNode: ReadonlyArray | nodes.ReflectSceneNode
+): Array | flutter.Widget {
+ console.log(`flutterWidgetGenerator handling scene node -`, sceneNode);
+ if (Array.isArray(sceneNode) && sceneNode.length > 0) {
+ // explicit type casting
+ sceneNode = sceneNode as ReadonlyArray;
+
+ // count of input nodes
+ const sceneLen = sceneNode.length;
+
+ // initialize output widgets array
+ let widgets: Array = [];
+
+ console.log(
+ `widget generator::
+ targetting list of nodes children of parent:{${sceneNode[0].parent?.toString()}}.
+ total count of ${sceneLen}`
+ );
+
+ sceneNode.forEach((node, index) => {
+ _log_current_node(node);
+ widgets.push(handleNode(node));
+
+ // if the parent is an AutoLayout, and itemSpacing is set, add a SizedBox between items.
+ widgets.push(addSpacingIfNeeded(node, index, sceneLen));
+ });
+
+ // filter empty widgets
+ widgets = widgets.filter((w) => array.filters.notEmpty(w));
+ if (widgets.length == 1) {
+ // TODO - inspect this logic - is it safe?
+ // console.log("flutterWidgetGenerator complete", widgets[0])
+ return widgets[0];
+ }
+ // console.log("flutterWidgetGenerator complete", widgets)
+ return widgets;
+ } else {
+ // explicit type casting
+ sceneNode = sceneNode as nodes.ReflectSceneNode;
+ console.log(
+ `widget generator::
+ targetting single node ${sceneNode.toString()}
+ this is child of ${sceneNode.parent?.toString()}`
+ );
+
+ return handleNode(sceneNode);
+ }
+
+ function handleNode(node: nodes.ReflectSceneNode): flutter.Widget {
+ _log_current_node(node);
+ console.log(
+ `starting handling node ${node.toString()} type of ${node.type}`
+ );
+
+ const chipDetectionResult = detectIf.chip(node);
+ if (chipDetectionResult.result) {
+ console.log("detected:: this node is detected as Chip", node.name);
+ return makeChip(chipDetectionResult.data);
+ }
+
+ const buttonDetectionResult = detectIf.button(node);
+ if (buttonDetectionResult.result) {
+ console.log("detected:: this node is detected as button.", node.name);
+ return makeFlatButton(buttonDetectionResult.data);
+ }
+
+ const iconDetectionResult = detectIf.icon(node);
+ if (iconDetectionResult.result) {
+ console.log("detected:: this node is detected as an icon.", node.name);
+ return makeDetectedIcon(iconDetectionResult.data);
+ }
+
+ const illustDetectionResult = detectIf.illust(node);
+ if (illustDetectionResult.result) {
+ console.log("detected:: this node is detected as an illust.", node.name);
+ return makeIllustImage(node);
+ }
+
+ if (
+ node instanceof nodes.ReflectRectangleNode ||
+ node instanceof nodes.ReflectEllipseNode
+ ) {
+ console.log(
+ `this node ${node.toString()} is a rect || ellipse. making it as a empty container`
+ );
+ return flutterContainer(node, undefined);
+ } else if (node instanceof nodes.ReflectLineNode) {
+ const _divider_detection_result = detectIf.divider(node);
+ if (_divider_detection_result.result) {
+ console.log(
+ `this node ${node.toString()} is a line. making it as a divider`
+ );
+ const dividerwidget = tokenizeDivider.fromManifest(
+ node,
+ _divider_detection_result.data
+ );
+ return makeFlutterDivider(dividerwidget);
+ }
+ } else if (node instanceof nodes.ReflectGroupNode) {
+ console.log(
+ `this node ${node.toString()} is a group. handling with group handler`
+ );
+ return flutterGroupHandler(node);
+ } else if (node instanceof nodes.ReflectFrameNode) {
+ return flutterFrame(node);
+ } else if (node instanceof nodes.ReflectTextNode) {
+ return flutterText(node);
+ }
+ }
+}
+
+function _log_current_node(node: { id: string }) {
+ // console.log(
+ // `
+ // ----------
+ // flutter app generation: targetting current processing node to ${node.id}
+ // ----------
+ // `
+ // );
+}
+
+function flutterGroupHandler(node: nodes.ReflectGroupNode): flutter.Widget {
+ // console.log(
+ // `group handler :: making ${node} as a stack with its children count of ${node.childrenCount}`
+ // );
+
+ return flutterContainer(
+ node,
+ makeStack(flutterWidgetGenerator(node.children) as [])
+ );
+}
+
+function flutterContainer(
+ node:
+ | nodes.ReflectFrameNode
+ | nodes.ReflectGroupNode
+ | nodes.ReflectRectangleNode
+ | nodes.ReflectEllipseNode,
+ child?: flutter.Widget
+): flutter.Widget {
+ const builder = new WidgetBuilder({ child: child, node: node });
+
+ const isBuildRoot = targetId === node.id;
+ const sizeOptions = isBuildRoot
+ ? {
+ size: new flutter.Size(
+ flutter.MediaQuery.of().size.width,
+ undefined
+ ).addComment(
+ 'container building for target root node. making the width with "MediaQuery.of().size.width"'
+ ),
+ }
+ : undefined;
+
+ builder
+ .wrapWithContainer(sizeOptions)
+ .blendWithAttributes()
+ .positionInParent(parentId);
+ return builder.child;
+}
+
+function flutterText(node: nodes.ReflectTextNode): flutter.Widget {
+ const builder = new TextBuilder({
+ child: undefined,
+ node: node,
+ });
+
+ builder.createText().blendWithAttributes().positionInParent(parentId);
+
+ return builder.child;
+}
+
+function flutterFrame(node: nodes.ReflectFrameNode): flutter.Widget {
+ // console.log(`start handling frame node ${node.toString()} and its children`);
+
+ const children = flutterWidgetGenerator(node.children);
+
+ if (node.children.length === 1) {
+ // if there is only one child, there is no need for Container or Row. Padding works indepdently of them.
+ return flutterContainer(node, children as flutter.Widget);
+ } else if (node.layoutMode !== undefined) {
+ const rowColumn = makeRowColumn(node, children as Array);
+ return flutterContainer(node, rowColumn);
+ } else {
+ // node.layoutMode === "NONE" && node.children.length > 1
+ // children needs to be absolute
+
+ // region
+ // if currently handled node is root node, and it's outcome is stack, then make it not scrollable. (singlechildscrollview with stack usage is not resolved, remaining as issue.)
+ if (node.id == targetId) {
+ scrollable = false;
+ }
+ // endregion
+
+ return flutterContainer(
+ node,
+ new flutter.Stack({
+ children: makeSafelyAsStackList(children),
+ })
+ );
+ }
+}
+
+function addSpacingIfNeeded(
+ node: nodes.ReflectSceneNode,
+ index: number,
+ length: number
+): flutter.Widget | undefined {
+ if (
+ node.parent instanceof nodes.ReflectFrameNode &&
+ node.parent.layoutMode !== undefined
+ ) {
+ // check if itemSpacing is set and if it isn't the last value.
+ // Don't add the SizedBox at last value. In Figma, itemSpacing CAN be negative; here it can't.
+ if (node.parent.itemSpacing > 0 && index < length - 1) {
+ if (node.parent.layoutMode === ReflectAxis.horizontal) {
+ return new flutter.SizedBox({
+ width: roundNumber(node.parent.itemSpacing),
+ });
+ } else {
+ // node.parent.layoutMode === "VERTICAL"
+ return new flutter.SizedBox({
+ height: roundNumber(node.parent.itemSpacing),
+ });
+ }
+ }
+ }
+ return undefined;
+}
+
+export * from "../make/make-flutter-material-app";
diff --git a/packages/designto-flutter/legacy-archives/rect.interpret.ts b/packages/designto-flutter/legacy-archives/rect.interpret.ts
index a5f75868..fa36f31b 100644
--- a/packages/designto-flutter/legacy-archives/rect.interpret.ts
+++ b/packages/designto-flutter/legacy-archives/rect.interpret.ts
@@ -5,7 +5,6 @@ import {
Color,
} from "@flutter-builder/flutter";
import { makeColorFromRGBO } from "../make";
-import { interpretGradient } from "../interpreter/gradient.interpret";
import { interpretBorderRadius } from "./border-radius.interpret";
import { roundNumber } from "@reflect-ui/uiutils";
import { ReflectRectangleNode } from "@design-sdk/core";
@@ -15,6 +14,8 @@ import {
Paint,
SolidPaint,
} from "@design-sdk/figma";
+import * as painting from "../painting";
+import { tokenize_gradient } from "../../designto-token";
export function interpretRect(rect: ReflectRectangleNode): Container {
const fills = rect.fills as Array;
@@ -46,7 +47,8 @@ export function interpretRect(rect: ReflectRectangleNode): Container {
break;
case BackgroundType.gradient:
const gradientFill = singleFill as GradientPaint;
- gradient = interpretGradient(gradientFill);
+ const g = tokenize_gradient(gradientFill);
+ gradient = painting.linearGradient(g);
break;
case BackgroundType.image:
const imageFill = singleFill as ImagePaint;
@@ -65,7 +67,8 @@ export function interpretRect(rect: ReflectRectangleNode): Container {
break;
case BackgroundType.gradient:
const gradientFill = primaryFill as GradientPaint;
- gradient = interpretGradient(gradientFill);
+ const g = tokenize_gradient(gradientFill);
+ gradient = painting.linearGradient(g);
break;
case BackgroundType.image:
const imageFill = primaryFill as ImagePaint;
diff --git a/packages/designto-flutter/length/README.md b/packages/designto-flutter/length/README.md
new file mode 100644
index 00000000..aba8e23e
--- /dev/null
+++ b/packages/designto-flutter/length/README.md
@@ -0,0 +1,8 @@
+# Special operator.
+
+Convert css length syntax to flutter size calculation snippet.
+
+```dart
+// e.g - calc(100vh - 500px)
+MediaQuery.of(context).size.height - 500;
+```
diff --git a/packages/designto-flutter/length/calc.ts b/packages/designto-flutter/length/calc.ts
new file mode 100644
index 00000000..e69de29b
diff --git a/packages/designto-flutter/length/index.ts b/packages/designto-flutter/length/index.ts
new file mode 100644
index 00000000..8a0b9dfe
--- /dev/null
+++ b/packages/designto-flutter/length/index.ts
@@ -0,0 +1,2 @@
+// export * from "./calc";
+export * from "./length";
diff --git a/packages/designto-flutter/length/length.ts b/packages/designto-flutter/length/length.ts
new file mode 100644
index 00000000..ccbf5ca3
--- /dev/null
+++ b/packages/designto-flutter/length/length.ts
@@ -0,0 +1,58 @@
+import { Axis, DimensionLength } from "@reflect-ui/core";
+import * as flutter from "@flutter-builder/flutter";
+
+export function length(d: DimensionLength, a?: Axis) {
+ if (d === undefined) {
+ return;
+ }
+
+ if (typeof d === "string") {
+ if (d === "match-screen-size") {
+ switch (a) {
+ case Axis.horizontal:
+ return flutter.MediaQuery.of().size.width;
+ case Axis.vertical:
+ return flutter.MediaQuery.of().size.height;
+ }
+ throw new Error("Invalid axis");
+ }
+
+ if (d.endsWith("px")) {
+ return parseFloat(d) as flutter.double;
+ }
+
+ if (d.endsWith("vw")) {
+ throw "not supported";
+ // return vw(parseFloat(d));
+ }
+
+ if (d.endsWith("vh")) {
+ throw "not supported";
+ // return vh(parseFloat(d));
+ }
+
+ if (d.endsWith("%")) {
+ throw "% not supported";
+ // return percent(d as `${number}%`);
+ }
+
+ // this case, the d value is already processed by other css builders.
+ else {
+ return d;
+ }
+ } else if (typeof d === "number") {
+ return d;
+ }
+
+ if (d.type == "calc") {
+ throw "calc not supported";
+ // return calc(d.operations, a);
+ }
+
+ if (d.type == "op") {
+ //@ts-ignore
+ return operation(d, a);
+ }
+
+ throw `no matching length type found. "${JSON.stringify(d)}" was givven`;
+}
diff --git a/packages/designto-flutter/make/index.ts b/packages/designto-flutter/make/index.ts
index 2a69b61d..c658b99f 100644
--- a/packages/designto-flutter/make/index.ts
+++ b/packages/designto-flutter/make/index.ts
@@ -1,10 +1,6 @@
-import { makeBorderRadius } from "./make-flutter-border-radius";
-import { makeBorder } from "./make-flutter-border";
-import { makeBoxShadow } from "./make-flutter-box-shadow";
+import { boxShadow } from "../painting/painting-box-shadow";
import { makeColor, makeColorFromRGBO } from "./make-flutter-color";
-import { makeEdgeInsets } from "./make-flutter-edge-insets";
import { makeShape } from "./make-flutter-shape-border";
-import { makeTextStyle } from "./make-flutter-text-style";
import { makeText } from "./make-flutter-text";
import {
makeBoxDecoration,
@@ -12,15 +8,11 @@ import {
} from "./make-flutter-box-decoration";
export {
- makeBorderRadius,
- makeBorder,
- makeBoxShadow,
+ boxShadow as makeBoxShadow,
makeBoxDecoration,
makeBoxDecorationColorBg as makeBoxDecorationBg,
makeColor,
makeColorFromRGBO,
- makeEdgeInsets,
makeShape,
- makeTextStyle,
makeText,
};
diff --git a/packages/designto-flutter/make/make-flutter-border-radius.ts b/packages/designto-flutter/make/make-flutter-border-radius.ts
deleted file mode 100644
index 970df4d6..00000000
--- a/packages/designto-flutter/make/make-flutter-border-radius.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-import * as flutter from "@flutter-builder/flutter";
-import {
- ReflectEllipseNode,
- IReflectRectangleCornerMixin,
-} from "@design-sdk/core";
-import { mapRadius } from "../core-type-mappers";
-import * as core from "@reflect-ui/core";
-import { roundNumber } from "@reflect-ui/uiutils";
-
-export function makeBorderRadius(
- node: IReflectRectangleCornerMixin
-): flutter.BorderRadiusGeometry {
- if (node instanceof ReflectEllipseNode) return undefined;
- if (node.cornerRadius === undefined || node.cornerRadius.all === 0) {
- return undefined;
- }
-
- return node.cornerRadius.all !== undefined
- ? flutter.BorderRadius.circular(
- roundNumber(node.cornerRadius.all as number)
- )
- : _makePartialBorderRadius(node.cornerRadius);
-}
-
-function _makePartialBorderRadius(cornerRadius: core.BorderRadiusManifest) {
- const _oneofRadiusIsHasValue = [
- cornerRadius.tl,
- cornerRadius.tr,
- cornerRadius.bl,
- cornerRadius.br,
- ].some((i) => i !== undefined);
-
- if (_oneofRadiusIsHasValue) {
- return flutter.BorderRadius.only({
- topLeft: mapRadius(cornerRadius.tl),
- topRight: mapRadius(cornerRadius.tr),
- bottomLeft: mapRadius(cornerRadius.bl),
- bottomRight: mapRadius(cornerRadius.br),
- });
- } else {
- // if none of each corner radius contains value (if every value is empty) do not return a value.
- return;
- }
-}
diff --git a/packages/designto-flutter/make/make-flutter-border-side.ts b/packages/designto-flutter/make/make-flutter-border-side.ts
deleted file mode 100644
index aa4f6884..00000000
--- a/packages/designto-flutter/make/make-flutter-border-side.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-import { ReflectDefaultShapeMixin } from "@design-sdk/core";
-import * as flutter from "@flutter-builder/flutter";
-import { roundNumber } from "@reflect-ui/uiutils";
-import { makeColor } from "./make-flutter-color";
-
-export function makeBorderSide(node: ReflectDefaultShapeMixin) {
- // TODO -> move this as member method
- if (!node.strokes || node.strokes.length === 0) {
- return undefined;
- }
-
- return new flutter.BorderSide({
- color: makeColor(node.strokes),
- width: roundNumber(node.strokeWeight),
- });
-}
diff --git a/packages/designto-flutter/make/make-flutter-border.ts b/packages/designto-flutter/make/make-flutter-border.ts
deleted file mode 100644
index 9464b0cc..00000000
--- a/packages/designto-flutter/make/make-flutter-border.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import * as flutter from "@flutter-builder/flutter";
-import { ReflectDefaultShapeMixin, ReflectSceneNode } from "@design-sdk/core";
-import { roundNumber } from "@reflect-ui/uiutils";
-import { makeColor } from "./make-flutter-color";
-
-// generate the border, when it exists
-export function makeBorder(node: ReflectSceneNode): flutter.Border {
- if (node instanceof ReflectDefaultShapeMixin) {
- if (!node.strokes || node.strokes.length === 0) {
- return undefined;
- }
-
- // generate the border, when it should exist
- return node.strokeWeight
- ? flutter.Border.all({
- color: makeColor(node.strokes),
- width: roundNumber(node.strokeWeight),
- })
- : undefined;
- }
-}
diff --git a/packages/designto-flutter/make/make-flutter-box-decoration.ts b/packages/designto-flutter/make/make-flutter-box-decoration.ts
index 10c6a2b5..2b60aca1 100644
--- a/packages/designto-flutter/make/make-flutter-box-decoration.ts
+++ b/packages/designto-flutter/make/make-flutter-box-decoration.ts
@@ -3,15 +3,9 @@ import { Figma } from "@design-sdk/figma";
import { retrieveFill } from "@design-sdk/core/utils";
import * as flutter from "@flutter-builder/flutter";
import { interpretImageFill } from "../interpreter/image.interpret";
-import { makeBorderRadius } from "./make-flutter-border-radius";
-import { makeBorder } from "./make-flutter-border";
-import { makeBoxShadow } from "./make-flutter-box-shadow";
-import {
- makeColorFromRGBO,
- makeFlutterColorFromReflectColor,
-} from "./make-flutter-color";
-import { tokenize_gradient } from "@designto/token";
-import { mapAlignment } from "../core-type-mappers";
+import * as painting from "../painting";
+import { makeColorFromRGBO } from "./make-flutter-color";
+import { tokenizeBorder, tokenize_gradient } from "@designto/token";
type DecorationBackgroundLike =
| flutter.Color
@@ -24,9 +18,10 @@ export function makeBoxDecoration(
| nodes.ReflectEllipseNode
| nodes.ReflectFrameNode
): flutter.BoxDecoration | flutter.Color {
- const decorationBorder = makeBorder(node);
- const decorationBoxShadow = makeBoxShadow(node);
- const decorationBorderRadius = makeBorderRadius(node);
+ const _border = tokenizeBorder.fromNode(node);
+ const decorationBorder = painting.border(_border);
+ const decorationBoxShadow = painting.boxShadow(node.shadows);
+ const decorationBorderRadius = painting.borderRadius(node.cornerRadius);
///
/// ----------------------------------------------------------------
@@ -119,12 +114,7 @@ export function makeBoxDecorationColorBg(
return undefined;
case "GRADIENT_LINEAR":
const g = tokenize_gradient(fill as Figma.GradientPaint);
- return new flutter.LinearGradient({
- begin: mapAlignment(g.begin),
- end: mapAlignment(g.end),
- colors: g.colors.map((c) => makeFlutterColorFromReflectColor(c)),
- stops: g.stops,
- });
+ return painting.linearGradient(g);
case "SOLID":
return makeColorFromRGBO(fill.color, opacity);
default:
diff --git a/packages/designto-flutter/make/make-flutter-box-shadow.ts b/packages/designto-flutter/make/make-flutter-box-shadow.ts
deleted file mode 100644
index 7e6054ec..00000000
--- a/packages/designto-flutter/make/make-flutter-box-shadow.ts
+++ /dev/null
@@ -1,70 +0,0 @@
-import * as flutter from "@flutter-builder/flutter";
-import { ReflectSceneNode } from "@design-sdk/core";
-import { Figma } from "@design-sdk/figma";
-import { roundNumber } from "@reflect-ui/uiutils";
-import { makeColorFromRGBO } from "./make-flutter-color";
-
-export function makeBoxShadow(
- node: ReflectSceneNode
-): Array {
- let boxShadows: Array = [];
-
- if (node.effects?.length > 0) {
- const shadows: Array = node.effects.filter(
- (d): d is Figma.ShadowEffect =>
- (d.type === "DROP_SHADOW" || d.type === "INNER_SHADOW") && d.visible
- );
-
- // if no shadow filtered available, return undefined
- if (shadows.length == 0) {
- return undefined;
- }
-
- shadows.forEach(function (d: Figma.ShadowEffect) {
- let boxShadow: flutter.BoxShadow;
- if (d.type == "DROP_SHADOW") {
- boxShadow = new flutter.BoxShadow({
- color: makeColorFromRGBO(d.color, d.color.a),
- blurRadius: requiredNumber(d.radius),
- spreadRadius: requiredNumber(d.spread),
- offset: requiredOffset(new flutter.Offset(d.offset.x, d.offset.y)),
- });
- } else if (d.type == "INNER_SHADOW") {
- // handling inner shadow
- // https://stackoverflow.com/a/55096682/5463235
-
- boxShadow = new flutter.BoxShadow({
- color: makeColorFromRGBO(d.color, d.color.a),
- blurRadius: requiredNumber(d.radius),
- // multiply -1 * blur for spread
- // TODO inspect this logic again.
- spreadRadius: requiredNumber((d.spread + d.radius) * -1),
- offset: requiredOffset(new flutter.Offset(d.offset.x, d.offset.y)),
- });
- }
-
- boxShadows.push(boxShadow);
- });
- }
-
- // return undefined if array is empty, since it's not needed.
- return boxShadows.length > 0 ? boxShadows : undefined;
-}
-
-function requiredNumber(number: number): number {
- const rounded = roundNumber(number);
- if (rounded == 0) {
- return undefined;
- }
- return rounded;
-}
-
-/**
- * returns undefined, if offset is redundant.
- */
-function requiredOffset(offset: flutter.Offset): flutter.Offset {
- if (offset.dx == 0 && offset.dy == 0) {
- return undefined;
- }
- return offset;
-}
diff --git a/packages/designto-flutter/make/make-flutter-chip.ts b/packages/designto-flutter/make/make-flutter-chip.ts
index 5cae0d51..ddd54065 100644
--- a/packages/designto-flutter/make/make-flutter-chip.ts
+++ b/packages/designto-flutter/make/make-flutter-chip.ts
@@ -1,18 +1,21 @@
+import { retrievePrimaryColor } from "@design-sdk/core/utils";
import * as flutter from "@flutter-builder/flutter";
import { manifests } from "@reflect-ui/detection";
-import { makeBorderRadius } from ".";
-import { makeBorderSide } from "./make-flutter-border-side";
+import { borderside } from "../painting/painting-border-side";
import { makeColor } from "./make-flutter-color";
+import * as painting from "../painting";
export function makeChip(manifest: manifests.DetectedChipManifest) {
- console.log({ manifest });
var content = new flutter.Text(manifest.content?.text);
const color: flutter.Color = makeColor(manifest.base.fills);
const textColor: flutter.Color = makeColor(manifest.content?.fills);
const height = manifest.base.height;
const shape = new flutter.RoundedRectangleBorder({
- borderRadius: makeBorderRadius(manifest.base),
- side: makeBorderSide(manifest.base),
+ borderRadius: painting.borderRadius(manifest.base.cornerRadius),
+ side: borderside({
+ color: retrievePrimaryColor(manifest.base.strokes),
+ width: manifest.base.strokeWeight,
+ }),
});
const onSelected = flutter.Snippet.fromStatic(
'(){ print("Chip onSelected"); }'
diff --git a/packages/designto-flutter/make/make-flutter-color.ts b/packages/designto-flutter/make/make-flutter-color.ts
index 40980491..e0b77afd 100644
--- a/packages/designto-flutter/make/make-flutter-color.ts
+++ b/packages/designto-flutter/make/make-flutter-color.ts
@@ -1,24 +1,8 @@
import { Figma } from "@design-sdk/figma";
import { retrieveFill } from "@design-sdk/core/utils";
import * as flutter from "@flutter-builder/flutter";
-import * as core from "@reflect-ui/core";
import { converters } from "@reflect-ui/core/lib";
-/**
- * this does not support named colors yet.
- * @param color : Reflect#Color;
- * @returns
- */
-export function makeFlutterColorFromReflectColor(
- color: core.Color
-): flutter.Color {
- const hex = converters.color.convertReflectColorToUniversal(
- color,
- core.ColorFormat.hex
- );
- return flutter.Color.fromHex(hex);
-}
-
/**
* Retrieve the SOLID color for Flutter when existent, otherwise ""
*/
diff --git a/packages/designto-flutter/make/make-flutter-column-row.ts b/packages/designto-flutter/make/make-flutter-column-row.ts
index a4988aa4..81f6ba26 100644
--- a/packages/designto-flutter/make/make-flutter-column-row.ts
+++ b/packages/designto-flutter/make/make-flutter-column-row.ts
@@ -1,12 +1,9 @@
import { ReflectFrameNode } from "@design-sdk/core";
import * as flutter from "@flutter-builder/flutter";
import { Axis as ReflectAxis } from "@reflect-ui/core/lib";
-import {
- mapCrossAxisAlignment,
- mapMainAxisAlignment,
- mapMainAxisSize,
-} from "../core-type-mappers";
-import { makeSafelyAsList } from "../utils/make-as-safe-list";
+import * as dartui from "../dart-ui";
+import * as rendering from "../rendering";
+import { makeSafelyAsList } from "../utils";
export type RowOrColumn = "Row" | "Column";
export function makeRowColumn(
@@ -17,9 +14,17 @@ export function makeRowColumn(
const rowOrColumn: RowOrColumn =
node.layoutMode === ReflectAxis.horizontal ? "Row" : "Column";
- const _mainAxisAlignment = mapMainAxisAlignment(node.mainAxisAlignment);
- const _mainAxisSize: flutter.MainAxisSize = mapMainAxisSize(node.layoutGrow);
- const _crossAxisAlignment = mapCrossAxisAlignment(node.crossAxisAlignment);
+ const _mainAxisAlignment = rendering.mainAxisAlignment(
+ node.mainAxisAlignment
+ );
+ const _mainAxisSize: flutter.MainAxisSize = rendering.mainAxisSize(
+ // FIXME:
+ // @ts-ignore
+ node.layoutGrow
+ );
+ const _crossAxisAlignment = rendering.crossAxisAlignment(
+ node.crossAxisAlignment
+ );
// safely make childeren as list type
children = makeSafelyAsList(children);
diff --git a/packages/designto-flutter/make/make-flutter-divider.ts b/packages/designto-flutter/make/make-flutter-divider.ts
index 4ab3d27b..bf89c151 100644
--- a/packages/designto-flutter/make/make-flutter-divider.ts
+++ b/packages/designto-flutter/make/make-flutter-divider.ts
@@ -1,10 +1,8 @@
import { nodes } from "@design-sdk/core";
import * as core from "@reflect-ui/core";
import * as flutter from "@flutter-builder/flutter";
-import {
- makeColor,
- makeFlutterColorFromReflectColor,
-} from "./make-flutter-color";
+import { makeColor } from "./make-flutter-color";
+import * as dartui from "../dart-ui";
/**
*
@@ -20,7 +18,7 @@ export function makeFlutterDivider(
// Case 3 has no stroke, height > 0 && has fill
return new flutter.Divider({
height: divider.height,
- color: makeFlutterColorFromReflectColor(divider.color),
+ color: dartui.color(divider.color),
thickness: divider.thickness,
indent: divider.indent,
endIndent: divider.endIndent,
diff --git a/packages/designto-flutter/make/make-flutter-edge-insets.ts b/packages/designto-flutter/make/make-flutter-edge-insets.ts
deleted file mode 100755
index 92ca982c..00000000
--- a/packages/designto-flutter/make/make-flutter-edge-insets.ts
+++ /dev/null
@@ -1,62 +0,0 @@
-import { nodes, utils } from "@design-sdk/core";
-import * as flutter from "@flutter-builder/flutter";
-
-// This must happen before Stack or after the Positioned, but not before.
-export function makeEdgeInsets(
- node: nodes.ReflectSceneNode
-): flutter.EdgeInsetsGeometry {
- if (!("layoutMode" in node)) {
- return undefined;
- }
-
- const padding = utils.commonPadding(node);
-
- if (!padding) {
- return undefined;
- }
-
- if ("all" in padding) {
- return flutter.EdgeInsets.all(padding.all);
- }
-
- // horizontal and vertical, as the default AutoLayout
- if (
- padding.horizontal + padding.vertical !== 0 &&
- padding.top + padding.bottom + padding.left + padding.right === 0
- ) {
- const propHorizontalPadding: number =
- padding.horizontal > 0 ? padding.horizontal : undefined;
-
- const propVerticalPadding: number =
- padding.vertical > 0 ? padding.vertical : undefined;
-
- return flutter.EdgeInsets.symmetric({
- horizontal: propHorizontalPadding,
- vertical: propVerticalPadding,
- });
- }
-
- // all padding to 0 does not require padding.
- if (
- padding.left === 0 &&
- padding.right === 0 &&
- padding.top === 0 &&
- padding.bottom === 0
- ) {
- return undefined;
- }
-
- return flutter.EdgeInsets.only({
- left: getOnlyIfNotZero(padding.left || padding.horizontal),
- right: getOnlyIfNotZero(padding.right || padding.horizontal),
- top: getOnlyIfNotZero(padding.top || padding.vertical),
- bottom: getOnlyIfNotZero(padding.bottom || padding.vertical),
- });
-}
-
-function getOnlyIfNotZero(value): number {
- if (value === 0) {
- return;
- }
- return value;
-}
diff --git a/packages/designto-flutter/make/make-flutter-flat-button.ts b/packages/designto-flutter/make/make-flutter-flat-button.ts
index a154572f..b18cc1fc 100644
--- a/packages/designto-flutter/make/make-flutter-flat-button.ts
+++ b/packages/designto-flutter/make/make-flutter-flat-button.ts
@@ -1,10 +1,11 @@
import { manifests } from "@reflect-ui/detection";
import * as flutter from "@flutter-builder/flutter";
import { makeColor } from "./make-flutter-color";
-import { makeBorderRadius } from "./make-flutter-border-radius";
-import { makeBorderSide } from "./make-flutter-border-side";
+import { borderRadius } from "../painting/painting-border-radius";
+import { borderside } from "../painting/painting-border-side";
import { makeDetectedIcon } from "./make-flutter-icon";
import { onPressed } from "../static-snippets";
+import { retrievePrimaryColor } from "@design-sdk/core/utils";
export function makeFlatButton(manifest: manifests.DetectedButtonManifest) {
const text = new flutter.Text(manifest.text?.text);
@@ -13,8 +14,11 @@ export function makeFlatButton(manifest: manifests.DetectedButtonManifest) {
const minWidth = manifest.base.width;
const height = manifest.base.height;
const shape = new flutter.RoundedRectangleBorder({
- borderRadius: makeBorderRadius(manifest.base),
- side: makeBorderSide(manifest.base),
+ borderRadius: borderRadius(manifest.base.cornerRadius),
+ side: borderside({
+ color: retrievePrimaryColor(manifest.base.strokes),
+ width: manifest.base.strokeWeight,
+ }),
});
if (manifest.icon) {
diff --git a/packages/designto-flutter/make/make-flutter-icon.ts b/packages/designto-flutter/make/make-flutter-icon.ts
index 260b8ec1..061f61ff 100644
--- a/packages/designto-flutter/make/make-flutter-icon.ts
+++ b/packages/designto-flutter/make/make-flutter-icon.ts
@@ -6,7 +6,7 @@ import {
interpretFlutterMaterialIconData,
} from "../interpreter/icon.interpreter";
import { Color, IconManifest, MdiConfig } from "@reflect-ui/core";
-import { makeFlutterColorFromReflectColor } from "./make-flutter-color";
+import * as dartui from "../dart-ui";
import { DetectedIconData } from "@reflect-ui/detection/lib/icon.detection";
type FlutterDynamicIconLike = flutter.Icon | flutter.Image;
@@ -72,7 +72,7 @@ export function makeIcon({
}) {
return new flutter.Icon(icon, {
size: size,
- color: makeFlutterColorFromReflectColor(color),
+ color: dartui.color(color),
});
}
diff --git a/packages/designto-flutter/make/make-flutter-shape-border.ts b/packages/designto-flutter/make/make-flutter-shape-border.ts
index de432e84..0d69cb37 100644
--- a/packages/designto-flutter/make/make-flutter-shape-border.ts
+++ b/packages/designto-flutter/make/make-flutter-shape-border.ts
@@ -1,7 +1,7 @@
import * as flutter from "@flutter-builder/flutter";
-import { nodes } from "@design-sdk/core";
-import { makeBorderRadius } from "./make-flutter-border-radius";
+import * as painting from "../painting";
import { makeColor } from "./make-flutter-color";
+import { nodes } from "@design-sdk/core";
/**
* [Flutter#ShapeBorder](https://api.flutter.dev/flutter/painting/ShapeBorder-class.html)
@@ -16,7 +16,7 @@ export function makeShape(
| nodes.ReflectFrameNode
): flutter.ShapeBorder {
const strokeColor = makeColor(node.strokes);
- const side: flutter.Border =
+ const side: flutter.BorderSide =
strokeColor && node.strokeWeight > 0
? new flutter.BorderSide({
width: node.strokeWeight,
@@ -32,6 +32,6 @@ export function makeShape(
return new flutter.RoundedRectangleBorder({
side: side,
- borderRadius: makeBorderRadius(node),
+ borderRadius: painting.borderRadius(node.cornerRadius),
});
}
diff --git a/packages/designto-flutter/make/make-flutter-text-style.ts b/packages/designto-flutter/make/make-flutter-text-style.ts
index 18fb8086..12e27b6c 100644
--- a/packages/designto-flutter/make/make-flutter-text-style.ts
+++ b/packages/designto-flutter/make/make-flutter-text-style.ts
@@ -1,9 +1,10 @@
import * as flutter from "@flutter-builder/flutter";
-import * as core from "@reflect-ui/core";
-import { nodes } from "@design-sdk/core";
-import { makeColor } from ".";
+// import * as core from "@reflect-ui/core";
+// import { nodes } from "@design-sdk/core";
+// import { makeColor } from ".";
import { TextStyleRepository } from "@design-sdk/figma";
-import { roundDouble } from "../convert";
+// import { roundDouble } from "../convert";
+// import { fontStyle, mapTextDecoration } from "../core-type-mappers";
/**
* get the code of Text#style (text-style) via the name of the defined textstyle.
@@ -17,27 +18,8 @@ function getThemedTextStyleByName(textStyleName: string): flutter.TextStyle {
return flutter.Theme.of().textTheme[styleDef] as flutter.TextStyle;
}
-export function makeTextStyleFromDesign(
- style: core.ITextStyle
-): flutter.TextStyle {
- let decoration: flutter.TextDecoration = makeTextDecoration(style.decoration);
- const fontFamily: string = style.fontFamily;
- const fontWeight: flutter.FontWeight = flutter.FontWeight[style.fontWeight];
- // percentage is not supported
- const letterSpacing = style.letterSpacing;
- const fontStyle = makeFontStyle(style.fontStyle);
-
- return new flutter.TextStyle({
- fontSize: style.fontSize,
- fontWeight: fontWeight,
- fontFamily: fontFamily,
- fontStyle: fontStyle,
- letterSpacing: letterSpacing,
- decoration: decoration,
- });
-}
-
// TODO lineSpacing
+/* - use tokenized text manifest instead.
export function makeTextStyle(node: nodes.ReflectTextNode): flutter.TextStyle {
const fontColor: flutter.Color = makeColor(node.fills);
@@ -46,10 +28,10 @@ export function makeTextStyle(node: nodes.ReflectTextNode): flutter.TextStyle {
fontSize = node.fontSize;
}
- const decoration: flutter.TextDecoration = makeTextDecoration(
+ const decoration: flutter.TextDecoration = mapTextDecoration(
node.textStyle.decoration
);
- let fontStyle: flutter.FontStyle = makeFontStyle(node.textStyle.fontStyle);
+ let fontStyle: flutter.FontStyle = mapFontStyle(node.textStyle.fontStyle);
let fontFamily: string;
if (node.textStyle) {
@@ -88,25 +70,4 @@ export function makeTextStyle(node: nodes.ReflectTextNode): flutter.TextStyle {
decoration: decoration,
});
}
-
-export function makeFontStyle(style: core.FontStyle): flutter.FontStyle {
- switch (style) {
- case core.FontStyle.italic:
- return flutter.FontStyle.italic as flutter.Snippet;
- case core.FontStyle.normal:
- return; // not returning any value, since normal is a default value.
- }
-}
-
-export function makeTextDecoration(
- textDecoration: core.TextDecoration
-): flutter.TextDecoration {
- if (!textDecoration) {
- return;
- }
- let decoration: flutter.TextDecoration;
- if (textDecoration === core.TextDecoration.underline) {
- decoration = flutter.TextDecoration.underline as flutter.Snippet;
- }
- return decoration;
-}
+ */
diff --git a/packages/designto-flutter/make/make-flutter-text-theme.ts b/packages/designto-flutter/make/make-flutter-text-theme.ts
index a6f1da66..effb0eb7 100644
--- a/packages/designto-flutter/make/make-flutter-text-theme.ts
+++ b/packages/designto-flutter/make/make-flutter-text-theme.ts
@@ -1,11 +1,11 @@
import { TextStyleRepository, TextThemeStyles } from "@design-sdk/figma";
import * as flutter from "@flutter-builder/flutter";
-import { makeTextStyleFromDesign } from "./make-flutter-text-style";
+import * as painting from "../painting";
export function makeTextTheme(): flutter.TextTheme {
function buildTextStyle(style: TextThemeStyles): flutter.TextStyle {
try {
- return makeTextStyleFromDesign(
+ return painting.textStyle(
TextStyleRepository.getDefaultDesignTextStyleFromRegistry(style)
);
} catch (e) {
diff --git a/packages/designto-flutter/make/make-flutter-text.ts b/packages/designto-flutter/make/make-flutter-text.ts
index e1e4bc3a..30fe30c7 100644
--- a/packages/designto-flutter/make/make-flutter-text.ts
+++ b/packages/designto-flutter/make/make-flutter-text.ts
@@ -1,8 +1,8 @@
import * as flutter from "@flutter-builder/flutter";
import { nodes } from "@design-sdk/figma";
-import { makeTextStyle } from "./make-flutter-text-style";
-import { mapTextAlign } from "../core-type-mappers";
import { escapeDartString } from "@coli.codes/escape-string";
+import * as dartui from "../dart-ui";
+import * as painting from "../painting";
/**
* [Flutter#Text](https://flutter.dev/docs/development/ui/widgets/text)
@@ -11,7 +11,7 @@ import { escapeDartString } from "@coli.codes/escape-string";
* @param node text node from desing
*/
export function makeText(node: nodes.ReflectTextNode): flutter.Text {
- const textAlign = mapTextAlign(node.textAlign);
+ const textAlign = dartui.textAlign(node.textAlign);
//#region get text content
let text = node.text;
@@ -28,13 +28,14 @@ export function makeText(node: nodes.ReflectTextNode): flutter.Text {
case "ORIGINAL":
break;
}
-
//#endregion
+
const escapedText = escapeDartString(text);
- const textStyle = makeTextStyle(node);
+ // throw "not used";
+ // const textStyle = painting.textStyle(node);
return new flutter.Text(escapedText, {
- style: textStyle,
+ // style: textStyle,
textAlign: textAlign,
});
}
diff --git a/packages/designto-flutter/painting/index.ts b/packages/designto-flutter/painting/index.ts
new file mode 100644
index 00000000..0dcb3e0a
--- /dev/null
+++ b/packages/designto-flutter/painting/index.ts
@@ -0,0 +1,13 @@
+export * from "./painting-alignment";
+export * from "./painting-border-radius";
+export * from "./painting-edge-insets";
+export * from "./painting-box-shape";
+export * from "./painting-box-shadow";
+export * from "./painting-border";
+export * from "./painting-border-side";
+export * from "./painting-text-style";
+export * from "./painting-text-decoration";
+export * from "./painting-font-style";
+export * from "./painting-linear-gradient";
+export * from "./painting-vertical-direction";
+export * from "./painting-box-decoration";
diff --git a/packages/designto-flutter/core-type-mappers/alignment.mapper.ts b/packages/designto-flutter/painting/painting-alignment.ts
similarity index 93%
rename from packages/designto-flutter/core-type-mappers/alignment.mapper.ts
rename to packages/designto-flutter/painting/painting-alignment.ts
index f153708a..1019dfe5 100644
--- a/packages/designto-flutter/core-type-mappers/alignment.mapper.ts
+++ b/packages/designto-flutter/painting/painting-alignment.ts
@@ -1,7 +1,7 @@
import { Alignment } from "@reflect-ui/core";
import * as flutter from "@flutter-builder/flutter";
-export function mapAlignment(a: Alignment): flutter.Alignment {
+export function alignment(a: Alignment): flutter.Alignment {
// TODO: Alignemt value comparison won't work. (not tested)
switch (a) {
case Alignment.center: {
diff --git a/packages/designto-flutter/painting/painting-border-radius.ts b/packages/designto-flutter/painting/painting-border-radius.ts
new file mode 100644
index 00000000..ad07c063
--- /dev/null
+++ b/packages/designto-flutter/painting/painting-border-radius.ts
@@ -0,0 +1,35 @@
+import * as flutter from "@flutter-builder/flutter";
+import { roundNumber } from "@reflect-ui/uiutils";
+import * as dartui from "../dart-ui";
+import { BorderRadius, BorderRadiusManifest } from "@reflect-ui/core";
+
+export function borderRadius(br: BorderRadius): flutter.BorderRadiusGeometry {
+ if (br === undefined || br.all === 0) {
+ return undefined;
+ }
+
+ return br.all !== undefined
+ ? flutter.BorderRadius.circular(roundNumber(br.all as number))
+ : _partialBorderRadius(br);
+}
+
+function _partialBorderRadius(cornerRadius: BorderRadiusManifest) {
+ const _oneofRadiusIsHasValue = [
+ cornerRadius.tl,
+ cornerRadius.tr,
+ cornerRadius.bl,
+ cornerRadius.br,
+ ].some((i) => i !== undefined);
+
+ if (_oneofRadiusIsHasValue) {
+ return flutter.BorderRadius.only({
+ topLeft: dartui.radius(cornerRadius.tl),
+ topRight: dartui.radius(cornerRadius.tr),
+ bottomLeft: dartui.radius(cornerRadius.bl),
+ bottomRight: dartui.radius(cornerRadius.br),
+ });
+ } else {
+ // if none of each corner radius contains value (if every value is empty) do not return a value.
+ return;
+ }
+}
diff --git a/packages/designto-flutter/painting/painting-border-side.ts b/packages/designto-flutter/painting/painting-border-side.ts
new file mode 100644
index 00000000..d7fbdb10
--- /dev/null
+++ b/packages/designto-flutter/painting/painting-border-side.ts
@@ -0,0 +1,11 @@
+import * as flutter from "@flutter-builder/flutter";
+import type { Color } from "@reflect-ui/core";
+import { roundNumber } from "@reflect-ui/uiutils";
+import * as dartui from "../dart-ui";
+
+export function borderside({ color, width }: { color: Color; width: number }) {
+ return new flutter.BorderSide({
+ color: dartui.color(color),
+ width: roundNumber(width),
+ });
+}
diff --git a/packages/designto-flutter/painting/painting-border.ts b/packages/designto-flutter/painting/painting-border.ts
new file mode 100644
index 00000000..94ece86b
--- /dev/null
+++ b/packages/designto-flutter/painting/painting-border.ts
@@ -0,0 +1,41 @@
+import * as flutter from "@flutter-builder/flutter";
+import { Border } from "@reflect-ui/core";
+import { borderside } from "./painting-border-side";
+
+// generate the border, when it exists
+export function border(border: Border): flutter.Border {
+ if (!border) {
+ return;
+ }
+
+ if (
+ // at least one side of the border's width shoul be higher than 0.
+ border.left?.width ||
+ border.right?.width ||
+ border.top?.width ||
+ border.bottom?.width
+ ) {
+ return new flutter.Border({
+ left: border.left ? borderside(border.left) : flutter.BorderSide.none,
+ top: border.top ? borderside(border.top) : flutter.BorderSide.none,
+ right: border.right ? borderside(border.right) : flutter.BorderSide.none,
+ bottom: border.bottom
+ ? borderside(border.bottom)
+ : flutter.BorderSide.none,
+ });
+ }
+
+ // TODO: support shorthands.
+ // 1. flutter.Border.all
+ // 2. flutter.Border.fromBorderSide
+ // 3. flutter.Border.symmetric
+
+ // border.
+ // generate the border, when it should exist
+ // return node.strokeWeight
+ // ? flutter.Border.all({
+ // color: makeColor(node.strokes),
+ // width: roundNumber(node.strokeWeight),
+ // })
+ // : undefined;
+}
diff --git a/packages/designto-flutter/painting/painting-box-decoration.ts b/packages/designto-flutter/painting/painting-box-decoration.ts
new file mode 100644
index 00000000..6fcf9b5f
--- /dev/null
+++ b/packages/designto-flutter/painting/painting-box-decoration.ts
@@ -0,0 +1,49 @@
+import { BoxDecoration } from "@flutter-builder/flutter";
+import { Color } from "@reflect-ui/core";
+import { Background } from "@reflect-ui/core/lib/background";
+import * as dartui from "../dart-ui";
+
+function fromColor(color: Color): BoxDecoration {
+ return new BoxDecoration({
+ color: dartui.color(color),
+ });
+}
+
+function fromBackground(b: Background): BoxDecoration {
+ if (!b) {
+ return;
+ }
+
+ if (Array.isArray(b)) {
+ throw "multiple bg not supported";
+ } else {
+ switch (b.type) {
+ case "gradient": {
+ console.error("gradient bg not ready");
+ break;
+ }
+ case "graphics": {
+ console.error("graphics bg not ready");
+ break;
+ }
+ case "solid-color": {
+ return fromColor(b as Color);
+ }
+ }
+ }
+}
+
+function fromGradient(): BoxDecoration {
+ throw "not ready.";
+}
+
+function fromImage(): BoxDecoration {
+ throw "not ready.";
+}
+
+export const boxDecorationPart = {
+ fromColor: fromColor,
+ fromBackground: fromBackground,
+ fromGradient: fromGradient,
+ fromImage: fromImage,
+};
diff --git a/packages/designto-flutter/painting/painting-box-shadow.ts b/packages/designto-flutter/painting/painting-box-shadow.ts
new file mode 100644
index 00000000..5c77dee8
--- /dev/null
+++ b/packages/designto-flutter/painting/painting-box-shadow.ts
@@ -0,0 +1,50 @@
+import * as flutter from "@flutter-builder/flutter";
+import * as dartui from "../dart-ui";
+import { roundNumber } from "@reflect-ui/uiutils";
+import { BoxShadowManifest } from "@reflect-ui/core";
+
+export function boxShadow(
+ shadows: ReadonlyArray
+): Array {
+ // if no shadow filtered available, return undefined
+ if (shadows.length == 0) {
+ return undefined;
+ }
+
+ const boxShadows: Array = shadows.map(
+ (d: BoxShadowManifest) => {
+ return new flutter.BoxShadow({
+ color: dartui.color(d.color),
+ blurRadius: requiredNumber(d.blurRadius),
+ spreadRadius: requiredNumber(d.spreadRadius),
+ offset: dartui.offset(d.offset),
+ });
+
+ // if (d.type == "INNER_SHADOW") {
+ // handling inner shadow
+ // https://stackoverflow.com/a/55096682/5463235
+ // inner shadow disabled.
+ // --------------------------------
+ // return new flutter.BoxShadow({
+ // color: makeColorFromRGBO(d.color, d.color.a),
+ // blurRadius: requiredNumber(d.radius),
+ // // multiply -1 * blur for spread
+ // // TODO inspect this logic again.
+ // spreadRadius: requiredNumber((d.spread + d.radius) * -1),
+ // offset: requiredOffset(new flutter.Offset(d.offset.x, d.offset.y)),
+ // });
+ // }
+ }
+ );
+
+ // return undefined if array is empty, since it's not needed.
+ return boxShadows.length > 0 ? boxShadows : undefined;
+}
+
+function requiredNumber(number: number): number {
+ const rounded = roundNumber(number);
+ if (rounded == 0) {
+ return undefined;
+ }
+ return rounded;
+}
diff --git a/packages/designto-flutter/painting/painting-box-shape.ts b/packages/designto-flutter/painting/painting-box-shape.ts
new file mode 100644
index 00000000..cf15d893
--- /dev/null
+++ b/packages/designto-flutter/painting/painting-box-shape.ts
@@ -0,0 +1,17 @@
+import { BoxShape } from "@reflect-ui/core";
+import * as flutter from "@flutter-builder/flutter";
+
+export function boxshape(shape: BoxShape): flutter.BoxShape {
+ if (!shape) {
+ return;
+ }
+
+ switch (shape) {
+ case BoxShape.circle:
+ return flutter.BoxShape.circle as flutter.BoxShape;
+ case BoxShape.rectangle:
+ return flutter.BoxShape.rectangle as flutter.BoxShape;
+ default:
+ throw new Error("Unknown BoxShape: " + shape);
+ }
+}
diff --git a/packages/designto-flutter/painting/painting-edge-insets.ts b/packages/designto-flutter/painting/painting-edge-insets.ts
new file mode 100644
index 00000000..dd7251d1
--- /dev/null
+++ b/packages/designto-flutter/painting/painting-edge-insets.ts
@@ -0,0 +1,49 @@
+import { EdgeInsets } from "@reflect-ui/core";
+import * as flutter from "@flutter-builder/flutter";
+
+export function edgeinsets(ei: EdgeInsets): flutter.EdgeInsets {
+ if (!ei) {
+ return undefined;
+ }
+
+ if ("all" in ei) {
+ // missing usage of commonPadding();
+ return flutter.EdgeInsets.all((ei as any).all);
+ }
+
+ // horizontal and vertical, as the default AutoLayout
+ if (
+ ei.horizontal + ei.vertical !== 0 &&
+ ei.top + ei.bottom + ei.left + ei.right === 0
+ ) {
+ const propHorizontalPadding: number =
+ ei.horizontal > 0 ? ei.horizontal : undefined;
+
+ const propVerticalPadding: number =
+ ei.vertical > 0 ? ei.vertical : undefined;
+
+ return flutter.EdgeInsets.symmetric({
+ horizontal: propHorizontalPadding,
+ vertical: propVerticalPadding,
+ });
+ }
+
+ // all padding to 0 does not require padding.
+ if (ei.left === 0 && ei.right === 0 && ei.top === 0 && ei.bottom === 0) {
+ return undefined;
+ }
+
+ return flutter.EdgeInsets.only({
+ left: getOnlyIfNotZero(ei.left || ei.horizontal),
+ right: getOnlyIfNotZero(ei.right || ei.horizontal),
+ top: getOnlyIfNotZero(ei.top || ei.vertical),
+ bottom: getOnlyIfNotZero(ei.bottom || ei.vertical),
+ });
+}
+
+function getOnlyIfNotZero(value): number {
+ if (value === 0) {
+ return;
+ }
+ return value;
+}
diff --git a/packages/designto-flutter/painting/painting-font-style.ts b/packages/designto-flutter/painting/painting-font-style.ts
new file mode 100644
index 00000000..cea909a1
--- /dev/null
+++ b/packages/designto-flutter/painting/painting-font-style.ts
@@ -0,0 +1,11 @@
+import { FontStyle } from "@reflect-ui/core";
+import * as flutter from "@flutter-builder/flutter";
+
+export function fontStyle(style: FontStyle): flutter.FontStyle {
+ switch (style) {
+ case FontStyle.italic:
+ return flutter.FontStyle.italic as flutter.Snippet;
+ case FontStyle.normal:
+ return; // not returning any value, since normal is a default value.
+ }
+}
diff --git a/packages/designto-flutter/painting/painting-linear-gradient.ts b/packages/designto-flutter/painting/painting-linear-gradient.ts
new file mode 100644
index 00000000..fcc4cb28
--- /dev/null
+++ b/packages/designto-flutter/painting/painting-linear-gradient.ts
@@ -0,0 +1,13 @@
+import { LinearGradient } from "@reflect-ui/core";
+import * as flutter from "@flutter-builder/flutter";
+import { alignment } from "./painting-alignment";
+import * as dartui from "../dart-ui";
+
+export function linearGradient(g: LinearGradient): flutter.LinearGradient {
+ return new flutter.LinearGradient({
+ begin: alignment(g.begin),
+ end: alignment(g.end),
+ colors: g.colors.map((c) => dartui.color(c)),
+ stops: g.stops,
+ });
+}
diff --git a/packages/designto-flutter/painting/painting-text-decoration.ts b/packages/designto-flutter/painting/painting-text-decoration.ts
new file mode 100644
index 00000000..d7bbcc02
--- /dev/null
+++ b/packages/designto-flutter/painting/painting-text-decoration.ts
@@ -0,0 +1,15 @@
+import { TextDecoration } from "@reflect-ui/core";
+import * as flutter from "@flutter-builder/flutter";
+
+export function textDecoration(
+ textDecoration: TextDecoration
+): flutter.TextDecoration {
+ if (!textDecoration) {
+ return;
+ }
+ let decoration: flutter.TextDecoration;
+ if (textDecoration === TextDecoration.underline) {
+ decoration = flutter.TextDecoration.underline as flutter.Snippet;
+ }
+ return decoration;
+}
diff --git a/packages/designto-flutter/painting/painting-text-style.ts b/packages/designto-flutter/painting/painting-text-style.ts
new file mode 100644
index 00000000..577a22ad
--- /dev/null
+++ b/packages/designto-flutter/painting/painting-text-style.ts
@@ -0,0 +1,21 @@
+import type { ITextStyle } from "@reflect-ui/core";
+import * as flutter from "@flutter-builder/flutter";
+import { textDecoration } from "./painting-text-decoration";
+import { fontStyle } from "./painting-font-style";
+import * as dartui from "../dart-ui";
+
+export function textStyle(style: ITextStyle): flutter.TextStyle {
+ const { fontFamily, letterSpacing } = style;
+ let decoration: flutter.TextDecoration = textDecoration(style.decoration);
+ const fontWeight: flutter.FontWeight = flutter.FontWeight[style.fontWeight];
+
+ return new flutter.TextStyle({
+ fontSize: style.fontSize,
+ fontWeight: fontWeight,
+ fontFamily: fontFamily,
+ color: dartui.color(style.color),
+ fontStyle: fontStyle(style.fontStyle),
+ letterSpacing: letterSpacing, // percentage is not supported
+ decoration: decoration,
+ });
+}
diff --git a/packages/designto-flutter/painting/painting-vertical-direction.ts b/packages/designto-flutter/painting/painting-vertical-direction.ts
new file mode 100644
index 00000000..3fc48ea2
--- /dev/null
+++ b/packages/designto-flutter/painting/painting-vertical-direction.ts
@@ -0,0 +1,14 @@
+import { VerticalDirection } from "@reflect-ui/core";
+import * as flutter from "@flutter-builder/flutter";
+
+export function verticalDirection(
+ vd: VerticalDirection
+): flutter.VerticalDirection {
+ switch (vd) {
+ case VerticalDirection.up:
+ return flutter.VerticalDirection.up as flutter.VerticalDirection;
+ case VerticalDirection.down:
+ return flutter.VerticalDirection.down as flutter.VerticalDirection;
+ }
+ throw new Error(`unknown vertical direction ${vd}`);
+}
diff --git a/packages/designto-flutter/rendering/index.ts b/packages/designto-flutter/rendering/index.ts
new file mode 100644
index 00000000..41e9e480
--- /dev/null
+++ b/packages/designto-flutter/rendering/index.ts
@@ -0,0 +1,3 @@
+export * from "./rendering-cross-axis-alignment";
+export * from "./rendering-main-axis-alignment";
+export * from "./rendering-main-axis-size";
diff --git a/packages/designto-flutter/core-type-mappers/cross-axis-alignment.mapper.ts b/packages/designto-flutter/rendering/rendering-cross-axis-alignment.ts
similarity index 94%
rename from packages/designto-flutter/core-type-mappers/cross-axis-alignment.mapper.ts
rename to packages/designto-flutter/rendering/rendering-cross-axis-alignment.ts
index def38069..09c1efd9 100644
--- a/packages/designto-flutter/core-type-mappers/cross-axis-alignment.mapper.ts
+++ b/packages/designto-flutter/rendering/rendering-cross-axis-alignment.ts
@@ -4,7 +4,7 @@ import * as core from "@reflect-ui/core/lib";
* returns CrossAxisAlignment by counterAxisAlignItems
* @param crossAxisAlignItems
*/
-export function mapCrossAxisAlignment(
+export function crossAxisAlignment(
crossAxisAlignItems: core.CrossAxisAlignment
): CrossAxisAlignment {
switch (crossAxisAlignItems) {
diff --git a/packages/designto-flutter/core-type-mappers/main-axis-alignment.mapper.ts b/packages/designto-flutter/rendering/rendering-main-axis-alignment.ts
similarity index 94%
rename from packages/designto-flutter/core-type-mappers/main-axis-alignment.mapper.ts
rename to packages/designto-flutter/rendering/rendering-main-axis-alignment.ts
index 882f33eb..d3a63a96 100644
--- a/packages/designto-flutter/core-type-mappers/main-axis-alignment.mapper.ts
+++ b/packages/designto-flutter/rendering/rendering-main-axis-alignment.ts
@@ -1,7 +1,7 @@
import { MainAxisAlignment, Snippet } from "@flutter-builder/flutter";
import { MainAxisAlignment as ReflectMainAxisAlignment } from "@reflect-ui/core/lib";
-export function mapMainAxisAlignment(
+export function mainAxisAlignment(
mainAxisAlignemt: ReflectMainAxisAlignment
): MainAxisAlignment {
switch (mainAxisAlignemt) {
diff --git a/packages/designto-flutter/rendering/rendering-main-axis-size.ts b/packages/designto-flutter/rendering/rendering-main-axis-size.ts
new file mode 100644
index 00000000..be6f5371
--- /dev/null
+++ b/packages/designto-flutter/rendering/rendering-main-axis-size.ts
@@ -0,0 +1,11 @@
+import { MainAxisSize } from "@reflect-ui/core";
+import * as flutter from "@flutter-builder/flutter";
+
+export function mainAxisSize(m: MainAxisSize): flutter.MainAxisSize {
+ switch (m) {
+ case MainAxisSize.max:
+ return flutter.MainAxisSize.max;
+ case MainAxisSize.min:
+ return flutter.MainAxisSize.min;
+ }
+}
diff --git a/packages/designto-flutter/tokens-to-flutter-widget/index.ts b/packages/designto-flutter/tokens-to-flutter-widget/index.ts
new file mode 100644
index 00000000..077dab0f
--- /dev/null
+++ b/packages/designto-flutter/tokens-to-flutter-widget/index.ts
@@ -0,0 +1,373 @@
+import * as core from "@reflect-ui/core";
+import * as flutter from "@flutter-builder/flutter";
+import * as painting from "../painting";
+import * as rendering from "../rendering";
+import * as dartui from "../dart-ui";
+import { tokens as special, t2t } from "@designto/token";
+import { MainImageRepository } from "@design-sdk/core/assets-repository";
+import { Axis, BoxShape } from "@reflect-ui/core";
+import { escapeDartString } from "@coli.codes/escape-string";
+import { boxDecorationPart } from "../painting";
+import {
+ flutter_handle_svg_vector_as_bitmap_converted,
+ handle_flutter_case_nested_positioned_stack,
+ handle_flutter_case_no_size_stack_children,
+} from "../case-handling";
+
+export function buildFlutterWidgetFromTokens(
+ widget: core.Widget
+): flutter.Widget {
+ const composed = compose(widget, {
+ is_root: true,
+ });
+
+ if (process.env.NODE_ENV === "development") {
+ console.info("dev::", "final flutter token composed", composed);
+ }
+
+ return composed;
+}
+
+function compose(widget: core.Widget, context: { is_root: boolean }) {
+ const handleChildren = (children: core.Widget[]): flutter.Widget[] => {
+ return children?.map((c) => {
+ return handleChild(c);
+ });
+ };
+
+ const handleChild = (child: core.Widget): flutter.Widget => {
+ return compose(child, { ...context, is_root: false });
+ };
+
+ const _remove_width_height_if_root_wh = {
+ width: context.is_root ? undefined : widget.width,
+ height: context.is_root ? undefined : widget.height,
+ };
+
+ const default_props_for_layout = {
+ ...widget,
+ ..._remove_width_height_if_root_wh,
+ };
+
+ const flex_props = (f: core.Flex) => {
+ return {
+ mainAxisAlignment: rendering.mainAxisAlignment(f.mainAxisAlignment),
+ crossAxisAlignment: rendering.crossAxisAlignment(f.crossAxisAlignment),
+ mainAxisSize: rendering.mainAxisSize(f.mainAxisSize),
+ verticalDirection: painting.verticalDirection(f.verticalDirection),
+ };
+ };
+ // const _key = keyFromWidget(widget);
+
+ let thisFlutterWidget: flutter.Widget;
+ if (widget instanceof core.Column) {
+ const children = compose_item_spacing_children(widget.children, {
+ itemspacing: widget.itemSpacing,
+ axis: widget.direction,
+ });
+ thisFlutterWidget = new flutter.Column({
+ ...default_props_for_layout,
+ ...flex_props(widget),
+ children: children,
+ // key: _key,
+ });
+ } else if (widget instanceof core.Row) {
+ const children = compose_item_spacing_children(widget.children, {
+ itemspacing: widget.itemSpacing,
+ axis: widget.direction,
+ });
+ thisFlutterWidget = new flutter.Row({
+ ...default_props_for_layout,
+ ...flex_props(widget),
+ children: children,
+ // key: _key,
+ });
+ } else if (widget instanceof core.Flex) {
+ // FIXME: FLEX not supported yet.
+ // thisFlutterWidget = new flutter.Flex({
+ // // direction: widget.direction,
+ // // ...widget,
+ // // ...default_props_for_layout,
+ // children: handleChildren(widget.children),
+ // // key: _key,
+ // });
+ } else if (widget instanceof core.Stack) {
+ const _remove_overflow_if_root_overflow = {
+ clipBehavior: context.is_root
+ ? undefined
+ : (widget as core.Stack).clipBehavior,
+ };
+
+ const children = handle_flutter_case_no_size_stack_children(
+ handleChildren(widget.children as [])
+ );
+ const stack = new flutter.Stack({
+ ...default_props_for_layout,
+ ..._remove_overflow_if_root_overflow,
+ children: children,
+ // key: _key,
+ });
+ if (!context.is_root) {
+ thisFlutterWidget = handle_flutter_case_nested_positioned_stack(stack);
+ } else {
+ thisFlutterWidget = stack;
+ }
+ } else if (widget instanceof core.SingleChildScrollView) {
+ const _child = handleChild(widget.child);
+ thisFlutterWidget = new flutter.SingleChildScrollView({
+ // TODO: map axis
+ // scrollDirection: widget.direction,
+ child: _child,
+ });
+ } else if (widget instanceof core.Positioned) {
+ const _tmp_length_convert = (l) => {
+ return l as number;
+ };
+
+ const _child = handleChild(widget.child);
+ if (_child) {
+ thisFlutterWidget = new flutter.Positioned({
+ left: widget.left && _tmp_length_convert(widget.left),
+ right: widget.right && _tmp_length_convert(widget.right),
+ top: widget.top && _tmp_length_convert(widget.top),
+ bottom: widget.bottom && _tmp_length_convert(widget.bottom),
+ child: _child,
+ });
+ // -------------------------------------
+ // override w & h with position provided w/h
+ if (_child instanceof flutter.Container) {
+ _child.width = widget.width;
+ _child.height = widget.height;
+ }
+ // -------------------------------------
+ }
+ } else if (widget instanceof core.Opacity) {
+ thisFlutterWidget = new flutter.Opacity({
+ opacity: widget.opacity,
+ child: handleChild(widget.child),
+ });
+ }
+ // ----- region clip path ------
+ else if (widget instanceof core.ClipRRect) {
+ // FIXME: flutter clip rrect support is not ready.
+ thisFlutterWidget = handleChild(widget.child);
+ } else if (widget instanceof core.ClipPath) {
+ // FIXME: flutter clip path support is not ready.
+ thisFlutterWidget = handleChild(widget.child);
+ }
+ // ----- endregion clip path ------
+ else if (widget instanceof core.Text) {
+ const _escaped_dart_string = escapeDartString(widget.data);
+ thisFlutterWidget = new flutter.Text(_escaped_dart_string, {
+ ...widget,
+ style: painting.textStyle(widget.style),
+ /** explicit assignment - field name is different */
+ // key: _key,
+ });
+ } else if (widget instanceof core.VectorWidget) {
+ const id = widget.key.id;
+ // use widget as baked image.
+ thisFlutterWidget = handleChild(t2t.vector_token_to_image_token(widget));
+ // TODO: convert vector data to bitmap, host the image, than load.
+ // thisFlutterWidget = flutter_handle_svg_vector_as_bitmap_converted(widget);
+ } else if (widget instanceof core.ImageWidget) {
+ thisFlutterWidget = flutter.Image.network(widget.src, {
+ width: widget.width,
+ height: widget.height,
+ // fit?: BoxFit;
+ // key: _key,
+ });
+ } else if (widget instanceof core.IconWidget) {
+ // TODO: not ready - svg & named icon not supported
+
+ switch ((widget.icon as core.IconData)._type) {
+ case "named-icon": {
+ const _tmp_icon_as_img = MainImageRepository.instance
+ .get("fill-later-assets")
+ .addImage({
+ key: widget.key.id,
+ });
+
+ thisFlutterWidget = flutter.Image.network(
+ _tmp_icon_as_img.url ||
+ /*fallback*/ "https://bridged-service-static.s3.us-west-1.amazonaws.com/branding/logo/32.png", // TODO: change this
+ {
+ width: widget.width,
+ height: widget.height,
+ // fit?: BoxFit;
+ // key: _key,
+ }
+ );
+ break;
+ }
+ case "remote-uri": {
+ thisFlutterWidget = flutter.Image.network(widget.icon.uri, {
+ width: widget.size,
+ height: widget.size,
+ semanticLabel: "icon",
+ // key: _key,
+ });
+ break;
+ }
+ }
+ }
+
+ // execution order matters - some above widgets inherits from Container, this shall be handled at the last.
+ else if (widget instanceof core.Container) {
+ // flutter cannot set both shape circle & border radius.
+ let _deco_part_shape_and_border_radius = {};
+ if (widget.shape == BoxShape.circle) {
+ _deco_part_shape_and_border_radius = {
+ shape: painting.boxshape(widget.shape),
+ borderRadius: undefined,
+ };
+ } else {
+ _deco_part_shape_and_border_radius = {
+ borderRadius: painting.borderRadius(widget.borderRadius),
+ shape: painting.boxshape(widget.shape),
+ };
+ }
+
+ const _deco_part_bg = boxDecorationPart.fromBackground(widget.background);
+
+ thisFlutterWidget = new flutter.Container({
+ padding: painting.edgeinsets(widget.padding),
+ margin: painting.edgeinsets(widget.margin),
+ width: widget.width,
+ height: widget.height,
+ decoration: new flutter.BoxDecoration({
+ border: painting.border(widget.border),
+ ..._deco_part_shape_and_border_radius,
+ ..._deco_part_bg,
+ // TODO:
+ // boxShadow:
+ // background:
+ }),
+ // key: _key,
+ });
+ // thisFlutterWidget.x = widget.x;
+ // thisFlutterWidget.y = widget.y;
+ // thisFlutterWidget.background = widget.background;
+ }
+
+ // -------------------------------------
+ // special tokens
+ // -------------------------------------
+ else if (widget instanceof special.Stretched) {
+ let remove_size;
+ switch (widget.axis) {
+ case Axis.horizontal:
+ remove_size = "height";
+ break;
+ case Axis.vertical:
+ remove_size = "width";
+ break;
+ }
+
+ thisFlutterWidget = handleChild(widget.child);
+ thisFlutterWidget = wrap_with_sized_and_inject_size(thisFlutterWidget, {
+ [remove_size]: undefined, // Double.infinity,
+ });
+ }
+ // -------------------------------------
+
+ // -------------------------------------
+ // end of logic gate
+ // -------------------------------------
+ else {
+ // todo - handle case more specific
+ thisFlutterWidget = new flutter.ErrorWidget.withDetails({
+ // key: _key,
+ message: `The input design was not handled. "${
+ widget.key.originName
+ }" type of "${widget._type}" - ${JSON.stringify(widget.key)}`,
+ });
+ }
+ // -------------------------------------
+ // -------------------------------------
+
+ // post extending - do not abuse this
+ if (context.is_root) {
+ // TODO: add overflow x hide handling by case.
+ }
+
+ return thisFlutterWidget;
+}
+
+/**
+ * children under col / row with item spacing on each between with sizedbox.
+ * ```
+ * s = SizedBox()
+ * | 1 | 2 | 3 | 4 |
+ * | 1 | s | 2 | s | 3 | s | 4
+ * ```
+ */
+function compose_item_spacing_children(
+ children: core.Widget[],
+ args: {
+ itemspacing: number;
+ axis: Axis;
+ }
+) {
+ let injection = undefined;
+ if (args.itemspacing) {
+ const wh = args.axis === Axis.horizontal ? "width" : "height";
+ injection = new flutter.SizedBox({
+ [wh]: args.itemspacing,
+ });
+ }
+ return compoes_children_with_injection(children, injection);
+}
+
+/**
+ * children under col / row with item spacing on each between.
+ * ```
+ * | 1 | 2 | 3 | 4 |
+ * | 1 | x | 2 | x | 3 | x | 4
+ * ```
+ */
+function compoes_children_with_injection(
+ children: core.Widget[],
+ between?: flutter.Widget
+): flutter.Widget[] {
+ const composedchildren = children.map((c) => {
+ return compose(c, {
+ is_root: false,
+ });
+ });
+
+ const result: flutter.Widget[] = [];
+ composedchildren.forEach((c, i) => {
+ result.push(c);
+ if (between) {
+ if (i !== children.length - 1) {
+ result.push(between);
+ }
+ }
+ });
+ return result;
+ // const result = array.reduce((r, a) => r.concat(a, 0), [0]);
+}
+
+function wrap_with_sized_and_inject_size(
+ widget: flutter.Widget,
+ size: {
+ width?: flutter.double;
+ height?: flutter.double;
+ }
+) {
+ if (
+ widget instanceof flutter.Container ||
+ widget instanceof flutter.SizedBox
+ ) {
+ size.width && (widget.width = size.width);
+ size.height && (widget.height = size.height);
+ return widget;
+ } else {
+ return new flutter.SizedBox({
+ child: widget,
+ width: size.width,
+ height: size.height,
+ });
+ }
+}
diff --git a/packages/designto-flutter/wrappers/container.wrap.ts b/packages/designto-flutter/wrappers/container.wrap.ts
index 41af7abb..086e23b9 100755
--- a/packages/designto-flutter/wrappers/container.wrap.ts
+++ b/packages/designto-flutter/wrappers/container.wrap.ts
@@ -1,10 +1,10 @@
-import { convertToSize } from "../convert";
+import { convertToSize } from "../_utils";
import { nodes } from "@design-sdk/core";
-import { makeEdgeInsets } from "../make";
import { array } from "@reflect-ui/uiutils";
import * as flutter from "@flutter-builder/flutter";
import { makeBoxDecoration } from "../make/make-flutter-box-decoration";
-import { roundDouble } from "../convert/double.convert";
+import { roundDouble } from "../_utils";
+import * as painting from "../painting";
export function wrapWithContainer(
node:
@@ -38,7 +38,7 @@ export function wrapWithContainer(
let _padding: flutter.EdgeInsetsGeometry;
if (node instanceof nodes.ReflectFrameNode) {
- _padding = makeEdgeInsets(node);
+ _padding = painting.edgeinsets(node.padding);
}
// Container is a container if [_size] or [_boxDecoration] are set.
diff --git a/packages/designto-flutter/wrappers/material.wrap.ts b/packages/designto-flutter/wrappers/material.wrap.ts
index 3137455b..291b19a1 100755
--- a/packages/designto-flutter/wrappers/material.wrap.ts
+++ b/packages/designto-flutter/wrappers/material.wrap.ts
@@ -1,10 +1,10 @@
-import { convertToSize } from "../convert/size.convert";
+import { convertToSize } from "../_utils";
import { Figma, nodes } from "@design-sdk/figma";
import { converters } from "@reflect-ui/core/lib";
import * as flutter from "@flutter-builder/flutter";
-import { makeColor } from "../make/color.make";
-import { makeShape as makeShape } from "../make/shape.make";
-import { makeBorderRadius } from "../make/border-radius.make";
+// import { makeColor } from "../make/color.make";
+// import { makeShape as makeShape } from "../make/shape.make";
+// import { makeBorderRadius } from "../make/border-radius.make";
import { wrapWithPadding } from "./padding.wrap";
// https://api.flutter.dev/flutter/material/Material-class.html
diff --git a/packages/designto-flutter/wrappers/positioned.wrap.ts b/packages/designto-flutter/wrappers/positioned.wrap.ts
index 095bf391..9e78879d 100755
--- a/packages/designto-flutter/wrappers/positioned.wrap.ts
+++ b/packages/designto-flutter/wrappers/positioned.wrap.ts
@@ -1,7 +1,7 @@
import * as flutter from "@flutter-builder/flutter";
import { utils, nodes } from "@design-sdk/core";
import { roundNumber } from "@reflect-ui/uiutils";
-import { makeSaflyAsSingle } from "../utils/make-as-safe-single";
+import { makeSaflyAsSingle } from "../_utils";
export function wrapWithPositioned(
node: nodes.ReflectSceneNode,
child: flutter.Widget,
diff --git a/packages/designto-token/index.ts b/packages/designto-token/index.ts
index 17f30341..2da72e3a 100644
--- a/packages/designto-token/index.ts
+++ b/packages/designto-token/index.ts
@@ -15,3 +15,6 @@ export { tokenizeMasking } from "./token-masking";
// simple atomics
export * from "./token-gradient";
+
+// t2t
+export * as t2t from "./token-to-token";
diff --git a/packages/designto-token/token-border/index.ts b/packages/designto-token/token-border/index.ts
index 74d78258..de638e7e 100644
--- a/packages/designto-token/token-border/index.ts
+++ b/packages/designto-token/token-border/index.ts
@@ -9,9 +9,11 @@ function fromNode(node: ReflectSceneNode) {
if (!node.strokes || node.strokes.length === 0) {
return undefined;
}
- return fromStrokes(node.strokes, {
- width: node.strokeWeight,
- });
+ if ("strokeWeight" in node) {
+ return fromStrokes(node.strokes, {
+ width: node.strokeWeight,
+ });
+ }
}
}
diff --git a/packages/designto-token/token-to-token/README.md b/packages/designto-token/token-to-token/README.md
new file mode 100644
index 00000000..3958e9f3
--- /dev/null
+++ b/packages/designto-token/token-to-token/README.md
@@ -0,0 +1 @@
+# Post tokenization token to token conversions
diff --git a/packages/designto-token/token-to-token/index.ts b/packages/designto-token/token-to-token/index.ts
new file mode 100644
index 00000000..a0ac122d
--- /dev/null
+++ b/packages/designto-token/token-to-token/index.ts
@@ -0,0 +1 @@
+export * from "./vector-token-to-image-token";
diff --git a/packages/designto-token/token-to-token/vector-token-to-image-token.ts b/packages/designto-token/token-to-token/vector-token-to-image-token.ts
new file mode 100644
index 00000000..5171aa34
--- /dev/null
+++ b/packages/designto-token/token-to-token/vector-token-to-image-token.ts
@@ -0,0 +1,24 @@
+import { MainImageRepository } from "@design-sdk/core/assets-repository";
+import { ImageWidget, VectorWidget } from "@reflect-ui/core";
+
+/**
+ * convert vector widget to image widget, ignoring that widget is already tokenized to vector widget
+ *
+ * this is dangerous since the vector token is already tokenized, we cannot ensure if the vector token's key will maintain its identity.
+ * @param vector
+ * @returns
+ */
+export function vector_token_to_image_token(vector: VectorWidget): ImageWidget {
+ const _tmp_img = MainImageRepository.instance
+ .get("fill-later-assets")
+ .addImage({
+ key: vector.key.id,
+ });
+
+ return new ImageWidget({
+ key: vector.key,
+ src: _tmp_img.url,
+ width: vector.width,
+ height: vector.height,
+ });
+}
diff --git a/packages/reflect-core b/packages/reflect-core
index 27f82724..3d78b933 160000
--- a/packages/reflect-core
+++ b/packages/reflect-core
@@ -1 +1 @@
-Subproject commit 27f82724a64bf740279668d00725d8d1f1d9da90
+Subproject commit 3d78b933f5bce0486e955cc0668e211ff325b838
diff --git a/yarn.lock b/yarn.lock
index a2968de1..1d6365b1 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1504,10 +1504,10 @@
resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.2.5.tgz#8eed982e2ee6f7f4e44c253e12962980791efd46"
integrity sha512-6U71C2Wp7r5XtFtQzYrW5iKFT67OixrSxjI4MptCHzdSVlgabczzqLe0ZSgnub/5Kp4hSbpDB1tMytZY9pwxxA==
-"@flutter-builder/flutter@^2.5.0-f2":
- version "2.5.0-f2"
- resolved "https://registry.yarnpkg.com/@flutter-builder/flutter/-/flutter-2.5.0-f2.tgz#eea915ff7ae9bc75959b55c3a3bcf2b07e86814a"
- integrity sha512-fq/299yw3fyFapRorHFNYGo2tOCrcD+qQ+MxGJxQv0VzdrlJd77WX0mWHIOoVHpBvvQtPGB9l/dFerdgd87JqA==
+"@flutter-builder/flutter@^2.5.0-f3":
+ version "2.5.0-f3"
+ resolved "https://registry.yarnpkg.com/@flutter-builder/flutter/-/flutter-2.5.0-f3.tgz#91e993d420a97f39d5a9bd781ac43ac969388edd"
+ integrity sha512-5UVI31fwEBjHk79ECWmqGSLviC+ezEe+n5mRK+IoWiQ6+VXNftUJPZR0mjX7wEpCJ7obyqeH8p8gXV8Ejot05g==
dependencies:
"@abraham/reflection" "^0.8.0"
dart-style "^1.3.2-dev"