+
+ {
+ wsprefef.debug_mode(e.target.checked);
+ }}
+ />
+ }
+ label="debug_mode"
+ />
+ {
+ wsprefef.enable_preview_feature_components_support(
+ e.target.checked
+ );
+ }}
+ />
+ }
+ label="enable_preview_feature_components_support"
+ />
+
);
}
diff --git a/editor/store/workspace-preference-store/index.ts b/editor/store/workspace-preference-store/index.ts
new file mode 100644
index 00000000..6af9b947
--- /dev/null
+++ b/editor/store/workspace-preference-store/index.ts
@@ -0,0 +1 @@
+export { WorkspacePreferenceStore } from "./workspace-preference-store";
diff --git a/editor/store/workspace-preference-store/workspace-preference-store.ts b/editor/store/workspace-preference-store/workspace-preference-store.ts
new file mode 100644
index 00000000..b0d53d83
--- /dev/null
+++ b/editor/store/workspace-preference-store/workspace-preference-store.ts
@@ -0,0 +1,37 @@
+import { WorkspacePreferences } from "core/states";
+export class WorkspacePreferenceStore {
+ readonly key: string;
+ constructor(ws?: string) {
+ this.key = "workspace-preferences-" + ws ?? "default";
+ }
+
+ enable_preview_feature_components_support(b: boolean) {
+ const pf = this.load();
+ pf.enable_preview_feature_components_support = b;
+ this.set(pf);
+ return pf;
+ }
+
+ debug_mode(b: boolean) {
+ const pf = this.load();
+ pf.debug_mode = b;
+ this.set(pf);
+ return pf;
+ }
+
+ set(pf: WorkspacePreferences) {
+ window.localStorage.setItem(this.key, JSON.stringify(pf));
+ }
+
+ load(): WorkspacePreferences {
+ try {
+ const pl = window.localStorage.getItem(this.key);
+ if (!pl) {
+ return;
+ }
+ return JSON.parse(pl) as WorkspacePreferences;
+ } catch (e) {
+ return;
+ }
+ }
+}
diff --git a/packages/builder-css-styles/index.ts b/packages/builder-css-styles/index.ts
index 8176110c..cf1cc4ca 100644
--- a/packages/builder-css-styles/index.ts
+++ b/packages/builder-css-styles/index.ts
@@ -11,6 +11,7 @@ export * from "./text-decoration";
export * from "./text-shadow";
export * from "./gradient";
export * from "./padding";
+export * from "./margin";
export * from "./position";
export * from "./justify-content";
export * from "./min-height";
diff --git a/packages/builder-css-styles/margin/index.ts b/packages/builder-css-styles/margin/index.ts
new file mode 100644
index 00000000..82040495
--- /dev/null
+++ b/packages/builder-css-styles/margin/index.ts
@@ -0,0 +1,56 @@
+import { CSSProperties } from "@coli.codes/css";
+import { EdgeInsets } from "@reflect-ui/core";
+import { px } from "../dimensions";
+
+type MarginValue = number | "auto";
+
+export function margin(m: EdgeInsets): CSSProperties {
+ if (!m) {
+ return {};
+ }
+ if (m.top === 0 && m.right === 0 && m.bottom === 0 && m.left === 0) {
+ return {};
+ }
+ if (m.top === m.bottom && m.left === m.right) {
+ return {
+ margin: `${_mv(m.top)} ${_mv(m.left)}`,
+ };
+ } else if (m.left === m.right) {
+ return {
+ margin: `${_mv(m.top)} ${_mv(m.left)} ${_mv(m.bottom)}`,
+ };
+ }
+ return {
+ "margin-bottom": _makeifRequired(m?.bottom),
+ "margin-top": _makeifRequired(m?.top),
+ "margin-left": _makeifRequired(m?.left),
+ "margin-right": _makeifRequired(m?.right),
+ };
+}
+
+/**
+ * Margin Value - mv
+ * @param mv
+ * @returns
+ */
+function _mv(mv: MarginValue) {
+ if (mv === undefined) {
+ return;
+ }
+ if (mv === "auto") {
+ return "auto";
+ }
+ return px(mv);
+}
+
+function _makeifRequired(val: MarginValue): string | undefined {
+ if (val === undefined) {
+ return;
+ }
+ if (val === "auto") {
+ return "auto";
+ }
+ if (val && val > 0) {
+ return px(val);
+ }
+}
diff --git a/packages/builder-web-core/widgets-native/container/index.ts b/packages/builder-web-core/widgets-native/container/index.ts
index 2c4a9e41..6d57f033 100644
--- a/packages/builder-web-core/widgets-native/container/index.ts
+++ b/packages/builder-web-core/widgets-native/container/index.ts
@@ -5,6 +5,7 @@ import {
BorderRadiusManifest,
BoxShadowManifest,
DimensionLength,
+ EdgeInsets,
} from "@reflect-ui/core";
import { Background } from "@reflect-ui/core/lib/background";
import * as css from "@web-builder/styles";
@@ -17,6 +18,7 @@ export class Container extends StylableJsxWidget {
children?: StylableJsxWidget[];
borderRadius?: BorderRadiusManifest;
border?: Border;
+ margin?: EdgeInsets;
constructor(p: {
key: WidgetKey;
@@ -30,6 +32,8 @@ export class Container extends StylableJsxWidget {
minHeight?: DimensionLength;
maxHeight?: DimensionLength;
+ margin?: EdgeInsets;
+
background?: Background;
borderRadius?: BorderRadiusManifest;
boxShadow?: BoxShadowManifest[];
@@ -44,6 +48,8 @@ export class Container extends StylableJsxWidget {
this.minHeight = p.minHeight;
this.maxHeight = p.maxHeight;
+ this.margin = p.margin;
+
this.x = p.x;
this.y = p.y;
this.background = p.background;
@@ -60,7 +66,7 @@ export class Container extends StylableJsxWidget {
"max-width": css.length(this.maxWidth),
"min-height": css.length(this.minHeight),
"max-height": css.length(this.maxHeight),
-
+ ...css.margin(this.margin),
"box-shadow": css.boxshadow(...(this.boxShadow ?? [])),
...css.background(this.background),
...css.border(this.border),
diff --git a/packages/designto-token/support-flags/token-wh/index.ts b/packages/designto-token/support-flags/token-wh/index.ts
index aa873f71..3aab303f 100644
--- a/packages/designto-token/support-flags/token-wh/index.ts
+++ b/packages/designto-token/support-flags/token-wh/index.ts
@@ -1,7 +1,9 @@
import { WHDeclarationFlag } from "@code-features/flags";
import { ReflectSceneNode } from "@design-sdk/figma-node";
import {
+ Container,
DimensionLength,
+ EdgeInsets,
isPossibleDimensionLength,
IWHStyleWidget,
Widget,
@@ -58,6 +60,7 @@ export function tokenize_flagged_wh_declaration(
const flag_target = unwrappedChild(widget) as IWHStyleWidget;
+ // set wh preference
merged.width && (flag_target.width = merged.width);
merged.minWidth && (flag_target.minWidth = merged.minWidth);
merged.maxWidth && (flag_target.maxWidth = merged.maxWidth);
@@ -65,5 +68,31 @@ export function tokenize_flagged_wh_declaration(
merged.minHeight && (flag_target.minHeight = merged.minHeight);
merged.maxHeight && (flag_target.maxHeight = merged.maxHeight);
+ // 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.
+ // Learn more about this transformation - https://stackoverflow.com/questions/17993471/css-wont-center-div-with-max-width
+ // TODO: the margin's value to "auto" is not acceptable. this is a abberation, needs to fixed.
+ const container = widget as Container;
+ const _provide_initial_margin_if_none = () => {
+ if (!container.margin) {
+ container.margin = new EdgeInsets({
+ top: undefined,
+ right: undefined,
+ bottom: undefined,
+ left: undefined,
+ });
+ }
+ };
+ if (node.constraints.horizontal == "STRETCH") {
+ _provide_initial_margin_if_none();
+ container.margin.left = "auto" as any;
+ container.margin.right = "auto" as any;
+ }
+
+ if (node.constraints.vertical == "STRETCH") {
+ _provide_initial_margin_if_none();
+ container.margin.top = "auto" as any;
+ container.margin.bottom = "auto" as any;
+ }
+
return widget;
}
diff --git a/packages/designto-token/token-layout/index.ts b/packages/designto-token/token-layout/index.ts
index 4ccf1991..68e6bec2 100644
--- a/packages/designto-token/token-layout/index.ts
+++ b/packages/designto-token/token-layout/index.ts
@@ -127,10 +127,31 @@ function flex_or_stack_from_frame(
};
if (frame.isAutoLayout) {
+ // TODO: inspect me. We're not 100% sure this is the correct behaviour.
switch (frame.layoutMode) {
case Axis.horizontal:
+ if (frame.primaryAxisSizingMode === "AUTO") {
+ // when horizontal, primaryAxisSizingMode is x axis
+ // don't specify width
+ initializer.width = undefined;
+ }
+ if (frame.counterAxisSizingMode === "AUTO") {
+ // when horizontal, counterAxisSizingMode is y axis
+ // don't specify height
+ initializer.height = undefined;
+ }
return new Row(initializer);
case Axis.vertical:
+ if (frame.counterAxisSizingMode === "AUTO") {
+ // when vertical, counterAxisSizingMode is x axis
+ // don't specify width
+ initializer.width = undefined;
+ }
+ if (frame.primaryAxisSizingMode === "AUTO") {
+ // when vertical, primaryAxisSizingMode is y axis
+ // don't specify height
+ initializer.height = undefined;
+ }
return new Column(initializer);
default:
console.info(`Frame: "${frame.name}" fallback to flex`);
diff --git a/packages/support-flags/docs/--as-p.md b/packages/support-flags/docs/--as-p.md
index f8705a1c..e5b84868 100644
--- a/packages/support-flags/docs/--as-p.md
+++ b/packages/support-flags/docs/--as-p.md
@@ -6,12 +6,11 @@ stage:
- proposal
- draft
- experimental
- - not-ready
---
# `--as-p` As Paragraph (Text)
-> This flag is for web platform. Otherwise, it will be ignored, have no impact on the final output.
+> This flag is for web platform. On other platforms, this will be ignored, have no impact on the final output.
**Accepted keys**
@@ -25,7 +24,7 @@ stage:
`--as-p${"="typeof boolean}`
```
-## Example
+**Example**
```
--paragraph
diff --git a/packages/support-flags/docs/translations/ko/--as-p.md b/packages/support-flags/docs/translations/ko/--as-p.md
new file mode 100644
index 00000000..12585204
--- /dev/null
+++ b/packages/support-flags/docs/translations/ko/--as-p.md
@@ -0,0 +1,67 @@
+---
+title: As Paragraph flag
+id: "--as-p"
+locale: en
+stage:
+ - proposal
+ - draft
+ - experimental
+---
+
+# `--as-p` Paragraph 명시 플래그 (Text)
+
+> 이 플래그는 웹 플랫폼을 위한것입니다. 다른 프랫폼에서는 무시되며, 결과물에 아무런 영향을 끼치지 않습니다.
+
+**지정 가능한 키**
+
+- `--as-p`
+- `--as-paragraph`
+- `--paragraph`
+
+## 문법
+
+```ts
+`--as-p${"="typeof boolean}`
+```
+
+**적용 예시**
+
+```
+--paragraph
+
+--paragraph=true
+--paragraph=false
+
+--paragraph=yes
+--paragraph=no
+
+----paragraph
+```
+
+## 언제 사용하면 좋을까
+
+
+
+**SEO**
+
+element tag 를 명시하는것은 SEO 에 있어, 필수적입니다. 특히 헤딩일 경우, 그 효과는 더 큽니다.
+모바일 앱의 경우, 해당 사항이 없겠지만, 웹어서는 의미에 맞게 h1~h6 과 함께 p 을 지정하는 것이 좋습니다.
+
+## 동작
+
+**엘레먼트 (Element)**
+이 플래그가 적용된다면, 해당 노드의 html 생성 엘레먼트는 `
` 로 렌더되어 표시됩니다. (이외의 로직에는 영향이 없으며, 태그가 변경되었기에 이에 따른 부작용은 사용자의 커스텀 css 또는 query 에 따라 변경될 수 있습니다.)
+
+**Text style**
+아직 p 를 사용함으로써 자동으로 적용되는 텍스트 스타일은 없습니다. 지정 하지 않았을때와 동일한 방식으로 스타일링이 적용됩니다. 다만 기존 글로벌한 스타일에 p 에 대한 텍스트 스타일이 존재한다면, 이는 직접 영향을 받지 않도록 글로벌 스타일을 수정해주어야 합니다.
+
+## 같이보기
+
+- [`--as-h1`](./--as-h1)
+- [`--as-h2`](./--as-h2)
+- [`--as-h3`](./--as-h3)
+- [`--as-h4`](./--as-h4)
+- [`--as-h5`](./--as-h5)
+- [`--as-h6`](./--as-h6)
+- [`--as-p`](./--as-p)
+- [`--as-br`](./--as-br)