@developer_tribe/react-builder 1.2.8 → 1.2.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 (192) hide show
  1. package/dist/AttributesEditor.d.ts +2 -11
  2. package/dist/attribute-analyser/style/native/useExtractImageStyle.d.ts +10 -0
  3. package/dist/attribute-analyser/style/native/useExtractTextStyle.d.ts +9 -0
  4. package/dist/attribute-analyser/style/native/useExtractViewStyle.d.ts +8 -0
  5. package/dist/attribute-analyser/style/web/useExtractImageStyle.d.ts +4 -0
  6. package/dist/attribute-analyser/style/web/useExtractTextStyle.d.ts +4 -0
  7. package/dist/attribute-analyser/style/web/useExtractViewStyle.d.ts +4 -0
  8. package/dist/attributes-editor/AttributesEditorFields.d.ts +18 -0
  9. package/dist/attributes-editor/AttributesEditorView.d.ts +4 -0
  10. package/dist/attributes-editor/attributesEditorModelTypes.d.ts +67 -0
  11. package/dist/attributes-editor/attributesEditorUtils.d.ts +19 -0
  12. package/dist/attributes-editor/useAttributesEditorModel.d.ts +2 -0
  13. package/dist/build-components/BIcon/BIconProps.generated.d.ts +6 -6
  14. package/dist/build-components/BackgroundImage/BackgroundImageProps.generated.d.ts +3 -3
  15. package/dist/build-components/Button/ButtonProps.generated.d.ts +1 -1
  16. package/dist/build-components/Carousel/CarouselProps.generated.d.ts +2 -2
  17. package/dist/build-components/CarouselButtons/CarouselButtonsProps.generated.d.ts +4 -4
  18. package/dist/build-components/CarouselDots/CarouselDotsProps.generated.d.ts +3 -3
  19. package/dist/build-components/CarouselItem/CarouselItemProps.generated.d.ts +1 -1
  20. package/dist/build-components/CarouselProvider/CarouselProviderProps.generated.d.ts +1 -1
  21. package/dist/build-components/Image/ImageProps.generated.d.ts +5 -3
  22. package/dist/build-components/Main/MainProps.generated.d.ts +2 -2
  23. package/dist/build-components/Onboard/OnboardProps.generated.d.ts +1 -1
  24. package/dist/build-components/OnboardButton/OnboardButtonProps.generated.d.ts +9 -8
  25. package/dist/build-components/OnboardButtons/OnboardButtonsProps.generated.d.ts +11 -11
  26. package/dist/build-components/OnboardDot/OnboardDotProps.generated.d.ts +15 -9
  27. package/dist/build-components/OnboardFooter/OnboardFooterProps.generated.d.ts +10 -10
  28. package/dist/build-components/OnboardImage/OnboardImageProps.generated.d.ts +8 -6
  29. package/dist/build-components/OnboardItem/OnboardItemProps.generated.d.ts +6 -3
  30. package/dist/build-components/OnboardProvider/OnboardProviderProps.generated.d.ts +5 -4
  31. package/dist/build-components/OnboardSubtitle/OnboardSubtitleProps.generated.d.ts +3 -3
  32. package/dist/build-components/OnboardTitle/OnboardTitleProps.generated.d.ts +3 -3
  33. package/dist/build-components/PaywallBackground/PaywallBackgroundProps.generated.d.ts +1 -1
  34. package/dist/build-components/PaywallCloseButton/PaywallCloseButtonProps.generated.d.ts +6 -6
  35. package/dist/build-components/PaywallOptions/PaywallOptionsProps.generated.d.ts +1 -1
  36. package/dist/build-components/PaywallProvider/PaywallProviderProps.generated.d.ts +1 -1
  37. package/dist/build-components/PaywallSubscribeButton/PaywallSubscribeButtonProps.generated.d.ts +1 -1
  38. package/dist/build-components/RadioButton/RadioButtonProps.generated.d.ts +4 -4
  39. package/dist/build-components/Text/TextProps.generated.d.ts +3 -3
  40. package/dist/build-components/View/ViewProps.generated.d.ts +1 -1
  41. package/dist/build-components/patterns.generated.d.ts +2690 -5804
  42. package/dist/index.cjs.js +5 -5
  43. package/dist/index.cjs.js.map +1 -1
  44. package/dist/index.d.ts +1 -0
  45. package/dist/index.esm.js +5 -5
  46. package/dist/index.esm.js.map +1 -1
  47. package/dist/index.native.cjs.js +6 -4
  48. package/dist/index.native.cjs.js.map +1 -1
  49. package/dist/index.native.d.ts +5 -6
  50. package/dist/index.native.esm.js +6 -4
  51. package/dist/index.native.esm.js.map +1 -1
  52. package/dist/migrations/migratePipe.d.ts +1 -1
  53. package/dist/migrations/migrations/1.1.2_extract_component_attributes_from_style.d.ts +2 -0
  54. package/dist/mockOS/components/PermissionModal.d.ts +1 -2
  55. package/dist/styles.css +1 -1
  56. package/dist/types/PreviewConfig.d.ts +1 -5
  57. package/dist/utils/getMeta.d.ts +5 -0
  58. package/dist/utils/patterns.d.ts +12 -0
  59. package/package.json +4 -2
  60. package/scripts/prebuild/prebuild.js +14 -0
  61. package/scripts/prebuild/utils/createGeneratedProps.js +19 -13
  62. package/scripts/prebuild/utils/index.js +1 -0
  63. package/scripts/prebuild/utils/updateMetaJson.js +66 -0
  64. package/scripts/prebuild/utils/validateAllComponentsOrThrow.js +37 -3
  65. package/scripts/prebuild/utils/validatePatternJson.js +27 -2
  66. package/scripts/public/scripts/build/index.js +20 -3
  67. package/scripts/public/scripts/build/info.json +6 -0
  68. package/scripts/public/scripts/build/utils/createComponentsIndex.js +9 -3
  69. package/scripts/public/scripts/build/utils/createRenderNodeGenerated.js +66 -8
  70. package/src/AttributesEditor.tsx +8 -944
  71. package/src/assets/meta.json +4 -0
  72. package/src/assets/samples/carousel-sample.json +1 -1
  73. package/src/assets/samples/getSamples.ts +2 -0
  74. package/src/assets/samples/paywall-1.json +11 -7
  75. package/src/assets/samples/simple-1.json +3 -3
  76. package/src/assets/samples/simple-2.json +3 -3
  77. package/src/assets/samples/unmigrated-builder-1.1.1.json +87 -0
  78. package/src/assets/samples/unmigrated-builder1.json +1 -1
  79. package/src/assets/samples/unvalidated-builder1.json +3 -3
  80. package/src/assets/samples/unvalidated-crash1.json +1 -1
  81. package/src/assets/samples/unvalidated-crashcomponent1.json +1 -1
  82. package/src/assets/samples/vpn-onboard-1.json +1 -1
  83. package/src/assets/samples/vpn-onboard-2.json +1 -1
  84. package/src/assets/samples/vpn-onboard-3.json +1 -1
  85. package/src/assets/samples/vpn-onboard-4.json +1 -1
  86. package/src/assets/samples/vpn-onboard-5.json +1 -1
  87. package/src/assets/samples/vpn-onboard-6.json +1 -1
  88. package/src/attribute-analyser/style/native/useExtractImageStyle.ts +46 -0
  89. package/src/attribute-analyser/style/native/useExtractTextStyle.ts +50 -0
  90. package/src/attribute-analyser/style/native/useExtractViewStyle.ts +32 -0
  91. package/src/attribute-analyser/style/web/useExtractImageStyle.ts +20 -0
  92. package/src/attribute-analyser/style/web/useExtractTextStyle.ts +27 -0
  93. package/src/attribute-analyser/style/web/useExtractViewStyle.ts +20 -0
  94. package/src/attributes-editor/AttributesEditorFields.tsx +248 -0
  95. package/src/attributes-editor/AttributesEditorView.tsx +360 -0
  96. package/src/attributes-editor/attributesEditorModelTypes.ts +86 -0
  97. package/src/attributes-editor/attributesEditorUtils.ts +102 -0
  98. package/src/attributes-editor/useAttributesEditorModel.ts +477 -0
  99. package/src/build-components/BIcon/BIcon.tsx +4 -4
  100. package/src/build-components/BIcon/BIconProps.generated.ts +6 -6
  101. package/src/build-components/BIcon/pattern.json +5 -6
  102. package/src/build-components/BackgroundImage/BackgroundImage.tsx +3 -2
  103. package/src/build-components/BackgroundImage/BackgroundImageProps.generated.ts +3 -3
  104. package/src/build-components/Button/Button.tsx +2 -2
  105. package/src/build-components/Button/ButtonProps.generated.ts +1 -1
  106. package/src/build-components/Button/pattern.json +17 -15
  107. package/src/build-components/Carousel/Carousel.tsx +1 -1
  108. package/src/build-components/Carousel/CarouselProps.generated.ts +2 -2
  109. package/src/build-components/CarouselButtons/CarouselButtons.tsx +4 -7
  110. package/src/build-components/CarouselButtons/CarouselButtonsProps.generated.ts +7 -7
  111. package/src/build-components/CarouselButtons/pattern.json +2 -1
  112. package/src/build-components/CarouselDots/CarouselDots.tsx +2 -2
  113. package/src/build-components/CarouselDots/CarouselDotsProps.generated.ts +9 -9
  114. package/src/build-components/CarouselItem/CarouselItem.tsx +1 -1
  115. package/src/build-components/CarouselItem/CarouselItemProps.generated.ts +1 -1
  116. package/src/build-components/CarouselProvider/CarouselProvider.tsx +1 -1
  117. package/src/build-components/CarouselProvider/CarouselProviderProps.generated.ts +1 -1
  118. package/src/build-components/Image/Image.tsx +1 -1
  119. package/src/build-components/Image/ImageProps.generated.ts +5 -3
  120. package/src/build-components/Image/pattern.json +10 -9
  121. package/src/build-components/Main/Main.tsx +2 -2
  122. package/src/build-components/Main/MainProps.generated.ts +2 -2
  123. package/src/build-components/Main/pattern.json +2 -1
  124. package/src/build-components/Onboard/OnboardProps.generated.ts +1 -1
  125. package/src/build-components/OnboardButton/OnboardButton.tsx +7 -6
  126. package/src/build-components/OnboardButton/OnboardButtonProps.generated.ts +14 -13
  127. package/src/build-components/OnboardButton/pattern.json +9 -7
  128. package/src/build-components/OnboardButtons/OnboardButtons.tsx +31 -31
  129. package/src/build-components/OnboardButtons/OnboardButtonsProps.generated.ts +14 -14
  130. package/src/build-components/OnboardButtons/pattern.json +9 -7
  131. package/src/build-components/OnboardDot/OnboardDot.tsx +7 -6
  132. package/src/build-components/OnboardDot/OnboardDotProps.generated.ts +26 -9
  133. package/src/build-components/OnboardFooter/OnboardFooter.tsx +17 -16
  134. package/src/build-components/OnboardFooter/OnboardFooterProps.generated.ts +10 -10
  135. package/src/build-components/OnboardFooter/pattern.json +16 -14
  136. package/src/build-components/OnboardImage/OnboardImage.tsx +8 -8
  137. package/src/build-components/OnboardImage/OnboardImageProps.generated.ts +8 -6
  138. package/src/build-components/OnboardImage/pattern.json +2 -1
  139. package/src/build-components/OnboardItem/OnboardItem.tsx +1 -1
  140. package/src/build-components/OnboardItem/OnboardItemProps.generated.ts +6 -3
  141. package/src/build-components/OnboardItem/pattern.json +2 -1
  142. package/src/build-components/OnboardProvider/OnboardProvider.tsx +1 -1
  143. package/src/build-components/OnboardProvider/OnboardProviderProps.generated.ts +5 -4
  144. package/src/build-components/OnboardProvider/pattern.json +2 -1
  145. package/src/build-components/OnboardSubtitle/OnboardSubtitleProps.generated.ts +3 -3
  146. package/src/build-components/OnboardTitle/OnboardTitleProps.generated.ts +3 -3
  147. package/src/build-components/PaywallBackground/PaywallBackground.tsx +1 -1
  148. package/src/build-components/PaywallBackground/PaywallBackgroundProps.generated.ts +1 -1
  149. package/src/build-components/PaywallCloseButton/PaywallCloseButton.tsx +5 -4
  150. package/src/build-components/PaywallCloseButton/PaywallCloseButtonProps.generated.ts +6 -6
  151. package/src/build-components/PaywallOptions/PaywallOptionButton.tsx +1 -1
  152. package/src/build-components/PaywallOptions/PaywallOptionsProps.generated.ts +1 -1
  153. package/src/build-components/PaywallProvider/PaywallProvider.tsx +1 -1
  154. package/src/build-components/PaywallProvider/PaywallProviderProps.generated.ts +1 -1
  155. package/src/build-components/PaywallSubscribeButton/PaywallSubscribeButton.tsx +1 -1
  156. package/src/build-components/PaywallSubscribeButton/PaywallSubscribeButtonProps.generated.ts +1 -1
  157. package/src/build-components/RadioButton/RadioButton.tsx +5 -5
  158. package/src/build-components/RadioButton/RadioButtonProps.generated.ts +4 -4
  159. package/src/build-components/RadioButton/pattern.json +9 -7
  160. package/src/build-components/Text/Text.tsx +6 -6
  161. package/src/build-components/Text/TextProps.generated.ts +3 -3
  162. package/src/build-components/Text/pattern.json +15 -11
  163. package/src/build-components/View/View.tsx +1 -1
  164. package/src/build-components/View/ViewProps.generated.ts +1 -1
  165. package/src/build-components/View/pattern.json +71 -66
  166. package/src/build-components/patterns.generated.ts +3059 -6008
  167. package/src/components/AttributesEditorPanel.tsx +2 -2
  168. package/src/index.native.ts +6 -9
  169. package/src/index.ts +1 -0
  170. package/src/migrations/migratePipe.ts +7 -3
  171. package/src/migrations/migrations/1.1.2_extract_component_attributes_from_style.ts +211 -0
  172. package/src/mockOS/components/MockOSRouter.tsx +3 -1
  173. package/src/mockOS/components/PermissionModal.tsx +20 -160
  174. package/src/mockOS/components/SubscriptionModal.tsx +41 -278
  175. package/src/pages/ProjectPage.tsx +12 -6
  176. package/src/styles/components/_attributes-editor.scss +122 -0
  177. package/src/styles/components/_mockos-router.scss +388 -0
  178. package/src/styles/components/_onboard.scss +23 -0
  179. package/src/styles/index.scss +1 -0
  180. package/src/types/PreviewConfig.ts +1 -5
  181. package/src/utils/analyseNodeByPatterns.ts +39 -4
  182. package/src/utils/extractTextStyle/extractTextStyle.ts +4 -1
  183. package/src/utils/getMeta.ts +15 -0
  184. package/src/utils/patterns.ts +47 -4
  185. package/dist/hooks/useExtractImageStyle.d.ts +0 -5
  186. package/dist/hooks/useExtractTextStyle.d.ts +0 -3
  187. package/dist/hooks/useExtractViewStyle.d.ts +0 -3
  188. package/dist/migrations/migrations/1.1.0_normalize_style_attributes.d.ts +0 -2
  189. package/src/hooks/useExtractImageStyle.ts +0 -30
  190. package/src/hooks/useExtractTextStyle.ts +0 -34
  191. package/src/hooks/useExtractViewStyle.ts +0 -30
  192. package/src/migrations/migrations/1.1.0_normalize_style_attributes.ts +0 -80
@@ -1,4 +1,4 @@
1
- import AttributesEditor from '../AttributesEditor';
1
+ import { AttributesEditor } from '../AttributesEditor';
2
2
  import type { Node } from '../types/Node';
3
3
  import type { ProjectColors } from '../types/Project';
4
4
  import { useLogRender } from '../utils/useLogRender';
@@ -56,7 +56,7 @@ export function AttributesEditorPanel({
56
56
  };
57
57
 
58
58
  return (
59
- <div style={{ padding: 12 }}>
59
+ <div className="attributes-editor-panel">
60
60
  <AttributesEditor
61
61
  node={current}
62
62
  onChange={handleAttributesChange}
@@ -9,7 +9,7 @@
9
9
  * This file is meant to be used via the package `react-native` entry (Metro)
10
10
  * or explicit `@developer_tribe/react-builder/native` style imports.
11
11
  */
12
-
12
+ //TODO: index's shoudl be reviewed and updated.
13
13
  // Types
14
14
  export type { TargetedScreenSize } from './types/TargetedScreenSize';
15
15
  export type { Node, NodeData, NodeDefaultAttribute } from './types/Node';
@@ -45,14 +45,9 @@ export { LocalizationParamsProvider } from './components/LocalizationParamsProvi
45
45
  export { useParams } from './hooks/useParams';
46
46
  export { useLocalizationParams } from './hooks/useLocalizationParams';
47
47
  export { useLocalize } from './hooks/useLocalize';
48
- export { useExtractTextStyle } from './hooks/useExtractTextStyle';
49
- export { useExtractViewStyle } from './hooks/useExtractViewStyle';
50
- export { useExtractImageStyle } from './hooks/useExtractImageStyle';
51
-
52
- // Native style extractors (RN-friendly style objects)
53
- export { extractViewStyleNative } from './utils/extractViewStyle';
54
- export { extractTextStyleNative } from './utils/extractTextStyle';
55
- export { extractImageStyleNative } from './utils/extractImageStyle';
48
+ export { useExtractTextStyle } from './attribute-analyser/style/native/useExtractTextStyle';
49
+ export { useExtractViewStyle } from './attribute-analyser/style/native/useExtractViewStyle';
50
+ export { useExtractImageStyle } from './attribute-analyser/style/native/useExtractImageStyle';
56
51
 
57
52
  // Pure utilities (RN-safe)
58
53
  export {
@@ -63,6 +58,7 @@ export {
63
58
  analyseNode,
64
59
  analyseAndProccess,
65
60
  } from './utils/analyseNode';
61
+ export { getMeta } from './utils/getMeta';
66
62
  export { novaToJson } from './utils/novaToJson';
67
63
  export { getDevices, getDefaultDevice } from './utils/getDevices';
68
64
  export { querySelector } from './utils/querySelector';
@@ -93,3 +89,4 @@ export {
93
89
  getOnboardSamples,
94
90
  } from './assets/samples/getSamples';
95
91
  export type { EventObjectGenerated } from './build-components/OnboardButton/OnboardButtonProps.generated';
92
+ export * from './build-components';
package/src/index.ts CHANGED
@@ -3,6 +3,7 @@ import './styles/index.scss';
3
3
  // Web entrypoint trimmed to what the `example/` app uses.
4
4
  export { ProjectPage } from './pages/ProjectPage';
5
5
  export { getSamples } from './assets/samples/getSamples';
6
+ export { getMeta } from './utils/getMeta';
6
7
  export { defaultAppConfig } from './types/PreviewConfig';
7
8
 
8
9
  export type { AppConfig } from './types/PreviewConfig';
@@ -1,11 +1,15 @@
1
+ import metaJson from '../assets/meta.json';
1
2
  import type { Project } from '../types/Project';
2
3
  import type { Migration } from './types';
3
4
  import { isSemverLess } from './semver';
4
- import { migration_1_1_0_normalize_style_attributes } from './migrations/1.1.0_normalize_style_attributes';
5
+ import { migration_1_1_2_extract_component_attributes_from_style } from './migrations/1.1.2_extract_component_attributes_from_style';
5
6
 
6
- export const CURRENT_PROJECT_VERSION = '1.1.0';
7
+ // CURRENT_PROJECT_VERSION is sourced from meta.json (written from package.json during prebuild) to avoid reading package.json directly at runtime.
8
+ export const CURRENT_PROJECT_VERSION = metaJson.supportedProjectVersion;
7
9
 
8
- const MIGRATIONS: Migration[] = [migration_1_1_0_normalize_style_attributes];
10
+ const MIGRATIONS: Migration[] = [
11
+ migration_1_1_2_extract_component_attributes_from_style,
12
+ ];
9
13
 
10
14
  export type MigrationPipe = {
11
15
  projectVersion: string;
@@ -0,0 +1,211 @@
1
+ import type { Project } from '../../types/Project';
2
+ import type { Node, NodeData, NodeDefaultAttribute } from '../../types/Node';
3
+ import {
4
+ getAttributeSchema,
5
+ getStyleAttributeKeySet,
6
+ normalizeComponentType,
7
+ NON_STYLE_ATTRIBUTE_KEYS,
8
+ } from '../../utils/patterns';
9
+ import {
10
+ isEmptyObject,
11
+ isNodeArray,
12
+ isNodeNullOrUndefined,
13
+ isNodeString,
14
+ } from '../../utils/nodeGuards';
15
+ import type { Migration } from '../types';
16
+
17
+ type SchemaCache = Map<
18
+ string,
19
+ { moveableKeys: Set<string>; styleKeys: Set<string> }
20
+ >;
21
+
22
+ function isPlainObject(value: unknown): value is Record<string, unknown> {
23
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
24
+ }
25
+
26
+ function buildStyleKeySet(): Set<string> {
27
+ return getStyleAttributeKeySet();
28
+ }
29
+
30
+ function normalizeStyleAttributes(node: Node, styleKeys: Set<string>): Node {
31
+ if (
32
+ isNodeNullOrUndefined(node) ||
33
+ isNodeString(node) ||
34
+ isEmptyObject(node)
35
+ ) {
36
+ return node;
37
+ }
38
+ if (isNodeArray(node)) {
39
+ return (node as Node[]).map((n) => normalizeStyleAttributes(n, styleKeys));
40
+ }
41
+
42
+ const record = node as NodeData<NodeDefaultAttribute>;
43
+ const nextChildren = normalizeStyleAttributes(
44
+ record.children as Node,
45
+ styleKeys,
46
+ );
47
+
48
+ if (!isPlainObject(record.attributes)) {
49
+ return { ...record, children: nextChildren };
50
+ }
51
+
52
+ const nextAttrs: Record<string, unknown> = { ...(record.attributes ?? {}) };
53
+ const prevStyle = isPlainObject(nextAttrs.style) ? nextAttrs.style : {};
54
+ const nextStyle: Record<string, unknown> = { ...prevStyle };
55
+
56
+ for (const [k, v] of Object.entries(nextAttrs)) {
57
+ if (k === 'style') continue;
58
+ if (!styleKeys.has(k)) continue;
59
+
60
+ // If already set in style, prefer style (drop legacy flat key).
61
+ if (!(k in nextStyle)) nextStyle[k] = v;
62
+ delete nextAttrs[k];
63
+ }
64
+
65
+ if (Object.keys(nextStyle).length > 0) {
66
+ nextAttrs.style = nextStyle;
67
+ }
68
+
69
+ return {
70
+ ...record,
71
+ children: nextChildren,
72
+ attributes: nextAttrs as NodeDefaultAttribute,
73
+ };
74
+ }
75
+
76
+ function getStyleSubSchemaKeys(
77
+ schema: Record<string, unknown> | undefined,
78
+ ): Set<string> {
79
+ if (!schema) return new Set();
80
+ const style = (schema as any).style;
81
+ if (!isPlainObject(style)) return new Set();
82
+ return new Set(Object.keys(style));
83
+ }
84
+
85
+ function getTopLevelAttributeKeys(
86
+ schema: Record<string, unknown> | undefined,
87
+ ): Set<string> {
88
+ if (!schema) return new Set();
89
+ const keys = Object.keys(schema).filter((k) => k !== 'style');
90
+ return new Set(keys);
91
+ }
92
+
93
+ function buildKeyInfo(schema: Record<string, unknown> | undefined): {
94
+ moveableKeys: Set<string>;
95
+ styleKeys: Set<string>;
96
+ } {
97
+ const topLevelKeys = getTopLevelAttributeKeys(schema);
98
+ const moveableKeys = new Set<string>([
99
+ ...Array.from(topLevelKeys),
100
+ ...Array.from(NON_STYLE_ATTRIBUTE_KEYS),
101
+ ]);
102
+ const styleKeys = getStyleSubSchemaKeys(schema);
103
+ return { moveableKeys, styleKeys };
104
+ }
105
+
106
+ function extractAttributesFromStyle(
107
+ node: Node,
108
+ schemaCache: SchemaCache,
109
+ ): Node {
110
+ if (
111
+ isNodeNullOrUndefined(node) ||
112
+ isNodeString(node) ||
113
+ isEmptyObject(node)
114
+ ) {
115
+ return node;
116
+ }
117
+ if (isNodeArray(node)) {
118
+ return (node as Node[]).map((n) =>
119
+ extractAttributesFromStyle(n, schemaCache),
120
+ );
121
+ }
122
+
123
+ const record = node as NodeData<NodeDefaultAttribute>;
124
+ const nextChildren = extractAttributesFromStyle(
125
+ record.children as Node,
126
+ schemaCache,
127
+ );
128
+
129
+ if (!isPlainObject(record.attributes)) {
130
+ return { ...record, children: nextChildren };
131
+ }
132
+
133
+ const nextAttrs: Record<string, unknown> = { ...(record.attributes ?? {}) };
134
+ const style = nextAttrs.style;
135
+
136
+ if (!isPlainObject(style)) {
137
+ return { ...record, children: nextChildren, attributes: nextAttrs };
138
+ }
139
+
140
+ const rawType = typeof record.type === 'string' ? record.type : '';
141
+ const normalizedType = normalizeComponentType(rawType) ?? rawType;
142
+ if (!normalizedType) {
143
+ return { ...record, children: nextChildren, attributes: nextAttrs };
144
+ }
145
+
146
+ if (!schemaCache.has(normalizedType)) {
147
+ const schema = getAttributeSchema(normalizedType) as unknown as
148
+ | Record<string, unknown>
149
+ | undefined;
150
+ schemaCache.set(normalizedType, buildKeyInfo(schema));
151
+ }
152
+
153
+ const keyInfo = schemaCache.get(normalizedType);
154
+ const styleKeys = keyInfo?.styleKeys ?? new Set<string>();
155
+ const moveableKeys = keyInfo?.moveableKeys ?? NON_STYLE_ATTRIBUTE_KEYS;
156
+
157
+ const nextStyle: Record<string, unknown> = { ...style };
158
+ let moved = false;
159
+
160
+ for (const k of moveableKeys) {
161
+ if (!(k in nextStyle)) continue;
162
+ if (styleKeys.has(k)) continue;
163
+ // Prefer the direct attribute if already present.
164
+ if (!(k in nextAttrs)) {
165
+ nextAttrs[k] = nextStyle[k];
166
+ }
167
+ delete nextStyle[k];
168
+ moved = true;
169
+ }
170
+
171
+ if (!moved) {
172
+ return { ...record, children: nextChildren, attributes: nextAttrs };
173
+ }
174
+
175
+ if (Object.keys(nextStyle).length === 0) {
176
+ delete nextAttrs.style;
177
+ } else {
178
+ nextAttrs.style = nextStyle;
179
+ }
180
+
181
+ return {
182
+ ...record,
183
+ children: nextChildren,
184
+ attributes: nextAttrs as NodeDefaultAttribute,
185
+ };
186
+ }
187
+
188
+ export const migration_1_1_2_extract_component_attributes_from_style: Migration =
189
+ {
190
+ id: '1.1.2-extract-attrs-from-style',
191
+ title:
192
+ 'Normalize style keys then extract non-style + component props out of attributes.style',
193
+ fromVersion: '0.0.0',
194
+ toVersion: '1.1.2',
195
+ run: (project: Project): Project => {
196
+ const styleKeys = buildStyleKeySet();
197
+ const normalized = normalizeStyleAttributes(
198
+ project.data as unknown as Node,
199
+ styleKeys,
200
+ );
201
+
202
+ const schemaCache: SchemaCache = new Map();
203
+ const migrated = extractAttributesFromStyle(normalized, schemaCache);
204
+
205
+ return {
206
+ ...project,
207
+ version: '1.1.2',
208
+ data: migrated as any,
209
+ };
210
+ },
211
+ };
@@ -28,7 +28,9 @@ function OnboardComponent() {
28
28
  return (
29
29
  <div className="mockos-screen mockos-screen--onboard">
30
30
  <div className="mockos-screen__heading">Onboarding</div>
31
- <div className="mockos-screen__text">Welcome! Let's get you started.</div>
31
+ <div className="mockos-screen__text">
32
+ Welcome! Let&apos;s get you started.
33
+ </div>
32
34
  </div>
33
35
  );
34
36
  }
@@ -50,111 +50,40 @@ const getPermissionText = (permission: PermissionType | string) => {
50
50
  );
51
51
  };
52
52
 
53
- export const PermissionModal: React.FC<PermissionModalProps> = ({
53
+ export function PermissionModal({
54
54
  permission,
55
55
  onAllow,
56
56
  onDeny,
57
- }) => {
57
+ }: PermissionModalProps) {
58
58
  const device = useRenderStore((s) => s.device);
59
59
  const isIOS = device.platform === 'ios';
60
60
  const { title, message } = getPermissionText(permission);
61
61
 
62
- // iOS Style
63
62
  if (isIOS) {
64
63
  return (
65
64
  <div
66
- style={{
67
- position: 'absolute',
68
- top: 0,
69
- left: 0,
70
- right: 0,
71
- bottom: 0,
72
- backgroundColor: 'rgba(0, 0, 0, 0.4)',
73
- display: 'flex',
74
- alignItems: 'center',
75
- justifyContent: 'center',
76
- zIndex: 9999,
77
- padding: 20,
78
- }}
65
+ className="mockos-modal-overlay mockos-modal-overlay--center mockos-modal-overlay--ios"
79
66
  onClick={(e) => {
80
67
  if (e.target === e.currentTarget) {
81
68
  onDeny();
82
69
  }
83
70
  }}
84
71
  >
85
- <div
86
- style={{
87
- backgroundColor:
88
- 'hsl(var(--card, var(--rb-card, 0 0% 100%)) / 0.95)',
89
- borderRadius: 14,
90
- width: '100%',
91
- maxWidth: 270,
92
- overflow: 'hidden',
93
- backdropFilter: 'blur(20px)',
94
- }}
95
- >
96
- <div
97
- style={{
98
- padding: '20px 16px',
99
- textAlign: 'center',
100
- }}
101
- >
102
- <div
103
- style={{
104
- fontSize: 17,
105
- fontWeight: 600,
106
- color: '#000',
107
- marginBottom: 8,
108
- lineHeight: 1.3,
109
- }}
110
- >
111
- {title}
112
- </div>
113
- <div
114
- style={{
115
- fontSize: 13,
116
- color: '#000',
117
- lineHeight: 1.4,
118
- opacity: 0.6,
119
- }}
120
- >
121
- {message}
122
- </div>
72
+ <div className="mockos-permission-modal mockos-permission-modal--ios">
73
+ <div className="mockos-permission-modal__content mockos-permission-modal__content--center">
74
+ <div className="mockos-permission-modal__title">{title}</div>
75
+ <div className="mockos-permission-modal__message">{message}</div>
123
76
  </div>
124
- <div
125
- style={{
126
- borderTop: '0.5px solid rgba(0, 0, 0, 0.2)',
127
- display: 'flex',
128
- }}
129
- >
77
+ <div className="mockos-permission-modal__actions mockos-permission-modal__actions--ios">
130
78
  <button
79
+ className="mockos-permission-modal__button mockos-permission-modal__button--ios"
131
80
  onClick={onDeny}
132
- style={{
133
- flex: 1,
134
- padding: '11px 0',
135
- fontSize: 17,
136
- fontWeight: 400,
137
- color: '#007AFF',
138
- background: 'transparent',
139
- border: 'none',
140
- borderRight: '0.5px solid rgba(0, 0, 0, 0.2)',
141
- cursor: 'pointer',
142
- }}
143
81
  >
144
- Don't Allow
82
+ Don&apos;t Allow
145
83
  </button>
146
84
  <button
85
+ className="mockos-permission-modal__button mockos-permission-modal__button--ios mockos-permission-modal__button--bold"
147
86
  onClick={onAllow}
148
- style={{
149
- flex: 1,
150
- padding: '11px 0',
151
- fontSize: 17,
152
- fontWeight: 600,
153
- color: '#007AFF',
154
- background: 'transparent',
155
- border: 'none',
156
- cursor: 'pointer',
157
- }}
158
87
  >
159
88
  Allow
160
89
  </button>
@@ -164,103 +93,34 @@ export const PermissionModal: React.FC<PermissionModalProps> = ({
164
93
  );
165
94
  }
166
95
 
167
- // Android Material Design Style
168
96
  return (
169
97
  <div
170
- style={{
171
- position: 'absolute',
172
- top: 0,
173
- left: 0,
174
- right: 0,
175
- bottom: 0,
176
- backgroundColor: 'rgba(0, 0, 0, 0.5)',
177
- display: 'flex',
178
- alignItems: 'center',
179
- justifyContent: 'center',
180
- zIndex: 9999,
181
- padding: 24,
182
- }}
98
+ className="mockos-modal-overlay mockos-modal-overlay--center mockos-modal-overlay--android"
183
99
  onClick={(e) => {
184
100
  if (e.target === e.currentTarget) {
185
101
  onDeny();
186
102
  }
187
103
  }}
188
104
  >
189
- <div
190
- style={{
191
- backgroundColor: 'hsl(var(--card, var(--rb-card, 0 0% 100%)))',
192
- borderRadius: 4,
193
- width: '100%',
194
- maxWidth: 280,
195
- boxShadow:
196
- '0 11px 15px -7px rgba(0,0,0,0.2), 0 24px 38px 3px rgba(0,0,0,0.14)',
197
- }}
198
- >
199
- <div
200
- style={{
201
- padding: '24px 24px 20px',
202
- }}
203
- >
204
- <div
205
- style={{
206
- fontSize: 20,
207
- fontWeight: 500,
208
- color: 'rgba(0, 0, 0, 0.87)',
209
- marginBottom: 16,
210
- lineHeight: 1.2,
211
- }}
212
- >
105
+ <div className="mockos-permission-modal mockos-permission-modal--android">
106
+ <div className="mockos-permission-modal__content">
107
+ <div className="mockos-permission-modal__title mockos-permission-modal__title--android">
213
108
  {title}
214
109
  </div>
215
- <div
216
- style={{
217
- fontSize: 16,
218
- color: 'rgba(0, 0, 0, 0.6)',
219
- lineHeight: 1.5,
220
- }}
221
- >
110
+ <div className="mockos-permission-modal__message mockos-permission-modal__message--android">
222
111
  {message}
223
112
  </div>
224
113
  </div>
225
- <div
226
- style={{
227
- padding: '8px 8px 8px 0',
228
- display: 'flex',
229
- justifyContent: 'flex-end',
230
- gap: 8,
231
- }}
232
- >
114
+ <div className="mockos-permission-modal__actions mockos-permission-modal__actions--android">
233
115
  <button
116
+ className="mockos-permission-modal__button mockos-permission-modal__button--android mockos-permission-modal__button--deny"
234
117
  onClick={onDeny}
235
- style={{
236
- padding: '8px 16px',
237
- fontSize: 14,
238
- fontWeight: 500,
239
- color: '#5F6368',
240
- background: 'transparent',
241
- border: 'none',
242
- borderRadius: 4,
243
- cursor: 'pointer',
244
- textTransform: 'uppercase',
245
- letterSpacing: 0.5,
246
- }}
247
118
  >
248
119
  Deny
249
120
  </button>
250
121
  <button
122
+ className="mockos-permission-modal__button mockos-permission-modal__button--android mockos-permission-modal__button--allow"
251
123
  onClick={onAllow}
252
- style={{
253
- padding: '8px 16px',
254
- fontSize: 14,
255
- fontWeight: 500,
256
- color: '#1A73E8',
257
- background: 'transparent',
258
- border: 'none',
259
- borderRadius: 4,
260
- cursor: 'pointer',
261
- textTransform: 'uppercase',
262
- letterSpacing: 0.5,
263
- }}
264
124
  >
265
125
  Allow
266
126
  </button>
@@ -268,4 +128,4 @@ export const PermissionModal: React.FC<PermissionModalProps> = ({
268
128
  </div>
269
129
  </div>
270
130
  );
271
- };
131
+ }