Skip to content

Commit 80218c1

Browse files
Merge pull request #111 from gridaco/staging
Fix autolayout stretch interpreter
2 parents a620628 + 93af033 commit 80218c1

12 files changed

Lines changed: 283 additions & 17 deletions

File tree

editor/core/states/workspace-initial-state.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
createPendingHistoryState,
66
} from "./history-initial-state";
77
import { react_presets, vanilla_presets } from "@grida/builder-config-preset";
8+
import { WorkspacePreferenceStore } from "store/workspace-preference-store";
89

910
const _IS_DEV = process.env.NODE_ENV === "development";
1011

@@ -21,15 +22,20 @@ const _ENABLE_PREVIEW_FEATURE_COMPONENTS_SUPPORT =
2122
export function createInitialWorkspaceState(
2223
editor: EditorSnapshot
2324
): WorkspaceState {
25+
const pref_store = new WorkspacePreferenceStore();
26+
const saved_pref = pref_store.load();
27+
const default_pref = {
28+
debug_mode: _IS_DEV,
29+
enable_preview_feature_components_support:
30+
_ENABLE_PREVIEW_FEATURE_COMPONENTS_SUPPORT,
31+
preview_runner_framework_config: vanilla_presets.vanilla_default,
32+
framework_config: react_presets.react_default,
33+
};
34+
if (!saved_pref) pref_store.set(default_pref);
35+
2436
return {
2537
history: createInitialHistoryState(editor),
26-
preferences: {
27-
debug_mode: _IS_DEV,
28-
enable_preview_feature_components_support:
29-
_ENABLE_PREVIEW_FEATURE_COMPONENTS_SUPPORT,
30-
preview_runner_framework_config: vanilla_presets.vanilla_default,
31-
framework_config: react_presets.react_default,
32-
},
38+
preferences: saved_pref ?? default_pref,
3339
};
3440
}
3541

editor/core/states/workspace-state.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@ import { HistoryState } from "core/states/history-state";
33

44
export interface WorkspaceState {
55
history: HistoryState;
6-
preferences: {
7-
debug_mode: boolean;
8-
framework_config: config.FrameworkConfig;
9-
preview_runner_framework_config: config.FrameworkConfig;
10-
enable_preview_feature_components_support: boolean;
11-
};
6+
preferences: WorkspacePreferences;
7+
}
8+
9+
export interface WorkspacePreferences {
10+
debug_mode: boolean;
11+
framework_config: config.FrameworkConfig;
12+
preview_runner_framework_config: config.FrameworkConfig;
13+
enable_preview_feature_components_support: boolean;
1214
}

editor/pages/preferences/index.tsx

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,53 @@
11
import React from "react";
22
import Link from "next/link";
33
import styled from "@emotion/styled";
4+
5+
import FormGroup from "@material-ui/core/FormGroup";
6+
import FormControlLabel from "@material-ui/core/FormControlLabel";
7+
import Checkbox from "@material-ui/core/Checkbox";
8+
import { WorkspacePreferenceStore } from "store/workspace-preference-store";
9+
410
export default function PreferencesHomePage() {
11+
const wsprefef = new WorkspacePreferenceStore();
12+
513
return (
614
<_Root>
715
<Link href="/preferences/access-tokens">
816
Set Personal Access token for figma
917
</Link>
18+
<br />
19+
<br />
20+
<br />
21+
<br />
22+
<h5>Workspace preferences</h5>
23+
<FormGroup>
24+
<FormControlLabel
25+
control={
26+
<Checkbox
27+
defaultChecked={wsprefef.load()?.debug_mode}
28+
onChange={(e) => {
29+
wsprefef.debug_mode(e.target.checked);
30+
}}
31+
/>
32+
}
33+
label="debug_mode"
34+
/>
35+
<FormControlLabel
36+
control={
37+
<Checkbox
38+
defaultChecked={
39+
wsprefef.load()?.enable_preview_feature_components_support
40+
}
41+
onChange={(e) => {
42+
wsprefef.enable_preview_feature_components_support(
43+
e.target.checked
44+
);
45+
}}
46+
/>
47+
}
48+
label="enable_preview_feature_components_support"
49+
/>
50+
</FormGroup>
1051
</_Root>
1152
);
1253
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { WorkspacePreferenceStore } from "./workspace-preference-store";
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { WorkspacePreferences } from "core/states";
2+
export class WorkspacePreferenceStore {
3+
readonly key: string;
4+
constructor(ws?: string) {
5+
this.key = "workspace-preferences-" + ws ?? "default";
6+
}
7+
8+
enable_preview_feature_components_support(b: boolean) {
9+
const pf = this.load();
10+
pf.enable_preview_feature_components_support = b;
11+
this.set(pf);
12+
return pf;
13+
}
14+
15+
debug_mode(b: boolean) {
16+
const pf = this.load();
17+
pf.debug_mode = b;
18+
this.set(pf);
19+
return pf;
20+
}
21+
22+
set(pf: WorkspacePreferences) {
23+
window.localStorage.setItem(this.key, JSON.stringify(pf));
24+
}
25+
26+
load(): WorkspacePreferences {
27+
try {
28+
const pl = window.localStorage.getItem(this.key);
29+
if (!pl) {
30+
return;
31+
}
32+
return JSON.parse(pl) as WorkspacePreferences;
33+
} catch (e) {
34+
return;
35+
}
36+
}
37+
}

packages/builder-css-styles/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export * from "./text-decoration";
1111
export * from "./text-shadow";
1212
export * from "./gradient";
1313
export * from "./padding";
14+
export * from "./margin";
1415
export * from "./position";
1516
export * from "./justify-content";
1617
export * from "./min-height";
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { CSSProperties } from "@coli.codes/css";
2+
import { EdgeInsets } from "@reflect-ui/core";
3+
import { px } from "../dimensions";
4+
5+
type MarginValue = number | "auto";
6+
7+
export function margin(m: EdgeInsets): CSSProperties {
8+
if (!m) {
9+
return {};
10+
}
11+
if (m.top === 0 && m.right === 0 && m.bottom === 0 && m.left === 0) {
12+
return {};
13+
}
14+
if (m.top === m.bottom && m.left === m.right) {
15+
return {
16+
margin: `${_mv(m.top)} ${_mv(m.left)}`,
17+
};
18+
} else if (m.left === m.right) {
19+
return {
20+
margin: `${_mv(m.top)} ${_mv(m.left)} ${_mv(m.bottom)}`,
21+
};
22+
}
23+
return {
24+
"margin-bottom": _makeifRequired(m?.bottom),
25+
"margin-top": _makeifRequired(m?.top),
26+
"margin-left": _makeifRequired(m?.left),
27+
"margin-right": _makeifRequired(m?.right),
28+
};
29+
}
30+
31+
/**
32+
* Margin Value - mv
33+
* @param mv
34+
* @returns
35+
*/
36+
function _mv(mv: MarginValue) {
37+
if (mv === undefined) {
38+
return;
39+
}
40+
if (mv === "auto") {
41+
return "auto";
42+
}
43+
return px(mv);
44+
}
45+
46+
function _makeifRequired(val: MarginValue): string | undefined {
47+
if (val === undefined) {
48+
return;
49+
}
50+
if (val === "auto") {
51+
return "auto";
52+
}
53+
if (val && val > 0) {
54+
return px(val);
55+
}
56+
}

packages/builder-web-core/widgets-native/container/index.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
BorderRadiusManifest,
66
BoxShadowManifest,
77
DimensionLength,
8+
EdgeInsets,
89
} from "@reflect-ui/core";
910
import { Background } from "@reflect-ui/core/lib/background";
1011
import * as css from "@web-builder/styles";
@@ -17,6 +18,7 @@ export class Container extends StylableJsxWidget {
1718
children?: StylableJsxWidget[];
1819
borderRadius?: BorderRadiusManifest;
1920
border?: Border;
21+
margin?: EdgeInsets;
2022

2123
constructor(p: {
2224
key: WidgetKey;
@@ -30,6 +32,8 @@ export class Container extends StylableJsxWidget {
3032
minHeight?: DimensionLength;
3133
maxHeight?: DimensionLength;
3234

35+
margin?: EdgeInsets;
36+
3337
background?: Background;
3438
borderRadius?: BorderRadiusManifest;
3539
boxShadow?: BoxShadowManifest[];
@@ -44,6 +48,8 @@ export class Container extends StylableJsxWidget {
4448
this.minHeight = p.minHeight;
4549
this.maxHeight = p.maxHeight;
4650

51+
this.margin = p.margin;
52+
4753
this.x = p.x;
4854
this.y = p.y;
4955
this.background = p.background;
@@ -60,7 +66,7 @@ export class Container extends StylableJsxWidget {
6066
"max-width": css.length(this.maxWidth),
6167
"min-height": css.length(this.minHeight),
6268
"max-height": css.length(this.maxHeight),
63-
69+
...css.margin(this.margin),
6470
"box-shadow": css.boxshadow(...(this.boxShadow ?? [])),
6571
...css.background(this.background),
6672
...css.border(this.border),

packages/designto-token/support-flags/token-wh/index.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
import { WHDeclarationFlag } from "@code-features/flags";
22
import { ReflectSceneNode } from "@design-sdk/figma-node";
33
import {
4+
Container,
45
DimensionLength,
6+
EdgeInsets,
57
isPossibleDimensionLength,
68
IWHStyleWidget,
79
Widget,
@@ -58,12 +60,39 @@ export function tokenize_flagged_wh_declaration(
5860

5961
const flag_target = unwrappedChild(widget) as IWHStyleWidget;
6062

63+
// set wh preference
6164
merged.width && (flag_target.width = merged.width);
6265
merged.minWidth && (flag_target.minWidth = merged.minWidth);
6366
merged.maxWidth && (flag_target.maxWidth = merged.maxWidth);
6467
merged.height && (flag_target.height = merged.height);
6568
merged.minHeight && (flag_target.minHeight = merged.minHeight);
6669
merged.maxHeight && (flag_target.maxHeight = merged.maxHeight);
6770

71+
// if the constraints are set to left & right or top & bottom, we have to add `margin-(?): auto;` to make align the item to center as it is on origin design.
72+
// Learn more about this transformation - https://stackoverflow.com/questions/17993471/css-wont-center-div-with-max-width
73+
// TODO: the margin's value to "auto" is not acceptable. this is a abberation, needs to fixed.
74+
const container = widget as Container;
75+
const _provide_initial_margin_if_none = () => {
76+
if (!container.margin) {
77+
container.margin = new EdgeInsets({
78+
top: undefined,
79+
right: undefined,
80+
bottom: undefined,
81+
left: undefined,
82+
});
83+
}
84+
};
85+
if (node.constraints.horizontal == "STRETCH") {
86+
_provide_initial_margin_if_none();
87+
container.margin.left = "auto" as any;
88+
container.margin.right = "auto" as any;
89+
}
90+
91+
if (node.constraints.vertical == "STRETCH") {
92+
_provide_initial_margin_if_none();
93+
container.margin.top = "auto" as any;
94+
container.margin.bottom = "auto" as any;
95+
}
96+
6897
return widget;
6998
}

packages/designto-token/token-layout/index.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,10 +127,31 @@ function flex_or_stack_from_frame(
127127
};
128128

129129
if (frame.isAutoLayout) {
130+
// TODO: inspect me. We're not 100% sure this is the correct behaviour.
130131
switch (frame.layoutMode) {
131132
case Axis.horizontal:
133+
if (frame.primaryAxisSizingMode === "AUTO") {
134+
// when horizontal, primaryAxisSizingMode is x axis
135+
// don't specify width
136+
initializer.width = undefined;
137+
}
138+
if (frame.counterAxisSizingMode === "AUTO") {
139+
// when horizontal, counterAxisSizingMode is y axis
140+
// don't specify height
141+
initializer.height = undefined;
142+
}
132143
return new Row(initializer);
133144
case Axis.vertical:
145+
if (frame.counterAxisSizingMode === "AUTO") {
146+
// when vertical, counterAxisSizingMode is x axis
147+
// don't specify width
148+
initializer.width = undefined;
149+
}
150+
if (frame.primaryAxisSizingMode === "AUTO") {
151+
// when vertical, primaryAxisSizingMode is y axis
152+
// don't specify height
153+
initializer.height = undefined;
154+
}
134155
return new Column(initializer);
135156
default:
136157
console.info(`Frame: "${frame.name}" fallback to flex`);

0 commit comments

Comments
 (0)