@developer_tribe/react-builder 1.2.32 → 1.2.34
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/assets/prompt-scheme-onboard.generated.d.ts +1 -0
- package/dist/assets/prompt-scheme-paywall.generated.d.ts +1 -0
- package/dist/build-components/OnboardDot/OnboardDotProps.generated.d.ts +3 -3
- package/dist/build-components/patterns.generated.d.ts +52 -52
- package/dist/components/BuilderProvider.d.ts +2 -4
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/index.web.cjs.js +6 -6
- package/dist/index.web.cjs.js.map +1 -1
- package/dist/index.web.esm.js +6 -6
- package/dist/index.web.esm.js.map +1 -1
- package/dist/modals/PromptManagerModal.d.ts +9 -0
- package/dist/modals/index.d.ts +1 -0
- package/dist/styles.css +1 -1
- package/dist/utils/nodeXml.d.ts +11 -0
- package/package.json +5 -1
- package/scripts/prebuild/assets/prompt_scheme.md +77 -0
- package/scripts/prebuild/generate-prompt-schemes.js +464 -0
- package/scripts/prebuild/prebuild.js +4 -0
- package/src/RenderPage.tsx +6 -6
- package/src/assets/meta.json +1 -1
- package/src/assets/prompt-scheme-onboard.generated.ts +4 -0
- package/src/assets/prompt-scheme-paywall.generated.ts +4 -0
- package/src/attribute-analyser/style/native/useExtractImageStyle.ts +1 -1
- package/src/attribute-analyser/style/native/useExtractTextStyle.ts +1 -1
- package/src/attribute-analyser/style/native/useExtractViewStyle.ts +1 -1
- package/src/attribute-analyser/style/web/useExtractImageStyle.ts +1 -1
- package/src/attribute-analyser/style/web/useExtractTextStyle.ts +1 -1
- package/src/attribute-analyser/style/web/useExtractViewStyle.ts +1 -1
- package/src/build-components/BIcon/pattern.json +1 -3
- package/src/build-components/BackgroundImage/pattern.json +2 -10
- package/src/build-components/Button/pattern.json +1 -3
- package/src/build-components/Carousel/pattern.json +2 -8
- package/src/build-components/CarouselDots/CarouselDots.tsx +1 -1
- package/src/build-components/CarouselProvider/pattern.json +1 -4
- package/src/build-components/CountDown/pattern.json +1 -3
- package/src/build-components/Image/pattern.json +2 -9
- package/src/build-components/Main/pattern.json +1 -3
- package/src/build-components/NavigationBarColor/NavigationBarColor.tsx +1 -1
- package/src/build-components/NavigationBarColor/pattern.json +1 -3
- package/src/build-components/Onboard/pattern.json +2 -6
- package/src/build-components/OnboardButton/OnboardButton.tsx +1 -1
- package/src/build-components/OnboardButton/pattern.json +3 -14
- package/src/build-components/OnboardButtons/pattern.json +4 -15
- package/src/build-components/OnboardDot/OnboardDot.tsx +1 -1
- package/src/build-components/OnboardDot/OnboardDotProps.generated.ts +3 -3
- package/src/build-components/OnboardDot/pattern.json +15 -16
- package/src/build-components/OnboardFooter/OnboardFooter.tsx +3 -3
- package/src/build-components/OnboardFooter/pattern.json +15 -19
- package/src/build-components/OnboardItem/pattern.json +3 -11
- package/src/build-components/OnboardProvider/pattern.json +2 -8
- package/src/build-components/OnboardSubtitle/pattern.json +1 -4
- package/src/build-components/OnboardTitle/pattern.json +1 -4
- package/src/build-components/PaywallBackground/pattern.json +1 -3
- package/src/build-components/PaywallCloseButton/pattern.json +1 -3
- package/src/build-components/PaywallOptions/pattern.json +1 -3
- package/src/build-components/PaywallProvider/pattern.json +1 -3
- package/src/build-components/PaywallSubscribeButton/pattern.json +1 -3
- package/src/build-components/PriceTag/pattern.json +2 -8
- package/src/build-components/Pricing/pattern.json +1 -3
- package/src/build-components/Promo/pattern.json +1 -3
- package/src/build-components/Separator/pattern.json +1 -3
- package/src/build-components/StatusBarColor/StatusBarColor.tsx +1 -1
- package/src/build-components/StatusBarColor/pattern.json +1 -3
- package/src/build-components/Text/pattern.json +1 -3
- package/src/build-components/View/pattern.json +4 -16
- package/src/build-components/patterns.generated.ts +52 -52
- package/src/components/BottomBar.tsx +28 -1
- package/src/components/BuilderProvider.tsx +5 -14
- package/src/hooks/useLocalize.ts +1 -1
- package/src/modals/MockableFeatureModal.tsx +552 -5
- package/src/modals/Modal.tsx +7 -1
- package/src/modals/PromptManagerModal.tsx +270 -0
- package/src/modals/index.ts +1 -0
- package/src/styles/index.scss +1 -0
- package/src/styles/modals/_prompt-manager-modal.scss +95 -0
- package/src/utils/nodeXml.ts +196 -0
|
@@ -0,0 +1,464 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* generate-prompt-schemes.js
|
|
4
|
+
*
|
|
5
|
+
* Reads all *Props.generated.ts files from src/build-components,
|
|
6
|
+
* extracts a compact (uglified) representation of each component's
|
|
7
|
+
* props/attributes, and combines them into a single patterns string.
|
|
8
|
+
*
|
|
9
|
+
* Then reads the prompt_scheme.md template and the two sample JSON
|
|
10
|
+
* files, converts each JSON to XML (Node.js-safe, no DOMParser),
|
|
11
|
+
* and generates two TypeScript assets:
|
|
12
|
+
* src/assets/prompt-scheme-onboard.generated.ts
|
|
13
|
+
* src/assets/prompt-scheme-paywall.generated.ts
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import fs from 'fs';
|
|
17
|
+
import path from 'path';
|
|
18
|
+
import url from 'url';
|
|
19
|
+
|
|
20
|
+
const __filename = url.fileURLToPath(import.meta.url);
|
|
21
|
+
const __dirname = path.dirname(__filename);
|
|
22
|
+
|
|
23
|
+
const PROJECT_ROOT = path.resolve(__dirname, '../..');
|
|
24
|
+
const SRC_ROOT = path.join(PROJECT_ROOT, 'src');
|
|
25
|
+
const COMPONENTS_ROOT = path.join(SRC_ROOT, 'build-components');
|
|
26
|
+
const ASSETS_ROOT = path.join(SRC_ROOT, 'assets');
|
|
27
|
+
const SAMPLES_ROOT = path.join(ASSETS_ROOT, 'samples');
|
|
28
|
+
const TEMPLATE_PATH = path.join(__dirname, 'assets', 'prompt_scheme.md');
|
|
29
|
+
|
|
30
|
+
/* ------------------------------------------------------------------ */
|
|
31
|
+
/* 0. Inline minified sample validator */
|
|
32
|
+
/* ------------------------------------------------------------------ */
|
|
33
|
+
|
|
34
|
+
// Validates a sample JSON root node tree. Throws with a descriptive message
|
|
35
|
+
// if the structure is invalid. This is intentionally kept as a self-contained
|
|
36
|
+
// function (uglified style) so it can be audited quickly.
|
|
37
|
+
// prettier-ignore
|
|
38
|
+
const validateSampleJson = (function(){
|
|
39
|
+
function v(n,p){
|
|
40
|
+
if(n===null||n===undefined)return;
|
|
41
|
+
const t=typeof n;
|
|
42
|
+
if(t==='string')return; // text node OK
|
|
43
|
+
if(Array.isArray(n)){n.forEach(function(c,i){v(c,p+'['+i+']');});return;}
|
|
44
|
+
if(t!=='object')throw new Error('validateSampleJson: expected object|string|array at '+p+', got '+t);
|
|
45
|
+
if(typeof n.type!=='string')throw new Error('validateSampleJson: missing string "type" at '+p);
|
|
46
|
+
if(n.attributes!==undefined&&n.attributes!==null&&typeof n.attributes!=='object')
|
|
47
|
+
throw new Error('validateSampleJson: "attributes" must be an object at '+p+'.'+n.type);
|
|
48
|
+
if(n.children!==undefined&&n.children!==null){
|
|
49
|
+
const ct=typeof n.children;
|
|
50
|
+
if(ct!=='string'&&ct!=='object')
|
|
51
|
+
throw new Error('validateSampleJson: "children" must be string|Node|Node[] at '+p+'.'+n.type);
|
|
52
|
+
v(n.children,p+'.'+n.type+'.children');
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return function(sample){
|
|
56
|
+
if(typeof sample!=='object'||sample===null)
|
|
57
|
+
throw new Error('validateSampleJson: root sample must be an object');
|
|
58
|
+
if(typeof sample.data!=='object'||sample.data===null)
|
|
59
|
+
throw new Error('validateSampleJson: sample must have a "data" object field');
|
|
60
|
+
v(sample.data,'root');
|
|
61
|
+
};
|
|
62
|
+
}());
|
|
63
|
+
|
|
64
|
+
/* ------------------------------------------------------------------ */
|
|
65
|
+
/* 1. JSON → XML converter (Node.js-safe, no DOMParser) */
|
|
66
|
+
/* ------------------------------------------------------------------ */
|
|
67
|
+
|
|
68
|
+
function escapeXmlAttr(str, quote) {
|
|
69
|
+
let result = str
|
|
70
|
+
.replace(/&/g, '&')
|
|
71
|
+
.replace(/</g, '<')
|
|
72
|
+
.replace(/>/g, '>');
|
|
73
|
+
if (quote === '"') {
|
|
74
|
+
result = result.replace(/"/g, '"');
|
|
75
|
+
} else {
|
|
76
|
+
result = result.replace(/'/g, ''');
|
|
77
|
+
}
|
|
78
|
+
return result;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function attrValueToString(value) {
|
|
82
|
+
if (value === null || value === undefined) return '';
|
|
83
|
+
if (typeof value === 'string') return value;
|
|
84
|
+
if (typeof value === 'number' || typeof value === 'boolean')
|
|
85
|
+
return String(value);
|
|
86
|
+
return JSON.stringify(value);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function nodeToXmlInner(node, indent) {
|
|
90
|
+
const pad = ' '.repeat(indent);
|
|
91
|
+
|
|
92
|
+
if (node === null || node === undefined) return '';
|
|
93
|
+
if (typeof node === 'string') return `${pad}${node}`;
|
|
94
|
+
|
|
95
|
+
if (Array.isArray(node)) {
|
|
96
|
+
return node.map((child) => nodeToXmlInner(child, indent)).join('\n');
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (typeof node !== 'object') return '';
|
|
100
|
+
|
|
101
|
+
const type = node.type;
|
|
102
|
+
if (!type) return '';
|
|
103
|
+
|
|
104
|
+
const attrs = [];
|
|
105
|
+
|
|
106
|
+
const addAttr = (key, val) => {
|
|
107
|
+
const strValue = attrValueToString(val);
|
|
108
|
+
const useSingle = strValue.includes('"') && !strValue.includes("'");
|
|
109
|
+
const quote = useSingle ? "'" : '"';
|
|
110
|
+
const escaped = escapeXmlAttr(strValue, quote);
|
|
111
|
+
attrs.push(`${key}=${quote}${escaped}${quote}`);
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
if (node.key) addAttr('key', node.key);
|
|
115
|
+
if (node.sourceType) addAttr('sourceType', node.sourceType);
|
|
116
|
+
if (node.isMain) addAttr('isMain', 'true');
|
|
117
|
+
|
|
118
|
+
if (node.attributes && typeof node.attributes === 'object') {
|
|
119
|
+
for (const [k, v] of Object.entries(node.attributes)) {
|
|
120
|
+
addAttr(k, v);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const attrStr = attrs.length > 0 ? ' ' + attrs.join(' ') : '';
|
|
125
|
+
const children = node.children;
|
|
126
|
+
|
|
127
|
+
if (
|
|
128
|
+
children === null ||
|
|
129
|
+
children === undefined ||
|
|
130
|
+
(Array.isArray(children) && children.length === 0)
|
|
131
|
+
) {
|
|
132
|
+
return `${pad}<${type}${attrStr} />`;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const childXml = nodeToXmlInner(children, indent + 1);
|
|
136
|
+
return `${pad}<${type}${attrStr}>\n${childXml}\n${pad}</${type}>`;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function nodeToXml(node) {
|
|
140
|
+
if (node === null || node === undefined) return '';
|
|
141
|
+
return nodeToXmlInner(node, 0);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/* ------------------------------------------------------------------ */
|
|
145
|
+
/* 2. Props.generated.ts parser → compact pattern string */
|
|
146
|
+
/* ------------------------------------------------------------------ */
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Parses a single *Props.generated.ts file and returns a compact
|
|
150
|
+
* one-liner representing the component's attributes.
|
|
151
|
+
*
|
|
152
|
+
* Format: ComponentName: {attr1:type, attr2:"a"|"b", styles:{prop:type}}
|
|
153
|
+
*/
|
|
154
|
+
function parsePropsFile(filePath, componentName) {
|
|
155
|
+
const src = fs.readFileSync(filePath, 'utf8');
|
|
156
|
+
|
|
157
|
+
// ── Collect enum/union types ──────────────────────────────────────
|
|
158
|
+
// e.g. export type DotTypeOptionType = 'a' | 'b';
|
|
159
|
+
const enumMap = {};
|
|
160
|
+
const enumRe =
|
|
161
|
+
/export\s+type\s+(\w+)\s*=\s*((?:'[^']*'|\||\s)+);/g;
|
|
162
|
+
let m;
|
|
163
|
+
while ((m = enumRe.exec(src)) !== null) {
|
|
164
|
+
const typeName = m[1];
|
|
165
|
+
// Collect all quoted values
|
|
166
|
+
const values = [...m[2].matchAll(/'([^']*)'/g)].map((x) => `"${x[1]}"`);
|
|
167
|
+
if (values.length > 0) enumMap[typeName] = values.join('|');
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// ── Find the *PropsGenerated interface ───────────────────────────
|
|
171
|
+
const propsInterfaceRe =
|
|
172
|
+
/export\s+interface\s+\w+PropsGenerated\s*\{([\s\S]*?)\n\}/;
|
|
173
|
+
const piMatch = propsInterfaceRe.exec(src);
|
|
174
|
+
if (!piMatch) return null;
|
|
175
|
+
|
|
176
|
+
// ── Extract the `attributes` block ─────────────────────────────
|
|
177
|
+
const attrBlockRe = /attributes\s*:\s*\{([\s\S]*?)\}\s*;/;
|
|
178
|
+
const abMatch = attrBlockRe.exec(piMatch[1]);
|
|
179
|
+
if (!abMatch) return null;
|
|
180
|
+
|
|
181
|
+
const attrBlock = abMatch[1];
|
|
182
|
+
|
|
183
|
+
// ── Find the style interface ────────────────────────────────────
|
|
184
|
+
const styleInterfaceRe =
|
|
185
|
+
/export\s+interface\s+\w+StyleGenerated\s*\{([\s\S]*?)\n\}/;
|
|
186
|
+
const siMatch = styleInterfaceRe.exec(src);
|
|
187
|
+
const styleProps = [];
|
|
188
|
+
if (siMatch) {
|
|
189
|
+
const stylePropRe = /^\s+(\w+)\??\s*:\s*(.+?);/gm;
|
|
190
|
+
let sm;
|
|
191
|
+
while ((sm = stylePropRe.exec(siMatch[1])) !== null) {
|
|
192
|
+
const propName = sm[1];
|
|
193
|
+
const rawType = sm[2].trim();
|
|
194
|
+
// Map the TypeScript type to a compact form
|
|
195
|
+
const compact = resolveType(rawType, enumMap);
|
|
196
|
+
styleProps.push(`${propName}:${compact}`);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// ── Parse non-style attributes ──────────────────────────────────
|
|
201
|
+
const nonStyleAttrs = [];
|
|
202
|
+
const attrPropRe = /^\s+(\w+)\??\s*:\s*(.+?);/gm;
|
|
203
|
+
let ap;
|
|
204
|
+
while ((ap = attrPropRe.exec(attrBlock)) !== null) {
|
|
205
|
+
const propName = ap[1];
|
|
206
|
+
if (propName === 'styles') continue; // handled via style interface
|
|
207
|
+
const rawType = ap[2].trim();
|
|
208
|
+
if (rawType === 'never') continue; // excluded props
|
|
209
|
+
const compact = resolveType(rawType, enumMap);
|
|
210
|
+
nonStyleAttrs.push(`${propName}:${compact}`);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// ── Also check for child type ───────────────────────────────────
|
|
214
|
+
const childRe = /^\s+child\s*:\s*(.+?);/m;
|
|
215
|
+
const childMatch = childRe.exec(piMatch[1]);
|
|
216
|
+
const childType = childMatch ? resolveType(childMatch[1].trim(), enumMap) : null;
|
|
217
|
+
|
|
218
|
+
// ── Build compact string ────────────────────────────────────────
|
|
219
|
+
const parts = [];
|
|
220
|
+
if (childType && childType !== 'string') parts.push(`child:${childType}`);
|
|
221
|
+
parts.push(...nonStyleAttrs);
|
|
222
|
+
if (styleProps.length > 0) {
|
|
223
|
+
parts.push(`styles:{${styleProps.join(',')}}`);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return `${componentName}:{${parts.join(',')}}`;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function resolveType(rawType, enumMap) {
|
|
230
|
+
// Direct enum reference
|
|
231
|
+
if (enumMap[rawType]) return enumMap[rawType];
|
|
232
|
+
|
|
233
|
+
// Array type like: EventObjectGenerated[]
|
|
234
|
+
if (rawType.endsWith('[]')) {
|
|
235
|
+
const inner = rawType.slice(0, -2).trim();
|
|
236
|
+
return `[${resolveType(inner, enumMap)}]`;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// Union with null: SomeType | null
|
|
240
|
+
const nullableMatch = rawType.match(/^(\w+)\s*\|\s*null$/);
|
|
241
|
+
if (nullableMatch) return resolveType(nullableMatch[1], enumMap) + '?';
|
|
242
|
+
|
|
243
|
+
// Simple primitives — keep as-is so LLMs understand them natively
|
|
244
|
+
if (rawType === 'string') return 'string';
|
|
245
|
+
if (rawType === 'number') return 'number';
|
|
246
|
+
if (rawType === 'boolean') return 'boolean';
|
|
247
|
+
|
|
248
|
+
// Interface reference (EventObjectGenerated etc.) — just label it "obj"
|
|
249
|
+
if (rawType.match(/^\w+$/)) return 'obj';
|
|
250
|
+
|
|
251
|
+
return rawType;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/* ------------------------------------------------------------------ */
|
|
255
|
+
/* 3. Collect all patterns */
|
|
256
|
+
/* ------------------------------------------------------------------ */
|
|
257
|
+
|
|
258
|
+
function collectPatterns() {
|
|
259
|
+
const entries = fs.readdirSync(COMPONENTS_ROOT, { withFileTypes: true });
|
|
260
|
+
const lines = [];
|
|
261
|
+
|
|
262
|
+
for (const entry of entries) {
|
|
263
|
+
if (!entry.isDirectory()) continue;
|
|
264
|
+
const componentName = entry.name;
|
|
265
|
+
const propsFile = path.join(
|
|
266
|
+
COMPONENTS_ROOT,
|
|
267
|
+
componentName,
|
|
268
|
+
`${componentName}Props.generated.ts`
|
|
269
|
+
);
|
|
270
|
+
if (!fs.existsSync(propsFile)) continue;
|
|
271
|
+
|
|
272
|
+
const line = parsePropsFile(propsFile, componentName);
|
|
273
|
+
if (line) lines.push(line);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
return lines.join('\n');
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/* ------------------------------------------------------------------ */
|
|
280
|
+
/* 4. Collect icon list from Icon.generated.tsx */
|
|
281
|
+
/* ------------------------------------------------------------------ */
|
|
282
|
+
|
|
283
|
+
function collectIcons() {
|
|
284
|
+
const iconFile = path.join(SRC_ROOT, 'components', 'Icon.generated.tsx');
|
|
285
|
+
if (!fs.existsSync(iconFile)) return '(icon list unavailable)';
|
|
286
|
+
|
|
287
|
+
const src = fs.readFileSync(iconFile, 'utf8');
|
|
288
|
+
|
|
289
|
+
// Match all keys of ICON_SVGS: both bare words and quoted strings
|
|
290
|
+
// activity:
|
|
291
|
+
// 'activity-heart':
|
|
292
|
+
const keyRe = /^\s+(?:'([^']+)'|(\w[\w-]*)?)\ s*:/gm;
|
|
293
|
+
const keys = [];
|
|
294
|
+
let m;
|
|
295
|
+
while ((m = keyRe.exec(src)) !== null) {
|
|
296
|
+
const key = m[1] ?? m[2];
|
|
297
|
+
if (key) keys.push(key);
|
|
298
|
+
// Stop once we leave the ICON_SVGS object (first export function)
|
|
299
|
+
if (src.slice(m.index, m.index + 200).includes('export function')) break;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// Dedup and sort
|
|
303
|
+
return [...new Set(keys)].sort().join(', ');
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/* ------------------------------------------------------------------ */
|
|
307
|
+
/* 5. Collect localization keys from PreviewConfig.ts */
|
|
308
|
+
/* ------------------------------------------------------------------ */
|
|
309
|
+
|
|
310
|
+
/**
|
|
311
|
+
* Reads defaultLocalization from PreviewConfig.ts and returns:
|
|
312
|
+
* - localizationKeys: sorted list of all unique keys (for the "Available Keys" section)
|
|
313
|
+
* - defaultLocalizationEn: the English localization as a formatted block
|
|
314
|
+
* - defaultColors: the defaultProjectColors formatted
|
|
315
|
+
*/
|
|
316
|
+
function collectLocalizationAndColors() {
|
|
317
|
+
// ── defaultLocalization keys from PreviewConfig.ts ───────────────
|
|
318
|
+
const previewConfigPath = path.join(SRC_ROOT, 'types', 'PreviewConfig.ts');
|
|
319
|
+
const previewConfigSrc = fs.readFileSync(previewConfigPath, 'utf8');
|
|
320
|
+
|
|
321
|
+
// Extract all string literal keys from the LocalizationKey type union
|
|
322
|
+
const locKeyTypeRe = /export\s+type\s+LocalizationKey\s*=[\s\S]*?(?=export\s|$)/;
|
|
323
|
+
const locKeyTypeMatch = locKeyTypeRe.exec(previewConfigSrc);
|
|
324
|
+
const localizationKeys = [];
|
|
325
|
+
if (locKeyTypeMatch) {
|
|
326
|
+
const keyRe = /'\s*([^'()+]+?)\s*'/g;
|
|
327
|
+
let km;
|
|
328
|
+
while ((km = keyRe.exec(locKeyTypeMatch[0])) !== null) {
|
|
329
|
+
const key = km[1].trim();
|
|
330
|
+
if (key && !key.includes(' ') && key !== 'string') {
|
|
331
|
+
localizationKeys.push(key);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// ── Default localization (en) values ────────────────────────────
|
|
337
|
+
// Extract the `en` block from defaultLocalization
|
|
338
|
+
const enBlockRe = /en\s*:\s*\{([\s\S]*?)\},?\s*(?:tr\s*:|};)/;
|
|
339
|
+
const enBlockMatch = enBlockRe.exec(previewConfigSrc);
|
|
340
|
+
const enLines = [];
|
|
341
|
+
if (enBlockMatch) {
|
|
342
|
+
const entryRe = /'([^']+)'\s*:\s*'([^']*)'/g;
|
|
343
|
+
let em;
|
|
344
|
+
while ((em = entryRe.exec(enBlockMatch[1])) !== null) {
|
|
345
|
+
enLines.push(` "${em[1]}": "${em[2]}"`);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
const defaultLocalizationEn = `{\n${enLines.join(',\n')}\n}`;
|
|
349
|
+
|
|
350
|
+
// ── defaultProjectColors ────────────────────────────────────────
|
|
351
|
+
const projectColorsPath = path.join(SRC_ROOT, 'utils', 'projectColors.ts');
|
|
352
|
+
const projectColorsSrc = fs.readFileSync(projectColorsPath, 'utf8');
|
|
353
|
+
|
|
354
|
+
// Parse STATIC_COLORS block
|
|
355
|
+
const staticRe = /STATIC_COLORS\s*:\s*\{([\s\S]*?)\},?\s*THEME_COLORS/;
|
|
356
|
+
const staticMatch = staticRe.exec(projectColorsSrc);
|
|
357
|
+
const staticLines = [];
|
|
358
|
+
if (staticMatch) {
|
|
359
|
+
const entryRe = /(\w+)\s*:\s*'([^']*)'/g;
|
|
360
|
+
let sm;
|
|
361
|
+
while ((sm = entryRe.exec(staticMatch[1])) !== null) {
|
|
362
|
+
staticLines.push(` STATIC_COLORS.${sm[1]}: "${sm[2]}"`);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// Parse THEME_COLORS light block
|
|
367
|
+
const lightRe = /light\s*:\s*\{([\s\S]*?)\},?\s*dark/;
|
|
368
|
+
const lightMatch = lightRe.exec(projectColorsSrc);
|
|
369
|
+
const lightLines = [];
|
|
370
|
+
if (lightMatch) {
|
|
371
|
+
const entryRe = /(\w+)\s*:\s*'([^']*)'/g;
|
|
372
|
+
let lm;
|
|
373
|
+
while ((lm = entryRe.exec(lightMatch[1])) !== null) {
|
|
374
|
+
lightLines.push(` THEME_COLORS.${lm[1]} (light): "${lm[2]}"`);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// Parse THEME_COLORS dark block
|
|
379
|
+
const darkRe = /dark\s*:\s*\{([\s\S]*?)\},?\s*\}/;
|
|
380
|
+
const darkMatch = darkRe.exec(projectColorsSrc);
|
|
381
|
+
const darkLines = [];
|
|
382
|
+
if (darkMatch) {
|
|
383
|
+
const entryRe = /(\w+)\s*:\s*'([^']*)'/g;
|
|
384
|
+
let dm;
|
|
385
|
+
while ((dm = entryRe.exec(darkMatch[1])) !== null) {
|
|
386
|
+
darkLines.push(` THEME_COLORS.${dm[1]} (dark): "${dm[2]}"`);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
const defaultColors =
|
|
391
|
+
[...staticLines, ...lightLines, ...darkLines].join('\n');
|
|
392
|
+
|
|
393
|
+
return {
|
|
394
|
+
localizationKeys: localizationKeys.join('\n'),
|
|
395
|
+
defaultLocalizationEn,
|
|
396
|
+
defaultColors,
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/* ------------------------------------------------------------------ */
|
|
401
|
+
/* 6. Generate a .generated.ts asset file */
|
|
402
|
+
/* ------------------------------------------------------------------ */
|
|
403
|
+
|
|
404
|
+
function generateAsset(schemeType, sampleJsonPath, outputPath) {
|
|
405
|
+
// Load template
|
|
406
|
+
const template = fs.readFileSync(TEMPLATE_PATH, 'utf8');
|
|
407
|
+
|
|
408
|
+
// Load patterns
|
|
409
|
+
const patterns = collectPatterns();
|
|
410
|
+
|
|
411
|
+
// Load sample JSON, validate it, and convert to XML
|
|
412
|
+
const sampleJson = JSON.parse(fs.readFileSync(sampleJsonPath, 'utf8'));
|
|
413
|
+
validateSampleJson(sampleJson);
|
|
414
|
+
const exampleXml = nodeToXml(sampleJson.data);
|
|
415
|
+
|
|
416
|
+
// Load icon list
|
|
417
|
+
const icons = collectIcons();
|
|
418
|
+
|
|
419
|
+
// Collect localization keys, default colors and default localization
|
|
420
|
+
const { localizationKeys, defaultLocalizationEn, defaultColors } =
|
|
421
|
+
collectLocalizationAndColors();
|
|
422
|
+
|
|
423
|
+
// Fill template — replace ALL occurrences of {screen_type}
|
|
424
|
+
const filled = template
|
|
425
|
+
.replaceAll('{screen_type}', schemeType)
|
|
426
|
+
.replace('{patterns}', patterns)
|
|
427
|
+
.replace('{icons}', icons)
|
|
428
|
+
.replace('{example}', exampleXml)
|
|
429
|
+
.replace('{localization_keys}', localizationKeys)
|
|
430
|
+
.replace('{default_colors}', defaultColors)
|
|
431
|
+
.replace('{default_localization_en}', defaultLocalizationEn);
|
|
432
|
+
|
|
433
|
+
// Write as a TypeScript string export
|
|
434
|
+
const tsContent = `/* AUTO-GENERATED FILE - DO NOT EDIT */
|
|
435
|
+
/* Prompt scheme for ${schemeType} screens. Generated by generate-prompt-schemes.js */
|
|
436
|
+
|
|
437
|
+
export const ${schemeType}PromptScheme: string = ${JSON.stringify(filled)};
|
|
438
|
+
`;
|
|
439
|
+
|
|
440
|
+
fs.writeFileSync(outputPath, tsContent, 'utf8');
|
|
441
|
+
console.info(
|
|
442
|
+
` ✓ Generated ${path.relative(PROJECT_ROOT, outputPath)} (${filled.length.toLocaleString()} chars)`
|
|
443
|
+
);
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/* ------------------------------------------------------------------ */
|
|
447
|
+
/* 7. Main */
|
|
448
|
+
/* ------------------------------------------------------------------ */
|
|
449
|
+
|
|
450
|
+
export async function generatePromptSchemes() {
|
|
451
|
+
generateAsset(
|
|
452
|
+
'onboard',
|
|
453
|
+
path.join(SAMPLES_ROOT, 'vpn-onboard-1.json'),
|
|
454
|
+
path.join(ASSETS_ROOT, 'prompt-scheme-onboard.generated.ts')
|
|
455
|
+
);
|
|
456
|
+
|
|
457
|
+
generateAsset(
|
|
458
|
+
'paywall',
|
|
459
|
+
path.join(SAMPLES_ROOT, 'paywall-1.json'),
|
|
460
|
+
path.join(ASSETS_ROOT, 'prompt-scheme-paywall.generated.ts')
|
|
461
|
+
);
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
export default generatePromptSchemes;
|
|
@@ -5,6 +5,7 @@ import url from 'url';
|
|
|
5
5
|
|
|
6
6
|
import run from './build-components.js';
|
|
7
7
|
import runIconGenerator from './icon-generator.js';
|
|
8
|
+
import generatePromptSchemes from './generate-prompt-schemes.js';
|
|
8
9
|
import { updateMetaJson } from './utils/index.js';
|
|
9
10
|
|
|
10
11
|
const __filename = url.fileURLToPath(import.meta.url);
|
|
@@ -28,6 +29,9 @@ try {
|
|
|
28
29
|
|
|
29
30
|
console.info('Building components...');
|
|
30
31
|
await run();
|
|
32
|
+
|
|
33
|
+
console.info('Generating prompt schemes...');
|
|
34
|
+
await generatePromptSchemes();
|
|
31
35
|
} catch (err) {
|
|
32
36
|
console.error(err?.stack || err?.message || err);
|
|
33
37
|
process.exit(1);
|
package/src/RenderPage.tsx
CHANGED
|
@@ -42,8 +42,8 @@ export function RenderPage({
|
|
|
42
42
|
const {
|
|
43
43
|
products,
|
|
44
44
|
benefits,
|
|
45
|
-
|
|
46
|
-
|
|
45
|
+
selectedTheme,
|
|
46
|
+
selectedLanguage,
|
|
47
47
|
overrideLocalization,
|
|
48
48
|
overrideBaseSize,
|
|
49
49
|
overrideProjectColors,
|
|
@@ -56,8 +56,8 @@ export function RenderPage({
|
|
|
56
56
|
} = useRenderStore((s) => ({
|
|
57
57
|
products: s.products,
|
|
58
58
|
benefits: s.benefits,
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
selectedTheme: s.theme,
|
|
60
|
+
selectedLanguage: s.defaultLanguage,
|
|
61
61
|
overrideLocalization: s.localization,
|
|
62
62
|
overrideBaseSize: s.baseSize,
|
|
63
63
|
overrideProjectColors: s.projectColors,
|
|
@@ -124,8 +124,8 @@ export function RenderPage({
|
|
|
124
124
|
<BuilderProvider
|
|
125
125
|
params={{
|
|
126
126
|
// Store defaults
|
|
127
|
-
|
|
128
|
-
|
|
127
|
+
selectedTheme,
|
|
128
|
+
selectedLanguage,
|
|
129
129
|
localization: overrideLocalization,
|
|
130
130
|
baseSize: overrideBaseSize,
|
|
131
131
|
mockProducts: products,
|
package/src/assets/meta.json
CHANGED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/* AUTO-GENERATED FILE - DO NOT EDIT */
|
|
2
|
+
/* Prompt scheme for onboard screens. Generated by generate-prompt-schemes.js */
|
|
3
|
+
|
|
4
|
+
export const onboardPromptScheme: string = "You are a React Native UI builder assistant. Your goal is to generate a valid **onboard** screen node tree in XML format.\n\n## Available Components & Their Props\n\nEach component is listed as `ComponentName: {attr: TypeScriptType, styles: {prop: TypeScriptType}}`.\nUse ONLY these component names and attribute names. Do NOT invent new components or attributes.\n\nUnion enum values must match exactly (e.g. `\"expanding_dot\"` not `expandingDot`).\nColor values: prefer `THEME_COLORS.KEY` or `STATIC_COLORS.KEY` for theme-aware colors. Literal values like `\"red\"` or `\"#000fff\"` are also valid when a specific color is intended.\nLocalization string values should use a localization key from the **Available Localization Keys** section. Do NOT invent new keys.\n\n```\nBIcon:{adjustsFontSizeToFit:boolean,showEllipsis:boolean,translateCounter:number,scrollable:boolean,iconType:string,size:number,strokeWidth:number,styles:{color:string,fontSize:string,fontFamily:string,fontWeight:string,flexDirection:\"row\"|\"column\",flexWrap:\"nowrap\"|\"wrap\"|\"wrap-reverse\",alignItems:\"flex-start\"|\"center\"|\"flex-end\"|\"stretch\"|\"baseline\",justifyContent:\"flex-start\"|\"center\"|\"flex-end\"|\"space-between\"|\"space-around\"|\"space-evenly\",gap:string,padding:string,paddingHorizontal:string,paddingVertical:string,paddingTop:string,paddingBottom:string,paddingLeft:string,paddingRight:string,margin:string,marginHorizontal:string,marginVertical:string,marginTop:string,marginBottom:string,marginLeft:string,marginRight:string,backgroundColor:string,borderRadius:string,width:string,minWidth:string,maxWidth:string,height:string,minHeight:string,maxHeight:string,flex:number,position:\"relative\"|\"absolute\",top:string,bottom:string,left:string,right:string,zIndex:number}}\nBackgroundImage:{scrollable:boolean,src:string,resizeMode:\"cover\"|\"contain\"|\"stretch\"|\"center\",styles:{flexDirection:\"row\"|\"column\",flexWrap:\"nowrap\"|\"wrap\"|\"wrap-reverse\",alignItems:\"flex-start\"|\"center\"|\"flex-end\"|\"stretch\"|\"baseline\",justifyContent:\"flex-start\"|\"center\"|\"flex-end\"|\"space-between\"|\"space-around\"|\"space-evenly\",gap:string,padding:string,paddingHorizontal:string,paddingVertical:string,paddingTop:string,paddingBottom:string,paddingLeft:string,paddingRight:string,margin:string,marginHorizontal:string,marginVertical:string,marginTop:string,marginBottom:string,marginLeft:string,marginRight:string,backgroundColor:string,borderRadius:string,width:string,minWidth:string,maxWidth:string,height:string,minHeight:string,maxHeight:string,flex:number,position:\"relative\"|\"absolute\",top:string,bottom:string,left:string,right:string,zIndex:number}}\nButton:{scrollable:boolean,styles:{flexDirection:\"row\"|\"column\",flexWrap:\"nowrap\"|\"wrap\"|\"wrap-reverse\",alignItems:\"flex-start\"|\"center\"|\"flex-end\"|\"stretch\"|\"baseline\",justifyContent:\"flex-start\"|\"center\"|\"flex-end\"|\"space-between\"|\"space-around\"|\"space-evenly\",gap:string,padding:string,paddingHorizontal:string,paddingVertical:string,paddingTop:string,paddingBottom:string,paddingLeft:string,paddingRight:string,margin:string,marginHorizontal:string,marginVertical:string,marginTop:string,marginBottom:string,marginLeft:string,marginRight:string,backgroundColor:string,borderRadius:string,width:string,minWidth:string,maxWidth:string,height:string,minHeight:string,maxHeight:string,flex:number,position:\"relative\"|\"absolute\",top:string,bottom:string,left:string,right:string,zIndex:number,color:string,fontSize:string,fontWeight:\"normal\"|\"bold\"|\"100\"|\"200\"|\"300\"|\"400\"|\"500\"|\"600\"|\"700\"|\"800\"|\"900\"}}\nCarousel:{scrollable:boolean,loop:boolean,dragFree:boolean,align:\"start\"|\"center\"|\"end\",styles:{flexDirection:\"row\"|\"column\",flexWrap:\"nowrap\"|\"wrap\"|\"wrap-reverse\",alignItems:\"flex-start\"|\"center\"|\"flex-end\"|\"stretch\"|\"baseline\",justifyContent:\"flex-start\"|\"center\"|\"flex-end\"|\"space-between\"|\"space-around\"|\"space-evenly\",gap:string,padding:string,paddingHorizontal:string,paddingVertical:string,paddingTop:string,paddingBottom:string,paddingLeft:string,paddingRight:string,margin:string,marginHorizontal:string,marginVertical:string,marginTop:string,marginBottom:string,marginLeft:string,marginRight:string,backgroundColor:string,borderRadius:string,width:string,minWidth:string,maxWidth:string,height:string,minHeight:string,maxHeight:string,flex:number,position:\"relative\"|\"absolute\",top:string,bottom:string,left:string,right:string,zIndex:number}}\nCarouselButtons:{scrollable:boolean,buttonType:\"previous_button\"|\"next_button\"|\"skip_button\",skipNumber:number,styles:{flexDirection:\"row\"|\"column\",flexWrap:\"nowrap\"|\"wrap\"|\"wrap-reverse\",alignItems:\"flex-start\"|\"center\"|\"flex-end\"|\"stretch\"|\"baseline\",justifyContent:\"flex-start\"|\"center\"|\"flex-end\"|\"space-between\"|\"space-around\"|\"space-evenly\",gap:string,padding:string,paddingHorizontal:string,paddingVertical:string,paddingTop:string,paddingBottom:string,paddingLeft:string,paddingRight:string,margin:string,marginHorizontal:string,marginVertical:string,marginTop:string,marginBottom:string,marginLeft:string,marginRight:string,backgroundColor:string,borderRadius:string,width:string,minWidth:string,maxWidth:string,height:string,minHeight:string,maxHeight:string,flex:number,position:\"relative\"|\"absolute\",top:string,bottom:string,left:string,right:string,zIndex:number}}\nCarouselDots:{scrollable:boolean,dotType:\"expanding_dot\"|\"normal_dot\"|\"scaling_dot\"|\"sliding_border\"|\"sliding_dot\"|\"liquid_like\",dot_thickness:string,inactive_dot_opacity:number,inactive_dot_color:string,active_dot_color:string,styles:{flexDirection:\"row\"|\"column\",flexWrap:\"nowrap\"|\"wrap\"|\"wrap-reverse\",alignItems:\"flex-start\"|\"center\"|\"flex-end\"|\"stretch\"|\"baseline\",justifyContent:\"flex-start\"|\"center\"|\"flex-end\"|\"space-between\"|\"space-around\"|\"space-evenly\",gap:string,padding:string,paddingHorizontal:string,paddingVertical:string,paddingTop:string,paddingBottom:string,paddingLeft:string,paddingRight:string,margin:string,marginHorizontal:string,marginVertical:string,marginTop:string,marginBottom:string,marginLeft:string,marginRight:string,backgroundColor:string,borderRadius:string,width:string,minWidth:string,maxWidth:string,height:string,minHeight:string,maxHeight:string,flex:number,position:\"relative\"|\"absolute\",top:string,bottom:string,left:string,right:string,zIndex:number}}\nCarouselItem:{scrollable:boolean,styles:{flexDirection:\"row\"|\"column\",flexWrap:\"nowrap\"|\"wrap\"|\"wrap-reverse\",alignItems:\"flex-start\"|\"center\"|\"flex-end\"|\"stretch\"|\"baseline\",justifyContent:\"flex-start\"|\"center\"|\"flex-end\"|\"space-between\"|\"space-around\"|\"space-evenly\",gap:string,padding:string,paddingHorizontal:string,paddingVertical:string,paddingTop:string,paddingBottom:string,paddingLeft:string,paddingRight:string,margin:string,marginHorizontal:string,marginVertical:string,marginTop:string,marginBottom:string,marginLeft:string,marginRight:string,backgroundColor:string,borderRadius:string,width:string,minWidth:string,maxWidth:string,height:string,minHeight:string,maxHeight:string,flex:number,position:\"relative\"|\"absolute\",top:string,bottom:string,left:string,right:string,zIndex:number}}\nCarouselProvider:{scrollable:boolean,styles:{flexDirection:\"row\"|\"column\",flexWrap:\"nowrap\"|\"wrap\"|\"wrap-reverse\",alignItems:\"flex-start\"|\"center\"|\"flex-end\"|\"stretch\"|\"baseline\",justifyContent:\"flex-start\"|\"center\"|\"flex-end\"|\"space-between\"|\"space-around\"|\"space-evenly\",gap:string,padding:string,paddingHorizontal:string,paddingVertical:string,paddingTop:string,paddingBottom:string,paddingLeft:string,paddingRight:string,margin:string,marginHorizontal:string,marginVertical:string,marginTop:string,marginBottom:string,marginLeft:string,marginRight:string,backgroundColor:string,borderRadius:string,width:string,minWidth:string,maxWidth:string,height:string,minHeight:string,maxHeight:string,flex:number,position:\"relative\"|\"absolute\",top:string,bottom:string,left:string,right:string,zIndex:number}}\nCountDown:{adjustsFontSizeToFit:boolean,showEllipsis:boolean,translateCounter:number,scrollable:boolean,count:number,styles:{color:string,fontSize:string,fontFamily:string,fontWeight:string,flexDirection:\"row\"|\"column\",flexWrap:\"nowrap\"|\"wrap\"|\"wrap-reverse\",alignItems:\"flex-start\"|\"center\"|\"flex-end\"|\"stretch\"|\"baseline\",justifyContent:\"flex-start\"|\"center\"|\"flex-end\"|\"space-between\"|\"space-around\"|\"space-evenly\",gap:string,padding:string,paddingHorizontal:string,paddingVertical:string,paddingTop:string,paddingBottom:string,paddingLeft:string,paddingRight:string,margin:string,marginHorizontal:string,marginVertical:string,marginTop:string,marginBottom:string,marginLeft:string,marginRight:string,backgroundColor:string,borderRadius:string,width:obj,minWidth:string,maxWidth:string,height:string,minHeight:string,maxHeight:string,flex:number,position:\"relative\"|\"absolute\",top:string,bottom:string,left:string,right:string,zIndex:number,textAlign:obj}}\nImage:{scrollable:boolean,src:string,styles:{flexDirection:\"row\"|\"column\",flexWrap:\"nowrap\"|\"wrap\"|\"wrap-reverse\",alignItems:\"flex-start\"|\"center\"|\"flex-end\"|\"stretch\"|\"baseline\",justifyContent:\"flex-start\"|\"center\"|\"flex-end\"|\"space-between\"|\"space-around\"|\"space-evenly\",gap:string,padding:string,paddingHorizontal:string,paddingVertical:string,paddingTop:string,paddingBottom:string,paddingLeft:string,paddingRight:string,margin:string,marginHorizontal:string,marginVertical:string,marginTop:string,marginBottom:string,marginLeft:string,marginRight:string,backgroundColor:string,borderRadius:string,width:string,minWidth:string,maxWidth:string,height:string,minHeight:string,maxHeight:string,flex:number,position:\"relative\"|\"absolute\",top:string,bottom:string,left:string,right:string,zIndex:number,resizeMode:\"cover\"|\"contain\"|\"stretch\"|\"center\"}}\nMain:{scrollable:boolean,useSafeAreaView:boolean,styles:{flexDirection:\"row\"|\"column\",flexWrap:\"nowrap\"|\"wrap\"|\"wrap-reverse\",alignItems:\"flex-start\"|\"center\"|\"flex-end\"|\"stretch\"|\"baseline\",justifyContent:\"flex-start\"|\"center\"|\"flex-end\"|\"space-between\"|\"space-around\"|\"space-evenly\",gap:string,padding:string,paddingHorizontal:string,paddingVertical:string,paddingTop:string,paddingBottom:string,paddingLeft:string,paddingRight:string,margin:string,marginHorizontal:string,marginVertical:string,marginTop:string,marginBottom:string,marginLeft:string,marginRight:string,backgroundColor:string,borderRadius:string,width:string,minWidth:string,maxWidth:string,height:string,minHeight:string,maxHeight:string,flex:number,position:\"relative\"|\"absolute\",top:string,bottom:string,left:string,right:string,zIndex:number}}\nNavigationBarColor:{scrollable:boolean,styles:{flexDirection:\"row\"|\"column\",flexWrap:\"nowrap\"|\"wrap\"|\"wrap-reverse\",alignItems:\"flex-start\"|\"center\"|\"flex-end\"|\"stretch\"|\"baseline\",justifyContent:\"flex-start\"|\"center\"|\"flex-end\"|\"space-between\"|\"space-around\"|\"space-evenly\",gap:string,padding:string,paddingHorizontal:string,paddingVertical:string,paddingTop:string,paddingBottom:string,paddingLeft:string,paddingRight:string,margin:string,marginHorizontal:string,marginVertical:string,marginTop:string,marginBottom:string,marginLeft:string,marginRight:string,backgroundColor:string,borderRadius:string,width:string,minWidth:string,maxWidth:string,height:string,minHeight:string,maxHeight:string,flex:number,position:\"relative\"|\"absolute\",top:string,bottom:string,left:string,right:string,zIndex:number}}\nOnboard:{scrollable:boolean,styles:{flexDirection:\"row\"|\"column\",flexWrap:\"nowrap\"|\"wrap\"|\"wrap-reverse\",alignItems:\"flex-start\"|\"center\"|\"flex-end\"|\"stretch\"|\"baseline\",justifyContent:\"flex-start\"|\"center\"|\"flex-end\"|\"space-between\"|\"space-around\"|\"space-evenly\",gap:string,padding:string,paddingHorizontal:string,paddingVertical:string,paddingTop:string,paddingBottom:string,paddingLeft:string,paddingRight:string,margin:string,marginHorizontal:string,marginVertical:string,marginTop:string,marginBottom:string,marginLeft:string,marginRight:string,backgroundColor:string,borderRadius:string,width:string,minWidth:string,maxWidth:string,height:string,minHeight:string,maxHeight:string,flex:number,position:\"relative\"|\"absolute\",top:string,bottom:string,left:string,right:string,zIndex:number}}\nOnboardButton:{scrollable:boolean,labelKey:string,animation:\"simple-animation\"|\"line-animation\"|\"blur\"|\"blur-animation\"|\"blur-line-animation\",animation_color:string,events:[obj],styles:{flexDirection:\"row\"|\"column\",flexWrap:\"nowrap\"|\"wrap\"|\"wrap-reverse\",alignItems:\"flex-start\"|\"center\"|\"flex-end\"|\"stretch\"|\"baseline\",justifyContent:\"flex-start\"|\"center\"|\"flex-end\"|\"space-between\"|\"space-around\"|\"space-evenly\",gap:string,padding:string,paddingHorizontal:string,paddingVertical:string,paddingTop:string,paddingBottom:string,paddingLeft:string,paddingRight:string,margin:string,marginHorizontal:string,marginVertical:string,marginTop:string,marginBottom:string,marginLeft:string,marginRight:string,backgroundColor:string,borderRadius:string,width:string,minWidth:string,maxWidth:string,height:string,minHeight:string,maxHeight:string,flex:number,position:\"relative\"|\"absolute\",top:string,bottom:string,left:string,right:string,zIndex:number,color:string}}\nOnboardButtons:{scrollable:boolean,buttonType:\"previous_button\"|\"next_button\"|\"skip_button\",skipNumber:number,buttons_direction:\"row\"|\"column\",forIndex:number,seperatorColor:string,condition:\"carousel-index\",conditionVariable:number,styles:{flexDirection:\"row\"|\"column\",flexWrap:\"nowrap\"|\"wrap\"|\"wrap-reverse\",alignItems:\"flex-start\"|\"center\"|\"flex-end\"|\"stretch\"|\"baseline\",justifyContent:\"flex-start\"|\"center\"|\"flex-end\"|\"space-between\"|\"space-around\"|\"space-evenly\",gap:string,padding:string,paddingHorizontal:string,paddingVertical:string,paddingTop:string,paddingBottom:string,paddingLeft:string,paddingRight:string,margin:string,marginHorizontal:string,marginVertical:string,marginTop:string,marginBottom:string,marginLeft:string,marginRight:string,backgroundColor:string,borderRadius:string,width:string,minWidth:string,maxWidth:string,height:string,minHeight:string,maxHeight:string,flex:number,position:\"relative\"|\"absolute\",top:string,bottom:string,left:string,right:string,zIndex:number}}\nOnboardDot:{scrollable:boolean,dotType:\"expanding_dot\"|\"normal_dot\"|\"scaling_dot\"|\"sliding_border\"|\"sliding_dot\"|\"liquid_like\",dot_thickness:string,inactive_dot_opacity:number,inactive_dot_color:string,active_dot_color:string,styles:{flexDirection:\"row\"|\"column\",flexWrap:\"nowrap\"|\"wrap\"|\"wrap-reverse\",alignItems:\"flex-start\"|\"center\"|\"flex-end\"|\"stretch\"|\"baseline\",justifyContent:\"flex-start\"|\"center\"|\"flex-end\"|\"space-between\"|\"space-around\"|\"space-evenly\",gap:string,padding:string,paddingHorizontal:string,paddingVertical:string,paddingTop:string,paddingBottom:string,paddingLeft:string,paddingRight:string,margin:string,marginHorizontal:string,marginVertical:string,marginTop:string,marginBottom:string,marginLeft:string,marginRight:string,backgroundColor:string,borderRadius:string,width:string,minWidth:string,maxWidth:string,height:string,minHeight:string,maxHeight:string,flex:number,position:\"relative\"|\"absolute\",top:string,bottom:string,left:string,right:string,zIndex:number}}\nOnboardFooter:{adjustsFontSizeToFit:boolean,showEllipsis:boolean,translateCounter:number,scrollable:boolean,textLocalizationKey:string,linkedWordFirstLocalizationKey:string,linkedWordFirstColor:string,linkedWordFirstPage:string,linkedWordSecondLocalizationKey:string,linkedWordSecondColor:string,linkedWordSecondPage:string,styles:{color:string,fontSize:string,fontFamily:string,fontWeight:string,flexDirection:\"row\"|\"column\",flexWrap:\"nowrap\"|\"wrap\"|\"wrap-reverse\",alignItems:\"flex-start\"|\"center\"|\"flex-end\"|\"stretch\"|\"baseline\",justifyContent:\"flex-start\"|\"center\"|\"flex-end\"|\"space-between\"|\"space-around\"|\"space-evenly\",gap:string,padding:string,paddingHorizontal:string,paddingVertical:string,paddingTop:string,paddingBottom:string,paddingLeft:string,paddingRight:string,margin:string,marginHorizontal:string,marginVertical:string,marginTop:string,marginBottom:string,marginLeft:string,marginRight:string,backgroundColor:string,borderRadius:string,width:string,minWidth:string,maxWidth:string,height:string,minHeight:string,maxHeight:string,flex:number,position:\"relative\"|\"absolute\",top:string,bottom:string,left:string,right:string,zIndex:number}}\nOnboardImage:{src:string,scrollable:boolean,video_url:string,lottie:string,styles:{resizeMode:\"cover\"|\"contain\"|\"stretch\"|\"center\",flexDirection:\"row\"|\"column\",flexWrap:\"nowrap\"|\"wrap\"|\"wrap-reverse\",alignItems:\"flex-start\"|\"center\"|\"flex-end\"|\"stretch\"|\"baseline\",justifyContent:\"flex-start\"|\"center\"|\"flex-end\"|\"space-between\"|\"space-around\"|\"space-evenly\",gap:string,padding:string,paddingHorizontal:string,paddingVertical:string,paddingTop:string,paddingBottom:string,paddingLeft:string,paddingRight:string,margin:string,marginHorizontal:string,marginVertical:string,marginTop:string,marginBottom:string,marginLeft:string,marginRight:string,backgroundColor:string,borderRadius:string,width:string,minWidth:string,maxWidth:string,height:string,minHeight:string,maxHeight:string,flex:number,position:\"relative\"|\"absolute\",top:string,bottom:string,left:string,right:string,zIndex:number}}\nOnboardItem:{scrollable:boolean,display:\"flex\"|\"block\",gap:string,flexDirection:\"row\"|\"column\",paddingHorizontal:string,styles:{flexDirection:\"row\"|\"column\",flexWrap:\"nowrap\"|\"wrap\"|\"wrap-reverse\",alignItems:\"flex-start\"|\"center\"|\"flex-end\"|\"stretch\"|\"baseline\",justifyContent:\"flex-start\"|\"center\"|\"flex-end\"|\"space-between\"|\"space-around\"|\"space-evenly\",gap:string,padding:string,paddingHorizontal:string,paddingVertical:string,paddingTop:string,paddingBottom:string,paddingLeft:string,paddingRight:string,margin:string,marginHorizontal:string,marginVertical:string,marginTop:string,marginBottom:string,marginLeft:string,marginRight:string,backgroundColor:string,borderRadius:string,width:string,minWidth:string,maxWidth:string,height:string,minHeight:string,maxHeight:string,flex:number,position:\"relative\"|\"absolute\",top:string,bottom:string,left:string,right:string,zIndex:number}}\nOnboardProvider:{scrollable:boolean,theme:\"light\"|\"dark\"|\"all\",styles:{flexDirection:\"row\"|\"column\",flexWrap:\"nowrap\"|\"wrap\"|\"wrap-reverse\",alignItems:\"flex-start\"|\"center\"|\"flex-end\"|\"stretch\"|\"baseline\",justifyContent:\"flex-start\"|\"center\"|\"flex-end\"|\"space-between\"|\"space-around\"|\"space-evenly\",gap:string,padding:string,paddingHorizontal:string,paddingVertical:string,paddingTop:string,paddingBottom:string,paddingLeft:string,paddingRight:string,margin:string,marginHorizontal:string,marginVertical:string,marginTop:string,marginBottom:string,marginLeft:string,marginRight:string,backgroundColor:string,borderRadius:string,width:string,minWidth:string,maxWidth:string,height:string,minHeight:string,maxHeight:string,flex:number,position:\"relative\"|\"absolute\",top:string,bottom:string,left:string,right:string,zIndex:number}}\nOnboardSubtitle:{adjustsFontSizeToFit:boolean,showEllipsis:boolean,translateCounter:number,scrollable:boolean,styles:{color:string,fontSize:string,fontFamily:string,fontWeight:string,flexDirection:\"row\"|\"column\",flexWrap:\"nowrap\"|\"wrap\"|\"wrap-reverse\",alignItems:\"flex-start\"|\"center\"|\"flex-end\"|\"stretch\"|\"baseline\",justifyContent:\"flex-start\"|\"center\"|\"flex-end\"|\"space-between\"|\"space-around\"|\"space-evenly\",gap:string,padding:string,paddingHorizontal:string,paddingVertical:string,paddingTop:string,paddingBottom:string,paddingLeft:string,paddingRight:string,margin:string,marginHorizontal:string,marginVertical:string,marginTop:string,marginBottom:string,marginLeft:string,marginRight:string,backgroundColor:string,borderRadius:string,width:string,minWidth:string,maxWidth:string,height:string,minHeight:string,maxHeight:string,flex:number,position:\"relative\"|\"absolute\",top:string,bottom:string,left:string,right:string,zIndex:number}}\nOnboardTitle:{adjustsFontSizeToFit:boolean,showEllipsis:boolean,translateCounter:number,scrollable:boolean,styles:{color:string,fontSize:string,fontFamily:string,fontWeight:string,flexDirection:\"row\"|\"column\",flexWrap:\"nowrap\"|\"wrap\"|\"wrap-reverse\",alignItems:\"flex-start\"|\"center\"|\"flex-end\"|\"stretch\"|\"baseline\",justifyContent:\"flex-start\"|\"center\"|\"flex-end\"|\"space-between\"|\"space-around\"|\"space-evenly\",gap:string,padding:string,paddingHorizontal:string,paddingVertical:string,paddingTop:string,paddingBottom:string,paddingLeft:string,paddingRight:string,margin:string,marginHorizontal:string,marginVertical:string,marginTop:string,marginBottom:string,marginLeft:string,marginRight:string,backgroundColor:string,borderRadius:string,width:string,minWidth:string,maxWidth:string,height:string,minHeight:string,maxHeight:string,flex:number,position:\"relative\"|\"absolute\",top:string,bottom:string,left:string,right:string,zIndex:number}}\nPaywallBackground:{src:string,resizeMode:\"cover\"|\"contain\"|\"stretch\"|\"center\",scrollable:boolean,styles:{flexDirection:\"row\"|\"column\",flexWrap:\"nowrap\"|\"wrap\"|\"wrap-reverse\",alignItems:\"flex-start\"|\"center\"|\"flex-end\"|\"stretch\"|\"baseline\",justifyContent:\"flex-start\"|\"center\"|\"flex-end\"|\"space-between\"|\"space-around\"|\"space-evenly\",gap:string,padding:string,paddingHorizontal:string,paddingVertical:string,paddingTop:string,paddingBottom:string,paddingLeft:string,paddingRight:string,margin:string,marginHorizontal:string,marginVertical:string,marginTop:string,marginBottom:string,marginLeft:string,marginRight:string,backgroundColor:string,borderRadius:string,width:string,minWidth:string,maxWidth:string,height:string,minHeight:string,maxHeight:string,flex:number,position:\"relative\"|\"absolute\",top:string,bottom:string,left:string,right:string,zIndex:number}}\nPaywallCloseButton:{iconType:string,size:number,strokeWidth:number,adjustsFontSizeToFit:boolean,showEllipsis:boolean,translateCounter:number,scrollable:boolean,styles:{color:string,fontSize:string,fontFamily:string,fontWeight:string,flexDirection:\"row\"|\"column\",flexWrap:\"nowrap\"|\"wrap\"|\"wrap-reverse\",alignItems:\"flex-start\"|\"center\"|\"flex-end\"|\"stretch\"|\"baseline\",justifyContent:\"flex-start\"|\"center\"|\"flex-end\"|\"space-between\"|\"space-around\"|\"space-evenly\",gap:string,padding:string,paddingHorizontal:string,paddingVertical:string,paddingTop:string,paddingBottom:string,paddingLeft:string,paddingRight:string,margin:string,marginHorizontal:string,marginVertical:string,marginTop:string,marginBottom:string,marginLeft:string,marginRight:string,backgroundColor:string,borderRadius:string,width:string,minWidth:string,maxWidth:string,height:string,minHeight:string,maxHeight:string,flex:number,position:\"relative\"|\"absolute\",top:string,bottom:string,left:string,right:string,zIndex:number}}\nPaywallOptions:{scrollable:boolean,styles:{flexDirection:\"row\"|\"column\",flexWrap:\"nowrap\"|\"wrap\"|\"wrap-reverse\",alignItems:\"flex-start\"|\"center\"|\"flex-end\"|\"stretch\"|\"baseline\",justifyContent:\"flex-start\"|\"center\"|\"flex-end\"|\"space-between\"|\"space-around\"|\"space-evenly\",gap:string,padding:string,paddingHorizontal:string,paddingVertical:string,paddingTop:string,paddingBottom:string,paddingLeft:string,paddingRight:string,margin:string,marginHorizontal:string,marginVertical:string,marginTop:string,marginBottom:string,marginLeft:string,marginRight:string,backgroundColor:string,borderRadius:string,width:string,minWidth:string,maxWidth:string,height:string,minHeight:string,maxHeight:string,flex:number,position:\"relative\"|\"absolute\",top:string,bottom:string,left:string,right:string,zIndex:number}}\nPaywallProvider:{scrollable:boolean,delay:number,styles:{flexDirection:\"row\"|\"column\",flexWrap:\"nowrap\"|\"wrap\"|\"wrap-reverse\",alignItems:\"flex-start\"|\"center\"|\"flex-end\"|\"stretch\"|\"baseline\",justifyContent:\"flex-start\"|\"center\"|\"flex-end\"|\"space-between\"|\"space-around\"|\"space-evenly\",gap:string,padding:string,paddingHorizontal:string,paddingVertical:string,paddingTop:string,paddingBottom:string,paddingLeft:string,paddingRight:string,margin:string,marginHorizontal:string,marginVertical:string,marginTop:string,marginBottom:string,marginLeft:string,marginRight:string,backgroundColor:string,borderRadius:string,width:string,minWidth:string,maxWidth:string,height:string,minHeight:string,maxHeight:string,flex:number,position:\"relative\"|\"absolute\",top:string,bottom:string,left:string,right:string,zIndex:number}}\nPaywallSubscribeButton:{scrollable:boolean,styles:{color:string,fontSize:string,fontWeight:\"normal\"|\"bold\"|\"100\"|\"200\"|\"300\"|\"400\"|\"500\"|\"600\"|\"700\"|\"800\"|\"900\",flexDirection:\"row\"|\"column\",flexWrap:\"nowrap\"|\"wrap\"|\"wrap-reverse\",alignItems:\"flex-start\"|\"center\"|\"flex-end\"|\"stretch\"|\"baseline\",justifyContent:\"flex-start\"|\"center\"|\"flex-end\"|\"space-between\"|\"space-around\"|\"space-evenly\",gap:string,padding:string,paddingHorizontal:string,paddingVertical:string,paddingTop:string,paddingBottom:string,paddingLeft:string,paddingRight:string,margin:string,marginHorizontal:string,marginVertical:string,marginTop:string,marginBottom:string,marginLeft:string,marginRight:string,backgroundColor:string,borderRadius:string,width:string,minWidth:string,maxWidth:string,height:string,minHeight:string,maxHeight:string,flex:number,position:\"relative\"|\"absolute\",top:string,bottom:string,left:string,right:string,zIndex:number}}\nPriceTag:{adjustsFontSizeToFit:boolean,showEllipsis:boolean,translateCounter:number,scrollable:boolean,showOriginalPricePossible:boolean,hideIfItsNotDiscount:boolean,styles:{color:string,fontSize:string,fontFamily:string,fontWeight:string,flexDirection:\"row\"|\"column\",flexWrap:\"nowrap\"|\"wrap\"|\"wrap-reverse\",alignItems:\"flex-start\"|\"center\"|\"flex-end\"|\"stretch\"|\"baseline\",justifyContent:\"flex-start\"|\"center\"|\"flex-end\"|\"space-between\"|\"space-around\"|\"space-evenly\",gap:string,padding:string,paddingHorizontal:string,paddingVertical:string,paddingTop:string,paddingBottom:string,paddingLeft:string,paddingRight:string,margin:string,marginHorizontal:string,marginVertical:string,marginTop:string,marginBottom:string,marginLeft:string,marginRight:string,backgroundColor:string,borderRadius:string,width:string,minWidth:string,maxWidth:string,height:string,minHeight:string,maxHeight:string,flex:number,position:\"relative\"|\"absolute\",top:string,bottom:string,left:string,right:string,zIndex:number,textDecorationLine:\"none\"|\"underline\"|\"line-through\"}}\nPricing:{adjustsFontSizeToFit:boolean,showEllipsis:boolean,translateCounter:number,scrollable:boolean,styles:{color:string,fontSize:string,fontFamily:string,fontWeight:string,flexDirection:\"row\"|\"column\",flexWrap:\"nowrap\"|\"wrap\"|\"wrap-reverse\",alignItems:\"flex-start\"|\"center\"|\"flex-end\"|\"stretch\"|\"baseline\",justifyContent:\"flex-start\"|\"center\"|\"flex-end\"|\"space-between\"|\"space-around\"|\"space-evenly\",gap:string,padding:string,paddingHorizontal:string,paddingVertical:string,paddingTop:string,paddingBottom:string,paddingLeft:string,paddingRight:string,margin:string,marginHorizontal:string,marginVertical:string,marginTop:string,marginBottom:string,marginLeft:string,marginRight:string,backgroundColor:string,borderRadius:string,width:string,minWidth:string,maxWidth:string,height:string,minHeight:string,maxHeight:string,flex:number,position:\"relative\"|\"absolute\",top:string,bottom:string,left:string,right:string,zIndex:number}}\nPromo:{adjustsFontSizeToFit:boolean,showEllipsis:boolean,translateCounter:number,scrollable:boolean,styles:{color:string,fontSize:string,fontFamily:string,fontWeight:string,flexDirection:\"row\"|\"column\",flexWrap:\"nowrap\"|\"wrap\"|\"wrap-reverse\",alignItems:\"flex-start\"|\"center\"|\"flex-end\"|\"stretch\"|\"baseline\",justifyContent:\"flex-start\"|\"center\"|\"flex-end\"|\"space-between\"|\"space-around\"|\"space-evenly\",gap:string,padding:string,paddingHorizontal:string,paddingVertical:string,paddingTop:string,paddingBottom:string,paddingLeft:string,paddingRight:string,margin:string,marginHorizontal:string,marginVertical:string,marginTop:string,marginBottom:string,marginLeft:string,marginRight:string,backgroundColor:string,borderRadius:string,width:string,minWidth:string,maxWidth:string,height:string,minHeight:string,maxHeight:string,flex:number,position:\"relative\"|\"absolute\",top:string,bottom:string,left:string,right:string,zIndex:number}}\nRadioButton:{scrollable:boolean,selected:boolean,color:string,size:number,styles:{flexDirection:\"row\"|\"column\",flexWrap:\"nowrap\"|\"wrap\"|\"wrap-reverse\",alignItems:\"flex-start\"|\"center\"|\"flex-end\"|\"stretch\"|\"baseline\",justifyContent:\"flex-start\"|\"center\"|\"flex-end\"|\"space-between\"|\"space-around\"|\"space-evenly\",gap:string,padding:string,paddingHorizontal:string,paddingVertical:string,paddingTop:string,paddingBottom:string,paddingLeft:string,paddingRight:string,margin:string,marginHorizontal:string,marginVertical:string,marginTop:string,marginBottom:string,marginLeft:string,marginRight:string,backgroundColor:string,borderRadius:string,width:string,minWidth:string,maxWidth:string,height:string,minHeight:string,maxHeight:string,flex:number,position:\"relative\"|\"absolute\",top:string,bottom:string,left:string,right:string,zIndex:number}}\nSeparator:{styles:{backgroundColor:string,width:string,height:string,marginHorizontal:string,marginVertical:string,marginTop:string,marginBottom:string}}\nStatusBarColor:{scrollable:boolean,styles:{flexDirection:\"row\"|\"column\",flexWrap:\"nowrap\"|\"wrap\"|\"wrap-reverse\",alignItems:\"flex-start\"|\"center\"|\"flex-end\"|\"stretch\"|\"baseline\",justifyContent:\"flex-start\"|\"center\"|\"flex-end\"|\"space-between\"|\"space-around\"|\"space-evenly\",gap:string,padding:string,paddingHorizontal:string,paddingVertical:string,paddingTop:string,paddingBottom:string,paddingLeft:string,paddingRight:string,margin:string,marginHorizontal:string,marginVertical:string,marginTop:string,marginBottom:string,marginLeft:string,marginRight:string,backgroundColor:string,borderRadius:string,width:string,minWidth:string,maxWidth:string,height:string,minHeight:string,maxHeight:string,flex:number,position:\"relative\"|\"absolute\",top:string,bottom:string,left:string,right:string,zIndex:number}}\nText:{scrollable:boolean,adjustsFontSizeToFit:boolean,showEllipsis:boolean,translateCounter:number,styles:{flexDirection:\"row\"|\"column\",flexWrap:\"nowrap\"|\"wrap\"|\"wrap-reverse\",alignItems:\"flex-start\"|\"center\"|\"flex-end\"|\"stretch\"|\"baseline\",justifyContent:\"flex-start\"|\"center\"|\"flex-end\"|\"space-between\"|\"space-around\"|\"space-evenly\",gap:string,padding:string,paddingHorizontal:string,paddingVertical:string,paddingTop:string,paddingBottom:string,paddingLeft:string,paddingRight:string,margin:string,marginHorizontal:string,marginVertical:string,marginTop:string,marginBottom:string,marginLeft:string,marginRight:string,backgroundColor:string,borderRadius:string,width:string,minWidth:string,maxWidth:string,height:string,minHeight:string,maxHeight:string,flex:number,position:\"relative\"|\"absolute\",top:string,bottom:string,left:string,right:string,zIndex:number,color:string,fontSize:string,fontFamily:string,fontWeight:string}}\nView:{scrollable:boolean,styles:{flexDirection:\"row\"|\"column\",flexWrap:\"nowrap\"|\"wrap\"|\"wrap-reverse\",alignItems:\"flex-start\"|\"center\"|\"flex-end\"|\"stretch\"|\"baseline\",justifyContent:\"flex-start\"|\"center\"|\"flex-end\"|\"space-between\"|\"space-around\"|\"space-evenly\",gap:string,padding:string,paddingHorizontal:string,paddingVertical:string,paddingTop:string,paddingBottom:string,paddingLeft:string,paddingRight:string,margin:string,marginHorizontal:string,marginVertical:string,marginTop:string,marginBottom:string,marginLeft:string,marginRight:string,backgroundColor:string,borderRadius:string,width:string,minWidth:string,maxWidth:string,height:string,minHeight:string,maxHeight:string,flex:number,position:\"relative\"|\"absolute\",top:string,bottom:string,left:string,right:string,zIndex:number}}\n```\n\n## Available Icons\n\nUse one of these values for `iconType` attributes:\n\n```\n\n```\n\n## XML Rules\n\n- Root element must always be `<Main isMain=\"true\">`.\n- Text content (children) goes as element body text, not as an attribute.\n- `styles` value must be a JSON object string (escape inner quotes): `styles=\"{"flex":1,"color":"THEME_COLORS.TEXT"}\"`.\n- `events` value must be a JSON array string.\n- Omit any attribute that has no value — no nulls, no empty strings.\n- Use a short unique slug for `key` when the component needs one.\n- Only use components appropriate for a onboard screen.\n\n## Embla Carousel Constraints\n\n> **IMPORTANT – Web uses Embla carousel under the hood.**\n> For `OnboardProvider` and `OnboardItem`, do **NOT** set any of the following outer layout styles via `styles`, because Embla manages them internally through its own CSS classes (`embla`, `embla__viewport`, `embla__slide`):\n>\n> `flex`, `flexGrow`, `flexShrink`, `margin`, `marginTop`, `marginBottom`, `marginLeft`, `marginRight`, `marginHorizontal`, `marginVertical`, `height`, `minHeight`, `maxHeight`, `width`, `minWidth`, `maxWidth`, `position`, `top`, `bottom`, `left`, `right`, `zIndex`, `display`\n>\n> Only **visual** styles are safe to set on `OnboardProvider` and `OnboardItem`:\n> `padding`, `paddingTop`, `paddingBottom`, `paddingLeft`, `paddingRight`, `paddingHorizontal`, `paddingVertical`, `backgroundColor`, `borderRadius`, `gap`, `alignItems`, `justifyContent`, `flexDirection`, `flexWrap`\n\n## Available Localization Keys\n\nUse ONLY the keys listed below for localization attributes (`labelKey`, `textLocalizationKey`, etc.).\nDo NOT invent new keys or use keys not in this list.\n\n```\nbase.builder.paywall.period.monthly\nbase.builder.paywall.period.annual\nbase.builder.paywall.period.weekly\nbase.builder.paywall.period.daily\nbase.builder.paywall.period.monthlyPromo\nbase.builder.paywall.period.annualPromo\nbase.builder.paywall.pricing.default.text\nbase.builder.paywall.pricing.freeTrial.text\nbase.builder.paywall.pricing.regular.text\nbase.builder.paywall.promo.default.text\nbase.builder.paywall.promo.freeTrial.text\nbase.builder.paywall.promo.regular.text\nonboard.title.one-page\nonboard.title.two-page\nonboard.title.three-page\nonboard.title.four-page\nonboard.title.one-page2\nonboard.title.two-page2\nonboard.title.three-page2\nonboard.title.four-page2\nonboard.subtitle.one-page\nonboard.subtitle.two-page\nonboard.subtitle.three-page\nonboard.subtitle.four-page\nonboard.subtitle.one-page2\nonboard.subtitle.two-page2\nonboard.subtitle.three-page2\nonboard.subtitle.four-page2\nonboard.next.one-page\nonboard.next.two-page\nonboard.next.three-page\nonboard.skip.one-page\nonboard.skip.two-page\nonboard.skip.three-page\nonboard.allow.four-page\nview.onboarding.footer.description\nview.onboarding.btnPrivacy\nview.onboarding.btnTerms\n```\n\n## Default Colors\n\nReference color tokens already defined in the project. Prefer these over hard-coded hex values.\n\n```\n STATIC_COLORS.BLACK: \"#000\"\n STATIC_COLORS.WHITE: \"#FFFFFF\"\n STATIC_COLORS.TRANSPARENT: \"#ffffff00\"\n STATIC_COLORS.ONBOARD_DOT_INACTIVE: \"#E4E5E7\"\n STATIC_COLORS.ONBOARD_DOT_ACTIVE: \"#007AFF\"\n STATIC_COLORS.ONBOARD_BUTTON_PRIMARY_BACKGROUND: \"#0066FF\"\n STATIC_COLORS.ONBOARD_BUTTON_PRIMARY_TEXT: \"#FFFFFF\"\n STATIC_COLORS.ONBOARD_LINK_COLOR: \"#1778F2\"\n STATIC_COLORS.ONBOARD_SEPARATOR_COLOR: \"#44454D\"\n STATIC_COLORS.RADIO_BUTTON_COLOR: \"#A6A6A6\"\n THEME_COLORS.TEXT (light): \"#161827\"\n THEME_COLORS.BACKGROUND (light): \"#F4F5FF\"\n THEME_COLORS.ICON (light): \"#0450E2\"\n THEME_COLORS.LINE (light): \"#E9EBF9\"\n THEME_COLORS.ONBOARD_TITLE (light): \"#161827\"\n THEME_COLORS.ONBOARD_SUBTITLE (light): \"#44454D\"\n THEME_COLORS.ONBOARD_BUTTON_SECONDARY_TEXT (light): \"#81838F\"\n THEME_COLORS.ONBOARD_FOOTER_TEXT (light): \"#81838F\"\n THEME_COLORS.TEXT (dark): \"#E9EBF9\"\n THEME_COLORS.BACKGROUND (dark): \"#080A17\"\n THEME_COLORS.ICON (dark): \"#0450E2\"\n THEME_COLORS.LINE (dark): \"#161827\"\n THEME_COLORS.ONBOARD_TITLE (dark): \"#FDFDFD\"\n THEME_COLORS.ONBOARD_SUBTITLE (dark): \"#C7C7C7\"\n THEME_COLORS.ONBOARD_BUTTON_SECONDARY_TEXT (dark): \"#A9AAAC\"\n THEME_COLORS.ONBOARD_FOOTER_TEXT (dark): \"#A2A4B1\"\n```\n\n## Default Localization (en)\n\n```\n{\n \"base.builder.paywall.period.monthly\": \"per month\",\n \"base.builder.paywall.period.annual\": \"per year\",\n \"base.builder.paywall.period.weekly\": \"per week\",\n \"base.builder.paywall.period.daily\": \"per day\",\n \"base.builder.paywall.period.monthlyPromo\": \"per month\",\n \"base.builder.paywall.period.annualPromo\": \"per year\",\n \"base.builder.paywall.pricing.default.text\": \"@promoPrice for the first @promoPeriod, then @localizedPrice @localizedPeriod\",\n \"base.builder.paywall.pricing.freeTrial.text\": \"@trialPeriod-@trialPeriodUnit free trial, then @localizedPrice @localizedPeriod\",\n \"base.builder.paywall.pricing.regular.text\": \"@localizedPrice @localizedPeriod\",\n \"base.builder.paywall.promo.default.text\": \"Save @discountPercentage%!\",\n \"base.builder.paywall.promo.freeTrial.text\": \"@trialPeriod-@trialPeriodUnit free trial\",\n \"base.builder.paywall.promo.regular.text\": \"@localizedPrice @localizedPeriod\",\n \"onboard.title.one-page\": \"Secure your connection\",\n \"onboard.title.two-page\": \"Access content worldwide\",\n \"onboard.title.three-page\": \"Fast and reliable\",\n \"onboard.title.four-page\": \"Stay notified and safe\",\n \"onboard.title.one-page2\": \"Secure your connection\",\n \"onboard.title.two-page2\": \"Access content worldwide\",\n \"onboard.title.three-page2\": \"Fast and reliable\",\n \"onboard.title.four-page2\": \"Stay notified and safe\",\n \"onboard.subtitle.one-page\": \"Encrypt your traffic and protect your privacy on public Wi\\u2011Fi.\",\n \"onboard.subtitle.two-page\": \"Connect to high\\u2011speed servers in many countries with one tap.\",\n \"onboard.subtitle.three-page\": \"Auto\\u2011connect to the best server for speed and stability.\",\n \"onboard.subtitle.four-page\": \"Enable notifications for connection status and security tips.\",\n \"onboard.subtitle.one-page2\": \"Encrypt your traffic and protect your privacy on public Wi\\u2011Fi.\",\n \"onboard.subtitle.two-page2\": \"Connect to high\\u2011speed servers in many countries with one tap.\",\n \"onboard.subtitle.three-page2\": \"Auto\\u2011connect to the best server for speed and stability.\",\n \"onboard.subtitle.four-page2\": \"Enable notifications for connection status and security tips.\",\n \"onboard.next.one-page\": \"Next\",\n \"onboard.next.two-page\": \"Next\",\n \"onboard.next.three-page\": \"Next\",\n \"onboard.skip.one-page\": \"Skip\",\n \"onboard.skip.two-page\": \"Skip\",\n \"onboard.skip.three-page\": \"Skip\",\n \"onboard.allow.four-page\": \"Allow\",\n \"view.onboarding.footer.description\": \"By clicking continue, you will be accepting the Terms of service and privacy policy\",\n \"view.onboarding.btnPrivacy\": \"Privacy Policy\",\n \"view.onboarding.btnTerms\": \"Terms of Service\"\n}\n```\n\n## Reference Example\n\nA complete, valid onboard XML:\n\n```xml\n<Main key=\"c92tR8J5wbTb3fav\" isMain=\"true\" useSafeAreaView=\"true\" description=\"Ekranın ana kapsayıcısı. (#1)\" title=\"Main 1\" styles='{\"paddingBottom\":16}'>\n <StatusBarColor title=\"Status Bar Color\" description=\"Status bar background color.\" styles='{\"backgroundColor\":\"THEME_COLORS.BACKGROUND\"}' />\n <NavigationBarColor title=\"Navigation Bar Color\" description=\"Navigation bar background color.\" styles='{\"backgroundColor\":\"THEME_COLORS.BACKGROUND\"}' />\n <OnboardProvider theme=\"dark\" description=\"Onboarding sağlayıcısı. (#1)\" title=\"OnboardProvider 1\">\n <Onboard description=\"Onboarding ana yapısı. (#1)\" title=\"Onboard 1\" styles='{\"flex\":1}'>\n <OnboardItem key=\"app_onboard-page1\" description=\"Onboarding sayfası. (#1)\" title=\"OnboardItem 1\">\n <OnboardTitle description=\"Sayfa başlığı. (#1)\" title=\"OnboardTitle 1\" styles='{\"color\":\"THEME_COLORS.ONBOARD_TITLE\",\"textAlign\":\"center\",\"marginTop\":40}'>\n onboard.title.one-page\n </OnboardTitle>\n <OnboardImage src=\"https://textcall-dev.s3.amazonaws.com/onboard/high/6c89e0da17a2d6fe2997e97a2b8a00a1.png\" resizeMode=\"contain\" styles='{\"height\":350}' />\n <OnboardSubtitle description=\"Sayfa alt başlığı. (#1)\" title=\"OnboardSubtitle 1\" styles='{\"color\":\"THEME_COLORS.ONBOARD_SUBTITLE\",\"fontSize\":16,\"textAlign\":\"center\"}'>\n onboard.subtitle.one-page\n </OnboardSubtitle>\n </OnboardItem>\n <OnboardItem key=\"app_onboard-page2\" description=\"Onboarding sayfası. (#2)\" title=\"OnboardItem 2\">\n <OnboardTitle description=\"Sayfa başlığı. (#2)\" title=\"OnboardTitle 2\" styles='{\"color\":\"THEME_COLORS.ONBOARD_TITLE\",\"textAlign\":\"center\",\"marginTop\":40}'>\n onboard.title.two-page\n </OnboardTitle>\n <OnboardImage src=\"https://textcall-dev.s3.amazonaws.com/onboard/high/497a627b30ab4a0daaafa3d648a26b07.png\" resizeMode=\"contain\" styles='{\"height\":350}' />\n <OnboardSubtitle description=\"Sayfa alt başlığı. (#2)\" title=\"OnboardSubtitle 2\" styles='{\"color\":\"THEME_COLORS.ONBOARD_SUBTITLE\",\"fontSize\":16,\"textAlign\":\"center\"}'>\n onboard.subtitle.two-page\n </OnboardSubtitle>\n </OnboardItem>\n <OnboardItem key=\"app_onboard-page3\" description=\"Onboarding sayfası. (#3)\" title=\"OnboardItem 3\">\n <OnboardTitle description=\"Sayfa başlığı. (#3)\" title=\"OnboardTitle 3\" styles='{\"color\":\"THEME_COLORS.ONBOARD_TITLE\",\"textAlign\":\"center\",\"marginTop\":40}'>\n onboard.title.three-page\n </OnboardTitle>\n <OnboardImage src=\"https://textcall-dev.s3.amazonaws.com/onboard/high/6e2bc370d38695f6845007fd302034c2.png\" resizeMode=\"contain\" styles='{\"height\":350}' />\n <OnboardSubtitle description=\"Sayfa alt başlığı. (#3)\" title=\"OnboardSubtitle 3\" styles='{\"color\":\"THEME_COLORS.ONBOARD_SUBTITLE\",\"fontSize\":16,\"textAlign\":\"center\"}'>\n onboard.subtitle.three-page\n </OnboardSubtitle>\n </OnboardItem>\n <OnboardItem key=\"app_onboard-page4\" description=\"Onboarding sayfası. (#4)\" title=\"OnboardItem 4\">\n <OnboardTitle description=\"Sayfa başlığı. (#4)\" title=\"OnboardTitle 4\" styles='{\"color\":\"THEME_COLORS.ONBOARD_TITLE\",\"textAlign\":\"center\",\"marginTop\":40}'>\n onboard.title.four-page\n </OnboardTitle>\n <OnboardImage src=\"https://textcall-dev.s3.amazonaws.com/onboard/high/b6e978fe3362e857212163486c22cc7c.png\" resizeMode=\"contain\" styles='{\"height\":350}' />\n <OnboardSubtitle description=\"Sayfa alt başlığı. (#4)\" title=\"OnboardSubtitle 4\" styles='{\"color\":\"THEME_COLORS.ONBOARD_SUBTITLE\",\"fontSize\":16,\"textAlign\":\"center\"}'>\n onboard.subtitle.four-page\n </OnboardSubtitle>\n </OnboardItem>\n </Onboard>\n <OnboardDot dotType=\"expanding_dot\" dot_thickness=\"20\" inactive_dot_opacity=\"0.3\" inactive_dot_color=\"STATIC_COLORS.ONBOARD_DOT_INACTIVE\" active_dot_color=\"STATIC_COLORS.ONBOARD_DOT_ACTIVE\" styles='{\"paddingVertical\":12}' />\n <Separator title=\"Separator\" description=\"Horizontal separator line\" styles='{\"width\":\"100%\",\"height\":2,\"backgroundColor\":\"STATIC_COLORS.ONBOARD_SEPARATOR_COLOR\"}' />\n <OnboardButtons buttons_direction=\"row\" condition=\"carousel-index\" conditionVariable=\"0\" description=\"Sayfa buton grubu. (#1)\" title=\"OnboardButtons 1\" styles='{\"height\":40,\"marginVertical\":12,\"flexShrink\":0}'>\n <OnboardButton labelKey=\"onboard.skip.one-page\" events='[{\"type\":\"Navigate\",\"navigate_to\":null,\"targetIndex\":3}]' styles='{\"flex\":1,\"color\":\"THEME_COLORS.ONBOARD_BUTTON_SECONDARY_TEXT\",\"backgroundColor\":\"STATIC_COLORS.TRANSPARENT\"}' />\n <OnboardButton labelKey=\"onboard.next.one-page\" events='[{\"type\":\"Navigate\",\"navigate_to\":null,\"targetIndex\":1}]' styles='{\"flex\":1,\"color\":\"STATIC_COLORS.WHITE\",\"backgroundColor\":\"STATIC_COLORS.ONBOARD_BUTTON_PRIMARY_BACKGROUND\"}' />\n </OnboardButtons>\n <OnboardButtons buttons_direction=\"row\" condition=\"carousel-index\" conditionVariable=\"1\" description=\"Sayfa buton grubu. (#2)\" title=\"OnboardButtons 2\" styles='{\"height\":40,\"marginVertical\":12,\"flexShrink\":0}'>\n <OnboardButton labelKey=\"onboard.skip.two-page\" events='[{\"type\":\"Permission\",\"permission\":\"att\"},{\"type\":\"Navigate\",\"navigate_to\":null,\"targetIndex\":3}]' styles='{\"flex\":1,\"color\":\"THEME_COLORS.ONBOARD_BUTTON_SECONDARY_TEXT\",\"backgroundColor\":\"STATIC_COLORS.TRANSPARENT\"}' />\n <OnboardButton labelKey=\"onboard.next.two-page\" events='[{\"type\":\"Permission\",\"permission\":\"att\"},{\"type\":\"Navigate\",\"navigate_to\":null,\"targetIndex\":2}]' styles='{\"flex\":1,\"color\":\"STATIC_COLORS.WHITE\",\"backgroundColor\":\"STATIC_COLORS.ONBOARD_BUTTON_PRIMARY_BACKGROUND\"}' />\n </OnboardButtons>\n <OnboardButtons buttons_direction=\"row\" condition=\"carousel-index\" conditionVariable=\"2\" description=\"Sayfa buton grubu. (#3)\" title=\"OnboardButtons 3\" styles='{\"height\":40,\"marginVertical\":12,\"flexShrink\":0}'>\n <OnboardButton labelKey=\"onboard.skip.three-page\" events='[{\"type\":\"Navigate\",\"navigate_to\":null,\"targetIndex\":3}]' styles='{\"flex\":1,\"color\":\"THEME_COLORS.ONBOARD_BUTTON_SECONDARY_TEXT\",\"backgroundColor\":\"STATIC_COLORS.TRANSPARENT\"}' />\n <OnboardButton labelKey=\"onboard.next.three-page\" events='[{\"type\":\"Permission\",\"permission\":\"rating\"},{\"type\":\"Navigate\",\"navigate_to\":null,\"targetIndex\":3}]' styles='{\"flex\":1,\"color\":\"STATIC_COLORS.WHITE\",\"backgroundColor\":\"STATIC_COLORS.ONBOARD_BUTTON_PRIMARY_BACKGROUND\"}' />\n </OnboardButtons>\n <OnboardButtons buttons_direction=\"row\" condition=\"carousel-index\" conditionVariable=\"3\" description=\"Sayfa buton grubu. (#4)\" title=\"OnboardButtons 4\" styles='{\"height\":40,\"marginVertical\":12,\"flexShrink\":0}'>\n <OnboardButton labelKey=\"onboard.allow.four-page\" events='[{\"type\":\"Permission\",\"permission\":\"notification\"},{\"type\":\"Navigate\",\"navigate_to\":\"home\"}]' styles='{\"flex\":1,\"color\":\"STATIC_COLORS.WHITE\",\"backgroundColor\":\"STATIC_COLORS.ONBOARD_BUTTON_PRIMARY_BACKGROUND\"}' />\n </OnboardButtons>\n <View title=\"Onboard Footer Wrap\" description=\"Wrapper for OnboardFooter component\" styles='{\"marginHorizontal\":25,\"flexShrink\":0}'>\n <OnboardFooter textLocalizationKey=\"view.onboarding.footer.description\" linkedWordFirstLocalizationKey=\"view.onboarding.btnPrivacy\" linkedWordFirstColor=\"STATIC_COLORS.ONBOARD_LINK_COLOR\" linkedWordFirstPage=\"privacy\" linkedWordSecondLocalizationKey=\"view.onboarding.btnTerms\" linkedWordSecondColor=\"STATIC_COLORS.ONBOARD_LINK_COLOR\" linkedWordSecondPage=\"terms\" styles='{\"gap\":8,\"color\":\"THEME_COLORS.ONBOARD_FOOTER_TEXT\"}' />\n </View>\n </OnboardProvider>\n</Main>\n```\n\n## Task\n\nGenerate a node tree XML for the user's request below. Output ONLY raw XML — no markdown fences, no explanation.\n";
|