@developer_tribe/react-builder 1.2.28 → 1.2.30
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 +7 -2
- package/dist/attributes-editor/attributesEditorModelTypes.d.ts +0 -1
- package/dist/build-components/index.generated.d.ts +38 -0
- package/dist/components/BuilderProvider.d.ts +9 -15
- package/dist/hooks/useLocalize.d.ts +3 -2
- package/dist/hooks/usePreviewSelection.d.ts +12 -0
- package/dist/index.cjs.js +1 -28
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.esm.js +1 -28
- package/dist/index.esm.js.map +1 -1
- package/dist/index.web.cjs.js +4 -4
- package/dist/index.web.cjs.js.map +1 -1
- package/dist/index.web.esm.js +4 -4
- package/dist/index.web.esm.js.map +1 -1
- package/dist/logger.d.ts +3 -6
- package/dist/modals/IconPickerModal.d.ts +1 -1
- package/dist/pages/DebugJsonPage.d.ts +1 -4
- package/dist/product-base/index.d.ts +24 -0
- package/dist/size-matters/index.d.ts +15 -6
- package/dist/store.d.ts +5 -3
- package/dist/types/Icons.generated.d.ts +2 -0
- package/dist/types/PreviewConfig.d.ts +6 -8
- package/dist/types/Project.d.ts +4 -3
- package/dist/utils/extractTextStyle/extractTextStyle.d.ts +2 -0
- package/dist/utils/extractTextStyle/extractTextStyleNative.d.ts +2 -0
- package/dist/utils/extractViewStyle/extractViewStyle.d.ts +2 -0
- package/dist/utils/extractViewStyle/extractViewStyleNative.d.ts +2 -0
- package/package.json +1 -1
- package/scripts/prebuild/utils/validateAllComponentsOrThrow.js +19 -9
- package/src/RenderPage.tsx +66 -57
- package/src/assets/.DS_Store +0 -0
- package/src/assets/meta.json +1 -1
- package/src/assets/samples/carousel-sample.json +2 -6
- package/src/assets/samples/getSamples.ts +14 -4
- package/src/attribute-analyser/style/native/useExtractImageStyle.ts +3 -3
- package/src/attribute-analyser/style/native/useExtractTextStyle.ts +8 -2
- package/src/attribute-analyser/style/native/useExtractViewStyle.ts +7 -3
- package/src/attribute-analyser/style/web/useExtractImageStyle.ts +3 -3
- package/src/attribute-analyser/style/web/useExtractTextStyle.ts +8 -2
- package/src/attribute-analyser/style/web/useExtractViewStyle.ts +3 -3
- package/src/attributes-editor/AttributesEditorFields.tsx +1 -1
- package/src/attributes-editor/attributesEditorModelTypes.ts +0 -3
- package/src/attributes-editor/useAttributesEditorModel.ts +0 -3
- package/src/build-components/BIcon/BIcon.tsx +1 -1
- package/src/build-components/Button/Button.tsx +2 -2
- package/src/build-components/CarouselDots/CarouselDots.tsx +3 -3
- package/src/build-components/OnboardButton/OnboardButton.tsx +2 -2
- package/src/build-components/OnboardDot/OnboardDot.tsx +9 -3
- package/src/build-components/OnboardFooter/OnboardFooter.tsx +4 -5
- package/src/build-components/PaywallCloseButton/PaywallCloseButton.tsx +1 -1
- package/src/build-components/PaywallSubscribeButton/PaywallSubscribeButton.tsx +2 -2
- package/src/build-components/Text/Text.tsx +2 -2
- package/src/build-components/index.generated.ts +184 -0
- package/src/components/BottomBar.tsx +7 -9
- package/src/components/BuilderProvider.tsx +47 -84
- package/src/components/EditorHeader.tsx +6 -3
- package/src/hooks/useLocalize.ts +14 -10
- package/src/hooks/usePreviewSelection.ts +66 -0
- package/src/index.ts +2 -2
- package/src/logger.ts +4 -20
- package/src/modals/IconPickerModal.tsx +1 -1
- package/src/modals/InspectModal.tsx +6 -7
- package/src/modals/ProductPresetsModal.tsx +2 -2
- package/src/pages/DebugJsonPage.tsx +0 -6
- package/src/pages/ProjectPage.tsx +12 -57
- package/src/pages/tabs/SideTool.tsx +7 -7
- package/src/product-base/extractAndroidParams.ts +4 -11
- package/src/product-base/extractIOSParams.ts +4 -10
- package/src/product-base/index.ts +36 -0
- package/src/size-matters/index.ts +44 -31
- package/src/store.ts +12 -6
- package/src/styles/modals/_inspect-modal.scss +7 -3
- package/src/types/Icons.generated.ts +244 -0
- package/src/types/PreviewConfig.ts +5 -9
- package/src/types/Project.ts +4 -3
- package/src/utils/extractImageStyle.ts +4 -2
- package/src/utils/extractTextStyle/extractTextStyle.ts +6 -1
- package/src/utils/extractTextStyle/extractTextStyleNative.ts +4 -1
- package/src/utils/extractViewStyle/extractViewStyle.ts +7 -5
- package/src/utils/extractViewStyle/extractViewStyleNative.ts +3 -1
- package/src/utils/getDefaultProject.ts +0 -1
- package/src/utils/replaceLocalizationParams.ts +1 -1
package/dist/logger.d.ts
CHANGED
|
@@ -5,14 +5,11 @@
|
|
|
5
5
|
* This minimal version keeps product-base compilable in the builder context.
|
|
6
6
|
*/
|
|
7
7
|
type LogPayload = Record<string, unknown>;
|
|
8
|
-
type LogOptions = {
|
|
9
|
-
remote?: boolean;
|
|
10
|
-
};
|
|
11
8
|
declare function noop(): void;
|
|
12
9
|
export declare const iapLogger: {
|
|
13
|
-
error(_tags: string[], message: string, payload?: LogPayload
|
|
14
|
-
warn(_tags: string[], message: string, payload?: LogPayload
|
|
15
|
-
info(_tags: string[], message: string, payload?: LogPayload
|
|
10
|
+
error(_tags: string[], message: string, payload?: LogPayload): void;
|
|
11
|
+
warn(_tags: string[], message: string, payload?: LogPayload): void;
|
|
12
|
+
info(_tags: string[], message: string, payload?: LogPayload): void;
|
|
16
13
|
debug: typeof noop;
|
|
17
14
|
};
|
|
18
15
|
export {};
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { Node } from '../types/Node';
|
|
3
|
-
import type { AppConfig } from '../types/PreviewConfig';
|
|
4
3
|
export type DebugJsonPageProps = {
|
|
5
4
|
data: Node | null | undefined;
|
|
6
5
|
setData: React.Dispatch<React.SetStateAction<Node>>;
|
|
@@ -10,8 +9,6 @@ export type DebugJsonPageProps = {
|
|
|
10
9
|
description?: string;
|
|
11
10
|
previewMode?: boolean;
|
|
12
11
|
setPreviewMode?: (next: boolean) => void;
|
|
13
|
-
appConfig?: AppConfig;
|
|
14
|
-
setAppConfig?: (next: AppConfig) => void;
|
|
15
12
|
logLabel?: string;
|
|
16
13
|
};
|
|
17
|
-
export declare function DebugJsonPage({ data, setData, project, onClose, title, description, previewMode, setPreviewMode,
|
|
14
|
+
export declare function DebugJsonPage({ data, setData, project, onClose, title, description, previewMode, setPreviewMode, logLabel, }: DebugJsonPageProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -25,3 +25,27 @@ export * from './extractAndroidParams';
|
|
|
25
25
|
export * from './extractIOSParams';
|
|
26
26
|
export * from './buildPaywallLocalizationParams';
|
|
27
27
|
export * from './usePaywallLocalizationParams';
|
|
28
|
+
import type { Product } from './types';
|
|
29
|
+
/** Preset map: preset key → product array. */
|
|
30
|
+
export type MockProductPresets = Record<string, Product[]>;
|
|
31
|
+
/**
|
|
32
|
+
* Returns a deep-copy of all mock product presets.
|
|
33
|
+
*
|
|
34
|
+
* Use this instead of importing `mockProducts.json` directly so that:
|
|
35
|
+
* 1. Consumers don't couple to a JSON file path.
|
|
36
|
+
* 2. Each call returns a fresh copy (safe to mutate).
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* import { getMockProducts } from '@developer_tribe/react-builder';
|
|
40
|
+
* const presets = getMockProducts(); // { 'preset-1': [...], ... }
|
|
41
|
+
*/
|
|
42
|
+
export declare function getMockProducts(): MockProductPresets;
|
|
43
|
+
/**
|
|
44
|
+
* Returns the product list for a specific preset key (deep-copied).
|
|
45
|
+
* Returns an empty array if the key doesn't exist.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* import { getMockProductsByPreset } from '@developer_tribe/react-builder';
|
|
49
|
+
* const products = getMockProductsByPreset('preset-1');
|
|
50
|
+
*/
|
|
51
|
+
export declare function getMockProductsByPreset(presetKey: string): Product[];
|
|
@@ -1,6 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export declare function
|
|
1
|
+
import { type BaseSize } from '../types/PreviewConfig';
|
|
2
|
+
import type { Device } from '../types/Device';
|
|
3
|
+
/**
|
|
4
|
+
* Calculates scaling factors based on baseSize and current device dimensions.
|
|
5
|
+
*/
|
|
6
|
+
export declare function getScalers(customBaseSize?: BaseSize, customDevice?: Device): {
|
|
7
|
+
scale: (size: number) => number;
|
|
8
|
+
verticalScale: (size: number) => number;
|
|
9
|
+
moderateScale: (size: number, factor?: number) => number;
|
|
10
|
+
};
|
|
11
|
+
export declare const s: (size: number) => number;
|
|
12
|
+
export declare const vs: (size: number) => number;
|
|
13
|
+
export declare const fs: (size: number) => number;
|
|
14
|
+
export declare const ms: (size: number, factor?: number) => number;
|
|
15
|
+
export declare function parseSize(value: string | number | undefined, baseSize?: BaseSize, device?: Device): string | number | undefined;
|
package/dist/store.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Device } from './types/Device';
|
|
2
|
-
import { type
|
|
2
|
+
import { type BaseSize, type Localication, type Theme } from './types/PreviewConfig';
|
|
3
3
|
import { Node } from './types/Node';
|
|
4
4
|
import type { LogEntry, LogLevel, ProjectColors } from './types/Project';
|
|
5
5
|
import type { Product } from './paywall/types/paywall-types';
|
|
@@ -16,14 +16,16 @@ type RenderStore = {
|
|
|
16
16
|
incForceRender: () => void;
|
|
17
17
|
device: Device;
|
|
18
18
|
setDevice: (device: Device) => void;
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
baseSize: BaseSize;
|
|
20
|
+
setBaseSize: (baseSize: BaseSize) => void;
|
|
21
21
|
projectColors?: ProjectColors;
|
|
22
22
|
setProjectColors: (projectColors?: ProjectColors) => void;
|
|
23
23
|
theme: Theme;
|
|
24
24
|
setTheme: (theme: Theme) => void;
|
|
25
25
|
defaultLanguage: string;
|
|
26
26
|
setDefaultLanguage: (lang: string) => void;
|
|
27
|
+
localization: Localication;
|
|
28
|
+
setLocalization: (localization: Localication) => void;
|
|
27
29
|
isRtl: boolean;
|
|
28
30
|
setIsRtl: (isRtl: boolean) => void;
|
|
29
31
|
previewMode: boolean;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export declare const Icons: readonly ["activity", "activity-heart", "alert-circle", "alert-triangle", "anchor", "archive", "arrow-down", "arrow-left", "arrow-narrow-down-left", "arrow-narrow-up-right", "arrow-right", "arrow-right-smooth", "asterisk-01", "asterisk-02", "at-sign", "award", "battery-charging", "bell-01", "bell-02", "bell-ringing-02", "bookmark", "bookmark-add", "bookmark-check", "bookmark-minus", "bookmark-x", "bubble", "building-01", "building-02", "building-03", "building-04", "building-05", "building-06", "building-07", "building-08", "building-09", "camera", "camera-01", "camera-steel", "check", "check-circle", "check-circle-bold", "check-circle-broken", "check-done-01", "check-done-02", "check-heart", "check-square", "check-square-broken", "check-verified-01", "check-verified-02", "check-verified-03", "checkbox", "checkv", "chevron-down", "chevron-down2", "chevron-left", "chevron-left-2", "chevron-right", "chevron-right-empty", "chevron-right-smooth", "chevron-up", "circle", "clock", "clock-fast-forward", "close", "close-circle", "cloud-01", "cloud-blank-01", "cloud-blank-02", "coin", "coins-02", "colors", "copy-01", "copy-02", "copy-03", "copy-04", "copy-05", "copy-06", "copy-07", "corner-down-right", "crypto-bold", "delete-icon", "diamond", "dice-3", "divide-01", "divide-02", "divide-03", "document-check-bold", "dots-circle", "dots-grid", "dots-horizontal", "dots-vertical", "download-01", "download-02", "download-03", "edit-03", "edit-04", "edit-05", "element-3", "ellipse-127", "exclaimation-circle", "eye-off-line", "face-smile", "file-04", "file-05", "file-check-02", "file-plus-01", "file-shield-02", "filter-funnel-01", "flag-03", "flash", "folder", "folder-plus", "gallery", "globe-01", "globe-04", "globe-bold", "guard", "headphones-01", "headphones-02", "headset-bold", "heart", "heart-bold", "help-circle", "home-2", "home-line", "hourglass-02", "image", "image-01", "image-03", "inbox-01", "inbox-arrow-down", "info-circle", "keyboard-line", "lamp-charge", "layer", "light", "like-dislike", "lock-03", "logout", "magicpen", "mail", "mail-01", "marker", "medal-star", "menu", "menu-04", "message-circle-01", "message-plus-circle", "message-question-circle", "message-text-circle-01", "message-text-square-02", "message-x-square", "microphone-02", "microphone-slash", "mirror", "moon-01", "moon-bold", "mouse-circle", "move", "notification", "notification-fill", "notification-text", "pdf-01", "pencil-01", "phone", "phone-01", "phone-arrow-down-left", "phone-arrow-up-right", "phone-hang-up", "phone-hangup2", "phone-incoming-01", "phone-outgoing-01", "phone-plus", "phone-x", "plus", "plus-circle", "printer", "question-mark-circle", "refresh-ccw-01", "refresh-cw-01", "refresh-cw-04", "refresh-right-square-bold", "remove-circle", "repeat-04", "repeat-bold", "ruler-pen", "search", "search-lg", "search-md", "search-refraction", "send-01", "send-02", "send-diagonal", "setting-2", "settings", "settings-02", "settings-04", "settings-2", "settings-cog", "share-01", "share-03", "share-04", "share-05", "share-06", "share-bold", "shield-01", "shield-bold", "solar-check", "speaker", "speaker-wave", "speedometer-03", "star", "star-rounded", "sun", "target-03", "text-input", "translate", "trash", "trash-02", "trash-03", "trash-04", "trush-square-bold", "unlimited", "user-circle", "user-jogging", "user-plus-01", "user-square", "user-x-01", "user-x-02", "user2", "users-02", "users-speaker", "verify", "voice-cricle", "x-circle", "x-close", "x-sm", "zap"];
|
|
2
|
+
export type IconsType = (typeof Icons)[number];
|
|
@@ -1,11 +1,4 @@
|
|
|
1
1
|
export type Theme = 'light' | 'dark';
|
|
2
|
-
export interface AppConfig {
|
|
3
|
-
localication: Localication;
|
|
4
|
-
baseSize: {
|
|
5
|
-
width: number;
|
|
6
|
-
height: number;
|
|
7
|
-
};
|
|
8
|
-
}
|
|
9
2
|
export type LocalizationKey = 'base.builder.paywall.period.monthly' | 'base.builder.paywall.period.annual' | 'base.builder.paywall.period.weekly' | 'base.builder.paywall.period.daily' | 'base.builder.paywall.period.monthlyPromo' | 'base.builder.paywall.period.annualPromo' | 'base.builder.paywall.pricing.default.text' | 'base.builder.paywall.pricing.freeTrial.text' | 'base.builder.paywall.pricing.regular.text' | 'base.builder.paywall.promo.default.text' | 'base.builder.paywall.promo.freeTrial.text' | 'base.builder.paywall.promo.regular.text' | 'onboard.title.one-page' | 'onboard.title.two-page' | 'onboard.title.three-page' | 'onboard.title.four-page' | 'onboard.title.one-page2' | 'onboard.title.two-page2' | 'onboard.title.three-page2' | 'onboard.title.four-page2' | 'onboard.subtitle.one-page' | 'onboard.subtitle.two-page' | 'onboard.subtitle.three-page' | 'onboard.subtitle.four-page' | 'onboard.subtitle.one-page2' | 'onboard.subtitle.two-page2' | 'onboard.subtitle.three-page2' | 'onboard.subtitle.four-page2' | 'onboard.next.one-page' | 'onboard.next.two-page' | 'onboard.next.three-page' | 'onboard.skip.one-page' | 'onboard.skip.two-page' | 'onboard.skip.three-page' | 'onboard.allow.four-page' | 'view.onboarding.footer.description' | 'view.onboarding.btnPrivacy' | 'view.onboarding.btnTerms' | (string & {});
|
|
10
3
|
export type Localication = Record<string, Partial<Record<LocalizationKey, string>>>;
|
|
11
4
|
export declare const defaultLocalization: Localication;
|
|
@@ -15,4 +8,9 @@ export declare const defaultLocalization: Localication;
|
|
|
15
8
|
*/
|
|
16
9
|
export declare function mergeLocalization(base: Localication, custom: Localication): Localication;
|
|
17
10
|
export declare const defaultTheme: Theme;
|
|
18
|
-
export
|
|
11
|
+
export type BaseSize = {
|
|
12
|
+
width: number;
|
|
13
|
+
height: number;
|
|
14
|
+
};
|
|
15
|
+
export declare const defaultBaseSize: BaseSize;
|
|
16
|
+
export declare const defaultLanguage = "en";
|
package/dist/types/Project.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Node } from '../types/Node';
|
|
2
|
-
import {
|
|
2
|
+
import { BaseSize, Localication } from './PreviewConfig';
|
|
3
3
|
export type ProjectColorTokenMap = Record<string, string>;
|
|
4
4
|
export type ProjectThemeColors = {
|
|
5
5
|
light?: ProjectColorTokenMap;
|
|
@@ -19,7 +19,8 @@ export interface ProjectBase<T> {
|
|
|
19
19
|
*/
|
|
20
20
|
type?: 'paywall' | 'onboard' | 'other';
|
|
21
21
|
data: T;
|
|
22
|
-
|
|
22
|
+
baseSize?: BaseSize;
|
|
23
|
+
localization?: Localication;
|
|
23
24
|
projectColors?: ProjectColors;
|
|
24
25
|
}
|
|
25
26
|
export interface Project extends ProjectBase<Node> {
|
|
@@ -27,7 +28,7 @@ export interface Project extends ProjectBase<Node> {
|
|
|
27
28
|
/**
|
|
28
29
|
* Lightweight subset of Project containing only the essential metadata
|
|
29
30
|
* needed for persistence (name, version, type, data).
|
|
30
|
-
* Excludes runtime/editor-only fields like
|
|
31
|
+
* Excludes runtime/editor-only fields like projectColors.
|
|
31
32
|
*/
|
|
32
33
|
export type ProjectMeta = Pick<Project, 'name' | 'version' | 'type' | 'data'>;
|
|
33
34
|
export type LogLevel = 'NONE' | 'ERROR' | 'WARN' | 'INFO' | 'VERBOSE';
|
|
@@ -3,6 +3,7 @@ import type { TextPropsGenerated } from '../../build-components/Text/TextProps.g
|
|
|
3
3
|
import type { Theme } from '../../types/PreviewConfig';
|
|
4
4
|
import type { ProjectColors } from '../../types/Project';
|
|
5
5
|
import type { Fonts } from '../../types/Fonts';
|
|
6
|
+
import type { BaseSize } from '../../types/PreviewConfig';
|
|
6
7
|
export type ExtractTextStyleOptions = {
|
|
7
8
|
theme?: Theme;
|
|
8
9
|
projectColors?: ProjectColors;
|
|
@@ -10,5 +11,6 @@ export type ExtractTextStyleOptions = {
|
|
|
10
11
|
onFontLoaded?: (fontFamily: string) => void;
|
|
11
12
|
onError?: (error: string) => void;
|
|
12
13
|
directlyTextStyle?: boolean;
|
|
14
|
+
baseSize?: BaseSize;
|
|
13
15
|
};
|
|
14
16
|
export declare function extractTextStyle<T extends TextPropsGenerated['attributes']>(node: NodeData<T>, options?: ExtractTextStyleOptions): import("react").CSSProperties;
|
|
@@ -3,10 +3,12 @@ import type { TextPropsGenerated } from '../../build-components/Text/TextProps.g
|
|
|
3
3
|
import type { Theme } from '../../types/PreviewConfig';
|
|
4
4
|
import type { ProjectColors } from '../../types/Project';
|
|
5
5
|
import type { Fonts } from '../../types/Fonts';
|
|
6
|
+
import type { BaseSize } from '../../types/PreviewConfig';
|
|
6
7
|
export type ExtractTextStyleNativeOptions = {
|
|
7
8
|
theme?: Theme;
|
|
8
9
|
projectColors?: ProjectColors;
|
|
9
10
|
fonts?: Fonts;
|
|
11
|
+
baseSize?: BaseSize;
|
|
10
12
|
};
|
|
11
13
|
/**
|
|
12
14
|
* React Native-friendly text style extraction.
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { ViewPropsGenerated } from '../../build-components/View/ViewProps.generated';
|
|
2
2
|
import type { NodeData } from '../../types/Node';
|
|
3
3
|
import type { ProjectColors } from '../../types/Project';
|
|
4
|
+
import type { BaseSize } from '../../types/PreviewConfig';
|
|
4
5
|
export type ExtractViewStyleOptions = {
|
|
5
6
|
projectColors?: ProjectColors;
|
|
6
7
|
theme?: string;
|
|
8
|
+
baseSize?: BaseSize;
|
|
7
9
|
};
|
|
8
10
|
export declare function extractViewStyle<T extends ViewPropsGenerated['attributes']>(node: NodeData<T>, options?: ExtractViewStyleOptions): import("react").CSSProperties;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import type { ViewPropsGenerated } from '../../build-components/View/ViewProps.generated';
|
|
2
2
|
import type { NodeData } from '../../types/Node';
|
|
3
3
|
import type { ProjectColors } from '../../types/Project';
|
|
4
|
+
import type { BaseSize } from '../../types/PreviewConfig';
|
|
4
5
|
export type ExtractViewStyleNativeOptions = {
|
|
5
6
|
projectColors?: ProjectColors;
|
|
6
7
|
theme?: string;
|
|
8
|
+
baseSize?: BaseSize;
|
|
7
9
|
};
|
|
8
10
|
/**
|
|
9
11
|
* Extracts a React Native-friendly style object from node attributes.
|
package/package.json
CHANGED
|
@@ -25,6 +25,7 @@ async function getAllEntriesInComponentsRoot(paths) {
|
|
|
25
25
|
d.name !== 'getDefaults.ts' &&
|
|
26
26
|
d.name !== 'useDefaults.ts' &&
|
|
27
27
|
d.name !== 'useNode.ts' &&
|
|
28
|
+
d.name !== 'index.generated.ts' &&
|
|
28
29
|
d.name !== 'patterns.generated.ts'
|
|
29
30
|
);
|
|
30
31
|
});
|
|
@@ -174,15 +175,17 @@ async function validatePatternJson(componentDir, componentName) {
|
|
|
174
175
|
const patternDefaults = isPlainObject(source?.pattern?.defaults)
|
|
175
176
|
? source.pattern.defaults
|
|
176
177
|
: {};
|
|
177
|
-
const directDefaults = isPlainObject(source?.defaults)
|
|
178
|
+
const directDefaults = isPlainObject(source?.defaults)
|
|
179
|
+
? source.defaults
|
|
180
|
+
: {};
|
|
178
181
|
const combined = { ...patternDefaults, ...directDefaults };
|
|
179
|
-
|
|
182
|
+
|
|
180
183
|
// Convert legacy `style` to `styles` (schemaVersion 2)
|
|
181
184
|
if (isPlainObject(combined.style)) {
|
|
182
185
|
combined.styles = { ...(combined.styles || {}), ...combined.style };
|
|
183
186
|
delete combined.style;
|
|
184
187
|
}
|
|
185
|
-
|
|
188
|
+
|
|
186
189
|
return combined;
|
|
187
190
|
};
|
|
188
191
|
|
|
@@ -358,17 +361,24 @@ async function validatePatternJson(componentDir, componentName) {
|
|
|
358
361
|
const mergedTypes = { ...(parentData.types || {}), ...(data.types || {}) };
|
|
359
362
|
const parentDefaults = buildDefaultsBlock(parentData);
|
|
360
363
|
const childDefaults = buildDefaultsBlock(data);
|
|
361
|
-
|
|
364
|
+
|
|
362
365
|
// Deep-merge `styles` from both parent and child (already converted from legacy `style` by buildDefaultsBlock)
|
|
363
|
-
const parentDefaultStyles = isPlainObject(parentDefaults?.styles)
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
366
|
+
const parentDefaultStyles = isPlainObject(parentDefaults?.styles)
|
|
367
|
+
? parentDefaults.styles
|
|
368
|
+
: {};
|
|
369
|
+
const childDefaultStyles = isPlainObject(childDefaults?.styles)
|
|
370
|
+
? childDefaults.styles
|
|
371
|
+
: {};
|
|
372
|
+
const mergedDefaultStyles = {
|
|
373
|
+
...parentDefaultStyles,
|
|
374
|
+
...childDefaultStyles,
|
|
375
|
+
};
|
|
376
|
+
|
|
367
377
|
const mergedDefaults = {
|
|
368
378
|
...parentDefaults,
|
|
369
379
|
...childDefaults,
|
|
370
380
|
};
|
|
371
|
-
|
|
381
|
+
|
|
372
382
|
// Set merged styles if there are any
|
|
373
383
|
if (Object.keys(mergedDefaultStyles).length > 0) {
|
|
374
384
|
mergedDefaults.styles = mergedDefaultStyles;
|
package/src/RenderPage.tsx
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useRef } from 'react';
|
|
2
2
|
import { DeviceMockFrame } from './DeviceMockFrame';
|
|
3
3
|
import { Node } from './types/Node';
|
|
4
4
|
import { RenderNode } from './build-components';
|
|
5
5
|
import { useRenderStore } from './store';
|
|
6
6
|
import { useLogRender } from './utils/useLogRender';
|
|
7
|
-
import { findNodeByKeyNested } from './utils/findNodeByKeyNested';
|
|
8
7
|
import {
|
|
9
8
|
BuilderProvider,
|
|
10
|
-
|
|
9
|
+
BuilderProviderParams,
|
|
11
10
|
} from './components/BuilderProvider';
|
|
12
11
|
import { RenderErrorBoundary } from './components/RenderErrorBoundary';
|
|
12
|
+
import { usePreviewSelection } from './hooks/usePreviewSelection';
|
|
13
13
|
export type ScreenStyle = {
|
|
14
14
|
light: { backgroundColor: string; color: string; seperatorColor?: string };
|
|
15
15
|
dark: { backgroundColor: string; color: string; seperatorColor?: string };
|
|
@@ -18,7 +18,12 @@ interface RenderPageProps {
|
|
|
18
18
|
data: Node;
|
|
19
19
|
name: string;
|
|
20
20
|
onSelectNode?: (node: Node | null) => void;
|
|
21
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Optional overrides for the builder provider.
|
|
23
|
+
* Useful for debug views or isolated rendering where we want to Inject
|
|
24
|
+
* specific mocks (products, benefits) instead of reading from the global store.
|
|
25
|
+
*/
|
|
26
|
+
params?: Partial<BuilderProviderParams>;
|
|
22
27
|
}
|
|
23
28
|
|
|
24
29
|
function isNullish(value: unknown): value is null | undefined {
|
|
@@ -32,65 +37,69 @@ export function RenderPage({
|
|
|
32
37
|
params,
|
|
33
38
|
}: RenderPageProps) {
|
|
34
39
|
useLogRender('RenderPage');
|
|
35
|
-
const {
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
const {
|
|
41
|
+
products,
|
|
42
|
+
benefits,
|
|
43
|
+
mockTheme,
|
|
44
|
+
mockDefaultLanguage,
|
|
45
|
+
overrideLocalization,
|
|
46
|
+
overrideBaseSize,
|
|
47
|
+
overrideProjectColors,
|
|
48
|
+
overrideFonts,
|
|
49
|
+
appFont,
|
|
50
|
+
previewMode,
|
|
51
|
+
current,
|
|
52
|
+
forceRender,
|
|
53
|
+
setCurrent,
|
|
54
|
+
} = useRenderStore((s) => ({
|
|
55
|
+
products: s.products,
|
|
56
|
+
benefits: s.benefits,
|
|
57
|
+
mockTheme: s.theme,
|
|
58
|
+
mockDefaultLanguage: s.defaultLanguage,
|
|
59
|
+
overrideLocalization: s.localization,
|
|
60
|
+
overrideBaseSize: s.baseSize,
|
|
61
|
+
overrideProjectColors: s.projectColors,
|
|
62
|
+
overrideFonts: s.fonts,
|
|
63
|
+
appFont: s.appFont,
|
|
64
|
+
previewMode: s.previewMode,
|
|
65
|
+
current: s.current,
|
|
66
|
+
forceRender: s.forceRender,
|
|
67
|
+
setCurrent: s.setCurrent,
|
|
68
|
+
}));
|
|
43
69
|
const previewRootRef = useRef<HTMLDivElement | null>(null);
|
|
44
70
|
const showEmptyState = isNullish(data);
|
|
45
71
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
const handleClick = (event: MouseEvent) => {
|
|
57
|
-
const target = event.target as HTMLElement | null;
|
|
58
|
-
|
|
59
|
-
if (!target) return;
|
|
60
|
-
|
|
61
|
-
// Ignore clicks on carousel dots to avoid interfering with navigation
|
|
62
|
-
if (target.closest('.embla__dot')) {
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// Some build-components may attach synthetic keys (e.g. React `useId()`),
|
|
67
|
-
// which are not present in the persisted node tree. Walk up until we find
|
|
68
|
-
// an attribute-key that resolves to a real node.
|
|
69
|
-
let element = target.closest('[attribute-key]') as HTMLElement | null;
|
|
70
|
-
while (element) {
|
|
71
|
-
const key = element.getAttribute('attribute-key');
|
|
72
|
-
if (key) {
|
|
73
|
-
const node = findNodeByKeyNested(data, key);
|
|
74
|
-
if (node) {
|
|
75
|
-
setCurrent(node);
|
|
76
|
-
onSelectNode?.(node);
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
element = element.parentElement?.closest('[attribute-key]') ?? null;
|
|
81
|
-
}
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
root.addEventListener('click', handleClick);
|
|
85
|
-
|
|
86
|
-
return () => {
|
|
87
|
-
root.removeEventListener('click', handleClick);
|
|
88
|
-
};
|
|
89
|
-
}, [previewMode, data, onSelectNode, setCurrent, forceRender]); // forceRender: retrigger effect when we want to force a refresh (e.g. route change)
|
|
72
|
+
usePreviewSelection({
|
|
73
|
+
previewMode: !!previewMode,
|
|
74
|
+
data,
|
|
75
|
+
rootRef: previewRootRef,
|
|
76
|
+
onSelectNode,
|
|
77
|
+
setCurrent,
|
|
78
|
+
forceRender,
|
|
79
|
+
});
|
|
90
80
|
|
|
91
81
|
return (
|
|
92
82
|
<RenderErrorBoundary subtitle="caught by RenderPage">
|
|
93
|
-
<BuilderProvider
|
|
83
|
+
<BuilderProvider
|
|
84
|
+
params={{
|
|
85
|
+
// Store defaults
|
|
86
|
+
mockTheme: mockTheme,
|
|
87
|
+
mockDefaultLanguage: mockDefaultLanguage,
|
|
88
|
+
localization: overrideLocalization,
|
|
89
|
+
baseSize: overrideBaseSize,
|
|
90
|
+
mockProducts: products,
|
|
91
|
+
mockBenefits: benefits as any,
|
|
92
|
+
projectColors: overrideProjectColors ?? undefined,
|
|
93
|
+
fonts: overrideFonts,
|
|
94
|
+
previewMode: previewMode,
|
|
95
|
+
selectedKey:
|
|
96
|
+
current && typeof current === 'object' && 'key' in current
|
|
97
|
+
? ((current as any).key as string)
|
|
98
|
+
: undefined,
|
|
99
|
+
// Explicit overrides take precedence
|
|
100
|
+
...params,
|
|
101
|
+
}}
|
|
102
|
+
>
|
|
94
103
|
<DeviceMockFrame appName={name}>
|
|
95
104
|
<div
|
|
96
105
|
className="screen-preview"
|
package/src/assets/.DS_Store
CHANGED
|
Binary file
|
package/src/assets/meta.json
CHANGED
|
@@ -280,9 +280,7 @@
|
|
|
280
280
|
{
|
|
281
281
|
"type": "carouselButtons",
|
|
282
282
|
"attributes": {
|
|
283
|
-
"buttonType": [
|
|
284
|
-
"previous_button"
|
|
285
|
-
],
|
|
283
|
+
"buttonType": ["previous_button"],
|
|
286
284
|
"styles": {
|
|
287
285
|
"backgroundColor": "#6366f1",
|
|
288
286
|
"borderRadius": 12,
|
|
@@ -295,9 +293,7 @@
|
|
|
295
293
|
{
|
|
296
294
|
"type": "carouselButtons",
|
|
297
295
|
"attributes": {
|
|
298
|
-
"buttonType": [
|
|
299
|
-
"next_button"
|
|
300
|
-
],
|
|
296
|
+
"buttonType": ["next_button"],
|
|
301
297
|
"styles": {
|
|
302
298
|
"backgroundColor": "#8b5cf6",
|
|
303
299
|
"borderRadius": 12,
|
|
@@ -20,13 +20,23 @@ import vpnOnboard4 from './vpn-onboard-4.json';
|
|
|
20
20
|
import vpnOnboard5 from './vpn-onboard-5.json';
|
|
21
21
|
import vpnOnboard6 from './vpn-onboard-6.json';
|
|
22
22
|
import vpnOnboard7 from './vpn-onboard-7.json';
|
|
23
|
-
import {
|
|
23
|
+
import {
|
|
24
|
+
defaultBaseSize,
|
|
25
|
+
defaultLocalization,
|
|
26
|
+
} from '../../types/PreviewConfig';
|
|
24
27
|
|
|
25
28
|
function normalizeSample(sample: any): Project {
|
|
26
|
-
|
|
29
|
+
// Legacy migration: extract baseSize/localization from appConfig if present
|
|
30
|
+
const legacyConfig = sample.appConfig || {};
|
|
31
|
+
const project = {
|
|
27
32
|
...sample,
|
|
28
|
-
|
|
29
|
-
|
|
33
|
+
baseSize: legacyConfig.baseSize || sample.baseSize || defaultBaseSize,
|
|
34
|
+
localization:
|
|
35
|
+
legacyConfig.localization || sample.localization || defaultLocalization,
|
|
36
|
+
};
|
|
37
|
+
// Ensure appConfig is removed if it existed
|
|
38
|
+
delete project.appConfig;
|
|
39
|
+
return project as Project;
|
|
30
40
|
}
|
|
31
41
|
|
|
32
42
|
export function getSamples(): Project[] {
|
|
@@ -22,13 +22,13 @@ export function useExtractImageStyle<
|
|
|
22
22
|
style: ImageStyle;
|
|
23
23
|
other: Omit<T, StyleAttrKey> & { resizeMode?: ResizeModeOptionType };
|
|
24
24
|
} {
|
|
25
|
-
const { theme, projectColors } = useBuilderParams();
|
|
25
|
+
const { mockTheme: theme, projectColors, baseSize } = useBuilderParams();
|
|
26
26
|
|
|
27
27
|
return useMemo(() => {
|
|
28
28
|
// extractImageStyleNative returns Record<string, unknown> that may include resizeMode.
|
|
29
29
|
// In RN, resizeMode is typically an Image prop, not a style property.
|
|
30
30
|
const { resizeMode: resizeModeFromStyle, ...style } =
|
|
31
|
-
extractImageStyleNative(node, { theme, projectColors });
|
|
31
|
+
extractImageStyleNative(node, { theme, projectColors, baseSize });
|
|
32
32
|
|
|
33
33
|
const attrs = node.attributes;
|
|
34
34
|
const stripped = stripStyleKeys(toAttributeRecord(attrs));
|
|
@@ -45,5 +45,5 @@ export function useExtractImageStyle<
|
|
|
45
45
|
resizeMode,
|
|
46
46
|
} as Omit<T, StyleAttrKey> & { resizeMode?: ResizeModeOptionType },
|
|
47
47
|
};
|
|
48
|
-
}, [node, theme, projectColors]);
|
|
48
|
+
}, [node, theme, projectColors, baseSize]);
|
|
49
49
|
}
|
|
@@ -20,7 +20,12 @@ export function useExtractTextStyle<T extends TextPropsGenerated['attributes']>(
|
|
|
20
20
|
showEllipsis?: boolean;
|
|
21
21
|
};
|
|
22
22
|
} {
|
|
23
|
-
const {
|
|
23
|
+
const {
|
|
24
|
+
mockTheme: theme,
|
|
25
|
+
projectColors,
|
|
26
|
+
fonts,
|
|
27
|
+
baseSize,
|
|
28
|
+
} = useBuilderParams();
|
|
24
29
|
|
|
25
30
|
return useMemo(
|
|
26
31
|
() => {
|
|
@@ -28,6 +33,7 @@ export function useExtractTextStyle<T extends TextPropsGenerated['attributes']>(
|
|
|
28
33
|
theme,
|
|
29
34
|
projectColors,
|
|
30
35
|
fonts,
|
|
36
|
+
baseSize,
|
|
31
37
|
});
|
|
32
38
|
|
|
33
39
|
const attrs = node.attributes;
|
|
@@ -51,6 +57,6 @@ export function useExtractTextStyle<T extends TextPropsGenerated['attributes']>(
|
|
|
51
57
|
};
|
|
52
58
|
},
|
|
53
59
|
// fonts is intentionally included: extractTextStyleNative resolves weights via font definitions.
|
|
54
|
-
[node, theme, projectColors, fonts],
|
|
60
|
+
[node, theme, projectColors, fonts, baseSize],
|
|
55
61
|
);
|
|
56
62
|
}
|
|
@@ -17,10 +17,14 @@ export function useExtractViewStyle<T extends ViewPropsGenerated['attributes']>(
|
|
|
17
17
|
style: ViewStyle;
|
|
18
18
|
other: Omit<T, StyleAttrKey> & { scrollable?: boolean };
|
|
19
19
|
} {
|
|
20
|
-
const { theme, projectColors } = useBuilderParams();
|
|
20
|
+
const { mockTheme: theme, projectColors, baseSize } = useBuilderParams();
|
|
21
21
|
|
|
22
22
|
return useMemo(() => {
|
|
23
|
-
const style = extractViewStyleNative(node, {
|
|
23
|
+
const style = extractViewStyleNative(node, {
|
|
24
|
+
theme,
|
|
25
|
+
projectColors,
|
|
26
|
+
baseSize,
|
|
27
|
+
});
|
|
24
28
|
const attrs = node.attributes;
|
|
25
29
|
const stripped = stripStyleKeys(toAttributeRecord(attrs));
|
|
26
30
|
const styleBag = getStyleBag(attrs);
|
|
@@ -35,5 +39,5 @@ export function useExtractViewStyle<T extends ViewPropsGenerated['attributes']>(
|
|
|
35
39
|
| undefined,
|
|
36
40
|
} as Omit<T, StyleAttrKey> & { scrollable?: boolean },
|
|
37
41
|
};
|
|
38
|
-
}, [node, theme, projectColors]);
|
|
42
|
+
}, [node, theme, projectColors, baseSize]);
|
|
39
43
|
}
|
|
@@ -8,10 +8,10 @@ import { extractImageStyle } from '../../../utils/extractImageStyle';
|
|
|
8
8
|
export function useExtractImageStyle<
|
|
9
9
|
T extends ImagePropsGenerated['attributes'],
|
|
10
10
|
>(node: NodeData<T>): CSSProperties {
|
|
11
|
-
const { theme, projectColors } = useBuilderParams();
|
|
11
|
+
const { mockTheme: theme, projectColors, baseSize } = useBuilderParams();
|
|
12
12
|
|
|
13
13
|
return useMemo(
|
|
14
|
-
() => extractImageStyle(node, { theme, projectColors }),
|
|
15
|
-
[node, theme, projectColors],
|
|
14
|
+
() => extractImageStyle(node, { theme, projectColors, baseSize }),
|
|
15
|
+
[node, theme, projectColors, baseSize],
|
|
16
16
|
);
|
|
17
17
|
}
|
|
@@ -9,7 +9,12 @@ export function useExtractTextStyle<T extends TextPropsGenerated['attributes']>(
|
|
|
9
9
|
node: NodeData<T>,
|
|
10
10
|
directlyTextStyle = false,
|
|
11
11
|
): CSSProperties {
|
|
12
|
-
const {
|
|
12
|
+
const {
|
|
13
|
+
mockTheme: theme,
|
|
14
|
+
projectColors,
|
|
15
|
+
fonts,
|
|
16
|
+
baseSize,
|
|
17
|
+
} = useBuilderParams();
|
|
13
18
|
|
|
14
19
|
return useMemo(
|
|
15
20
|
() =>
|
|
@@ -18,8 +23,9 @@ export function useExtractTextStyle<T extends TextPropsGenerated['attributes']>(
|
|
|
18
23
|
projectColors,
|
|
19
24
|
fonts,
|
|
20
25
|
directlyTextStyle,
|
|
26
|
+
baseSize,
|
|
21
27
|
}),
|
|
22
28
|
// fonts is intentionally included: extractTextStyle resolves weights via font definitions.
|
|
23
|
-
[node, theme, projectColors, fonts, directlyTextStyle],
|
|
29
|
+
[node, theme, projectColors, fonts, directlyTextStyle, baseSize],
|
|
24
30
|
);
|
|
25
31
|
}
|