@developer_tribe/react-builder 1.0.8 → 1.0.9
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.
- package/dist/build-components/BIcon/BIconProps.generated.d.ts +3 -0
- package/dist/build-components/BackgroundImage/BackgroundImageProps.generated.d.ts +1 -0
- package/dist/build-components/Button/ButtonProps.generated.d.ts +1 -0
- package/dist/build-components/Carousel/CarouselProps.generated.d.ts +5 -0
- package/dist/build-components/CarouselButtons/CarouselButtonsProps.generated.d.ts +1 -0
- package/dist/build-components/CarouselDots/CarouselDotsProps.generated.d.ts +1 -0
- package/dist/build-components/CarouselItem/CarouselItemProps.generated.d.ts +1 -0
- package/dist/build-components/CarouselProvider/CarouselProviderProps.generated.d.ts +1 -0
- package/dist/build-components/Image/ImageProps.generated.d.ts +1 -0
- package/dist/build-components/Main/MainProps.generated.d.ts +1 -1
- package/dist/build-components/Onboard/OnboardProps.generated.d.ts +1 -0
- package/dist/build-components/OnboardButton/OnboardButtonProps.generated.d.ts +1 -0
- package/dist/build-components/OnboardButtons/OnboardButtonsProps.generated.d.ts +1 -0
- package/dist/build-components/OnboardDot/OnboardDotProps.generated.d.ts +1 -0
- package/dist/build-components/OnboardFooter/OnboardFooterProps.generated.d.ts +3 -0
- package/dist/build-components/OnboardImage/OnboardImageProps.generated.d.ts +1 -0
- package/dist/build-components/OnboardItem/OnboardItemProps.generated.d.ts +1 -0
- package/dist/build-components/OnboardProvider/OnboardProviderProps.generated.d.ts +3 -0
- package/dist/build-components/OnboardSubtitle/OnboardSubtitleProps.generated.d.ts +3 -0
- package/dist/build-components/OnboardTitle/OnboardTitleProps.generated.d.ts +3 -0
- package/dist/build-components/PaywallBackground/PaywallBackgroundProps.generated.d.ts +1 -1
- package/dist/build-components/PaywallCloseButton/PaywallCloseButtonProps.generated.d.ts +3 -1
- package/dist/build-components/PaywallOptions/PaywallOptionsProps.generated.d.ts +1 -1
- package/dist/build-components/PaywallProvider/PaywallContext.d.ts +12 -0
- package/dist/build-components/PaywallProvider/PaywallProviderProps.generated.d.ts +1 -1
- package/dist/build-components/PaywallSubscribeButton/PaywallSubscribeButtonProps.generated.d.ts +1 -0
- package/dist/build-components/RadioButton/RadioButtonProps.generated.d.ts +1 -1
- package/dist/build-components/Text/TextProps.generated.d.ts +3 -0
- package/dist/build-components/View/ViewProps.generated.d.ts +1 -0
- package/dist/build-components/patterns.generated.d.ts +372 -374
- package/dist/components/BuilderProvider.d.ts +2 -0
- package/dist/components/ParamsProvider.d.ts +5 -0
- package/dist/components/RenderErrorBoundary.d.ts +28 -0
- package/dist/hooks/useSyncHtmlThemeClass.d.ts +7 -0
- package/dist/index.cjs.js +5 -5
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.esm.js +3 -3
- package/dist/index.esm.js.map +1 -1
- package/dist/index.native.cjs.js +4 -4
- package/dist/index.native.cjs.js.map +1 -1
- package/dist/index.native.d.ts +1 -0
- package/dist/index.native.esm.js +4 -4
- package/dist/index.native.esm.js.map +1 -1
- package/dist/migrations/migratePipe.d.ts +14 -0
- package/dist/migrations/migrations/1.1.0_normalize_style_attributes.d.ts +2 -0
- package/dist/migrations/semver.d.ts +8 -0
- package/dist/migrations/types.d.ts +8 -0
- package/dist/mockOS/components/SubscriptionModal.d.ts +7 -0
- package/dist/mockOS/context/MockOSContextBase.d.ts +1 -0
- package/dist/mockOS/hooks/useMockIap.d.ts +3 -0
- package/dist/mockOS/index.d.ts +4 -0
- package/dist/mockOS/managers/mockOSIapManager.d.ts +6 -0
- package/dist/mockOS/managers/subscriptionManager.d.ts +10 -0
- package/dist/pages/ProjectDebug.d.ts +14 -0
- package/dist/pages/ProjectMigrationPage.d.ts +23 -0
- package/dist/pages/ProjectValidationPage.d.ts +15 -0
- package/dist/styles.css +1 -1
- package/dist/types/Device.d.ts +5 -0
- package/dist/utils/__special_exceptions.d.ts +7 -0
- package/dist/utils/getImage.d.ts +23 -0
- package/dist/utils/pasteNode.d.ts +15 -0
- package/dist/utils/patterns.d.ts +1 -2
- package/package.json +6 -2
- package/scripts/migrate-patterns-to-v2.mjs +131 -0
- package/scripts/migrate-samples-to-current.ts +79 -0
- package/scripts/prebuild/utils/createGeneratedProps.js +4 -5
- package/scripts/prebuild/utils/validateAllComponentsOrThrow.js +32 -21
- package/scripts/prebuild/utils/validatePatternJson.js +12 -10
- package/src/.DS_Store +0 -0
- package/src/AttributesEditor.tsx +41 -11
- package/src/RenderPage.tsx +55 -0
- package/src/assets/.DS_Store +0 -0
- package/src/assets/devices.json +91 -0
- package/src/assets/samples/carousel-sample.json +141 -29
- package/src/assets/samples/getSamples.ts +9 -0
- package/src/assets/samples/paywall-1.json +119 -71
- package/src/assets/samples/simple-1.json +28 -16
- package/src/assets/samples/simple-2.json +157 -82
- package/src/assets/samples/unmigrated-builder1.json +42 -0
- package/src/assets/samples/unvalidated-builder1.json +49 -0
- package/src/assets/samples/unvalidated-crash1.json +19 -0
- package/src/assets/samples/unvalidated-crashcomponent1.json +16 -0
- package/src/assets/samples/vpn-onboard-1.json +91 -51
- package/src/assets/samples/vpn-onboard-2.json +318 -278
- package/src/assets/samples/vpn-onboard-3.json +286 -252
- package/src/assets/samples/vpn-onboard-4.json +286 -252
- package/src/assets/samples/vpn-onboard-5.json +434 -374
- package/src/assets/samples/vpn-onboard-6.json +290 -250
- package/src/attributes-editor/Field.tsx +1 -1
- package/src/attributes-editor/LayoutPreviewPicker.tsx +5 -2
- package/src/build-components/BIcon/BIconProps.generated.ts +3 -0
- package/src/build-components/BIcon/pattern.json +12 -9
- package/src/build-components/BackgroundImage/BackgroundImage.tsx +3 -1
- package/src/build-components/BackgroundImage/BackgroundImageProps.generated.ts +1 -0
- package/src/build-components/BackgroundImage/pattern.json +25 -16
- package/src/build-components/Button/Button.tsx +26 -3
- package/src/build-components/Button/ButtonProps.generated.ts +1 -0
- package/src/build-components/Button/pattern.json +10 -6
- package/src/build-components/Carousel/CarouselProps.generated.ts +5 -0
- package/src/build-components/Carousel/pattern.json +19 -8
- package/src/build-components/CarouselButtons/CarouselButtonsProps.generated.ts +1 -0
- package/src/build-components/CarouselButtons/pattern.json +11 -5
- package/src/build-components/CarouselDots/CarouselDotsProps.generated.ts +1 -0
- package/src/build-components/CarouselDots/pattern.json +5 -4
- package/src/build-components/CarouselItem/CarouselItemProps.generated.ts +1 -0
- package/src/build-components/CarouselItem/pattern.json +5 -4
- package/src/build-components/CarouselProvider/CarouselProvider.tsx +44 -2
- package/src/build-components/CarouselProvider/CarouselProviderProps.generated.ts +1 -0
- package/src/build-components/Image/Image.tsx +2 -1
- package/src/build-components/Image/ImageProps.generated.ts +1 -0
- package/src/build-components/Image/pattern.json +11 -5
- package/src/build-components/Main/MainProps.generated.ts +1 -1
- package/src/build-components/Main/pattern.json +12 -9
- package/src/build-components/Onboard/OnboardProps.generated.ts +1 -0
- package/src/build-components/Onboard/pattern.json +14 -9
- package/src/build-components/OnboardButton/OnboardButtonProps.generated.ts +1 -0
- package/src/build-components/OnboardButton/pattern.json +5 -4
- package/src/build-components/OnboardButtons/OnboardButtonsProps.generated.ts +1 -0
- package/src/build-components/OnboardButtons/pattern.json +5 -4
- package/src/build-components/OnboardDot/OnboardDotProps.generated.ts +1 -0
- package/src/build-components/OnboardDot/pattern.json +5 -4
- package/src/build-components/OnboardFooter/OnboardFooterProps.generated.ts +3 -0
- package/src/build-components/OnboardFooter/pattern.json +8 -5
- package/src/build-components/OnboardImage/OnboardImageProps.generated.ts +1 -0
- package/src/build-components/OnboardImage/pattern.json +7 -4
- package/src/build-components/OnboardItem/OnboardItemProps.generated.ts +1 -0
- package/src/build-components/OnboardItem/pattern.json +18 -9
- package/src/build-components/OnboardProvider/OnboardProviderProps.generated.ts +3 -0
- package/src/build-components/OnboardProvider/pattern.json +21 -6
- package/src/build-components/OnboardSubtitle/OnboardSubtitleProps.generated.ts +3 -0
- package/src/build-components/OnboardSubtitle/pattern.json +10 -6
- package/src/build-components/OnboardTitle/OnboardTitleProps.generated.ts +3 -0
- package/src/build-components/OnboardTitle/pattern.json +11 -7
- package/src/build-components/PaywallBackground/PaywallBackgroundProps.generated.ts +1 -1
- package/src/build-components/PaywallBackground/pattern.json +5 -4
- package/src/build-components/PaywallCloseButton/PaywallCloseButton.tsx +6 -1
- package/src/build-components/PaywallCloseButton/PaywallCloseButtonProps.generated.ts +3 -1
- package/src/build-components/PaywallCloseButton/pattern.json +15 -12
- package/src/build-components/PaywallOptions/PaywallOptionButton.tsx +0 -1
- package/src/build-components/PaywallOptions/PaywallOptions.tsx +3 -2
- package/src/build-components/PaywallOptions/PaywallOptionsProps.generated.ts +1 -1
- package/src/build-components/PaywallOptions/pattern.json +14 -11
- package/src/build-components/PaywallProvider/PaywallContext.ts +25 -0
- package/src/build-components/PaywallProvider/PaywallProvider.tsx +102 -5
- package/src/build-components/PaywallProvider/PaywallProviderProps.generated.ts +1 -1
- package/src/build-components/PaywallProvider/pattern.json +11 -8
- package/src/build-components/PaywallSubscribeButton/PaywallSubscribeButton.tsx +7 -0
- package/src/build-components/PaywallSubscribeButton/PaywallSubscribeButtonProps.generated.ts +1 -0
- package/src/build-components/PaywallSubscribeButton/pattern.json +16 -13
- package/src/build-components/RadioButton/RadioButtonProps.generated.ts +1 -1
- package/src/build-components/RadioButton/pattern.json +5 -4
- package/src/build-components/Text/Text.tsx +107 -4
- package/src/build-components/Text/TextProps.generated.ts +3 -0
- package/src/build-components/Text/pattern.json +19 -4
- package/src/build-components/View/ViewProps.generated.ts +1 -0
- package/src/build-components/View/pattern.json +28 -13
- package/src/build-components/other.tsx +15 -0
- package/src/build-components/patterns.generated.ts +340 -235
- package/src/build-components/useNode.ts +22 -3
- package/src/components/Builder.tsx +20 -6
- package/src/components/BuilderButton.tsx +75 -38
- package/src/components/BuilderProvider.tsx +22 -2
- package/src/components/DeviceButton.tsx +12 -5
- package/src/components/EditorHeader.tsx +296 -38
- package/src/components/ParamsProvider.tsx +7 -0
- package/src/components/RenderErrorBoundary.tsx +200 -0
- package/src/hooks/useParams.ts +5 -1
- package/src/hooks/useSyncHtmlThemeClass.ts +19 -0
- package/src/index.native.ts +7 -0
- package/src/index.ts +8 -0
- package/src/migrations/migratePipe.ts +59 -0
- package/src/migrations/migrations/1.1.0_normalize_style_attributes.ts +80 -0
- package/src/migrations/semver.ts +24 -0
- package/src/migrations/types.ts +9 -0
- package/src/mockOS/components/PermissionModal.tsx +3 -2
- package/src/mockOS/components/SubscriptionModal.tsx +400 -0
- package/src/mockOS/context/MockOSContext.tsx +61 -10
- package/src/mockOS/context/MockOSContextBase.ts +1 -0
- package/src/mockOS/hooks/useMockIap.ts +11 -0
- package/src/mockOS/index.ts +7 -0
- package/src/mockOS/managers/mockOSIapManager.ts +10 -0
- package/src/mockOS/managers/subscriptionManager.ts +36 -0
- package/src/modals/IconPickerModal.tsx +1 -1
- package/src/pages/ProjectDebug.tsx +331 -0
- package/src/pages/ProjectMigrationPage.tsx +92 -0
- package/src/pages/ProjectPage.tsx +313 -161
- package/src/pages/ProjectValidationPage.tsx +54 -0
- package/src/styles/base/_global.scss +58 -11
- package/src/styles/components/_attributes-editor.scss +1 -1
- package/src/styles/components/_bottom-bar.scss +7 -4
- package/src/styles/components/_editor-shell.scss +126 -4
- package/src/styles/components/_mockos-router.scss +3 -2
- package/src/styles/components/_ui-components.scss +10 -5
- package/src/styles/foundation/_colors.scss +78 -11
- package/src/styles/foundation/_mixins.scss +4 -1
- package/src/styles/foundation/_sizes.scss +4 -2
- package/src/styles/index.scss +1 -0
- package/src/styles/layout/_builder.scss +61 -0
- package/src/styles/layout/_project-validation.scss +214 -0
- package/src/styles/modals/_add-component.scss +4 -2
- package/src/styles/modals/_color-modal.scss +4 -2
- package/src/styles/modals/_modal-shell.scss +3 -1
- package/src/types/Device.ts +5 -0
- package/src/utils/__special_exceptions.ts +88 -0
- package/src/utils/analyseNode.ts +8 -2
- package/src/utils/analyseNodeByPatterns.ts +43 -9
- package/src/utils/extractTextStyle.ts +19 -6
- package/src/utils/extractViewStyle.ts +68 -59
- package/src/utils/getImage.ts +76 -0
- package/src/utils/novaToJson.ts +2 -1
- package/src/utils/pasteNode.ts +172 -0
- package/src/utils/patterns.ts +4 -3
- package/dist/android.svg +0 -43
- package/dist/apple.svg +0 -16
- package/dist/background.jpg +0 -0
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
@use '../foundation/colors' as colors;
|
|
2
|
+
@use '../foundation/sizes' as sizes;
|
|
3
|
+
@use '../foundation/mixins' as *;
|
|
4
|
+
|
|
5
|
+
.rb-project-debug {
|
|
6
|
+
display: flex;
|
|
7
|
+
width: 100%;
|
|
8
|
+
height: calc(100vh - 60px);
|
|
9
|
+
overflow: hidden;
|
|
10
|
+
background: colors.$canvasColor;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.rb-project-debug__json {
|
|
14
|
+
@include thin-scrollbar;
|
|
15
|
+
flex: 0 0 34%;
|
|
16
|
+
min-width: 320px;
|
|
17
|
+
max-width: 640px;
|
|
18
|
+
border-right: 1px solid colors.$borderColor;
|
|
19
|
+
overflow: auto;
|
|
20
|
+
padding: sizes.$spaceComfy;
|
|
21
|
+
background: colors.$surfaceColor;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.rb-project-debug__preview {
|
|
25
|
+
@include thin-scrollbar;
|
|
26
|
+
position: relative;
|
|
27
|
+
flex: 1 1 auto;
|
|
28
|
+
overflow: auto;
|
|
29
|
+
padding: sizes.$spaceComfy;
|
|
30
|
+
display: flex;
|
|
31
|
+
align-items: center;
|
|
32
|
+
justify-content: center;
|
|
33
|
+
background-image: var(--rb-canvas-bg, none);
|
|
34
|
+
background-position: center;
|
|
35
|
+
background-repeat: repeat;
|
|
36
|
+
background-size: 500px auto;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/* Hide the canvas grid background in dark theme (Tailwind/shadcn convention). */
|
|
40
|
+
.dark .rb-project-debug__preview {
|
|
41
|
+
--rb-canvas-bg: none !important;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.rb-project-debug__error {
|
|
45
|
+
@include thin-scrollbar;
|
|
46
|
+
flex: 0 0 32%;
|
|
47
|
+
min-width: 280px;
|
|
48
|
+
max-width: 520px;
|
|
49
|
+
border-left: 1px solid colors.$borderColor;
|
|
50
|
+
overflow: auto;
|
|
51
|
+
padding: sizes.$spaceComfy;
|
|
52
|
+
background: colors.$surfaceColor;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.rb-project-debug__title {
|
|
56
|
+
margin: 0 0 sizes.$spaceTight 0;
|
|
57
|
+
font-size: 16px;
|
|
58
|
+
font-weight: 700;
|
|
59
|
+
color: colors.$textColor;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.rb-project-debug__error-block {
|
|
63
|
+
@include card;
|
|
64
|
+
padding: sizes.$spaceCozy;
|
|
65
|
+
margin: 0 0 sizes.$spaceCozy 0;
|
|
66
|
+
background: colors.$canvasColor;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
.rb-project-debug__error-label {
|
|
70
|
+
font-size: 12px;
|
|
71
|
+
font-weight: 800;
|
|
72
|
+
color: colors.$textColor;
|
|
73
|
+
margin: 0 0 sizes.$spaceTight 0;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.rb-project-debug__error-pre {
|
|
77
|
+
margin: 0;
|
|
78
|
+
padding: sizes.$spaceTight;
|
|
79
|
+
border-radius: sizes.$radiusSoft;
|
|
80
|
+
background: colors.$surfaceColor;
|
|
81
|
+
border: 1px solid colors.$borderColor;
|
|
82
|
+
font-family:
|
|
83
|
+
ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono',
|
|
84
|
+
'Courier New', monospace;
|
|
85
|
+
font-size: 11px;
|
|
86
|
+
line-height: 1.45;
|
|
87
|
+
white-space: pre-wrap;
|
|
88
|
+
word-break: break-word;
|
|
89
|
+
overflow: auto;
|
|
90
|
+
max-height: 220px;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.rb-project-debug__meta {
|
|
94
|
+
margin: 0 0 sizes.$spaceCozy 0;
|
|
95
|
+
font-size: 12px;
|
|
96
|
+
color: colors.$mutedTextColor;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.rb-project-debug__meta-label {
|
|
100
|
+
font-weight: 700;
|
|
101
|
+
color: colors.$textColor;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.rb-project-debug__toolbar {
|
|
105
|
+
display: flex;
|
|
106
|
+
gap: sizes.$spaceTight;
|
|
107
|
+
align-items: center;
|
|
108
|
+
margin: 0 0 sizes.$spaceCozy 0;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.rb-project-debug__toolbar .editor-button {
|
|
112
|
+
min-width: 0;
|
|
113
|
+
height: 34px;
|
|
114
|
+
padding: 0 sizes.$spaceCozy;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.rb-project-debug__below-name {
|
|
118
|
+
margin: 0 0 sizes.$spaceCozy 0;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.rb-project-debug__error-head {
|
|
122
|
+
display: flex;
|
|
123
|
+
align-items: center;
|
|
124
|
+
justify-content: space-between;
|
|
125
|
+
gap: sizes.$spaceCozy;
|
|
126
|
+
margin: 0 0 sizes.$spaceCozy 0;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.rb-project-debug__error-head .rb-project-debug__title {
|
|
130
|
+
margin: 0;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.rb-project-debug__error-head .editor-button {
|
|
134
|
+
min-width: 0;
|
|
135
|
+
height: 34px;
|
|
136
|
+
padding: 0 sizes.$spaceCozy;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
.rb-project-validation__actions {
|
|
140
|
+
display: flex;
|
|
141
|
+
gap: sizes.$spaceTight;
|
|
142
|
+
align-items: center;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.rb-project-validation__actions .editor-button {
|
|
146
|
+
min-width: 0;
|
|
147
|
+
height: 34px;
|
|
148
|
+
padding: 0 sizes.$spaceCozy;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.rb-project-debug__code {
|
|
152
|
+
@include card;
|
|
153
|
+
margin: 0;
|
|
154
|
+
padding: sizes.$spaceCozy;
|
|
155
|
+
font-family:
|
|
156
|
+
ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono',
|
|
157
|
+
'Courier New', monospace;
|
|
158
|
+
font-size: 12px;
|
|
159
|
+
line-height: 1.5;
|
|
160
|
+
white-space: pre;
|
|
161
|
+
overflow: auto;
|
|
162
|
+
max-height: calc(100vh - 60px - 160px);
|
|
163
|
+
background: colors.$canvasColor;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/* Legacy selectors kept for backward compatibility (no-op if unused) */
|
|
167
|
+
.rb-project-validation__error {
|
|
168
|
+
margin: 0 0 sizes.$spaceCozy 0;
|
|
169
|
+
font-size: 13px;
|
|
170
|
+
line-height: 1.4;
|
|
171
|
+
color: colors.$dangerColor;
|
|
172
|
+
font-weight: 600;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.rb-project-validation__error--render {
|
|
176
|
+
color: colors.$accentColor;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.rb-project-validation__error-label {
|
|
180
|
+
font-weight: 800;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
@media (max-width: 1000px) {
|
|
184
|
+
.rb-project-debug {
|
|
185
|
+
flex-direction: column;
|
|
186
|
+
height: calc(100vh - 60px);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
.rb-project-debug__json {
|
|
190
|
+
flex: 0 0 auto;
|
|
191
|
+
width: 100%;
|
|
192
|
+
min-width: 0;
|
|
193
|
+
max-width: none;
|
|
194
|
+
border-right: none;
|
|
195
|
+
border-bottom: 1px solid colors.$borderColor;
|
|
196
|
+
max-height: 45%;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.rb-project-debug__preview {
|
|
200
|
+
flex: 1 1 auto;
|
|
201
|
+
width: 100%;
|
|
202
|
+
min-height: 0;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
.rb-project-debug__error {
|
|
206
|
+
flex: 0 0 auto;
|
|
207
|
+
width: 100%;
|
|
208
|
+
min-width: 0;
|
|
209
|
+
max-width: none;
|
|
210
|
+
border-left: none;
|
|
211
|
+
border-top: 1px solid colors.$borderColor;
|
|
212
|
+
max-height: 40%;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
@@ -49,7 +49,8 @@
|
|
|
49
49
|
border-radius: 12px;
|
|
50
50
|
padding: sizes.$spaceComfy;
|
|
51
51
|
margin-bottom: sizes.$spaceCozy;
|
|
52
|
-
box-shadow: 0 10px 20px
|
|
52
|
+
box-shadow: 0 10px 20px
|
|
53
|
+
hsl(var(--foreground, var(--rb-foreground, 220.9 39.3% 11%)) / 0.05);
|
|
53
54
|
}
|
|
54
55
|
|
|
55
56
|
.add-component-modal__group-title {
|
|
@@ -86,7 +87,8 @@
|
|
|
86
87
|
|
|
87
88
|
.add-component-modal__card:hover {
|
|
88
89
|
border-color: colors.$accentColor;
|
|
89
|
-
box-shadow: 0 10px 25px
|
|
90
|
+
box-shadow: 0 10px 25px
|
|
91
|
+
hsl(var(--primary, var(--rb-primary, 221.2 83.2% 53.3%)) / 0.15);
|
|
90
92
|
transform: translateY(-2px);
|
|
91
93
|
}
|
|
92
94
|
|
|
@@ -30,7 +30,8 @@
|
|
|
30
30
|
width: 32px;
|
|
31
31
|
height: 32px;
|
|
32
32
|
border-radius: 6px;
|
|
33
|
-
border: 1px solid
|
|
33
|
+
border: 1px solid
|
|
34
|
+
hsl(var(--foreground, var(--rb-foreground, 220.9 39.3% 11%)) / 0.1);
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
.color-modal__selected-label {
|
|
@@ -158,7 +159,8 @@
|
|
|
158
159
|
}
|
|
159
160
|
|
|
160
161
|
.color-modal__swatch-preview--light {
|
|
161
|
-
border: 1px solid
|
|
162
|
+
border: 1px solid
|
|
163
|
+
hsl(var(--foreground, var(--rb-foreground, 220.9 39.3% 11%)) / 0.1);
|
|
162
164
|
}
|
|
163
165
|
|
|
164
166
|
.color-modal__swatch-label {
|
package/src/types/Device.ts
CHANGED
|
@@ -3,6 +3,11 @@ export interface Device {
|
|
|
3
3
|
platform: string; // ios, android
|
|
4
4
|
width: number;
|
|
5
5
|
height: number;
|
|
6
|
+
/**
|
|
7
|
+
* High-level screen shape bucket derived from portrait aspect ratio (height / width).
|
|
8
|
+
* Useful for quickly filtering "tall" vs "wide-ish" devices without hardcoding sizes.
|
|
9
|
+
*/
|
|
10
|
+
aspect?: 'tall' | 'regular' | 'wide';
|
|
6
11
|
type: 'phone' | 'tablet';
|
|
7
12
|
/**
|
|
8
13
|
* Optional physical corner radius of the device screen area in CSS pixels.
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import type { Node, NodeData, NodeDefaultAttribute } from '../types/Node';
|
|
2
|
+
import { isNodeArray, isNodeNullOrUndefined, isNodeString } from './nodeGuards';
|
|
3
|
+
|
|
4
|
+
function isPlainObject(value: unknown): value is Record<string, unknown> {
|
|
5
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function looksLikeSelectOptionObject(
|
|
9
|
+
value: unknown,
|
|
10
|
+
): value is { value: unknown } {
|
|
11
|
+
if (!isPlainObject(value)) return false;
|
|
12
|
+
// Avoid unwrapping actual node-like objects or typed objects that use `type`.
|
|
13
|
+
if ('type' in value || 'children' in value || 'attributes' in value) {
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
if (!('value' in value)) return false;
|
|
17
|
+
const keys = Object.keys(value);
|
|
18
|
+
// Typical shapes: { value }, { value, label }, { value, label, id }
|
|
19
|
+
if (keys.length < 1 || keys.length > 3) return false;
|
|
20
|
+
const allowed = new Set(['value', 'label', 'id']);
|
|
21
|
+
for (const k of keys) if (!allowed.has(k)) return false;
|
|
22
|
+
const v = (value as Record<string, unknown>).value;
|
|
23
|
+
return (
|
|
24
|
+
v == null ||
|
|
25
|
+
typeof v === 'string' ||
|
|
26
|
+
typeof v === 'number' ||
|
|
27
|
+
typeof v === 'boolean'
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function normalizeUnknownValue(value: unknown): unknown {
|
|
32
|
+
if (value == null) return value;
|
|
33
|
+
|
|
34
|
+
if (Array.isArray(value)) {
|
|
35
|
+
return value.map(normalizeUnknownValue);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (!isPlainObject(value)) return value;
|
|
39
|
+
|
|
40
|
+
if (looksLikeSelectOptionObject(value)) {
|
|
41
|
+
return normalizeUnknownValue((value as { value: unknown }).value);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const out: Record<string, unknown> = {};
|
|
45
|
+
for (const [k, v] of Object.entries(value)) {
|
|
46
|
+
out[k] = normalizeUnknownValue(v);
|
|
47
|
+
}
|
|
48
|
+
return out;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Special-case normalization for persisted JSON before validation.
|
|
53
|
+
*
|
|
54
|
+
* Keep "exceptions" here rather than inside the core validation logic.
|
|
55
|
+
*/
|
|
56
|
+
export function normalizeNodeForValidation(
|
|
57
|
+
node: Node<NodeDefaultAttribute>,
|
|
58
|
+
): Node<NodeDefaultAttribute> {
|
|
59
|
+
if (isNodeNullOrUndefined(node) || isNodeString(node)) {
|
|
60
|
+
return node;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (isNodeArray(node)) {
|
|
64
|
+
const nodeArray = node as unknown as Node<NodeDefaultAttribute>[];
|
|
65
|
+
return nodeArray.map(
|
|
66
|
+
normalizeNodeForValidation,
|
|
67
|
+
) as unknown as Node<NodeDefaultAttribute>;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const recordData = node as NodeData<NodeDefaultAttribute>;
|
|
71
|
+
|
|
72
|
+
const attributes = isPlainObject(recordData.attributes)
|
|
73
|
+
? (normalizeUnknownValue(recordData.attributes) as Record<string, unknown>)
|
|
74
|
+
: recordData.attributes;
|
|
75
|
+
|
|
76
|
+
const children =
|
|
77
|
+
recordData.children !== undefined
|
|
78
|
+
? (normalizeNodeForValidation(
|
|
79
|
+
recordData.children as Node<NodeDefaultAttribute>,
|
|
80
|
+
) as Node<NodeDefaultAttribute>)
|
|
81
|
+
: recordData.children;
|
|
82
|
+
|
|
83
|
+
return {
|
|
84
|
+
...recordData,
|
|
85
|
+
attributes: attributes as any,
|
|
86
|
+
children,
|
|
87
|
+
};
|
|
88
|
+
}
|
package/src/utils/analyseNode.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { generateRandomKeyForNode } from './generateRandomKeyForNode';
|
|
|
3
3
|
import { analyseNodeByPatterns } from './analyseNodeByPatterns';
|
|
4
4
|
import { analyseNodeStructural } from './analyseNodeStructural';
|
|
5
5
|
import { isNodeArray, isNodeNullOrUndefined, isNodeString } from './nodeGuards';
|
|
6
|
+
import { normalizeNodeForValidation } from './__special_exceptions';
|
|
6
7
|
|
|
7
8
|
export {
|
|
8
9
|
isEmptyObject,
|
|
@@ -78,11 +79,16 @@ export function analyseAndProccess(
|
|
|
78
79
|
return null;
|
|
79
80
|
}
|
|
80
81
|
|
|
81
|
-
|
|
82
|
+
// Normalize persisted JSON "select option" objects into primitives before
|
|
83
|
+
// validation (e.g. { label, value } -> value). This commonly appears in
|
|
84
|
+
// attributes like events[].navigate_to.
|
|
85
|
+
const normalized = normalizeNodeForValidation(node);
|
|
86
|
+
|
|
87
|
+
const { valid, message } = analyseNode(normalized);
|
|
82
88
|
if (!valid) {
|
|
83
89
|
throw new Error(message ?? 'Node is not valid');
|
|
84
90
|
}
|
|
85
91
|
|
|
86
92
|
const usedKeys = new Set<string>();
|
|
87
|
-
return assignMissingKeys(
|
|
93
|
+
return assignMissingKeys(normalized, usedKeys);
|
|
88
94
|
}
|
|
@@ -24,7 +24,6 @@ type AttributeTypeSpec = string | string[];
|
|
|
24
24
|
type AttributeSchema = Record<string, AttributeTypeSpec>;
|
|
25
25
|
|
|
26
26
|
type PatternLike = {
|
|
27
|
-
allowUnknownAttributes: boolean;
|
|
28
27
|
pattern: {
|
|
29
28
|
type: string;
|
|
30
29
|
children: unknown;
|
|
@@ -56,7 +55,10 @@ function isNodeDataLike(
|
|
|
56
55
|
): value is NodeData<NodeDefaultAttribute> {
|
|
57
56
|
if (!isPlainObject(value)) return false;
|
|
58
57
|
const maybeType = (value as Record<string, unknown>).type;
|
|
59
|
-
|
|
58
|
+
// `children` is optional in persisted JSON; treat missing as `undefined`.
|
|
59
|
+
// The structural validator handles overall shape; the pattern validator should
|
|
60
|
+
// focus on types/attributes/children rules, not require the key to exist.
|
|
61
|
+
return typeof maybeType === 'string';
|
|
60
62
|
}
|
|
61
63
|
|
|
62
64
|
function normalizeTypeOrFallback(type: string): string {
|
|
@@ -71,14 +73,19 @@ function getChildrenSpecTokens(pattern: PatternLike): string[] {
|
|
|
71
73
|
}
|
|
72
74
|
|
|
73
75
|
function splitChildrenSpec(tokens: string[]): {
|
|
74
|
-
baseKinds: Set<'never' | 'string' | 'node'
|
|
76
|
+
baseKinds: Set<'never' | 'string' | 'node'>;
|
|
75
77
|
allowedComponentTypes: Set<string>;
|
|
76
78
|
} {
|
|
77
|
-
const baseKinds = new Set<'never' | 'string' | 'node'
|
|
79
|
+
const baseKinds = new Set<'never' | 'string' | 'node'>();
|
|
78
80
|
const allowedComponentTypes = new Set<string>();
|
|
79
81
|
for (const t of tokens) {
|
|
80
|
-
|
|
82
|
+
// NOTE: pattern.children no longer uses the 'array' token.
|
|
83
|
+
// 'node' means "a node OR an array of nodes".
|
|
84
|
+
if (t === 'never' || t === 'string' || t === 'node') {
|
|
81
85
|
baseKinds.add(t);
|
|
86
|
+
} else if (t === 'array') {
|
|
87
|
+
// Backwards-compat: treat 'array' as 'node'
|
|
88
|
+
baseKinds.add('node');
|
|
82
89
|
} else if (typeof t === 'string' && t) {
|
|
83
90
|
allowedComponentTypes.add(normalizeTypeOrFallback(t));
|
|
84
91
|
}
|
|
@@ -88,7 +95,7 @@ function splitChildrenSpec(tokens: string[]): {
|
|
|
88
95
|
|
|
89
96
|
function validateChildrenNeverRule(
|
|
90
97
|
children: Node<NodeDefaultAttribute>,
|
|
91
|
-
baseKinds: Set<'never' | 'string' | 'node'
|
|
98
|
+
baseKinds: Set<'never' | 'string' | 'node'>,
|
|
92
99
|
path: string,
|
|
93
100
|
): AnalyseResultWithPath {
|
|
94
101
|
if (!baseKinds.has('never')) return ok();
|
|
@@ -98,7 +105,7 @@ function validateChildrenNeverRule(
|
|
|
98
105
|
|
|
99
106
|
function validateChildrenKindRule(
|
|
100
107
|
children: Node<NodeDefaultAttribute>,
|
|
101
|
-
baseKinds: Set<'never' | 'string' | 'node'
|
|
108
|
+
baseKinds: Set<'never' | 'string' | 'node'>,
|
|
102
109
|
allowedComponentTypes: Set<string>,
|
|
103
110
|
path: string,
|
|
104
111
|
): AnalyseResultWithPath {
|
|
@@ -122,7 +129,8 @@ function validateChildrenKindRule(
|
|
|
122
129
|
: fail(`Children must not be a string`, path);
|
|
123
130
|
}
|
|
124
131
|
if (isNodeArray(children)) {
|
|
125
|
-
|
|
132
|
+
// 'node' allows both a single node and an array of nodes
|
|
133
|
+
return baseKinds.has('node')
|
|
126
134
|
? ok()
|
|
127
135
|
: fail(`Children must not be an array`, path);
|
|
128
136
|
}
|
|
@@ -295,6 +303,11 @@ function validateAttributeValue(
|
|
|
295
303
|
spec: AttributeTypeSpec,
|
|
296
304
|
path: string,
|
|
297
305
|
): AnalyseResultWithPath {
|
|
306
|
+
// Pattern validation does not enforce requiredness (it only validates types for
|
|
307
|
+
// keys that exist). Treat null/undefined as "unset" so persisted JSON can use
|
|
308
|
+
// null to clear fields (e.g. events[].navigate_to = null).
|
|
309
|
+
if (value == null) return ok();
|
|
310
|
+
|
|
298
311
|
if (Array.isArray(spec)) {
|
|
299
312
|
return validateEnumValue(value, spec, path);
|
|
300
313
|
}
|
|
@@ -338,10 +351,31 @@ function validateAttributesByPattern(
|
|
|
338
351
|
pattern.pattern.attributes ??
|
|
339
352
|
{}) as AttributeSchema;
|
|
340
353
|
|
|
354
|
+
// Validate nested `attributes.style` as an object; validate any style keys that also exist in schema.
|
|
355
|
+
const maybeStyle = (attrs as Record<string, unknown>).style;
|
|
356
|
+
if (maybeStyle != null) {
|
|
357
|
+
if (!isPlainObject(maybeStyle)) {
|
|
358
|
+
return fail(`style must be an object`, joinPath(path, 'style'));
|
|
359
|
+
}
|
|
360
|
+
for (const [styleKey, styleValue] of Object.entries(
|
|
361
|
+
maybeStyle as Record<string, unknown>,
|
|
362
|
+
)) {
|
|
363
|
+
const spec = schema?.[styleKey];
|
|
364
|
+
if (!spec) continue; // allow unknown style keys (free-form CSSProperties)
|
|
365
|
+
const res = validateAttributeValue(
|
|
366
|
+
pattern.pattern.type,
|
|
367
|
+
styleValue,
|
|
368
|
+
spec,
|
|
369
|
+
joinPath(joinPath(path, 'style'), styleKey),
|
|
370
|
+
);
|
|
371
|
+
if (!res.valid) return res;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
|
|
341
375
|
for (const [attrName, attrValue] of Object.entries(attrs)) {
|
|
376
|
+
if (attrName === 'style') continue;
|
|
342
377
|
const attrSpec = schema?.[attrName];
|
|
343
378
|
if (!attrSpec) {
|
|
344
|
-
if (pattern.allowUnknownAttributes) continue;
|
|
345
379
|
return fail(`Unknown attribute "${attrName}"`, joinPath(path, attrName));
|
|
346
380
|
}
|
|
347
381
|
const res = validateAttributeValue(
|
|
@@ -17,6 +17,16 @@ export function extractTextStyle<T extends TextPropsGenerated['attributes']>(
|
|
|
17
17
|
options: ExtractTextStyleOptions = {},
|
|
18
18
|
) {
|
|
19
19
|
const attributes = node.attributes;
|
|
20
|
+
const styleBag = (attributes as any)?.style as
|
|
21
|
+
| Record<string, unknown>
|
|
22
|
+
| undefined;
|
|
23
|
+
const get = <K extends keyof TextPropsGenerated['attributes']>(
|
|
24
|
+
key: K,
|
|
25
|
+
): TextPropsGenerated['attributes'][K] | undefined => {
|
|
26
|
+
const direct = (attributes as any)?.[key];
|
|
27
|
+
if (direct !== undefined && direct !== null) return direct;
|
|
28
|
+
return styleBag?.[key as unknown as string] as any;
|
|
29
|
+
};
|
|
20
30
|
const resolvedAppConfig = options.appConfig ?? defaultAppConfig;
|
|
21
31
|
const { screenStyle, theme } = resolvedAppConfig;
|
|
22
32
|
const fallbackColor =
|
|
@@ -31,20 +41,23 @@ export function extractTextStyle<T extends TextPropsGenerated['attributes']>(
|
|
|
31
41
|
}
|
|
32
42
|
|
|
33
43
|
// Typography
|
|
34
|
-
|
|
35
|
-
|
|
44
|
+
const fontSize = get('fontSize') as any;
|
|
45
|
+
if (fontSize !== undefined) {
|
|
46
|
+
const parsed = parseSize(fontSize);
|
|
36
47
|
style.fontSize = parsed as React.CSSProperties['fontSize'];
|
|
37
48
|
} else {
|
|
38
49
|
style.fontSize = fs(14);
|
|
39
50
|
}
|
|
40
|
-
|
|
41
|
-
|
|
51
|
+
const fontWeight = get('fontWeight') as any;
|
|
52
|
+
if (fontWeight) style.fontWeight = fontWeight;
|
|
53
|
+
const resolvedTextColor = parseColor(get('color') as any, {
|
|
42
54
|
projectColors: options.projectColors,
|
|
43
55
|
appConfig: resolvedAppConfig,
|
|
44
56
|
});
|
|
45
57
|
style.color = resolvedTextColor ?? fallbackColor;
|
|
46
|
-
|
|
47
|
-
|
|
58
|
+
const textAlign = get('textAlign') as any;
|
|
59
|
+
if (textAlign)
|
|
60
|
+
style.textAlign = textAlign as React.CSSProperties['textAlign'];
|
|
48
61
|
|
|
49
62
|
return { ...extractViewStyle(node, options), ...style };
|
|
50
63
|
}
|