@builder.io/sdk-svelte 0.0.9 → 0.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/package/--package.json +2 -1
  2. package/package/blocks/columns/columns.svelte +74 -24
  3. package/package/blocks/columns/columns.svelte.d.ts +3 -0
  4. package/package/blocks/section/section.svelte +12 -5
  5. package/package/blocks/symbol/symbol.svelte +17 -4
  6. package/package/blocks/symbol/symbol.svelte.d.ts +2 -1
  7. package/package/components/render-block/render-block.svelte +5 -1
  8. package/package/components/render-block/render-component.svelte.d.ts +2 -0
  9. package/package/components/render-content/render-content.svelte +18 -0
  10. package/package/functions/get-block-properties.d.ts +1 -0
  11. package/package/functions/get-block-properties.js +27 -1
  12. package/package/functions/get-react-native-block-styles.d.ts +2 -1
  13. package/package/functions/get-react-native-block-styles.js +2 -1
  14. package/package/functions/transform-block-properties.d.ts +1 -0
  15. package/package/functions/transform-block-properties.js +3 -0
  16. package/package/helpers/css.d.ts +2 -0
  17. package/package/helpers/css.js +8 -3
  18. package/package/types/builder-block.d.ts +1 -0
  19. package/package/types/builder-content.d.ts +6 -4
  20. package/package/types/targets.d.ts +1 -1
  21. package/package.json +1 -1
  22. package/src/blocks/columns/columns.svelte +78 -27
  23. package/src/blocks/section/section.svelte +12 -5
  24. package/src/blocks/symbol/symbol.svelte +17 -4
  25. package/src/components/render-block/render-block.svelte +5 -1
  26. package/src/components/render-block/render-component.svelte +3 -0
  27. package/src/components/render-content/render-content.svelte +23 -1
  28. package/src/functions/get-block-properties.ts +31 -1
  29. package/src/functions/get-react-native-block-styles.ts +3 -0
  30. package/src/functions/transform-block-properties.ts +3 -0
  31. package/src/helpers/css.ts +12 -3
  32. package/src/types/builder-block.ts +1 -0
  33. package/src/types/builder-content.ts +6 -4
  34. package/src/types/targets.ts +1 -1
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@builder.io/sdk-svelte",
3
3
  "description": "Builder.io SDK for Svelte",
4
- "version": "0.0.9-3",
4
+ "version": "0.0.10-0",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "package",
@@ -117,6 +117,7 @@
117
117
  "./functions/set.test": "./functions/set.test.js",
118
118
  "./functions/set": "./functions/set.js",
119
119
  "./functions/track": "./functions/track.js",
120
+ "./functions/transform-block-properties": "./functions/transform-block-properties.js",
120
121
  "./functions/transform-block": "./functions/transform-block.js",
121
122
  "./helpers/ab-tests": "./helpers/ab-tests.js",
122
123
  "./helpers/cookie": "./helpers/cookie.js",
@@ -1,10 +1,15 @@
1
1
  <script context="module"></script>
2
2
 
3
3
  <script>import RenderBlocks from "../../components/render-blocks.svelte";
4
+ import { getSizesForBreakpoints } from "../../constants/device-sizes";
5
+ import RenderInlinedStyles from "../../components/render-inlined-styles.svelte";
6
+ import { TARGET } from "../../constants/target.js";
7
+ import { convertStyleMapToCSS } from "../../helpers/css";
4
8
  export let space;
5
9
  export let columns;
6
10
  export let stackColumnsAt;
7
11
  export let reverseColumnsWhenStacked;
12
+ export let customBreakpoints;
8
13
  export let builderBlock;
9
14
  function mitosis_styling(node, vars) {
10
15
  Object.entries(vars || {}).forEach(([p, v]) => {
@@ -36,6 +41,10 @@ function maybeApplyForTablet(prop) {
36
41
  const _stackColumnsAt = stackColumnsAt || "tablet";
37
42
  return _stackColumnsAt === "tablet" ? prop : "inherit";
38
43
  }
44
+ function getWidthForBreakpointSize(size) {
45
+ const breakpointSizes = getSizesForBreakpoints(customBreakpoints || {});
46
+ return breakpointSizes[size].max;
47
+ }
39
48
  $: columnsCssVars = () => {
40
49
  const flexDir = stackColumnsAt === "never"
41
50
  ? "inherit"
@@ -57,14 +66,78 @@ $: columnCssVars = () => {
57
66
  "--column-margin-left-tablet": maybeApplyForTablet(marginLeft),
58
67
  };
59
68
  };
69
+ $: columnStyleObjects = () => {
70
+ return {
71
+ columns: {
72
+ small: {
73
+ flexDirection: "var(--flex-dir)",
74
+ alignItems: "stretch",
75
+ },
76
+ medium: {
77
+ flexDirection: "var(--flex-dir-tablet)",
78
+ alignItems: "stretch",
79
+ },
80
+ },
81
+ column: {
82
+ small: {
83
+ width: "var(--column-width) !important",
84
+ marginLeft: "var(--column-margin-left) !important",
85
+ },
86
+ medium: {
87
+ width: "var(--column-width-tablet) !important",
88
+ marginLeft: "var(--column-margin-left-tablet) !important",
89
+ },
90
+ },
91
+ };
92
+ };
93
+ $: columnsStyles = () => {
94
+ return `
95
+ @media (max-width: ${getWidthForBreakpointSize("medium")}px) {
96
+ .${builderBlock.id}-breakpoints {
97
+ ${convertStyleMapToCSS(columnStyleObjects().columns.medium)}
98
+ }
99
+
100
+ .${builderBlock.id}-breakpoints > .builder-column {
101
+ ${convertStyleMapToCSS(columnStyleObjects().column.medium)}
102
+ }
103
+ }
104
+
105
+ @media (max-width: ${getWidthForBreakpointSize("small")}px) {
106
+ .${builderBlock.id}-breakpoints {
107
+ ${convertStyleMapToCSS(columnStyleObjects().columns.small)}
108
+ }
109
+
110
+ .${builderBlock.id}-breakpoints > .builder-column {
111
+ ${convertStyleMapToCSS(columnStyleObjects().column.small)}
112
+ }
113
+ },
114
+ `;
115
+ };
116
+ $: reactNativeColumnsStyles = () => {
117
+ return columnStyleObjects.columns.small;
118
+ };
119
+ $: reactNativeColumnStyles = () => {
120
+ return columnStyleObjects.column.small;
121
+ };
60
122
  </script>
61
123
 
62
- <div use:mitosis_styling={columnsCssVars()} class="builder-columns div">
124
+ <div
125
+ use:mitosis_styling={{
126
+ ...(TARGET === "reactNative" ? reactNativeColumnsStyles() : {}),
127
+ ...columnsCssVars(),
128
+ }}
129
+ class={`builder-columns ${builderBlock.id}-breakpoints` + " div"}
130
+ >
131
+ {#if TARGET !== "reactNative"}
132
+ <RenderInlinedStyles styles={columnsStyles()} />
133
+ {/if}
134
+
63
135
  {#each columns as column, index (index)}
64
136
  <div
65
137
  use:mitosis_styling={{
66
138
  width: getColumnCssWidth(index),
67
139
  marginLeft: `${index === 0 ? 0 : getGutterSize()}px`,
140
+ ...(TARGET === "reactNative" ? reactNativeColumnStyles() : {}),
68
141
  ...columnCssVars(),
69
142
  }}
70
143
  class="builder-column div-2"
@@ -84,34 +157,11 @@ $: columnCssVars = () => {
84
157
  <style>
85
158
  .div {
86
159
  display: flex;
87
- align-items: stretch;
88
160
  line-height: normal;
89
161
  }
90
- @media (max-width: 991px) {
91
- .div {
92
- flex-direction: var(--flex-dir-tablet);
93
- }
94
- }
95
- @media (max-width: 639px) {
96
- .div {
97
- flex-direction: var(--flex-dir);
98
- }
99
- }
100
162
  .div-2 {
101
163
  display: flex;
102
164
  flex-direction: column;
103
165
  align-items: stretch;
104
166
  }
105
- @media (max-width: 991px) {
106
- .div-2 {
107
- width: var(--column-width-tablet) !important;
108
- margin-left: var(--column-margin-left-tablet) !important;
109
- }
110
- }
111
- @media (max-width: 639px) {
112
- .div-2 {
113
- width: var(--column-width) !important;
114
- margin-left: var(--column-margin-left) !important;
115
- }
116
- }
117
167
  </style>
@@ -1,5 +1,6 @@
1
1
  import { SvelteComponentTyped } from "svelte";
2
2
  import type { BuilderBlock } from "../../types/builder-block";
3
+ import type { Breakpoints } from "../../types/builder-content";
3
4
  declare type Column = {
4
5
  blocks: any;
5
6
  width?: number;
@@ -11,6 +12,7 @@ export interface ColumnProps {
11
12
  space?: number;
12
13
  stackColumnsAt?: StackColumnsAt;
13
14
  reverseColumnsWhenStacked?: boolean;
15
+ customBreakpoints?: Breakpoints;
14
16
  }
15
17
  declare const __propDef: {
16
18
  props: {
@@ -18,6 +20,7 @@ declare const __propDef: {
18
20
  columns: ColumnProps["columns"];
19
21
  stackColumnsAt: ColumnProps["stackColumnsAt"];
20
22
  reverseColumnsWhenStacked: ColumnProps["reverseColumnsWhenStacked"];
23
+ customBreakpoints: ColumnProps["customBreakpoints"];
21
24
  builderBlock: ColumnProps["builderBlock"];
22
25
  };
23
26
  events: {
@@ -42,11 +42,18 @@ function mitosis_styling(node, vars) {
42
42
  </script>
43
43
 
44
44
  <section
45
- use:mitosis_styling={maxWidth && typeof maxWidth === "number"
46
- ? {
47
- maxWidth: maxWidth,
48
- }
49
- : undefined}
45
+ use:mitosis_styling={{
46
+ width: "100%",
47
+ alignSelf: "stretch",
48
+ flexGrow: "1",
49
+ boxSizing: "border-box",
50
+ maxWidth: `${maxWidth && typeof maxWidth === "number" ? maxWidth : 1200}px`,
51
+ display: "flex",
52
+ flexDirection: "column",
53
+ alignItems: "stretch",
54
+ marginLeft: "auto",
55
+ marginRight: "auto",
56
+ }}
50
57
  {...filterAttrs(attributes, isNonEvent)}
51
58
  use:setAttrs={filterAttrs(attributes, isEvent)}
52
59
  >
@@ -4,6 +4,7 @@
4
4
  import RenderContent from "../../components/render-content/render-content.svelte";
5
5
  import BuilderContext from "../../context/builder.context.js";
6
6
  import { getContent } from "../../functions/get-content/index.js";
7
+ import { TARGET } from "../../constants/target";
7
8
  const isEvent = (attr) => attr.startsWith("on:");
8
9
  const isNonEvent = (attr) => !attr.startsWith("on:");
9
10
  const filterAttrs = (attrs, filter) => {
@@ -31,13 +32,25 @@ const setAttrs = (node, attrs) => {
31
32
  },
32
33
  };
33
34
  };
34
- export let symbol;
35
35
  export let attributes;
36
+ export let symbol;
37
+ export let dynamic;
36
38
  let builderContext = getContext(BuilderContext.key);
39
+ $: className = () => {
40
+ return [
41
+ ...(TARGET === "vue2" || TARGET === "vue3"
42
+ ? Object.keys(attributes.class)
43
+ : [attributes.class]),
44
+ "builder-symbol",
45
+ symbol?.inline ? "builder-inline-symbol" : undefined,
46
+ symbol?.dynamic || dynamic ? "builder-dynamic-symbol" : undefined,
47
+ ]
48
+ .filter(Boolean)
49
+ .join(" ");
50
+ };
37
51
  $: contentToUse = () => {
38
52
  return symbol?.content || fetchedContent;
39
53
  };
40
- let className = "builder-symbol";
41
54
  let fetchedContent = null;
42
55
  function onUpdateFn_0() {
43
56
  const symbolToUse = symbol;
@@ -71,9 +84,9 @@ $: onUpdateFn_0(...[symbol, fetchedContent]);
71
84
  <div
72
85
  {...filterAttrs(attributes, isNonEvent)}
73
86
  dataSet={{
74
- class: className,
87
+ class: className(),
75
88
  }}
76
- class={className}
89
+ class={className()}
77
90
  use:setAttrs={filterAttrs(attributes, isEvent)}
78
91
  >
79
92
  <RenderContent
@@ -19,8 +19,9 @@ export interface SymbolProps {
19
19
  }
20
20
  declare const __propDef: {
21
21
  props: {
22
- symbol: SymbolProps["symbol"];
23
22
  attributes: SymbolProps["attributes"];
23
+ symbol: SymbolProps["symbol"];
24
+ dynamic: SymbolProps["dynamic"];
24
25
  };
25
26
  events: {
26
27
  [evt: string]: CustomEvent<any>;
@@ -75,13 +75,15 @@ $: actions = () => {
75
75
  });
76
76
  };
77
77
  $: attributes = () => {
78
+ const blockProperties = getBlockProperties(useBlock());
78
79
  return {
79
- ...getBlockProperties(useBlock()),
80
+ ...blockProperties,
80
81
  ...(TARGET === "reactNative"
81
82
  ? {
82
83
  style: getReactNativeBlockStyles({
83
84
  block: useBlock(),
84
85
  context: context,
86
+ blockStyles: blockProperties.style,
85
87
  }),
86
88
  }
87
89
  : {}),
@@ -108,6 +110,7 @@ $: renderComponentProps = () => {
108
110
  ...actions(),
109
111
  },
110
112
  }),
113
+ customBreakpoints: childrenContext?.()?.content?.meta?.breakpoints,
111
114
  },
112
115
  context: childrenContext(),
113
116
  };
@@ -170,6 +173,7 @@ $: inheritedTextStyles = () => {
170
173
  const styles = getReactNativeBlockStyles({
171
174
  block: useBlock(),
172
175
  context: context,
176
+ blockStyles: attributes().style,
173
177
  });
174
178
  return extractTextStyles(styles);
175
179
  };
@@ -1,11 +1,13 @@
1
1
  import { SvelteComponentTyped } from "svelte";
2
2
  import type { BuilderBlock } from "../../types/builder-block.js";
3
3
  import type { BuilderContextInterface } from "../../context/types.js";
4
+ import type { Breakpoints } from "../../types/builder-content.js";
4
5
  export interface RenderComponentProps {
5
6
  componentRef: any;
6
7
  componentOptions: any;
7
8
  blockChildren: BuilderBlock[];
8
9
  context: BuilderContextInterface;
10
+ customBreakpoints?: Breakpoints;
9
11
  }
10
12
  declare const __propDef: {
11
13
  props: {
@@ -45,6 +45,16 @@ function processMessage(event) {
45
45
  const { data } = event;
46
46
  if (data) {
47
47
  switch (data.type) {
48
+ case "builder.configureSdk": {
49
+ const messageContent = data.data;
50
+ const { breakpoints, contentId } = messageContent;
51
+ if (!contentId || contentId !== useContent?.()?.id) {
52
+ return;
53
+ }
54
+ useBreakpoints = breakpoints;
55
+ forceReRenderCount = forceReRenderCount + 1; // This is a hack to force Qwik to re-render.
56
+ break;
57
+ }
48
58
  case "builder.contentUpdate": {
49
59
  const messageContent = data.data;
50
60
  const key = messageContent.key ||
@@ -147,6 +157,13 @@ $: useContent = () => {
147
157
  ...data,
148
158
  ...overrideContent?.data,
149
159
  },
160
+ meta: {
161
+ ...content?.meta,
162
+ ...overrideContent?.meta,
163
+ breakpoints: useBreakpoints ||
164
+ overrideContent?.meta?.breakpoints ||
165
+ content?.meta?.breakpoints,
166
+ },
150
167
  };
151
168
  return mergedContent;
152
169
  };
@@ -197,6 +214,7 @@ let elementRef;
197
214
  let forceReRenderCount = 0;
198
215
  let overrideContent = null;
199
216
  let update = 0;
217
+ let useBreakpoints = null;
200
218
  let overrideState = {};
201
219
  onMount(() => {
202
220
  if (!apiKey) {
@@ -1,5 +1,6 @@
1
1
  import type { BuilderBlock } from '../types/builder-block.js';
2
2
  export declare function getBlockProperties(block: BuilderBlock): {
3
3
  'builder-id': string | undefined;
4
+ style: string | Partial<CSSStyleDeclaration> | undefined;
4
5
  class: string;
5
6
  };
@@ -1,9 +1,35 @@
1
+ import { TARGET } from '../constants/target.js';
2
+ import { convertStyleMapToCSSArray } from '../helpers/css.js';
3
+ import { transformBlockProperties } from './transform-block-properties.js';
1
4
  export function getBlockProperties(block) {
2
- return {
5
+ const properties = {
3
6
  ...block.properties,
4
7
  'builder-id': block.id,
8
+ style: getStyleAttribute(block.style),
5
9
  class: [block.id, 'builder-block', block.class, block.properties?.class]
6
10
  .filter(Boolean)
7
11
  .join(' '),
8
12
  };
13
+ return transformBlockProperties(properties);
14
+ }
15
+ /**
16
+ * Svelte does not support style attribute as an object so we need to flatten it.
17
+ *
18
+ * Additionally, Svelte, Vue and other frameworks use kebab-case styles, so we need to convert them.
19
+ */
20
+ function getStyleAttribute(style) {
21
+ if (!style) {
22
+ return undefined;
23
+ }
24
+ switch (TARGET) {
25
+ case 'svelte':
26
+ case 'vue2':
27
+ case 'vue3':
28
+ case 'solid':
29
+ return convertStyleMapToCSSArray(style).join(' ');
30
+ case 'qwik':
31
+ case 'reactNative':
32
+ case 'react':
33
+ return style;
34
+ }
9
35
  }
@@ -1,6 +1,7 @@
1
1
  import type { BuilderContextInterface } from '../context/types.js';
2
2
  import type { BuilderBlock } from '../types/builder-block.js';
3
- export declare function getReactNativeBlockStyles({ block, context, }: {
3
+ export declare function getReactNativeBlockStyles({ block, context, blockStyles, }: {
4
4
  block: BuilderBlock;
5
5
  context: BuilderContextInterface;
6
+ blockStyles: any;
6
7
  }): CSSStyleDeclaration | Record<string, string | undefined>;
@@ -1,5 +1,5 @@
1
1
  import { sanitizeReactNativeBlockStyles } from './sanitize-react-native-block-styles.js';
2
- export function getReactNativeBlockStyles({ block, context, }) {
2
+ export function getReactNativeBlockStyles({ block, context, blockStyles, }) {
3
3
  const responsiveStyles = block.responsiveStyles;
4
4
  if (!responsiveStyles) {
5
5
  return {};
@@ -10,6 +10,7 @@ export function getReactNativeBlockStyles({ block, context, }) {
10
10
  ...(responsiveStyles.large || {}),
11
11
  ...(responsiveStyles.medium || {}),
12
12
  ...(responsiveStyles.small || {}),
13
+ ...blockStyles,
13
14
  };
14
15
  const newStyles = sanitizeReactNativeBlockStyles(styles);
15
16
  return newStyles;
@@ -0,0 +1 @@
1
+ export declare function transformBlockProperties<T>(properties: T): T;
@@ -0,0 +1,3 @@
1
+ export function transformBlockProperties(properties) {
2
+ return properties;
3
+ }
@@ -1,3 +1,5 @@
1
+ export declare const convertStyleMapToCSSArray: (style: Partial<CSSStyleDeclaration>) => string[];
2
+ export declare const convertStyleMapToCSS: (style: Partial<CSSStyleDeclaration>) => string;
1
3
  export declare const createCssClass: ({ mediaQuery, className, styles, }: {
2
4
  mediaQuery?: string | undefined;
3
5
  className: string;
@@ -1,15 +1,20 @@
1
1
  import { camelToKebabCase } from '../functions/camel-to-kebab-case.js';
2
- const convertStyleMaptoCSS = (style) => {
2
+ import { checkIsDefined } from './nullable.js';
3
+ export const convertStyleMapToCSSArray = (style) => {
3
4
  const cssProps = Object.entries(style).map(([key, value]) => {
4
5
  if (typeof value === 'string') {
5
6
  return `${camelToKebabCase(key)}: ${value};`;
6
7
  }
8
+ else {
9
+ return undefined;
10
+ }
7
11
  });
8
- return cssProps.join('\n');
12
+ return cssProps.filter(checkIsDefined);
9
13
  };
14
+ export const convertStyleMapToCSS = (style) => convertStyleMapToCSSArray(style).join('\n');
10
15
  export const createCssClass = ({ mediaQuery, className, styles, }) => {
11
16
  const cssClass = `.${className} {
12
- ${convertStyleMaptoCSS(styles)}
17
+ ${convertStyleMapToCSS(styles)}
13
18
  }`;
14
19
  if (mediaQuery) {
15
20
  return `${mediaQuery} {
@@ -53,5 +53,6 @@ export interface BuilderBlock {
53
53
  itemName?: string;
54
54
  } | null;
55
55
  animations?: any[];
56
+ style?: Partial<CSSStyleDeclaration>;
56
57
  }
57
58
  export {};
@@ -1,5 +1,10 @@
1
1
  import type { BuilderBlock } from './builder-block.js';
2
+ import type { Nullable } from './typescript.js';
2
3
  declare type Input = any;
4
+ export interface Breakpoints {
5
+ small: number;
6
+ medium: number;
7
+ }
3
8
  export interface BuilderContentVariation {
4
9
  data?: {
5
10
  title?: string;
@@ -19,10 +24,7 @@ export interface BuilderContentVariation {
19
24
  testRatio?: number;
20
25
  id?: string;
21
26
  meta?: {
22
- breakpoints?: {
23
- small: number;
24
- medium: number;
25
- };
27
+ breakpoints?: Nullable<Breakpoints>;
26
28
  [key: string]: any;
27
29
  };
28
30
  }
@@ -1,3 +1,3 @@
1
1
  declare type MitosisTargets = import('@builder.io/mitosis').Target;
2
- export declare type Target = Extract<MitosisTargets, 'vue3' | 'vue2' | 'reactNative' | 'svelte' | 'qwik'>;
2
+ export declare type Target = Extract<MitosisTargets, 'vue3' | 'vue2' | 'reactNative' | 'svelte' | 'qwik' | 'react' | 'solid'>;
3
3
  export {};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@builder.io/sdk-svelte",
3
3
  "description": "Builder.io SDK for Svelte",
4
- "version": "0.0.9",
4
+ "version": "0.0.10",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "package",
@@ -1,9 +1,9 @@
1
1
  <script context="module" lang="ts">
2
2
  import type { BuilderBlock } from "../../types/builder-block";
3
3
 
4
- type CSS = {
5
- [key: string]: string;
6
- };
4
+ import type { SizeName } from "../../constants/device-sizes";
5
+
6
+ import type { Breakpoints } from "../../types/builder-content";
7
7
 
8
8
  type Column = {
9
9
  blocks: any;
@@ -23,16 +23,22 @@
23
23
  stackColumnsAt?: StackColumnsAt;
24
24
  // TODO: Implement this when support for dynamic CSS lands
25
25
  reverseColumnsWhenStacked?: boolean;
26
+ customBreakpoints?: Breakpoints;
26
27
  }
27
28
  </script>
28
29
 
29
30
  <script lang="ts">
30
31
  import RenderBlocks from "../../components/render-blocks.svelte";
32
+ import { getSizesForBreakpoints } from "../../constants/device-sizes";
33
+ import RenderInlinedStyles from "../../components/render-inlined-styles.svelte";
34
+ import { TARGET } from "../../constants/target.js";
35
+ import { convertStyleMapToCSS } from "../../helpers/css";
31
36
 
32
37
  export let space: ColumnProps["space"];
33
38
  export let columns: ColumnProps["columns"];
34
39
  export let stackColumnsAt: ColumnProps["stackColumnsAt"];
35
40
  export let reverseColumnsWhenStacked: ColumnProps["reverseColumnsWhenStacked"];
41
+ export let customBreakpoints: ColumnProps["customBreakpoints"];
36
42
  export let builderBlock: ColumnProps["builderBlock"];
37
43
 
38
44
  function mitosis_styling(node, vars) {
@@ -65,6 +71,10 @@
65
71
  const _stackColumnsAt = stackColumnsAt || "tablet";
66
72
  return _stackColumnsAt === "tablet" ? prop : "inherit";
67
73
  }
74
+ function getWidthForBreakpointSize(size) {
75
+ const breakpointSizes = getSizesForBreakpoints(customBreakpoints || {});
76
+ return breakpointSizes[size].max;
77
+ }
68
78
  $: columnsCssVars = () => {
69
79
  const flexDir =
70
80
  stackColumnsAt === "never"
@@ -87,14 +97,78 @@
87
97
  "--column-margin-left-tablet": maybeApplyForTablet(marginLeft),
88
98
  };
89
99
  };
100
+ $: columnStyleObjects = () => {
101
+ return {
102
+ columns: {
103
+ small: {
104
+ flexDirection: "var(--flex-dir)",
105
+ alignItems: "stretch",
106
+ },
107
+ medium: {
108
+ flexDirection: "var(--flex-dir-tablet)",
109
+ alignItems: "stretch",
110
+ },
111
+ },
112
+ column: {
113
+ small: {
114
+ width: "var(--column-width) !important",
115
+ marginLeft: "var(--column-margin-left) !important",
116
+ },
117
+ medium: {
118
+ width: "var(--column-width-tablet) !important",
119
+ marginLeft: "var(--column-margin-left-tablet) !important",
120
+ },
121
+ },
122
+ };
123
+ };
124
+ $: columnsStyles = () => {
125
+ return `
126
+ @media (max-width: ${getWidthForBreakpointSize("medium")}px) {
127
+ .${builderBlock.id}-breakpoints {
128
+ ${convertStyleMapToCSS(columnStyleObjects().columns.medium)}
129
+ }
130
+
131
+ .${builderBlock.id}-breakpoints > .builder-column {
132
+ ${convertStyleMapToCSS(columnStyleObjects().column.medium)}
133
+ }
134
+ }
135
+
136
+ @media (max-width: ${getWidthForBreakpointSize("small")}px) {
137
+ .${builderBlock.id}-breakpoints {
138
+ ${convertStyleMapToCSS(columnStyleObjects().columns.small)}
139
+ }
140
+
141
+ .${builderBlock.id}-breakpoints > .builder-column {
142
+ ${convertStyleMapToCSS(columnStyleObjects().column.small)}
143
+ }
144
+ },
145
+ `;
146
+ };
147
+ $: reactNativeColumnsStyles = () => {
148
+ return columnStyleObjects.columns.small;
149
+ };
150
+ $: reactNativeColumnStyles = () => {
151
+ return columnStyleObjects.column.small;
152
+ };
90
153
  </script>
91
154
 
92
- <div use:mitosis_styling={columnsCssVars()} class="builder-columns div">
155
+ <div
156
+ use:mitosis_styling={{
157
+ ...(TARGET === "reactNative" ? reactNativeColumnsStyles() : {}),
158
+ ...columnsCssVars(),
159
+ }}
160
+ class={`builder-columns ${builderBlock.id}-breakpoints` + " div"}
161
+ >
162
+ {#if TARGET !== "reactNative"}
163
+ <RenderInlinedStyles styles={columnsStyles()} />
164
+ {/if}
165
+
93
166
  {#each columns as column, index (index)}
94
167
  <div
95
168
  use:mitosis_styling={{
96
169
  width: getColumnCssWidth(index),
97
170
  marginLeft: `${index === 0 ? 0 : getGutterSize()}px`,
171
+ ...(TARGET === "reactNative" ? reactNativeColumnStyles() : {}),
98
172
  ...columnCssVars(),
99
173
  }}
100
174
  class="builder-column div-2"
@@ -114,34 +188,11 @@
114
188
  <style>
115
189
  .div {
116
190
  display: flex;
117
- align-items: stretch;
118
191
  line-height: normal;
119
192
  }
120
- @media (max-width: 991px) {
121
- .div {
122
- flex-direction: var(--flex-dir-tablet);
123
- }
124
- }
125
- @media (max-width: 639px) {
126
- .div {
127
- flex-direction: var(--flex-dir);
128
- }
129
- }
130
193
  .div-2 {
131
194
  display: flex;
132
195
  flex-direction: column;
133
196
  align-items: stretch;
134
197
  }
135
- @media (max-width: 991px) {
136
- .div-2 {
137
- width: var(--column-width-tablet) !important;
138
- margin-left: var(--column-margin-left-tablet) !important;
139
- }
140
- }
141
- @media (max-width: 639px) {
142
- .div-2 {
143
- width: var(--column-width) !important;
144
- margin-left: var(--column-margin-left) !important;
145
- }
146
- }
147
198
  </style>
@@ -57,11 +57,18 @@
57
57
  </script>
58
58
 
59
59
  <section
60
- use:mitosis_styling={maxWidth && typeof maxWidth === "number"
61
- ? {
62
- maxWidth: maxWidth,
63
- }
64
- : undefined}
60
+ use:mitosis_styling={{
61
+ width: "100%",
62
+ alignSelf: "stretch",
63
+ flexGrow: "1",
64
+ boxSizing: "border-box",
65
+ maxWidth: `${maxWidth && typeof maxWidth === "number" ? maxWidth : 1200}px`,
66
+ display: "flex",
67
+ flexDirection: "column",
68
+ alignItems: "stretch",
69
+ marginLeft: "auto",
70
+ marginRight: "auto",
71
+ }}
65
72
  {...filterAttrs(attributes, isNonEvent)}
66
73
  use:setAttrs={filterAttrs(attributes, isEvent)}
67
74
  >
@@ -30,6 +30,7 @@
30
30
  import RenderContent from "../../components/render-content/render-content.svelte";
31
31
  import BuilderContext from "../../context/builder.context.js";
32
32
  import { getContent } from "../../functions/get-content/index.js";
33
+ import { TARGET } from "../../constants/target";
33
34
 
34
35
  const isEvent = (attr) => attr.startsWith("on:");
35
36
  const isNonEvent = (attr) => !attr.startsWith("on:");
@@ -65,16 +66,28 @@
65
66
  };
66
67
  };
67
68
 
68
- export let symbol: SymbolProps["symbol"];
69
69
  export let attributes: SymbolProps["attributes"];
70
+ export let symbol: SymbolProps["symbol"];
71
+ export let dynamic: SymbolProps["dynamic"];
70
72
 
71
73
  let builderContext = getContext(BuilderContext.key);
72
74
 
75
+ $: className = () => {
76
+ return [
77
+ ...(TARGET === "vue2" || TARGET === "vue3"
78
+ ? Object.keys(attributes.class)
79
+ : [attributes.class]),
80
+ "builder-symbol",
81
+ symbol?.inline ? "builder-inline-symbol" : undefined,
82
+ symbol?.dynamic || dynamic ? "builder-dynamic-symbol" : undefined,
83
+ ]
84
+ .filter(Boolean)
85
+ .join(" ");
86
+ };
73
87
  $: contentToUse = () => {
74
88
  return symbol?.content || fetchedContent;
75
89
  };
76
90
 
77
- let className = "builder-symbol";
78
91
  let fetchedContent = null;
79
92
 
80
93
  function onUpdateFn_0() {
@@ -112,9 +125,9 @@
112
125
  <div
113
126
  {...filterAttrs(attributes, isNonEvent)}
114
127
  dataSet={{
115
- class: className,
128
+ class: className(),
116
129
  }}
117
- class={className}
130
+ class={className()}
118
131
  use:setAttrs={filterAttrs(attributes, isEvent)}
119
132
  >
120
133
  <RenderContent
@@ -100,13 +100,15 @@
100
100
  });
101
101
  };
102
102
  $: attributes = () => {
103
+ const blockProperties = getBlockProperties(useBlock());
103
104
  return {
104
- ...getBlockProperties(useBlock()),
105
+ ...blockProperties,
105
106
  ...(TARGET === "reactNative"
106
107
  ? {
107
108
  style: getReactNativeBlockStyles({
108
109
  block: useBlock(),
109
110
  context: context,
111
+ blockStyles: blockProperties.style,
110
112
  }),
111
113
  }
112
114
  : {}),
@@ -133,6 +135,7 @@
133
135
  ...actions(),
134
136
  },
135
137
  }),
138
+ customBreakpoints: childrenContext?.()?.content?.meta?.breakpoints,
136
139
  },
137
140
  context: childrenContext(),
138
141
  };
@@ -197,6 +200,7 @@
197
200
  const styles = getReactNativeBlockStyles({
198
201
  block: useBlock(),
199
202
  context: context,
203
+ blockStyles: attributes().style,
200
204
  });
201
205
  return extractTextStyles(styles);
202
206
  };
@@ -3,11 +3,14 @@
3
3
 
4
4
  import type { BuilderContextInterface } from "../../context/types.js";
5
5
 
6
+ import type { Breakpoints } from "../../types/builder-content.js";
7
+
6
8
  export interface RenderComponentProps {
7
9
  componentRef: any;
8
10
  componentOptions: any;
9
11
  blockChildren: BuilderBlock[];
10
12
  context: BuilderContextInterface;
13
+ customBreakpoints?: Breakpoints;
11
14
  }
12
15
  </script>
13
16
 
@@ -6,7 +6,10 @@
6
6
  RegisteredComponents,
7
7
  } from "../../context/types.js";
8
8
 
9
- import type { BuilderContent } from "../../types/builder-content.js";
9
+ import type {
10
+ Breakpoints,
11
+ BuilderContent,
12
+ } from "../../types/builder-content.js";
10
13
 
11
14
  import type { Dictionary, Nullable } from "../../types/typescript.js";
12
15
 
@@ -99,6 +102,16 @@
99
102
  const { data } = event;
100
103
  if (data) {
101
104
  switch (data.type) {
105
+ case "builder.configureSdk": {
106
+ const messageContent = data.data;
107
+ const { breakpoints, contentId } = messageContent;
108
+ if (!contentId || contentId !== useContent?.()?.id) {
109
+ return;
110
+ }
111
+ useBreakpoints = breakpoints;
112
+ forceReRenderCount = forceReRenderCount + 1; // This is a hack to force Qwik to re-render.
113
+ break;
114
+ }
102
115
  case "builder.contentUpdate": {
103
116
  const messageContent = data.data;
104
117
  const key =
@@ -207,6 +220,14 @@
207
220
  ...data,
208
221
  ...overrideContent?.data,
209
222
  },
223
+ meta: {
224
+ ...content?.meta,
225
+ ...overrideContent?.meta,
226
+ breakpoints:
227
+ useBreakpoints ||
228
+ overrideContent?.meta?.breakpoints ||
229
+ content?.meta?.breakpoints,
230
+ },
210
231
  };
211
232
  return mergedContent;
212
233
  };
@@ -264,6 +285,7 @@
264
285
  let forceReRenderCount = 0;
265
286
  let overrideContent = null;
266
287
  let update = 0;
288
+ let useBreakpoints = null;
267
289
  let overrideState = {};
268
290
 
269
291
  onMount(() => {
@@ -1,11 +1,41 @@
1
+ import { TARGET } from '../constants/target.js';
2
+ import { convertStyleMapToCSSArray } from '../helpers/css.js';
1
3
  import type { BuilderBlock } from '../types/builder-block.js';
4
+ import { transformBlockProperties } from './transform-block-properties.js';
2
5
 
3
6
  export function getBlockProperties(block: BuilderBlock) {
4
- return {
7
+ const properties = {
5
8
  ...block.properties,
6
9
  'builder-id': block.id,
10
+ style: getStyleAttribute(block.style),
7
11
  class: [block.id, 'builder-block', block.class, block.properties?.class]
8
12
  .filter(Boolean)
9
13
  .join(' '),
10
14
  };
15
+
16
+ return transformBlockProperties(properties);
17
+ }
18
+ /**
19
+ * Svelte does not support style attribute as an object so we need to flatten it.
20
+ *
21
+ * Additionally, Svelte, Vue and other frameworks use kebab-case styles, so we need to convert them.
22
+ */
23
+ function getStyleAttribute(
24
+ style: Partial<CSSStyleDeclaration> | undefined
25
+ ): string | Partial<CSSStyleDeclaration> | undefined {
26
+ if (!style) {
27
+ return undefined;
28
+ }
29
+
30
+ switch (TARGET) {
31
+ case 'svelte':
32
+ case 'vue2':
33
+ case 'vue3':
34
+ case 'solid':
35
+ return convertStyleMapToCSSArray(style).join(' ');
36
+ case 'qwik':
37
+ case 'reactNative':
38
+ case 'react':
39
+ return style;
40
+ }
11
41
  }
@@ -5,9 +5,11 @@ import { sanitizeReactNativeBlockStyles } from './sanitize-react-native-block-st
5
5
  export function getReactNativeBlockStyles({
6
6
  block,
7
7
  context,
8
+ blockStyles,
8
9
  }: {
9
10
  block: BuilderBlock;
10
11
  context: BuilderContextInterface;
12
+ blockStyles: any;
11
13
  }): CSSStyleDeclaration | Record<string, string | undefined> {
12
14
  const responsiveStyles = block.responsiveStyles;
13
15
  if (!responsiveStyles) {
@@ -20,6 +22,7 @@ export function getReactNativeBlockStyles({
20
22
  ...(responsiveStyles.large || {}),
21
23
  ...(responsiveStyles.medium || {}),
22
24
  ...(responsiveStyles.small || {}),
25
+ ...blockStyles,
23
26
  } as Record<string, string | number>;
24
27
 
25
28
  const newStyles = sanitizeReactNativeBlockStyles(
@@ -0,0 +1,3 @@
1
+ export function transformBlockProperties<T>(properties: T) {
2
+ return properties;
3
+ }
@@ -1,15 +1,24 @@
1
1
  import { camelToKebabCase } from '../functions/camel-to-kebab-case.js';
2
+ import { checkIsDefined } from './nullable.js';
2
3
 
3
- const convertStyleMaptoCSS = (style: Partial<CSSStyleDeclaration>): string => {
4
+ export const convertStyleMapToCSSArray = (
5
+ style: Partial<CSSStyleDeclaration>
6
+ ): string[] => {
4
7
  const cssProps = Object.entries(style).map(([key, value]) => {
5
8
  if (typeof value === 'string') {
6
9
  return `${camelToKebabCase(key)}: ${value};`;
10
+ } else {
11
+ return undefined;
7
12
  }
8
13
  });
9
14
 
10
- return cssProps.join('\n');
15
+ return cssProps.filter(checkIsDefined);
11
16
  };
12
17
 
18
+ export const convertStyleMapToCSS = (
19
+ style: Partial<CSSStyleDeclaration>
20
+ ): string => convertStyleMapToCSSArray(style).join('\n');
21
+
13
22
  export const createCssClass = ({
14
23
  mediaQuery,
15
24
  className,
@@ -20,7 +29,7 @@ export const createCssClass = ({
20
29
  styles: Partial<CSSStyleDeclaration>;
21
30
  }) => {
22
31
  const cssClass = `.${className} {
23
- ${convertStyleMaptoCSS(styles)}
32
+ ${convertStyleMapToCSS(styles)}
24
33
  }`;
25
34
 
26
35
  if (mediaQuery) {
@@ -55,4 +55,5 @@ export interface BuilderBlock {
55
55
  itemName?: string;
56
56
  } | null;
57
57
  animations?: any[]; // TODO: type the animation spec
58
+ style?: Partial<CSSStyleDeclaration>;
58
59
  }
@@ -1,8 +1,13 @@
1
1
  import type { BuilderBlock } from './builder-block.js';
2
+ import type { Nullable } from './typescript.js';
2
3
 
3
4
  // TODO
4
5
  type Input = any;
5
6
 
7
+ export interface Breakpoints {
8
+ small: number;
9
+ medium: number;
10
+ }
6
11
  export interface BuilderContentVariation {
7
12
  data?: {
8
13
  title?: string;
@@ -18,10 +23,7 @@ export interface BuilderContentVariation {
18
23
  testRatio?: number;
19
24
  id?: string;
20
25
  meta?: {
21
- breakpoints?: {
22
- small: number;
23
- medium: number;
24
- };
26
+ breakpoints?: Nullable<Breakpoints>;
25
27
  [key: string]: any;
26
28
  };
27
29
  }
@@ -2,5 +2,5 @@ type MitosisTargets = import('@builder.io/mitosis').Target;
2
2
 
3
3
  export type Target = Extract<
4
4
  MitosisTargets,
5
- 'vue3' | 'vue2' | 'reactNative' | 'svelte' | 'qwik'
5
+ 'vue3' | 'vue2' | 'reactNative' | 'svelte' | 'qwik' | 'react' | 'solid'
6
6
  >;