@developer_tribe/react-builder 0.1.25 → 0.1.27
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/DeviceMockFrame.d.ts +22 -0
- package/dist/RenderPage.d.ts +6 -3
- package/dist/build-components/OnboardProvider/OnboardProviderProps.generated.d.ts +4 -1
- package/dist/build-components/OnboardSubtitle/OnboardSubtitleProps.generated.d.ts +1 -0
- package/dist/build-components/index.d.ts +0 -1
- package/dist/build-components/useNode.d.ts +2 -0
- package/dist/index.cjs.js +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.esm.js +1 -1
- package/dist/types/Device.d.ts +16 -0
- package/dist/types/Node.d.ts +2 -1
- package/dist/types/Project.d.ts +1 -1
- package/dist/utils/patterns.d.ts +4 -0
- package/package.json +1 -1
- package/scripts/prebuild/build-components.js +4 -4
- package/scripts/prebuild/utils/createBuildComponentsIndex.js +1 -4
- package/scripts/prebuild/utils/createBuildComponentsRootGetDefaults.js +2 -55
- package/scripts/prebuild/utils/createGetDefaultsPerComponent.js +2 -19
- package/scripts/prebuild/utils/createRootGetDefaults.js +2 -44
- package/scripts/prebuild/utils/validateAllComponentsOrThrow.js +3 -1
- package/src/AttributesEditor.tsx +19 -15
- package/src/DeviceMockFrame.tsx +119 -0
- package/src/RenderPage.tsx +19 -27
- package/src/assets/devices.json +364 -91
- package/src/assets/samples/getSamples.ts +5 -1
- package/src/build-components/Button/Button.tsx +2 -0
- package/src/build-components/Carousel/Carousel.tsx +2 -0
- package/src/build-components/CarouselButtons/CarouselButtons.tsx +2 -0
- package/src/build-components/CarouselDots/CarouselDots.tsx +2 -0
- package/src/build-components/CarouselItem/CarouselItem.tsx +2 -0
- package/src/build-components/CarouselProvider/CarouselProvider.tsx +2 -0
- package/src/build-components/Image/Image.tsx +2 -0
- package/src/build-components/Onboard/Onboard.tsx +2 -0
- package/src/build-components/OnboardButton/OnboardButton.tsx +2 -0
- package/src/build-components/OnboardButtons/OnboardButtons.tsx +2 -0
- package/src/build-components/OnboardDot/OnboardDot.tsx +2 -0
- package/src/build-components/OnboardFooter/OnboardFooter.tsx +2 -0
- package/src/build-components/OnboardImage/OnboardImage.tsx +2 -0
- package/src/build-components/OnboardItem/OnboardItem.tsx +2 -0
- package/src/build-components/OnboardProvider/OnboardProvider.tsx +13 -1
- package/src/build-components/OnboardProvider/OnboardProviderProps.generated.ts +4 -1
- package/src/build-components/OnboardProvider/pattern.json +4 -1
- package/src/build-components/OnboardSubtitle/OnboardSubtitle.tsx +2 -0
- package/src/build-components/OnboardSubtitle/OnboardSubtitleProps.generated.ts +1 -0
- package/src/build-components/OnboardSubtitle/pattern.json +2 -1
- package/src/build-components/OnboardTitle/OnboardTitle.tsx +2 -0
- package/src/build-components/OnboardTitle/pattern.json +1 -1
- package/src/build-components/Text/Text.tsx +2 -0
- package/src/build-components/View/View.tsx +2 -0
- package/src/build-components/index.ts +0 -2
- package/src/build-components/useNode.ts +15 -0
- package/src/index.ts +2 -0
- package/src/types/Device.ts +21 -0
- package/src/types/Node.ts +2 -11
- package/src/types/Project.ts +1 -1
- package/src/utils/novaToJson.ts +166 -3
- package/src/utils/patterns.ts +11 -0
- package/dist/build-components/Button/getDefaults.d.ts +0 -3
- package/dist/build-components/Carousel/getDefaults.d.ts +0 -3
- package/dist/build-components/CarouselButtons/getDefaults.d.ts +0 -3
- package/dist/build-components/CarouselDots/getDefaults.d.ts +0 -3
- package/dist/build-components/CarouselItem/getDefaults.d.ts +0 -3
- package/dist/build-components/CarouselProvider/getDefaults.d.ts +0 -3
- package/dist/build-components/Image/getDefaults.d.ts +0 -3
- package/dist/build-components/Onboard/getDefaults.d.ts +0 -3
- package/dist/build-components/OnboardButton/getDefaults.d.ts +0 -3
- package/dist/build-components/OnboardButtons/getDefaults.d.ts +0 -3
- package/dist/build-components/OnboardDot/getDefaults.d.ts +0 -3
- package/dist/build-components/OnboardFooter/getDefaults.d.ts +0 -3
- package/dist/build-components/OnboardImage/getDefaults.d.ts +0 -3
- package/dist/build-components/OnboardItem/getDefaults.d.ts +0 -3
- package/dist/build-components/OnboardProvider/getDefaults.d.ts +0 -3
- package/dist/build-components/OnboardSubtitle/getDefaults.d.ts +0 -3
- package/dist/build-components/OnboardTitle/getDefaults.d.ts +0 -3
- package/dist/build-components/Text/getDefaults.d.ts +0 -3
- package/dist/build-components/View/getDefaults.d.ts +0 -3
- package/dist/build-components/getDefaults.d.ts +0 -25
- package/src/build-components/Button/getDefaults.ts +0 -11
- package/src/build-components/Carousel/getDefaults.ts +0 -11
- package/src/build-components/CarouselButtons/getDefaults.ts +0 -13
- package/src/build-components/CarouselDots/getDefaults.ts +0 -13
- package/src/build-components/CarouselItem/getDefaults.ts +0 -13
- package/src/build-components/CarouselProvider/getDefaults.ts +0 -13
- package/src/build-components/Image/getDefaults.ts +0 -11
- package/src/build-components/Onboard/getDefaults.ts +0 -11
- package/src/build-components/OnboardButton/getDefaults.ts +0 -13
- package/src/build-components/OnboardButtons/getDefaults.ts +0 -13
- package/src/build-components/OnboardDot/getDefaults.ts +0 -13
- package/src/build-components/OnboardFooter/getDefaults.ts +0 -13
- package/src/build-components/OnboardImage/getDefaults.ts +0 -13
- package/src/build-components/OnboardItem/getDefaults.ts +0 -13
- package/src/build-components/OnboardProvider/getDefaults.ts +0 -13
- package/src/build-components/OnboardSubtitle/getDefaults.ts +0 -13
- package/src/build-components/OnboardTitle/getDefaults.ts +0 -13
- package/src/build-components/Text/getDefaults.ts +0 -11
- package/src/build-components/View/getDefaults.ts +0 -11
- package/src/build-components/getDefaults.ts +0 -149
|
@@ -32,10 +32,14 @@ export function getBasicSamples(): Project[] {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
export function getOnboardSamples(): Project[] {
|
|
35
|
-
|
|
35
|
+
const legacySamples = [
|
|
36
36
|
vpnOnboard1 as Project,
|
|
37
37
|
vpnOnboard2 as Project,
|
|
38
38
|
vpnOnboard3 as Project,
|
|
39
39
|
vpnOnboard4 as Project,
|
|
40
40
|
];
|
|
41
|
+
legacySamples.forEach((sample) => {
|
|
42
|
+
sample.data = novaToJson(sample);
|
|
43
|
+
});
|
|
44
|
+
return legacySamples;
|
|
41
45
|
}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { ButtonComponentProps } from './ButtonProps.generated';
|
|
3
|
+
import useDefaults from '../useNode';
|
|
3
4
|
|
|
4
5
|
function Button({ node }: ButtonComponentProps) {
|
|
6
|
+
node = useDefaults(node);
|
|
5
7
|
return String(node?.type ?? 'button');
|
|
6
8
|
}
|
|
7
9
|
|
|
@@ -2,8 +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 useDefaults from '../useNode';
|
|
5
6
|
|
|
6
7
|
function Carousel({ node }: CarouselComponentProps) {
|
|
8
|
+
node = useDefaults(node);
|
|
7
9
|
// Ensure children are carouselItems
|
|
8
10
|
const renderChildren = () => {
|
|
9
11
|
if (Array.isArray(node.children)) {
|
|
@@ -1,8 +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 useDefaults from '../useNode';
|
|
4
5
|
|
|
5
6
|
function CarouselButtons({ node }: CarouselButtonsComponentProps) {
|
|
7
|
+
node = useDefaults(node);
|
|
6
8
|
const emblaApi = useContext(carouselContext);
|
|
7
9
|
const buttonTypes = node.attributes?.buttonType || [
|
|
8
10
|
'previous_button',
|
|
@@ -1,8 +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 useDefaults from '../useNode';
|
|
4
5
|
|
|
5
6
|
function CarouselDots({ node }: CarouselDotsComponentProps) {
|
|
7
|
+
node = useDefaults(node);
|
|
6
8
|
const dotType = node.attributes?.dotType || 'normal_dot';
|
|
7
9
|
const emblaApi = useContext(carouselContext);
|
|
8
10
|
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { CarouselItemComponentProps } from './CarouselItemProps.generated';
|
|
3
3
|
import { RenderNode } from '../..';
|
|
4
|
+
import useDefaults from '../useNode';
|
|
4
5
|
|
|
5
6
|
export function CarouselItem({ node }: CarouselItemComponentProps) {
|
|
7
|
+
node = useDefaults(node);
|
|
6
8
|
return (
|
|
7
9
|
<div className="embla__slide" {...node.attributes}>
|
|
8
10
|
{node.children && <RenderNode node={node.children} />}
|
|
@@ -2,9 +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 useDefaults from '../useNode';
|
|
5
6
|
|
|
6
7
|
export const carouselContext = createContext<any>(undefined);
|
|
7
8
|
function CarouselProvider({ node }: CarouselProviderComponentProps) {
|
|
9
|
+
node = useDefaults(node);
|
|
8
10
|
const [emblaRef, emblaApi] = useEmblaCarousel(node.attributes as any);
|
|
9
11
|
return (
|
|
10
12
|
<carouselContext.Provider value={emblaApi}>
|
|
@@ -1,8 +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 useDefaults from '../useNode';
|
|
4
5
|
|
|
5
6
|
function Onboard({ node }: OnboardComponentProps) {
|
|
7
|
+
node = useDefaults(node);
|
|
6
8
|
return <Carousel node={{ ...node, type: 'carousel' } as any} />;
|
|
7
9
|
}
|
|
8
10
|
|
|
@@ -2,8 +2,10 @@ import React, { useContext } from 'react';
|
|
|
2
2
|
import type { OnboardButtonComponentProps } from './OnboardButtonProps.generated';
|
|
3
3
|
import { onboardContext } from '../OnboardProvider/OnboardProvider';
|
|
4
4
|
import { mainNodeContext } from '../../RenderMainNode';
|
|
5
|
+
import useDefaults from '../useNode';
|
|
5
6
|
|
|
6
7
|
function OnboardButton({ node }: OnboardButtonComponentProps) {
|
|
8
|
+
node = useDefaults(node);
|
|
7
9
|
const { emblaApi } = useContext(onboardContext) ?? {};
|
|
8
10
|
const { localication, defaultLanguage } = useContext(mainNodeContext) ?? {};
|
|
9
11
|
|
|
@@ -3,12 +3,14 @@ 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 useDefaults from '../useNode';
|
|
6
7
|
|
|
7
8
|
const THEME_COLORS = {
|
|
8
9
|
ONBOARD_SEPARATOR_COLOR: '#E5E7EB',
|
|
9
10
|
};
|
|
10
11
|
|
|
11
12
|
function OnboardButtons({ node }: OnboardButtonsComponentProps) {
|
|
13
|
+
node = useDefaults(node);
|
|
12
14
|
const ctx = useContext(onboardContext) ?? {};
|
|
13
15
|
const emblaApi = ctx.emblaApi;
|
|
14
16
|
const [selectedIndex, setSelectedIndex] = useState(ctx.selectedIndex ?? 0);
|
|
@@ -1,8 +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 useDefaults from '../useNode';
|
|
4
5
|
|
|
5
6
|
function OnboardDot({ node }: OnboardDotComponentProps) {
|
|
7
|
+
node = useDefaults(node);
|
|
6
8
|
return <CarouselDots node={{ ...node, type: 'carouselDots' } as any} />;
|
|
7
9
|
}
|
|
8
10
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React, { useContext } from 'react';
|
|
2
2
|
import type { OnboardFooterComponentProps } from './OnboardFooterProps.generated';
|
|
3
3
|
import { mainNodeContext } from '../../RenderMainNode';
|
|
4
|
+
import useDefaults from '../useNode';
|
|
4
5
|
|
|
5
6
|
type Segment =
|
|
6
7
|
| { type: 'text'; value: string }
|
|
@@ -83,6 +84,7 @@ function buildSegments(
|
|
|
83
84
|
}
|
|
84
85
|
|
|
85
86
|
function OnboardFooter({ node }: OnboardFooterComponentProps) {
|
|
87
|
+
node = useDefaults(node);
|
|
86
88
|
const { localication, defaultLanguage, setWarning } =
|
|
87
89
|
useContext(mainNodeContext) ?? {};
|
|
88
90
|
const t = (key?: string) =>
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { OnboardImageComponentProps } from './OnboardImageProps.generated';
|
|
3
3
|
import Image from '../Image/Image';
|
|
4
|
+
import useDefaults from '../useNode';
|
|
4
5
|
|
|
5
6
|
function OnboardImage({ node }: OnboardImageComponentProps) {
|
|
7
|
+
node = useDefaults(node);
|
|
6
8
|
return <Image node={{ ...node, type: 'image' } as any} />;
|
|
7
9
|
}
|
|
8
10
|
|
|
@@ -3,8 +3,10 @@ import type { NodeData } from '../../types/Node';
|
|
|
3
3
|
import type { OnboardItemComponentProps } from './OnboardItemProps.generated';
|
|
4
4
|
import CarouselItem from '../CarouselItem/CarouselItem';
|
|
5
5
|
import { isNodeArray } from '../../utils/analyseNode';
|
|
6
|
+
import useDefaults from '../useNode';
|
|
6
7
|
|
|
7
8
|
function OnboardItem({ node }: OnboardItemComponentProps) {
|
|
9
|
+
node = useDefaults(node);
|
|
8
10
|
const children = useMemo(() => {
|
|
9
11
|
return (
|
|
10
12
|
(
|
|
@@ -10,9 +10,13 @@ import type { OnboardProviderComponentProps } from './OnboardProviderProps.gener
|
|
|
10
10
|
import { mainNodeContext } from '../../RenderMainNode';
|
|
11
11
|
import useEmblaCarousel from 'embla-carousel-react';
|
|
12
12
|
import RenderNode from '../RenderNode.generated';
|
|
13
|
+
import { renderPageContext } from '../../RenderPage';
|
|
14
|
+
import useDefaults from '../useNode';
|
|
13
15
|
|
|
14
16
|
export const onboardContext = createContext<any>(undefined);
|
|
15
17
|
function OnboardProvider({ node }: OnboardProviderComponentProps) {
|
|
18
|
+
node = useDefaults(node);
|
|
19
|
+
const { device } = useContext(renderPageContext) ?? {};
|
|
16
20
|
const [emblaRef, emblaApi] = useEmblaCarousel(node.attributes as any);
|
|
17
21
|
const { theme, setWarning } = useContext(mainNodeContext) ?? {};
|
|
18
22
|
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
@@ -49,7 +53,15 @@ function OnboardProvider({ node }: OnboardProviderComponentProps) {
|
|
|
49
53
|
|
|
50
54
|
return (
|
|
51
55
|
<onboardContext.Provider value={{ emblaApi, selectedIndex }}>
|
|
52
|
-
<div
|
|
56
|
+
<div
|
|
57
|
+
className="carousel-provider"
|
|
58
|
+
style={{
|
|
59
|
+
paddingTop: device?.insets?.[0],
|
|
60
|
+
paddingRight: device?.insets?.[1],
|
|
61
|
+
paddingBottom: device?.insets?.[2],
|
|
62
|
+
paddingLeft: device?.insets?.[3],
|
|
63
|
+
}}
|
|
64
|
+
>
|
|
53
65
|
<div className="embla">
|
|
54
66
|
<div className="embla__viewport" ref={emblaRef}>
|
|
55
67
|
{node.children && <RenderNode node={children} />}
|
|
@@ -4,7 +4,10 @@ import type { NodeData } from '../../types/Node';
|
|
|
4
4
|
|
|
5
5
|
export interface OnboardProviderPropsGenerated {
|
|
6
6
|
child: string;
|
|
7
|
-
attributes: {
|
|
7
|
+
attributes: {
|
|
8
|
+
theme?: string;
|
|
9
|
+
use_safe_area_inset?: boolean;
|
|
10
|
+
};
|
|
8
11
|
}
|
|
9
12
|
|
|
10
13
|
export interface OnboardProviderComponentProps {
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { OnboardSubtitleComponentProps } from './OnboardSubtitleProps.generated';
|
|
3
3
|
import Text from '../Text/Text';
|
|
4
|
+
import useDefaults from '../useNode';
|
|
4
5
|
|
|
5
6
|
function OnboardSubtitle({ node }: OnboardSubtitleComponentProps) {
|
|
7
|
+
node = useDefaults(node);
|
|
6
8
|
return (
|
|
7
9
|
<Text
|
|
8
10
|
node={
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
"attributes": {
|
|
8
8
|
"color": "string",
|
|
9
9
|
"fontSize": "number",
|
|
10
|
+
"textAlign": ["left", "center", "right", "justify"],
|
|
10
11
|
"fontWeight": [
|
|
11
12
|
"normal",
|
|
12
13
|
"bold",
|
|
@@ -22,7 +23,7 @@
|
|
|
22
23
|
]
|
|
23
24
|
}
|
|
24
25
|
},
|
|
25
|
-
"
|
|
26
|
+
"defaults": {
|
|
26
27
|
"fontSize": 14,
|
|
27
28
|
"fontWeight": "600"
|
|
28
29
|
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { OnboardTitleComponentProps } from './OnboardTitleProps.generated';
|
|
3
3
|
import Text from '../Text/Text';
|
|
4
|
+
import useDefaults from '../useNode';
|
|
4
5
|
|
|
5
6
|
function OnboardTitle({ node }: OnboardTitleComponentProps) {
|
|
7
|
+
node = useDefaults(node);
|
|
6
8
|
return (
|
|
7
9
|
<Text
|
|
8
10
|
node={
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import React, { useContext } from 'react';
|
|
2
2
|
import type { TextComponentProps } from './TextProps.generated';
|
|
3
3
|
import { mainNodeContext } from '../../RenderMainNode';
|
|
4
|
+
import useDefaults from '../useNode';
|
|
4
5
|
|
|
5
6
|
function Text({ node }: TextComponentProps) {
|
|
7
|
+
node = useDefaults(node);
|
|
6
8
|
const { localication, defaultLanguage } = useContext(mainNodeContext) ?? {};
|
|
7
9
|
const keyOrText: string = node.children as string;
|
|
8
10
|
return (
|
|
@@ -5,6 +5,7 @@ import type {
|
|
|
5
5
|
} from './ViewProps.generated';
|
|
6
6
|
import RenderNode from '../RenderNode.generated';
|
|
7
7
|
import { Node } from '../../types/Node';
|
|
8
|
+
import useDefaults from '../useNode';
|
|
8
9
|
|
|
9
10
|
function mapAttributesToStyle(
|
|
10
11
|
attributes: ViewPropsGenerated['attributes'],
|
|
@@ -48,6 +49,7 @@ function mapAttributesToStyle(
|
|
|
48
49
|
}
|
|
49
50
|
|
|
50
51
|
export function View({ node }: ViewComponentProps) {
|
|
52
|
+
node = useDefaults(node);
|
|
51
53
|
return (
|
|
52
54
|
<div
|
|
53
55
|
style={mapAttributesToStyle(node.attributes ?? {})}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { NodeData, NodeDefaultAttribute } from '../types/Node';
|
|
2
|
+
import { getDefaultsForType } from '../utils/patterns';
|
|
3
|
+
|
|
4
|
+
export default function useNode<
|
|
5
|
+
T extends NodeDefaultAttribute = NodeDefaultAttribute,
|
|
6
|
+
>(node: NodeData<T>): NodeData<T> {
|
|
7
|
+
const type = node?.type;
|
|
8
|
+
const defaults = getDefaultsForType(type) as Partial<T> | undefined;
|
|
9
|
+
if (!defaults) return node;
|
|
10
|
+
const mergedAttributes: T = {
|
|
11
|
+
...(defaults as T),
|
|
12
|
+
...((node.attributes as T) ?? ({} as T)),
|
|
13
|
+
};
|
|
14
|
+
return { ...node, attributes: mergedAttributes };
|
|
15
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -17,9 +17,11 @@ export { getOnboardSamples } from './assets/samples/getSamples';
|
|
|
17
17
|
export { PreviewConfig } from './types/PreviewConfig';
|
|
18
18
|
export { RenderPage } from './RenderPage';
|
|
19
19
|
export { RenderMainNode } from './RenderMainNode';
|
|
20
|
+
export { DeviceMockFrame } from './DeviceMockFrame';
|
|
20
21
|
export { novaToJson } from './utils/novaToJson';
|
|
21
22
|
export type { Localication } from './types/PreviewConfig';
|
|
22
23
|
export { getDevices } from './utils/getDevices';
|
|
23
24
|
export type { Device } from './types/Device';
|
|
24
25
|
export { AttributesEditor };
|
|
25
26
|
export * from './build-components/index';
|
|
27
|
+
export { default as useNode } from './build-components/useNode';
|
package/src/types/Device.ts
CHANGED
|
@@ -4,6 +4,27 @@ export interface Device {
|
|
|
4
4
|
width: number;
|
|
5
5
|
height: number;
|
|
6
6
|
type: 'phone' | 'tablet';
|
|
7
|
+
/**
|
|
8
|
+
* Optional physical corner radius of the device screen area in CSS pixels.
|
|
9
|
+
* Used only for visual preview rounding; has no effect on layout calculations.
|
|
10
|
+
*/
|
|
11
|
+
radius?: number;
|
|
12
|
+
/**
|
|
13
|
+
* Insets in CSS pixels in the order: [top, right, bottom, left]
|
|
14
|
+
* Represents safe area or system UI overlaps (status bar, home indicator, etc.).
|
|
15
|
+
*/
|
|
16
|
+
insets?: [number, number, number, number];
|
|
17
|
+
/**
|
|
18
|
+
* Navigation bar style depending on platform.
|
|
19
|
+
* - iOS: 'none' | 'homeIndicator' | 'tabBar' (visual reference only)
|
|
20
|
+
* - Android: 'threeButtons' | 'gesture' | 'none'
|
|
21
|
+
*/
|
|
22
|
+
navigationBarType?:
|
|
23
|
+
| 'none'
|
|
24
|
+
| 'homeIndicator' // iOS
|
|
25
|
+
| 'tabBar' // iOS (for previewing tab bar overlap if desired)
|
|
26
|
+
| 'threeButtons' // Android classic nav bar
|
|
27
|
+
| 'gesture'; // Android gesture navigation
|
|
7
28
|
/**
|
|
8
29
|
* Relative importance for generic targeting and display ordering.
|
|
9
30
|
* 1 = highest importance, 100 = lowest importance
|
package/src/types/Node.ts
CHANGED
|
@@ -1,14 +1,4 @@
|
|
|
1
|
-
export type NodeDefaultAttribute = Record<
|
|
2
|
-
string,
|
|
3
|
-
| boolean
|
|
4
|
-
| string
|
|
5
|
-
| number
|
|
6
|
-
| null
|
|
7
|
-
| undefined
|
|
8
|
-
| string[]
|
|
9
|
-
| Record<string, unknown>
|
|
10
|
-
| Array<Record<string, unknown>>
|
|
11
|
-
>;
|
|
1
|
+
export type NodeDefaultAttribute = Record<string, unknown>;
|
|
12
2
|
|
|
13
3
|
export type Node<T = NodeDefaultAttribute> =
|
|
14
4
|
| null
|
|
@@ -23,4 +13,5 @@ export interface NodeData<T = Record<string, unknown>> {
|
|
|
23
13
|
children: Node<Record<string, unknown>>;
|
|
24
14
|
attributes?: T;
|
|
25
15
|
key?: string;
|
|
16
|
+
isMain?: boolean;
|
|
26
17
|
}
|
package/src/types/Project.ts
CHANGED
package/src/utils/novaToJson.ts
CHANGED
|
@@ -26,6 +26,8 @@ function onboardNovaToJson(nova: ProjectBase<unknown>): Node {
|
|
|
26
26
|
|
|
27
27
|
const providerNode: NodeData = {
|
|
28
28
|
type: 'OnboardProvider',
|
|
29
|
+
isMain: true,
|
|
30
|
+
key: (nova?.data as any)?.data?.key,
|
|
29
31
|
children: [
|
|
30
32
|
carouselNode,
|
|
31
33
|
// Place dots above buttons in visual order
|
|
@@ -35,6 +37,11 @@ function onboardNovaToJson(nova: ProjectBase<unknown>): Node {
|
|
|
35
37
|
],
|
|
36
38
|
attributes: {
|
|
37
39
|
theme: (nova?.data as any)?.theme,
|
|
40
|
+
// forward safe area inset preference; default to true when absent
|
|
41
|
+
use_safe_area_inset:
|
|
42
|
+
(attributes as any)?.use_safe_area_inset !== undefined
|
|
43
|
+
? (attributes as any)?.use_safe_area_inset
|
|
44
|
+
: true,
|
|
38
45
|
},
|
|
39
46
|
};
|
|
40
47
|
|
|
@@ -88,17 +95,45 @@ function buildCarouselItem(
|
|
|
88
95
|
if (comp?.layout === 'title-layout') {
|
|
89
96
|
const title = comp?.attributes?.title_localization_key || '';
|
|
90
97
|
const color = comp?.attributes?.title_color || undefined;
|
|
98
|
+
const { fontSize: titleFontSize, fontWeight: titleFontWeight } =
|
|
99
|
+
extractTextStyleAttributesFromComponent(comp);
|
|
91
100
|
children.push({
|
|
92
101
|
type: 'OnboardTitle',
|
|
93
|
-
attributes:
|
|
102
|
+
attributes:
|
|
103
|
+
color || titleFontSize || titleFontWeight
|
|
104
|
+
? {
|
|
105
|
+
...(color ? { color } : {}),
|
|
106
|
+
...(typeof titleFontSize === 'number'
|
|
107
|
+
? { fontSize: titleFontSize }
|
|
108
|
+
: {}),
|
|
109
|
+
...(titleFontWeight ? { fontWeight: titleFontWeight } : {}),
|
|
110
|
+
}
|
|
111
|
+
: undefined,
|
|
94
112
|
children: title,
|
|
95
113
|
});
|
|
96
114
|
} else if (comp?.layout === 'subtitle-layout') {
|
|
97
115
|
const subtitle = comp?.attributes?.subtitle_localization_key || '';
|
|
98
116
|
const color = comp?.attributes?.subtitle_color || undefined;
|
|
117
|
+
const {
|
|
118
|
+
fontSize: subtitleFontSize,
|
|
119
|
+
textAlign: subtitleTextAlign,
|
|
120
|
+
fontWeight: subtitleFontWeight,
|
|
121
|
+
} = extractTextStyleAttributesFromComponent(comp);
|
|
99
122
|
children.push({
|
|
100
123
|
type: 'OnboardSubtitle',
|
|
101
|
-
attributes:
|
|
124
|
+
attributes:
|
|
125
|
+
color || subtitleFontSize || subtitleTextAlign || subtitleFontWeight
|
|
126
|
+
? {
|
|
127
|
+
...(color ? { color } : {}),
|
|
128
|
+
...(typeof subtitleFontSize === 'number'
|
|
129
|
+
? { fontSize: subtitleFontSize }
|
|
130
|
+
: {}),
|
|
131
|
+
...(subtitleTextAlign ? { textAlign: subtitleTextAlign } : {}),
|
|
132
|
+
...(subtitleFontWeight
|
|
133
|
+
? { fontWeight: subtitleFontWeight }
|
|
134
|
+
: {}),
|
|
135
|
+
}
|
|
136
|
+
: undefined,
|
|
102
137
|
children: subtitle,
|
|
103
138
|
});
|
|
104
139
|
} else if (comp?.layout === 'image-layout') {
|
|
@@ -114,13 +149,20 @@ function buildCarouselItem(
|
|
|
114
149
|
? rawHeight
|
|
115
150
|
: undefined;
|
|
116
151
|
|
|
152
|
+
// derive resizeMode from is_bg_image and try to extract borderRadius from styles
|
|
153
|
+
const isBgImage = Boolean(comp?.attributes?.is_bg_image);
|
|
154
|
+
const imageStyle = extractViewStyleAttributesFromComponent(comp);
|
|
155
|
+
|
|
117
156
|
if (src) {
|
|
118
157
|
children.push({
|
|
119
158
|
type: 'OnboardImage',
|
|
120
159
|
attributes: {
|
|
121
160
|
src,
|
|
122
161
|
...(height ? { height } : {}),
|
|
123
|
-
resizeMode: 'contain',
|
|
162
|
+
resizeMode: isBgImage ? 'cover' : 'contain',
|
|
163
|
+
...(typeof imageStyle.borderRadius === 'number'
|
|
164
|
+
? { borderRadius: imageStyle.borderRadius }
|
|
165
|
+
: {}),
|
|
124
166
|
},
|
|
125
167
|
children: undefined as unknown as Node,
|
|
126
168
|
} as unknown as NodeData);
|
|
@@ -229,6 +271,127 @@ function buildCarouselItem(
|
|
|
229
271
|
};
|
|
230
272
|
}
|
|
231
273
|
|
|
274
|
+
//@eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
275
|
+
function extractTextStyleAttributesFromComponent(comp: any): {
|
|
276
|
+
fontSize?: number;
|
|
277
|
+
textAlign?: 'left' | 'center' | 'right' | 'justify';
|
|
278
|
+
fontWeight?:
|
|
279
|
+
| 'normal'
|
|
280
|
+
| 'bold'
|
|
281
|
+
| '100'
|
|
282
|
+
| '200'
|
|
283
|
+
| '300'
|
|
284
|
+
| '400'
|
|
285
|
+
| '500'
|
|
286
|
+
| '600'
|
|
287
|
+
| '700'
|
|
288
|
+
| '800'
|
|
289
|
+
| '900';
|
|
290
|
+
} {
|
|
291
|
+
const result: {
|
|
292
|
+
fontSize?: number;
|
|
293
|
+
textAlign?: 'left' | 'center' | 'right' | 'justify';
|
|
294
|
+
fontWeight?:
|
|
295
|
+
| 'normal'
|
|
296
|
+
| 'bold'
|
|
297
|
+
| '100'
|
|
298
|
+
| '200'
|
|
299
|
+
| '300'
|
|
300
|
+
| '400'
|
|
301
|
+
| '500'
|
|
302
|
+
| '600'
|
|
303
|
+
| '700'
|
|
304
|
+
| '800'
|
|
305
|
+
| '900';
|
|
306
|
+
} = {};
|
|
307
|
+
|
|
308
|
+
//@eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
309
|
+
const stylesRoot = (comp?.attributes?.styles || []) as any[];
|
|
310
|
+
if (!Array.isArray(stylesRoot) || stylesRoot.length === 0) return result;
|
|
311
|
+
|
|
312
|
+
const allowedAligns = new Set(['left', 'center', 'right', 'justify']);
|
|
313
|
+
const allowedWeights = new Set([
|
|
314
|
+
'normal',
|
|
315
|
+
'bold',
|
|
316
|
+
'100',
|
|
317
|
+
'200',
|
|
318
|
+
'300',
|
|
319
|
+
'400',
|
|
320
|
+
'500',
|
|
321
|
+
'600',
|
|
322
|
+
'700',
|
|
323
|
+
'800',
|
|
324
|
+
'900',
|
|
325
|
+
]);
|
|
326
|
+
|
|
327
|
+
for (const s of stylesRoot) {
|
|
328
|
+
if (s?.layout !== 'style-layout') continue;
|
|
329
|
+
//@eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
330
|
+
const nested = (s?.attributes?.styles || []) as any[];
|
|
331
|
+
if (!Array.isArray(nested)) continue;
|
|
332
|
+
for (const st of nested) {
|
|
333
|
+
if (st?.layout !== 'Styles') continue;
|
|
334
|
+
const type = st?.attributes?.type;
|
|
335
|
+
if (type !== 'textStyle') continue;
|
|
336
|
+
const style = st?.attributes?.style || {};
|
|
337
|
+
|
|
338
|
+
const rawFontSize = style?.fontSize;
|
|
339
|
+
if (typeof rawFontSize === 'number' && Number.isFinite(rawFontSize)) {
|
|
340
|
+
result.fontSize = rawFontSize;
|
|
341
|
+
} else if (typeof rawFontSize === 'string') {
|
|
342
|
+
const n = Number.parseInt(rawFontSize, 10);
|
|
343
|
+
if (Number.isFinite(n)) result.fontSize = n;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
const align = style?.textAlign;
|
|
347
|
+
if (typeof align === 'string' && allowedAligns.has(align)) {
|
|
348
|
+
result.textAlign = align as typeof result.textAlign;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
const rawWeight = style?.fontWeight;
|
|
352
|
+
let normalizedWeight: string | undefined;
|
|
353
|
+
if (typeof rawWeight === 'number' && Number.isFinite(rawWeight)) {
|
|
354
|
+
normalizedWeight = String(rawWeight);
|
|
355
|
+
} else if (typeof rawWeight === 'string') {
|
|
356
|
+
normalizedWeight = rawWeight;
|
|
357
|
+
}
|
|
358
|
+
if (normalizedWeight && allowedWeights.has(normalizedWeight)) {
|
|
359
|
+
result.fontWeight = normalizedWeight as typeof result.fontWeight;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
return result;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
//@eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
368
|
+
function extractViewStyleAttributesFromComponent(comp: any): {
|
|
369
|
+
borderRadius?: number;
|
|
370
|
+
} {
|
|
371
|
+
const result: { borderRadius?: number } = {};
|
|
372
|
+
//@eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
373
|
+
const stylesRoot = (comp?.attributes?.styles || []) as any[];
|
|
374
|
+
if (!Array.isArray(stylesRoot) || stylesRoot.length === 0) return result;
|
|
375
|
+
for (const s of stylesRoot) {
|
|
376
|
+
if (s?.layout !== 'style-layout') continue;
|
|
377
|
+
//@eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
378
|
+
const nested = (s?.attributes?.styles || []) as any[];
|
|
379
|
+
if (!Array.isArray(nested)) continue;
|
|
380
|
+
for (const st of nested) {
|
|
381
|
+
if (st?.layout !== 'Styles') continue;
|
|
382
|
+
const style = st?.attributes?.style || {};
|
|
383
|
+
const rawBr = style?.borderRadius;
|
|
384
|
+
if (typeof rawBr === 'number' && Number.isFinite(rawBr)) {
|
|
385
|
+
result.borderRadius = rawBr;
|
|
386
|
+
} else if (typeof rawBr === 'string') {
|
|
387
|
+
const n = Number.parseInt(rawBr, 10);
|
|
388
|
+
if (Number.isFinite(n)) result.borderRadius = n;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
return result;
|
|
393
|
+
}
|
|
394
|
+
|
|
232
395
|
function mapDotsFromGeneralComponents(generalComponents: any[]): Node | null {
|
|
233
396
|
const dots = generalComponents.find((gc) => gc?.layout === 'dots-layout');
|
|
234
397
|
if (!dots) return null;
|