@developer_tribe/react-builder 0.1.27 → 0.1.28
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/RenderPage.d.ts +13 -13
- package/dist/build-components/OnboardFooter/OnboardFooterProps.generated.d.ts +18 -4
- package/dist/build-components/OnboardItem/OnboardItemProps.generated.d.ts +6 -1
- package/dist/build-components/OnboardProvider/OnboardProviderProps.generated.d.ts +4 -0
- package/dist/build-components/OnboardSubtitle/OnboardSubtitleProps.generated.d.ts +23 -1
- package/dist/build-components/OnboardTitle/OnboardTitleProps.generated.d.ts +23 -0
- package/dist/build-components/Text/TextProps.generated.d.ts +23 -0
- package/dist/build-components/View/ViewProps.generated.d.ts +15 -3
- package/dist/build-components/index.d.ts +1 -0
- package/dist/build-components/patterns.generated.d.ts +389 -0
- package/dist/index.cjs.js +28 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.esm.js +28 -1
- package/dist/size-matters/index.d.ts +6 -0
- package/dist/store.d.ts +25 -0
- package/dist/styles.css +1 -1
- package/dist/types/PreviewConfig.d.ts +2 -0
- package/dist/utils/getDevices.d.ts +1 -0
- package/dist/utils/patterns.d.ts +3 -2
- package/package.json +2 -1
- package/scripts/prebuild/build-components.js +2 -0
- package/scripts/prebuild/utils/createBuildComponentsIndex.js +5 -1
- package/scripts/prebuild/utils/createPatternsGenerated.js +23 -0
- package/scripts/prebuild/utils/index.js +1 -0
- package/scripts/prebuild/utils/validateAllComponentsOrThrow.js +126 -1
- package/src/RenderPage.tsx +33 -29
- package/src/build-components/Button/Button.tsx +2 -2
- package/src/build-components/Carousel/Carousel.tsx +2 -2
- package/src/build-components/CarouselButtons/CarouselButtons.tsx +2 -2
- package/src/build-components/CarouselDots/CarouselDots.tsx +2 -2
- package/src/build-components/CarouselItem/CarouselItem.tsx +2 -2
- package/src/build-components/CarouselProvider/CarouselProvider.tsx +2 -2
- package/src/build-components/Image/Image.tsx +2 -3
- package/src/build-components/Onboard/Onboard.tsx +2 -2
- package/src/build-components/OnboardButton/OnboardButton.tsx +7 -4
- package/src/build-components/OnboardButtons/OnboardButtons.tsx +14 -9
- package/src/build-components/OnboardDot/OnboardDot.tsx +2 -2
- package/src/build-components/OnboardFooter/OnboardFooter.tsx +22 -12
- package/src/build-components/OnboardFooter/OnboardFooterProps.generated.ts +29 -4
- package/src/build-components/OnboardFooter/pattern.json +4 -19
- package/src/build-components/OnboardImage/OnboardImage.tsx +2 -2
- package/src/build-components/OnboardItem/OnboardItem.tsx +20 -19
- package/src/build-components/OnboardItem/OnboardItemProps.generated.ts +6 -1
- package/src/build-components/OnboardItem/pattern.json +12 -1
- package/src/build-components/OnboardProvider/OnboardProvider.tsx +15 -12
- package/src/build-components/OnboardProvider/OnboardProviderProps.generated.ts +4 -0
- package/src/build-components/OnboardProvider/pattern.json +11 -1
- package/src/build-components/OnboardSubtitle/OnboardSubtitle.tsx +3 -17
- package/src/build-components/OnboardSubtitle/OnboardSubtitleProps.generated.ts +29 -1
- package/src/build-components/OnboardSubtitle/pattern.json +3 -19
- package/src/build-components/OnboardTitle/OnboardTitle.tsx +4 -17
- package/src/build-components/OnboardTitle/OnboardTitleProps.generated.ts +29 -0
- package/src/build-components/OnboardTitle/pattern.json +5 -19
- package/src/build-components/Text/Text.tsx +21 -9
- package/src/build-components/Text/TextProps.generated.ts +29 -0
- package/src/build-components/Text/pattern.json +1 -0
- package/src/build-components/View/View.tsx +3 -3
- package/src/build-components/View/ViewProps.generated.ts +15 -3
- package/src/build-components/View/pattern.json +15 -3
- package/src/build-components/index.ts +2 -0
- package/src/build-components/patterns.generated.ts +502 -0
- package/src/build-components/useNode.ts +1 -0
- package/src/index.ts +1 -2
- package/src/size-matters/index.ts +64 -0
- package/src/store.ts +56 -0
- package/src/styles/_reset.scss +30 -0
- package/src/styles/index.scss +2 -0
- package/src/types/PreviewConfig.ts +2 -2
- package/src/utils/getDevices.ts +4 -0
- package/src/utils/novaToJson.ts +34 -4
- package/src/utils/patterns.ts +14 -45
- package/dist/RenderMainNode.d.ts +0 -16
- package/src/RenderMainNode.tsx +0 -37
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare function scale(size: number): number;
|
|
2
|
+
export declare function verticalScale(size: number): number;
|
|
3
|
+
export declare const s: typeof scale;
|
|
4
|
+
export declare const vs: typeof verticalScale;
|
|
5
|
+
export declare const fs: typeof verticalScale;
|
|
6
|
+
export declare function parseSize(value?: string | number): string | number | undefined;
|
package/dist/store.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Device } from './types/Device';
|
|
2
|
+
import type { Localication } from './types/PreviewConfig';
|
|
3
|
+
import { ScreenStyle } from './RenderPage';
|
|
4
|
+
type RenderStore = {
|
|
5
|
+
device: Device;
|
|
6
|
+
localication: Localication | null;
|
|
7
|
+
defaultLanguage?: string;
|
|
8
|
+
baseSize: {
|
|
9
|
+
width: number;
|
|
10
|
+
height: number;
|
|
11
|
+
};
|
|
12
|
+
theme: 'dark' | 'light';
|
|
13
|
+
screenStyle: ScreenStyle;
|
|
14
|
+
setBaseSize: (baseSize: {
|
|
15
|
+
width: number;
|
|
16
|
+
height: number;
|
|
17
|
+
}) => void;
|
|
18
|
+
setDevice: (device: Device) => void;
|
|
19
|
+
setLocalication: (localication: Localication | null) => void;
|
|
20
|
+
setDefaultLanguage: (defaultLanguage?: string) => void;
|
|
21
|
+
setTheme: (theme: 'dark' | 'light') => void;
|
|
22
|
+
setScreenStyle: (screenStyle: ScreenStyle) => void;
|
|
23
|
+
};
|
|
24
|
+
export declare const useRenderStore: import("zustand/traditional").UseBoundStoreWithEqualityFn<import("zustand/vanilla").StoreApi<RenderStore>>;
|
|
25
|
+
export {};
|
package/dist/styles.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.embla{max-width:48rem;margin:auto;--slide-height: 19rem;--slide-spacing: 1rem;--slide-size: 70%}.embla__viewport{overflow:hidden}.embla__container{display:flex;touch-action:pan-y pinch-zoom;margin-left:calc(var(--slide-spacing)*-1)}.embla__slide{transform:translate3d(0, 0, 0);flex:0 0 var(--slide-size);min-width:0;padding-left:var(--slide-spacing);flex:0 0 100%}.embla__slide__number{box-shadow:inset 0 0 0 .2rem var(--detail-medium-contrast);border-radius:1.8rem;font-size:4rem;font-weight:600;display:flex;align-items:center;justify-content:center;height:var(--slide-height);user-select:none}.embla__controls{display:grid;grid-template-columns:auto 1fr;justify-content:space-between;gap:1.2rem;margin-top:1.8rem}.embla__buttons{display:grid;grid-template-columns:repeat(2, 1fr);gap:.6rem;align-items:center}.embla__button{-webkit-tap-highlight-color:rgba(var(--text-high-contrast-rgb-value), 0.5);-webkit-appearance:none;appearance:none;background-color:rgba(0,0,0,0);touch-action:manipulation;display:inline-flex;text-decoration:none;cursor:pointer;border:0;padding:0;margin:0;box-shadow:inset 0 0 0 .2rem var(--detail-medium-contrast);width:3.6rem;height:3.6rem;z-index:1;border-radius:50%;color:var(--text-body);display:flex;align-items:center;justify-content:center}.embla__button:disabled{color:var(--detail-high-contrast)}.embla__button__svg{width:35%;height:35%}.embla__dots{display:flex;flex-wrap:wrap;justify-content:center;align-items:center;margin-right:0;height:50px}.embla__dot{-webkit-tap-highlight-color:rgba(var(--text-high-contrast-rgb-value), 0.5);-webkit-appearance:none;appearance:none;background-color:rgba(0,0,0,0);touch-action:manipulation;display:inline-flex;text-decoration:none;cursor:pointer;border:0;padding:0;margin:0;width:2.6rem;height:2.6rem;display:flex;align-items:center;justify-content:center;border-radius:50%}.embla__dot:after{box-shadow:inset 0 0 0 .2rem var(--detail-medium-contrast);width:1.4rem;height:1.4rem;border-radius:50%;display:flex;align-items:center;content:""}.embla__dot--selected:after{box-shadow:inset 0 0 0 .2rem var(--text-body)}.carousel-provider{height:100%}.embla{height:100%}.embla__viewport{height:100%;display:flex;flex-direction:column}.embla__container{flex:1}
|
|
1
|
+
*,*::before,*::after{box-sizing:border-box}html,body,#root{height:100%;margin:0;padding:0}body{background:#fff;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;overflow:hidden}button{font-family:inherit}input,button{font-size:100%}p{margin:0;padding:0}.embla{max-width:48rem;margin:auto;--slide-height: 19rem;--slide-spacing: 1rem;--slide-size: 70%}.embla__viewport{overflow:hidden}.embla__container{display:flex;touch-action:pan-y pinch-zoom;margin-left:calc(var(--slide-spacing)*-1)}.embla__slide{transform:translate3d(0, 0, 0);flex:0 0 var(--slide-size);min-width:0;padding-left:var(--slide-spacing);flex:0 0 100%}.embla__slide__number{box-shadow:inset 0 0 0 .2rem var(--detail-medium-contrast);border-radius:1.8rem;font-size:4rem;font-weight:600;display:flex;align-items:center;justify-content:center;height:var(--slide-height);user-select:none}.embla__controls{display:grid;grid-template-columns:auto 1fr;justify-content:space-between;gap:1.2rem;margin-top:1.8rem}.embla__buttons{display:grid;grid-template-columns:repeat(2, 1fr);gap:.6rem;align-items:center}.embla__button{-webkit-tap-highlight-color:rgba(var(--text-high-contrast-rgb-value), 0.5);-webkit-appearance:none;appearance:none;background-color:rgba(0,0,0,0);touch-action:manipulation;display:inline-flex;text-decoration:none;cursor:pointer;border:0;padding:0;margin:0;box-shadow:inset 0 0 0 .2rem var(--detail-medium-contrast);width:3.6rem;height:3.6rem;z-index:1;border-radius:50%;color:var(--text-body);display:flex;align-items:center;justify-content:center}.embla__button:disabled{color:var(--detail-high-contrast)}.embla__button__svg{width:35%;height:35%}.embla__dots{display:flex;flex-wrap:wrap;justify-content:center;align-items:center;margin-right:0;height:50px}.embla__dot{-webkit-tap-highlight-color:rgba(var(--text-high-contrast-rgb-value), 0.5);-webkit-appearance:none;appearance:none;background-color:rgba(0,0,0,0);touch-action:manipulation;display:inline-flex;text-decoration:none;cursor:pointer;border:0;padding:0;margin:0;width:2.6rem;height:2.6rem;display:flex;align-items:center;justify-content:center;border-radius:50%}.embla__dot:after{box-shadow:inset 0 0 0 .2rem var(--detail-medium-contrast);width:1.4rem;height:1.4rem;border-radius:50%;display:flex;align-items:center;content:""}.embla__dot--selected:after{box-shadow:inset 0 0 0 .2rem var(--text-body)}.carousel-provider{height:100%}.embla{height:100%}.embla__viewport{height:100%;display:flex;flex-direction:column}.embla__container{flex:1}
|
package/dist/utils/patterns.d.ts
CHANGED
|
@@ -2,13 +2,14 @@ import type { NodeDefaultAttribute } from '../types/Node';
|
|
|
2
2
|
type Pattern = {
|
|
3
3
|
schemaVersion: number;
|
|
4
4
|
allowUnknownAttributes: boolean;
|
|
5
|
+
extends: string;
|
|
5
6
|
pattern: {
|
|
6
7
|
type: string;
|
|
7
8
|
children: unknown;
|
|
8
|
-
attributes
|
|
9
|
+
attributes?: Record<string, string | string[]>;
|
|
9
10
|
};
|
|
10
|
-
types?: Record<string, Record<string, string | string[]>>;
|
|
11
11
|
defaults?: NodeDefaultAttribute;
|
|
12
|
+
types?: Record<string, Record<string, string | string[]>>;
|
|
12
13
|
};
|
|
13
14
|
export declare function getPatternByType(type?: string | null): Pattern | undefined;
|
|
14
15
|
export declare function getAttributeSchema(type?: string | null): Record<string, string | string[]> | undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@developer_tribe/react-builder",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.28",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"restricted": true,
|
|
6
6
|
"main": "dist/index.cjs.js",
|
|
@@ -56,6 +56,7 @@
|
|
|
56
56
|
"sass": "^1.93.2",
|
|
57
57
|
"typescript": "^5.9.2",
|
|
58
58
|
"typescript-eslint": "^8.44.1",
|
|
59
|
+
"use-sync-external-store": "^1.6.0",
|
|
59
60
|
"yargs": "^18.0.0"
|
|
60
61
|
},
|
|
61
62
|
"engines": {
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
validateExistingComponentTsx,
|
|
14
14
|
createRenderNodeGenerated,
|
|
15
15
|
createBuildComponentsIndex,
|
|
16
|
+
createPatternsGenerated,
|
|
16
17
|
// createGetDefaultsPerComponent,
|
|
17
18
|
// createBuildComponentsRootGetDefaults,
|
|
18
19
|
formatAllSourceFiles,
|
|
@@ -42,6 +43,7 @@ async function run() {
|
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
await createRenderNodeGenerated(validated, paths);
|
|
46
|
+
await createPatternsGenerated(validated, paths);
|
|
45
47
|
await createBuildComponentsIndex(validated, paths);
|
|
46
48
|
// Removed: root getDefaults generator
|
|
47
49
|
await formatAllSourceFiles(paths);
|
|
@@ -16,7 +16,11 @@ export async function createBuildComponentsIndex(validated, paths) {
|
|
|
16
16
|
|
|
17
17
|
const renderNodeExport = `export { default as RenderNode } from './RenderNode.generated';`;
|
|
18
18
|
|
|
19
|
-
const
|
|
19
|
+
const patternsExport = `export { patterns } from './patterns.generated';`;
|
|
20
|
+
|
|
21
|
+
const sections = [renderNodeExport, patternsExport, exportLines]
|
|
22
|
+
.filter(Boolean)
|
|
23
|
+
.join('\n\n');
|
|
20
24
|
|
|
21
25
|
const fileContent =
|
|
22
26
|
`/* AUTO-GENERATED FILE - DO NOT EDIT */\n\n` +
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { promises as fs } from 'fs';
|
|
3
|
+
import { formatWithPrettier } from './formatWithPrettier.js';
|
|
4
|
+
|
|
5
|
+
// Creates src/build-components/patterns.generated.ts that aggregates all component pattern.json files
|
|
6
|
+
export async function createPatternsGenerated(validated, paths) {
|
|
7
|
+
const { COMPONENTS_ROOT } = paths;
|
|
8
|
+
const targetPath = path.join(COMPONENTS_ROOT, 'patterns.generated.ts');
|
|
9
|
+
|
|
10
|
+
// Use already-validated and resolved patternJson objects and emit inline
|
|
11
|
+
const objectEntries = validated
|
|
12
|
+
.map(({ patternJson }) => JSON.stringify(patternJson))
|
|
13
|
+
.join(',\n ');
|
|
14
|
+
|
|
15
|
+
const fileContent =
|
|
16
|
+
`/* AUTO-GENERATED FILE - DO NOT EDIT */\n` +
|
|
17
|
+
`\n` +
|
|
18
|
+
`// Export resolved patterns (after extends resolution)\n` +
|
|
19
|
+
`export const patterns = [\n ${objectEntries}\n] as const;\n`;
|
|
20
|
+
|
|
21
|
+
const formatted = await formatWithPrettier(fileContent);
|
|
22
|
+
await fs.writeFile(targetPath, formatted, 'utf8');
|
|
23
|
+
}
|
|
@@ -11,6 +11,7 @@ export { ensurePropsTs } from './ensurePropsTs.js';
|
|
|
11
11
|
export { createComponentTsx } from './createComponentTsx.js';
|
|
12
12
|
export { createRenderNodeGenerated } from './createRenderNodeGenerated.js';
|
|
13
13
|
export { createBuildComponentsIndex } from './createBuildComponentsIndex.js';
|
|
14
|
+
export { createPatternsGenerated } from './createPatternsGenerated.js';
|
|
14
15
|
export { formatAllSourceFiles } from './formatAllSourceFiles.js';
|
|
15
16
|
export { validateExistingComponentTsx } from './validateExistingComponentTsx.js';
|
|
16
17
|
export { createGetDefaultsPerComponent } from './createGetDefaultsPerComponent.js';
|
|
@@ -24,7 +24,8 @@ async function getAllEntriesInComponentsRoot(paths) {
|
|
|
24
24
|
d.name !== 'index.ts' &&
|
|
25
25
|
d.name !== 'getDefaults.ts' &&
|
|
26
26
|
d.name !== 'useDefaults.ts' &&
|
|
27
|
-
d.name !== 'useNode.ts'
|
|
27
|
+
d.name !== 'useNode.ts' &&
|
|
28
|
+
d.name !== 'patterns.generated.ts'
|
|
28
29
|
);
|
|
29
30
|
});
|
|
30
31
|
}
|
|
@@ -173,6 +174,130 @@ async function validatePatternJson(componentDir, componentName) {
|
|
|
173
174
|
}
|
|
174
175
|
}
|
|
175
176
|
|
|
177
|
+
// Resolve chained extends: walk up the chain, detect cycles, merge from base to child
|
|
178
|
+
const componentsRoot = path.dirname(componentDir);
|
|
179
|
+
const visited = new Set();
|
|
180
|
+
const ancestorStack = [];
|
|
181
|
+
|
|
182
|
+
// Track both componentName and current type for cycle detection
|
|
183
|
+
visited.add(componentName);
|
|
184
|
+
if (typeof data?.pattern?.type === 'string') visited.add(data.pattern.type);
|
|
185
|
+
|
|
186
|
+
let cursor = data;
|
|
187
|
+
// Collect raw ancestors without mutating child yet
|
|
188
|
+
while (
|
|
189
|
+
typeof cursor?.pattern?.extends === 'string' &&
|
|
190
|
+
cursor.pattern.extends.trim().length > 0
|
|
191
|
+
) {
|
|
192
|
+
const parentName = cursor.pattern.extends.trim();
|
|
193
|
+
if (visited.has(parentName)) {
|
|
194
|
+
return fail(
|
|
195
|
+
`Circular dependency detected in extends chain at '${parentName}'. We don't allow circular dependency.`
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
visited.add(parentName);
|
|
199
|
+
|
|
200
|
+
const parentDir = path.join(componentsRoot, parentName);
|
|
201
|
+
const parentDirExists = await fs
|
|
202
|
+
.stat(parentDir)
|
|
203
|
+
.then(() => true)
|
|
204
|
+
.catch(() => false);
|
|
205
|
+
if (!parentDirExists) {
|
|
206
|
+
return fail(
|
|
207
|
+
`[${componentName}] extends '${parentName}' but folder not found at ${parentDir}`
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
const parentPatternPath = path.join(parentDir, 'pattern.json');
|
|
211
|
+
const parentPatternExists = await fs
|
|
212
|
+
.stat(parentPatternPath)
|
|
213
|
+
.then(() => true)
|
|
214
|
+
.catch(() => false);
|
|
215
|
+
if (!parentPatternExists) {
|
|
216
|
+
return fail(
|
|
217
|
+
`[${componentName}] extends '${parentName}' but missing pattern.json at ${parentPatternPath}`
|
|
218
|
+
);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
let parentData;
|
|
222
|
+
try {
|
|
223
|
+
const parentContent = await fs.readFile(parentPatternPath, 'utf8');
|
|
224
|
+
parentData = JSON.parse(parentContent);
|
|
225
|
+
} catch (error) {
|
|
226
|
+
const reason =
|
|
227
|
+
error instanceof SyntaxError
|
|
228
|
+
? 'Invalid JSON'
|
|
229
|
+
: error.code || error.message;
|
|
230
|
+
return fail(`Failed to read JSON at ${parentPatternPath}: ${reason}`);
|
|
231
|
+
}
|
|
232
|
+
if (typeof parentData?.pattern !== 'object' || parentData.pattern == null) {
|
|
233
|
+
return fail(
|
|
234
|
+
`[${componentName}] extends '${parentName}' but parent pattern.json -> 'pattern' must be an object`
|
|
235
|
+
);
|
|
236
|
+
}
|
|
237
|
+
if (typeof parentData.pattern.type !== 'string') {
|
|
238
|
+
return fail(
|
|
239
|
+
`[${componentName}] extends '${parentName}' but parent pattern.json -> 'pattern.type' must be a string`
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Detect cycle by type name too
|
|
244
|
+
const parentType = parentData.pattern.type;
|
|
245
|
+
if (visited.has(parentType)) {
|
|
246
|
+
return fail(
|
|
247
|
+
`Circular dependency detected in extends chain via type '${parentType}'. We don't allow circular dependency.`
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
visited.add(parentType);
|
|
251
|
+
|
|
252
|
+
ancestorStack.push(parentData);
|
|
253
|
+
cursor = parentData;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Merge from the top-most ancestor down to the child
|
|
257
|
+
for (let i = ancestorStack.length - 1; i >= 0; i -= 1) {
|
|
258
|
+
const parentData = ancestorStack[i];
|
|
259
|
+
const parentAttributes = parentData?.pattern?.attributes || {};
|
|
260
|
+
const childAttributes = data?.pattern?.attributes || {};
|
|
261
|
+
const mergedAttributes = { ...parentAttributes, ...childAttributes };
|
|
262
|
+
|
|
263
|
+
// If child does not define children, inherit parent's
|
|
264
|
+
const childHasChildren = Object.prototype.hasOwnProperty.call(
|
|
265
|
+
data.pattern,
|
|
266
|
+
'children'
|
|
267
|
+
);
|
|
268
|
+
const mergedChildren = childHasChildren
|
|
269
|
+
? data.pattern.children
|
|
270
|
+
: parentData?.pattern?.children;
|
|
271
|
+
|
|
272
|
+
const mergedTypes = { ...(parentData.types || {}), ...(data.types || {}) };
|
|
273
|
+
const mergedDefaults = {
|
|
274
|
+
...(parentData.defaults || {}),
|
|
275
|
+
...(data.defaults || {}),
|
|
276
|
+
};
|
|
277
|
+
const mergedAllowUnknown =
|
|
278
|
+
typeof data.allowUnknownAttributes === 'boolean'
|
|
279
|
+
? data.allowUnknownAttributes
|
|
280
|
+
: parentData.allowUnknownAttributes;
|
|
281
|
+
|
|
282
|
+
const mergedPattern = {
|
|
283
|
+
...parentData.pattern,
|
|
284
|
+
...data.pattern,
|
|
285
|
+
type: data.pattern.type, // keep child's type
|
|
286
|
+
attributes: mergedAttributes,
|
|
287
|
+
children: mergedChildren,
|
|
288
|
+
};
|
|
289
|
+
delete mergedPattern.extends;
|
|
290
|
+
|
|
291
|
+
data = {
|
|
292
|
+
...parentData,
|
|
293
|
+
...data,
|
|
294
|
+
allowUnknownAttributes: mergedAllowUnknown,
|
|
295
|
+
types: mergedTypes,
|
|
296
|
+
defaults: mergedDefaults,
|
|
297
|
+
pattern: mergedPattern,
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
|
|
176
301
|
return data;
|
|
177
302
|
}
|
|
178
303
|
|
package/src/RenderPage.tsx
CHANGED
|
@@ -1,26 +1,24 @@
|
|
|
1
1
|
import { Localication } from './types/PreviewConfig';
|
|
2
2
|
import { TargetedScreenSize } from './types/TargetedScreenSize';
|
|
3
|
-
import { RenderMainNode } from './RenderMainNode';
|
|
4
3
|
import { DeviceMockFrame } from './DeviceMockFrame';
|
|
5
4
|
import { Node } from './types/Node';
|
|
6
5
|
import { RenderNode } from './build-components';
|
|
7
6
|
import { Device } from './types/Device';
|
|
8
|
-
import {
|
|
7
|
+
import { useEffect } from 'react';
|
|
8
|
+
import { useRenderStore } from './store';
|
|
9
|
+
export type ScreenStyle = {
|
|
10
|
+
light: { backgroundColor: string; color: string; seperatorColor?: string };
|
|
11
|
+
dark: { backgroundColor: string; color: string; seperatorColor?: string };
|
|
12
|
+
};
|
|
9
13
|
type RenderPageProps = {
|
|
10
14
|
data: Node;
|
|
11
15
|
isRtl: boolean;
|
|
12
|
-
screenStyle:
|
|
13
|
-
light: { backgroundColor: string; color: string };
|
|
14
|
-
dark: { backgroundColor: string; color: string };
|
|
15
|
-
};
|
|
16
|
+
screenStyle: ScreenStyle;
|
|
16
17
|
theme: 'dark' | 'light';
|
|
17
18
|
localication: Localication;
|
|
18
19
|
defaultLanguage?: string;
|
|
19
20
|
device: Device;
|
|
20
21
|
};
|
|
21
|
-
export const renderPageContext = createContext<{
|
|
22
|
-
device: Device;
|
|
23
|
-
} | null>(null);
|
|
24
22
|
export function RenderPage({
|
|
25
23
|
data,
|
|
26
24
|
theme,
|
|
@@ -36,26 +34,32 @@ export function RenderPage({
|
|
|
36
34
|
// width = (previewHeight * targetWidth) / targetHeight
|
|
37
35
|
const height = screenPreviewHeight;
|
|
38
36
|
const width = (height * device.width) / device.height;
|
|
37
|
+
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
const {
|
|
40
|
+
setDevice,
|
|
41
|
+
setLocalication,
|
|
42
|
+
setDefaultLanguage,
|
|
43
|
+
setTheme,
|
|
44
|
+
setScreenStyle,
|
|
45
|
+
} = useRenderStore.getState();
|
|
46
|
+
setDevice(device);
|
|
47
|
+
setLocalication(localication);
|
|
48
|
+
setDefaultLanguage(defaultLanguage);
|
|
49
|
+
setTheme(theme);
|
|
50
|
+
setScreenStyle(screenStyle);
|
|
51
|
+
}, [device, localication, defaultLanguage, theme, screenStyle]);
|
|
52
|
+
|
|
39
53
|
return (
|
|
40
|
-
<
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
<RenderMainNode
|
|
51
|
-
localication={localication}
|
|
52
|
-
defaultLanguage={defaultLanguage}
|
|
53
|
-
theme={theme}
|
|
54
|
-
>
|
|
55
|
-
<RenderNode node={data} />
|
|
56
|
-
</RenderMainNode>
|
|
57
|
-
}
|
|
58
|
-
</DeviceMockFrame>
|
|
59
|
-
</renderPageContext.Provider>
|
|
54
|
+
<DeviceMockFrame
|
|
55
|
+
width={width}
|
|
56
|
+
height={height}
|
|
57
|
+
isRtl={isRtl}
|
|
58
|
+
screenStyle={screenStyle}
|
|
59
|
+
theme={theme}
|
|
60
|
+
device={device}
|
|
61
|
+
>
|
|
62
|
+
<RenderNode node={data} />
|
|
63
|
+
</DeviceMockFrame>
|
|
60
64
|
);
|
|
61
65
|
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { ButtonComponentProps } from './ButtonProps.generated';
|
|
3
|
-
import
|
|
3
|
+
import useNode from '../useNode';
|
|
4
4
|
|
|
5
5
|
function Button({ node }: ButtonComponentProps) {
|
|
6
|
-
node =
|
|
6
|
+
node = useNode(node);
|
|
7
7
|
return String(node?.type ?? 'button');
|
|
8
8
|
}
|
|
9
9
|
|
|
@@ -2,10 +2,10 @@ import React from 'react';
|
|
|
2
2
|
import type { CarouselComponentProps } from './CarouselProps.generated';
|
|
3
3
|
import RenderNode from '../RenderNode.generated';
|
|
4
4
|
import { isCarouselItem } from '../../utils/isCarousel';
|
|
5
|
-
import
|
|
5
|
+
import useNode from '../useNode';
|
|
6
6
|
|
|
7
7
|
function Carousel({ node }: CarouselComponentProps) {
|
|
8
|
-
node =
|
|
8
|
+
node = useNode(node);
|
|
9
9
|
// Ensure children are carouselItems
|
|
10
10
|
const renderChildren = () => {
|
|
11
11
|
if (Array.isArray(node.children)) {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import React, { useContext } from 'react';
|
|
2
2
|
import type { CarouselButtonsComponentProps } from './CarouselButtonsProps.generated';
|
|
3
3
|
import { carouselContext } from '../CarouselProvider/CarouselProvider';
|
|
4
|
-
import
|
|
4
|
+
import useNode from '../useNode';
|
|
5
5
|
|
|
6
6
|
function CarouselButtons({ node }: CarouselButtonsComponentProps) {
|
|
7
|
-
node =
|
|
7
|
+
node = useNode(node);
|
|
8
8
|
const emblaApi = useContext(carouselContext);
|
|
9
9
|
const buttonTypes = node.attributes?.buttonType || [
|
|
10
10
|
'previous_button',
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import React, { useContext, useEffect, useState } from 'react';
|
|
2
2
|
import type { CarouselDotsComponentProps } from './CarouselDotsProps.generated';
|
|
3
3
|
import { carouselContext } from '../CarouselProvider/CarouselProvider';
|
|
4
|
-
import
|
|
4
|
+
import useNode from '../useNode';
|
|
5
5
|
|
|
6
6
|
function CarouselDots({ node }: CarouselDotsComponentProps) {
|
|
7
|
-
node =
|
|
7
|
+
node = useNode(node);
|
|
8
8
|
const dotType = node.attributes?.dotType || 'normal_dot';
|
|
9
9
|
const emblaApi = useContext(carouselContext);
|
|
10
10
|
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { CarouselItemComponentProps } from './CarouselItemProps.generated';
|
|
3
3
|
import { RenderNode } from '../..';
|
|
4
|
-
import
|
|
4
|
+
import useNode from '../useNode';
|
|
5
5
|
|
|
6
6
|
export function CarouselItem({ node }: CarouselItemComponentProps) {
|
|
7
|
-
node =
|
|
7
|
+
node = useNode(node);
|
|
8
8
|
return (
|
|
9
9
|
<div className="embla__slide" {...node.attributes}>
|
|
10
10
|
{node.children && <RenderNode node={node.children} />}
|
|
@@ -2,11 +2,11 @@ import React, { createContext } from 'react';
|
|
|
2
2
|
import type { CarouselProviderComponentProps } from './CarouselProviderProps.generated';
|
|
3
3
|
import { RenderNode } from '../..';
|
|
4
4
|
import useEmblaCarousel from 'embla-carousel-react';
|
|
5
|
-
import
|
|
5
|
+
import useNode from '../useNode';
|
|
6
6
|
|
|
7
7
|
export const carouselContext = createContext<any>(undefined);
|
|
8
8
|
function CarouselProvider({ node }: CarouselProviderComponentProps) {
|
|
9
|
-
node =
|
|
9
|
+
node = useNode(node);
|
|
10
10
|
const [emblaRef, emblaApi] = useEmblaCarousel(node.attributes as any);
|
|
11
11
|
return (
|
|
12
12
|
<carouselContext.Provider value={emblaApi}>
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { ImageComponentProps } from './ImageProps.generated';
|
|
3
|
-
import
|
|
3
|
+
import useNode from '../useNode';
|
|
4
4
|
|
|
5
5
|
function Image({ node }: ImageComponentProps) {
|
|
6
|
-
node =
|
|
6
|
+
node = useNode(node);
|
|
7
7
|
return (
|
|
8
8
|
<img
|
|
9
9
|
key={node.key}
|
|
10
|
-
className="primitive primitive-image"
|
|
11
10
|
src={node.attributes?.src}
|
|
12
11
|
width={node.attributes?.width}
|
|
13
12
|
height={node.attributes?.height}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { OnboardComponentProps } from './OnboardProps.generated';
|
|
3
3
|
import Carousel from '../Carousel/Carousel';
|
|
4
|
-
import
|
|
4
|
+
import useNode from '../useNode';
|
|
5
5
|
|
|
6
6
|
function Onboard({ node }: OnboardComponentProps) {
|
|
7
|
-
node =
|
|
7
|
+
node = useNode(node);
|
|
8
8
|
return <Carousel node={{ ...node, type: 'carousel' } as any} />;
|
|
9
9
|
}
|
|
10
10
|
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import React, { useContext } from 'react';
|
|
2
2
|
import type { OnboardButtonComponentProps } from './OnboardButtonProps.generated';
|
|
3
3
|
import { onboardContext } from '../OnboardProvider/OnboardProvider';
|
|
4
|
-
import
|
|
5
|
-
import
|
|
4
|
+
import useNode from '../useNode';
|
|
5
|
+
import { useRenderStore } from '../../store';
|
|
6
6
|
|
|
7
7
|
function OnboardButton({ node }: OnboardButtonComponentProps) {
|
|
8
|
-
node =
|
|
8
|
+
node = useNode(node);
|
|
9
9
|
const { emblaApi } = useContext(onboardContext) ?? {};
|
|
10
|
-
const {
|
|
10
|
+
const { defaultLanguage, localication } = useRenderStore((s) => ({
|
|
11
|
+
defaultLanguage: s.defaultLanguage,
|
|
12
|
+
localication: s.localication,
|
|
13
|
+
}));
|
|
11
14
|
|
|
12
15
|
const labelRaw = node.attributes?.labelKey ?? '';
|
|
13
16
|
const label =
|
|
@@ -3,14 +3,19 @@ import type { Node } from '../../types/Node';
|
|
|
3
3
|
import type { OnboardButtonsComponentProps } from './OnboardButtonsProps.generated';
|
|
4
4
|
import { onboardContext } from '../OnboardProvider/OnboardProvider';
|
|
5
5
|
import RenderNode from '../RenderNode.generated';
|
|
6
|
-
import
|
|
7
|
-
|
|
8
|
-
const THEME_COLORS = {
|
|
9
|
-
ONBOARD_SEPARATOR_COLOR: '#E5E7EB',
|
|
10
|
-
};
|
|
6
|
+
import useNode from '../useNode';
|
|
7
|
+
import { useRenderStore } from '../../store';
|
|
11
8
|
|
|
12
9
|
function OnboardButtons({ node }: OnboardButtonsComponentProps) {
|
|
13
|
-
node =
|
|
10
|
+
node = useNode(node);
|
|
11
|
+
const { screenStyle, theme } = useRenderStore((s) => ({
|
|
12
|
+
screenStyle: s.screenStyle,
|
|
13
|
+
theme: s.theme,
|
|
14
|
+
}));
|
|
15
|
+
const seperatorColorDefault =
|
|
16
|
+
theme === 'light'
|
|
17
|
+
? screenStyle.light.seperatorColor
|
|
18
|
+
: screenStyle.dark.seperatorColor;
|
|
14
19
|
const ctx = useContext(onboardContext) ?? {};
|
|
15
20
|
const emblaApi = ctx.emblaApi;
|
|
16
21
|
const [selectedIndex, setSelectedIndex] = useState(ctx.selectedIndex ?? 0);
|
|
@@ -30,7 +35,8 @@ function OnboardButtons({ node }: OnboardButtonsComponentProps) {
|
|
|
30
35
|
|
|
31
36
|
const direction =
|
|
32
37
|
node.attributes?.buttons_direction === 'column' ? 'column' : 'row';
|
|
33
|
-
const seperatorColor =
|
|
38
|
+
const seperatorColor =
|
|
39
|
+
node.attributes?.seperatorColor ?? seperatorColorDefault;
|
|
34
40
|
|
|
35
41
|
const renderChildren = () => {
|
|
36
42
|
if (Array.isArray(node.children)) {
|
|
@@ -47,8 +53,7 @@ function OnboardButtons({ node }: OnboardButtonsComponentProps) {
|
|
|
47
53
|
className="onboard__separator"
|
|
48
54
|
style={{
|
|
49
55
|
height: 1,
|
|
50
|
-
backgroundColor:
|
|
51
|
-
seperatorColor ?? THEME_COLORS.ONBOARD_SEPARATOR_COLOR,
|
|
56
|
+
backgroundColor: seperatorColor,
|
|
52
57
|
width: '100%',
|
|
53
58
|
}}
|
|
54
59
|
/>
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { OnboardDotComponentProps } from './OnboardExpandingDotProps.generated';
|
|
3
3
|
import CarouselDots from '../CarouselDots/CarouselDots';
|
|
4
|
-
import
|
|
4
|
+
import useNode from '../useNode';
|
|
5
5
|
|
|
6
6
|
function OnboardDot({ node }: OnboardDotComponentProps) {
|
|
7
|
-
node =
|
|
7
|
+
node = useNode(node);
|
|
8
8
|
return <CarouselDots node={{ ...node, type: 'carouselDots' } as any} />;
|
|
9
9
|
}
|
|
10
10
|
|