@developer_tribe/react-builder 1.2.43 → 1.2.44-test.2
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/attributes-editor/Field.d.ts +3 -1
- package/dist/attributes-editor/attributesEditorModelTypes.d.ts +3 -0
- package/dist/attributes-editor/useAttributesEditorModel.d.ts +1 -1
- package/dist/build-components/Checkbox/Checkbox.d.ts +6 -0
- package/dist/build-components/Checkbox/CheckboxProps.generated.d.ts +67 -0
- package/dist/build-components/FormCheckbox/FormCheckbox.d.ts +3 -0
- package/dist/build-components/FormCheckbox/FormCheckboxProps.generated.d.ts +69 -0
- package/dist/build-components/FormErrorText/FormErrorText.d.ts +3 -0
- package/dist/build-components/FormErrorText/FormErrorTextProps.generated.d.ts +61 -0
- package/dist/build-components/FormProvider/FormProvider.d.ts +11 -0
- package/dist/build-components/FormProvider/FormProviderProps.generated.d.ts +55 -0
- package/dist/build-components/FormSubmitButton/FormSubmitButton.d.ts +2 -0
- package/dist/build-components/FormSubmitButton/FormSubmitButtonProps.generated.d.ts +78 -0
- package/dist/build-components/GlobalProvider/GlobalContext.d.ts +28 -0
- package/dist/build-components/GlobalProvider/GlobalProvider.d.ts +5 -0
- package/dist/build-components/GlobalProvider/GlobalProviderProps.generated.d.ts +60 -0
- package/dist/build-components/GlobalProvider/globalProviderUtils.d.ts +28 -0
- package/dist/build-components/GlobalProvider/useGlobalNavigation.d.ts +19 -0
- package/dist/build-components/GlobalProvider/useGlobalProviderLogic.d.ts +15 -0
- package/dist/build-components/OnboardButton/OnboardButtonProps.generated.d.ts +22 -10
- package/dist/build-components/OnboardProvider/OnboardProviderProps.generated.d.ts +2 -0
- package/dist/build-components/PaywallProvider/PaywallProviderProps.generated.d.ts +2 -0
- package/dist/build-components/SystemButton/SystemButton.d.ts +7 -0
- package/dist/build-components/SystemButton/SystemButtonProps.generated.d.ts +76 -0
- package/dist/build-components/SystemButton/usePlacementButtonEvents.d.ts +35 -0
- package/dist/build-components/TermsProvider/TermsProvider.d.ts +5 -0
- package/dist/build-components/TermsProvider/TermsProviderProps.generated.d.ts +55 -0
- package/dist/build-components/WebView/WebView.d.ts +2 -0
- package/dist/build-components/WebView/WebViewProps.generated.d.ts +59 -0
- package/dist/build-components/index.d.ts +10 -1
- package/dist/build-components/patterns.generated.d.ts +5645 -1686
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/index.web.cjs.js +5 -5
- package/dist/index.web.cjs.js.map +1 -1
- package/dist/index.web.d.ts +1 -0
- package/dist/index.web.esm.js +4 -4
- package/dist/index.web.esm.js.map +1 -1
- package/dist/mockOS/context/MockOSContextBase.d.ts +3 -1
- package/dist/styles.css +1 -1
- package/dist/types/PreviewConfig.d.ts +1 -1
- package/dist/utils/nodeTree.d.ts +18 -0
- package/package.json +2 -1
- package/scripts/prebuild/utils/validateAllComponentsOrThrow.js +68 -4
- package/src/assets/meta.json +1 -1
- package/src/assets/prompt-scheme-onboard.generated.ts +1 -1
- package/src/assets/prompt-scheme-paywall.generated.ts +1 -1
- package/src/assets/samples/getSamples.ts +7 -0
- package/src/assets/samples/global-onboard-flow.json +735 -0
- package/src/assets/samples/terms-and-privacy-no-form.json +108 -0
- package/src/assets/samples/terms-and-privacy.json +130 -0
- package/src/attributes-editor/AttributesEditorView.tsx +3 -0
- package/src/attributes-editor/Field.tsx +91 -2
- package/src/attributes-editor/attributesEditorModelTypes.ts +3 -0
- package/src/attributes-editor/useAttributesEditorModel.ts +8 -0
- package/src/build-components/Checkbox/Checkbox.tsx +165 -0
- package/src/build-components/Checkbox/CheckboxProps.generated.ts +84 -0
- package/src/build-components/Checkbox/pattern.json +83 -0
- package/src/build-components/FormCheckbox/FormCheckbox.tsx +108 -0
- package/src/build-components/FormCheckbox/FormCheckboxProps.generated.ts +86 -0
- package/src/build-components/FormCheckbox/pattern.json +39 -0
- package/src/build-components/FormErrorText/FormErrorText.tsx +34 -0
- package/src/build-components/FormErrorText/FormErrorTextProps.generated.ts +78 -0
- package/src/build-components/FormErrorText/pattern.json +21 -0
- package/src/build-components/FormProvider/FormProvider.tsx +131 -0
- package/src/build-components/FormProvider/FormProviderProps.generated.ts +72 -0
- package/src/build-components/FormProvider/pattern.json +33 -0
- package/src/build-components/FormSubmitButton/FormSubmitButton.tsx +52 -0
- package/src/build-components/FormSubmitButton/FormSubmitButtonProps.generated.ts +114 -0
- package/src/build-components/FormSubmitButton/pattern.json +33 -0
- package/src/build-components/GlobalProvider/GlobalContext.ts +48 -0
- package/src/build-components/GlobalProvider/GlobalProvider.tsx +51 -0
- package/src/build-components/GlobalProvider/GlobalProviderProps.generated.ts +78 -0
- package/src/build-components/GlobalProvider/globalProviderUtils.ts +204 -0
- package/src/build-components/GlobalProvider/pattern.json +55 -0
- package/src/build-components/GlobalProvider/useGlobalNavigation.ts +65 -0
- package/src/build-components/GlobalProvider/useGlobalProviderLogic.ts +172 -0
- package/src/build-components/OnboardButton/OnboardButton.tsx +44 -36
- package/src/build-components/OnboardButton/OnboardButtonProps.generated.ts +40 -10
- package/src/build-components/OnboardButton/pattern.json +7 -4
- package/src/build-components/OnboardProvider/OnboardProviderProps.generated.ts +12 -0
- package/src/build-components/OnboardProvider/pattern.json +9 -1
- package/src/build-components/PaywallProvider/PaywallProviderProps.generated.ts +12 -0
- package/src/build-components/PaywallProvider/pattern.json +9 -1
- package/src/build-components/RenderNode.generated.tsx +46 -1
- package/src/build-components/SystemButton/SystemButton.tsx +74 -0
- package/src/build-components/SystemButton/SystemButtonProps.generated.ts +112 -0
- package/src/build-components/SystemButton/pattern.json +63 -0
- package/src/build-components/SystemButton/usePlacementButtonEvents.ts +114 -0
- package/src/build-components/TermsProvider/TermsProvider.tsx +45 -0
- package/src/build-components/TermsProvider/TermsProviderProps.generated.ts +82 -0
- package/src/build-components/TermsProvider/pattern.json +35 -0
- package/src/build-components/WebView/WebView.tsx +149 -0
- package/src/build-components/WebView/WebViewProps.generated.ts +76 -0
- package/src/build-components/WebView/pattern.json +71 -0
- package/src/build-components/index.ts +45 -0
- package/src/build-components/patterns.generated.ts +5735 -1557
- package/src/components/AttributesEditorPanel.tsx +1 -0
- package/src/index.web.ts +3 -0
- package/src/mockOS/components/MockOSRouter.tsx +21 -0
- package/src/mockOS/context/MockOSContext.tsx +7 -0
- package/src/mockOS/context/MockOSContextBase.ts +4 -0
- package/src/patterns/event-constants.json +19 -0
- package/src/styles/components/_checkbox.scss +19 -0
- package/src/styles/components/_global-provider.scss +131 -0
- package/src/styles/components/_webview.scss +52 -0
- package/src/styles/index.scss +4 -0
- package/src/types/PreviewConfig.ts +19 -0
- package/src/utils/analyseNodeByPatterns.ts +5 -2
- package/src/utils/nodeTree.ts +115 -0
- package/src/utils/projectColors.ts +4 -0
- package/src/.DS_Store +0 -0
- package/src/assets/.DS_Store +0 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Terms and Privacy (no form)",
|
|
3
|
+
"version": "1.1.2",
|
|
4
|
+
"type": "terms",
|
|
5
|
+
"data": {
|
|
6
|
+
"type": "Main",
|
|
7
|
+
"isMain": true,
|
|
8
|
+
"attributes": {
|
|
9
|
+
"useSafeAreaView": true,
|
|
10
|
+
"description": "Terms and Privacy screen without FormProvider; plain Checkbox and SystemButton.",
|
|
11
|
+
"title": "Terms & Privacy",
|
|
12
|
+
"styles": {
|
|
13
|
+
"backgroundColor": "THEME_COLORS.BACKGROUND",
|
|
14
|
+
"flex": 1
|
|
15
|
+
},
|
|
16
|
+
"testID": "TermsPrivacyNoForm-Main"
|
|
17
|
+
},
|
|
18
|
+
"children": [
|
|
19
|
+
{
|
|
20
|
+
"type": "View",
|
|
21
|
+
"attributes": {
|
|
22
|
+
"description": "Header section",
|
|
23
|
+
"styles": {
|
|
24
|
+
"padding": 16,
|
|
25
|
+
"alignItems": "center",
|
|
26
|
+
"borderBottomWidth": 1,
|
|
27
|
+
"borderBottomColor": "THEME_COLORS.LINE",
|
|
28
|
+
"backgroundColor": "THEME_COLORS.BACKGROUND"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"children": [
|
|
32
|
+
{
|
|
33
|
+
"type": "Text",
|
|
34
|
+
"children": "view.terms.header.title",
|
|
35
|
+
"attributes": {
|
|
36
|
+
"styles": {
|
|
37
|
+
"fontSize": 20,
|
|
38
|
+
"fontWeight": "700",
|
|
39
|
+
"color": "THEME_COLORS.TEXT"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
]
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"type": "WebView",
|
|
47
|
+
"attributes": {
|
|
48
|
+
"iosUrl": "https://stage.vpn111.net/page/ios/privacy",
|
|
49
|
+
"androidUrl": "https://stage.vpn111.net/page/android/privacy",
|
|
50
|
+
"styles": {
|
|
51
|
+
"flex": 1,
|
|
52
|
+
"backgroundColor": "THEME_COLORS.BACKGROUND"
|
|
53
|
+
},
|
|
54
|
+
"testID": "TermsPrivacyNoForm-WebView"
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"type": "View",
|
|
59
|
+
"attributes": {
|
|
60
|
+
"description": "Footer section",
|
|
61
|
+
"styles": {
|
|
62
|
+
"padding": 20,
|
|
63
|
+
"backgroundColor": "THEME_COLORS.BACKGROUND",
|
|
64
|
+
"borderTopWidth": 1,
|
|
65
|
+
"borderTopColor": "THEME_COLORS.LINE",
|
|
66
|
+
"gap": 16
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
"children": [
|
|
70
|
+
{
|
|
71
|
+
"type": "Checkbox",
|
|
72
|
+
"attributes": {
|
|
73
|
+
"checked": false,
|
|
74
|
+
"label": "view.terms.checkbox.label",
|
|
75
|
+
"checkedColor": "THEME_COLORS.CHECKBOX_ACTIVE_COLOR",
|
|
76
|
+
"styles": {
|
|
77
|
+
"marginBottom": 8
|
|
78
|
+
},
|
|
79
|
+
"testID": "TermsPrivacyNoForm-Checkbox"
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"type": "SystemButton",
|
|
84
|
+
"attributes": {
|
|
85
|
+
"labelKey": "view.terms.accept.button",
|
|
86
|
+
"events": [
|
|
87
|
+
{
|
|
88
|
+
"type": "Navigate",
|
|
89
|
+
"navigate_to": "home"
|
|
90
|
+
}
|
|
91
|
+
],
|
|
92
|
+
"styles": {
|
|
93
|
+
"backgroundColor": "STATIC_COLORS.ONBOARD_BUTTON_PRIMARY_BACKGROUND",
|
|
94
|
+
"color": "#FFFFFF",
|
|
95
|
+
"height": 48,
|
|
96
|
+
"borderRadius": 8,
|
|
97
|
+
"alignItems": "center",
|
|
98
|
+
"justifyContent": "center",
|
|
99
|
+
"fontWeight": "600"
|
|
100
|
+
},
|
|
101
|
+
"testID": "TermsPrivacyNoForm-AcceptButton"
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
]
|
|
105
|
+
}
|
|
106
|
+
]
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "Terms and Privacy",
|
|
3
|
+
"version": "1.1.2",
|
|
4
|
+
"type": "terms",
|
|
5
|
+
"data": {
|
|
6
|
+
"type": "Main",
|
|
7
|
+
"isMain": true,
|
|
8
|
+
"attributes": {
|
|
9
|
+
"useSafeAreaView": true,
|
|
10
|
+
"description": "Terms and Privacy screen container",
|
|
11
|
+
"title": "Terms & Privacy",
|
|
12
|
+
"styles": {
|
|
13
|
+
"backgroundColor": "THEME_COLORS.BACKGROUND",
|
|
14
|
+
"flex": 1
|
|
15
|
+
},
|
|
16
|
+
"testID": "TermsPrivacy-Main"
|
|
17
|
+
},
|
|
18
|
+
"children": [
|
|
19
|
+
{
|
|
20
|
+
"type": "View",
|
|
21
|
+
"attributes": {
|
|
22
|
+
"description": "Header section",
|
|
23
|
+
"styles": {
|
|
24
|
+
"padding": 16,
|
|
25
|
+
"alignItems": "center",
|
|
26
|
+
"borderBottomWidth": 1,
|
|
27
|
+
"borderBottomColor": "THEME_COLORS.LINE",
|
|
28
|
+
"backgroundColor": "THEME_COLORS.BACKGROUND"
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
"children": [
|
|
32
|
+
{
|
|
33
|
+
"type": "Text",
|
|
34
|
+
"children": "view.terms.header.title",
|
|
35
|
+
"attributes": {
|
|
36
|
+
"styles": {
|
|
37
|
+
"fontSize": 20,
|
|
38
|
+
"fontWeight": "700",
|
|
39
|
+
"color": "THEME_COLORS.TEXT"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
]
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"type": "WebView",
|
|
47
|
+
"attributes": {
|
|
48
|
+
"iosUrl": "https://stage.vpn111.net/page/ios/privacy",
|
|
49
|
+
"androidUrl": "https://stage.vpn111.net/page/android/privacy",
|
|
50
|
+
"styles": {
|
|
51
|
+
"flex": 1,
|
|
52
|
+
"backgroundColor": "THEME_COLORS.BACKGROUND"
|
|
53
|
+
},
|
|
54
|
+
"testID": "TermsPrivacy-WebView"
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"type": "View",
|
|
59
|
+
"attributes": {
|
|
60
|
+
"description": "Footer section",
|
|
61
|
+
"styles": {
|
|
62
|
+
"padding": 20,
|
|
63
|
+
"backgroundColor": "THEME_COLORS.BACKGROUND",
|
|
64
|
+
"borderTopWidth": 1,
|
|
65
|
+
"borderTopColor": "THEME_COLORS.LINE",
|
|
66
|
+
"gap": 16
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
"children": [
|
|
70
|
+
{
|
|
71
|
+
"type": "FormProvider",
|
|
72
|
+
"attributes": {
|
|
73
|
+
"defaultValues": "{\"termsAccepted\": false}",
|
|
74
|
+
"validationErrorMessageKey": "view.terms.error.must_accept"
|
|
75
|
+
},
|
|
76
|
+
"children": [
|
|
77
|
+
{
|
|
78
|
+
"type": "FormCheckbox",
|
|
79
|
+
"attributes": {
|
|
80
|
+
"name": "termsAccepted",
|
|
81
|
+
"validation": ["required"],
|
|
82
|
+
"checked": false,
|
|
83
|
+
"label": "view.terms.checkbox.label",
|
|
84
|
+
"checkedColor": "THEME_COLORS.CHECKBOX_ACTIVE_COLOR",
|
|
85
|
+
"styles": {
|
|
86
|
+
"marginBottom": 8
|
|
87
|
+
},
|
|
88
|
+
"testID": "TermsPrivacy-Checkbox"
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"type": "FormErrorText",
|
|
93
|
+
"attributes": {
|
|
94
|
+
"styles": {
|
|
95
|
+
"marginBottom": 8
|
|
96
|
+
},
|
|
97
|
+
"testID": "TermsPrivacy-FormErrorText"
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"type": "FormSubmitButton",
|
|
102
|
+
"attributes": {
|
|
103
|
+
"labelKey": "view.terms.accept.button",
|
|
104
|
+
"validationRequired": true,
|
|
105
|
+
"disableIfUnvalidated": true,
|
|
106
|
+
"events": [
|
|
107
|
+
{
|
|
108
|
+
"type": "Navigate",
|
|
109
|
+
"navigate_to": "home"
|
|
110
|
+
}
|
|
111
|
+
],
|
|
112
|
+
"styles": {
|
|
113
|
+
"backgroundColor": "STATIC_COLORS.ONBOARD_BUTTON_PRIMARY_BACKGROUND",
|
|
114
|
+
"color": "#FFFFFF",
|
|
115
|
+
"height": 48,
|
|
116
|
+
"borderRadius": 8,
|
|
117
|
+
"alignItems": "center",
|
|
118
|
+
"justifyContent": "center",
|
|
119
|
+
"fontWeight": "600"
|
|
120
|
+
},
|
|
121
|
+
"testID": "TermsPrivacy-AcceptButton"
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
]
|
|
125
|
+
}
|
|
126
|
+
]
|
|
127
|
+
}
|
|
128
|
+
]
|
|
129
|
+
}
|
|
130
|
+
}
|
|
@@ -81,6 +81,7 @@ export function AttributesEditorView(props: AttributesEditorViewProps) {
|
|
|
81
81
|
loadedFonts,
|
|
82
82
|
markFontLoaded,
|
|
83
83
|
addError,
|
|
84
|
+
projectOptions,
|
|
84
85
|
} = props;
|
|
85
86
|
|
|
86
87
|
const headerSection = (
|
|
@@ -277,6 +278,7 @@ export function AttributesEditorView(props: AttributesEditorViewProps) {
|
|
|
277
278
|
viewAttributes={viewAttributes}
|
|
278
279
|
label={isBoolean ? label : undefined}
|
|
279
280
|
preferredScale={preferredScale}
|
|
281
|
+
projectOptions={projectOptions}
|
|
280
282
|
/>
|
|
281
283
|
)}
|
|
282
284
|
</div>
|
|
@@ -355,6 +357,7 @@ export function AttributesEditorView(props: AttributesEditorViewProps) {
|
|
|
355
357
|
viewAttributes={viewAttributes}
|
|
356
358
|
label={isBoolean ? label : undefined}
|
|
357
359
|
preferredScale={preferredScale}
|
|
360
|
+
projectOptions={projectOptions}
|
|
358
361
|
/>
|
|
359
362
|
)}
|
|
360
363
|
</div>
|
|
@@ -12,6 +12,7 @@ import { Checkbox } from '../components/Checkbox';
|
|
|
12
12
|
import { LayoutPreviewPicker } from './LayoutPreviewPicker';
|
|
13
13
|
import { SizeField, type PreferredScale } from './SizeField';
|
|
14
14
|
import { LayoutContext, LayoutFieldName, isBooleanFieldType } from './types';
|
|
15
|
+
import type { ProjectOptions } from '../utils/nodeTree';
|
|
15
16
|
|
|
16
17
|
type FieldProps = {
|
|
17
18
|
name: string;
|
|
@@ -24,6 +25,7 @@ type FieldProps = {
|
|
|
24
25
|
viewAttributes?: Partial<ViewPropsGenerated['attributes']>;
|
|
25
26
|
label?: React.ReactNode;
|
|
26
27
|
preferredScale?: PreferredScale;
|
|
28
|
+
projectOptions?: ProjectOptions;
|
|
27
29
|
};
|
|
28
30
|
|
|
29
31
|
const layoutFieldNames: LayoutFieldName[] = [
|
|
@@ -47,6 +49,7 @@ export function Field({
|
|
|
47
49
|
viewAttributes,
|
|
48
50
|
label,
|
|
49
51
|
preferredScale,
|
|
52
|
+
projectOptions,
|
|
50
53
|
}: FieldProps) {
|
|
51
54
|
if (Array.isArray(type)) {
|
|
52
55
|
if (isLayoutField(name)) {
|
|
@@ -64,6 +67,11 @@ export function Field({
|
|
|
64
67
|
/>
|
|
65
68
|
);
|
|
66
69
|
}
|
|
70
|
+
const options =
|
|
71
|
+
name === 'type'
|
|
72
|
+
? Array.from(new Set([...type, ...(projectOptions?.eventTypes ?? [])]))
|
|
73
|
+
: type;
|
|
74
|
+
|
|
67
75
|
return (
|
|
68
76
|
<select
|
|
69
77
|
value={value ?? ''}
|
|
@@ -71,7 +79,7 @@ export function Field({
|
|
|
71
79
|
className="input"
|
|
72
80
|
>
|
|
73
81
|
<option value="">(none)</option>
|
|
74
|
-
{
|
|
82
|
+
{options.map((opt) => (
|
|
75
83
|
<option key={opt} value={opt}>
|
|
76
84
|
{opt}
|
|
77
85
|
</option>
|
|
@@ -117,6 +125,54 @@ export function Field({
|
|
|
117
125
|
);
|
|
118
126
|
case 'string':
|
|
119
127
|
case 'description':
|
|
128
|
+
if (name === 'validation') {
|
|
129
|
+
const options = projectOptions?.validationTypes ?? [];
|
|
130
|
+
return (
|
|
131
|
+
<select
|
|
132
|
+
value={itemValue ?? ''}
|
|
133
|
+
onChange={(e) => {
|
|
134
|
+
const next = [...arr];
|
|
135
|
+
next[idx] =
|
|
136
|
+
e.target.value === '' ? undefined : e.target.value;
|
|
137
|
+
onChange(next);
|
|
138
|
+
}}
|
|
139
|
+
className="input"
|
|
140
|
+
style={{ flex: 1 }}
|
|
141
|
+
>
|
|
142
|
+
<option value="">(none)</option>
|
|
143
|
+
{options.map((opt) => (
|
|
144
|
+
<option key={opt} value={opt}>
|
|
145
|
+
{opt}
|
|
146
|
+
</option>
|
|
147
|
+
))}
|
|
148
|
+
</select>
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
if (name === 'type') {
|
|
152
|
+
const options = projectOptions?.eventTypes ?? [];
|
|
153
|
+
if (options.length > 0) {
|
|
154
|
+
return (
|
|
155
|
+
<select
|
|
156
|
+
value={itemValue ?? ''}
|
|
157
|
+
onChange={(e) => {
|
|
158
|
+
const next = [...arr];
|
|
159
|
+
next[idx] =
|
|
160
|
+
e.target.value === '' ? undefined : e.target.value;
|
|
161
|
+
onChange(next);
|
|
162
|
+
}}
|
|
163
|
+
className="input"
|
|
164
|
+
style={{ flex: 1 }}
|
|
165
|
+
>
|
|
166
|
+
<option value="">(none)</option>
|
|
167
|
+
{options.map((opt) => (
|
|
168
|
+
<option key={opt} value={opt}>
|
|
169
|
+
{opt}
|
|
170
|
+
</option>
|
|
171
|
+
))}
|
|
172
|
+
</select>
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
120
176
|
return (
|
|
121
177
|
<input
|
|
122
178
|
type="text"
|
|
@@ -244,6 +300,7 @@ export function Field({
|
|
|
244
300
|
layoutContext={layoutContext}
|
|
245
301
|
viewAttributes={viewAttributes}
|
|
246
302
|
label={fieldName}
|
|
303
|
+
projectOptions={projectOptions}
|
|
247
304
|
/>
|
|
248
305
|
</div>
|
|
249
306
|
);
|
|
@@ -265,6 +322,7 @@ export function Field({
|
|
|
265
322
|
projectColors={projectColors}
|
|
266
323
|
layoutContext={layoutContext}
|
|
267
324
|
viewAttributes={viewAttributes}
|
|
325
|
+
projectOptions={projectOptions}
|
|
268
326
|
/>
|
|
269
327
|
</React.Fragment>
|
|
270
328
|
);
|
|
@@ -369,6 +427,7 @@ export function Field({
|
|
|
369
427
|
layoutContext={layoutContext}
|
|
370
428
|
viewAttributes={viewAttributes}
|
|
371
429
|
label={fieldName}
|
|
430
|
+
projectOptions={projectOptions}
|
|
372
431
|
/>
|
|
373
432
|
</div>
|
|
374
433
|
);
|
|
@@ -388,6 +447,7 @@ export function Field({
|
|
|
388
447
|
projectColors={projectColors}
|
|
389
448
|
layoutContext={layoutContext}
|
|
390
449
|
viewAttributes={viewAttributes}
|
|
450
|
+
projectOptions={projectOptions}
|
|
391
451
|
/>
|
|
392
452
|
</React.Fragment>
|
|
393
453
|
);
|
|
@@ -496,7 +556,35 @@ export function Field({
|
|
|
496
556
|
/>
|
|
497
557
|
);
|
|
498
558
|
case 'string':
|
|
499
|
-
case 'description':
|
|
559
|
+
case 'description': {
|
|
560
|
+
let options: string[] = [];
|
|
561
|
+
if (name === 'navigate_to' || name === 'pageKey') {
|
|
562
|
+
options = projectOptions?.pageKeys ?? [];
|
|
563
|
+
} else if (name === 'conditionKey') {
|
|
564
|
+
options = projectOptions?.conditionKeys ?? [];
|
|
565
|
+
} else if (name === 'placementKey') {
|
|
566
|
+
options = projectOptions?.placementKeys ?? [];
|
|
567
|
+
} else if (name === 'name' && componentType?.startsWith('Form')) {
|
|
568
|
+
options = projectOptions?.formFieldNames ?? [];
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
if (options.length > 0) {
|
|
572
|
+
return (
|
|
573
|
+
<select
|
|
574
|
+
value={value ?? ''}
|
|
575
|
+
onChange={(e) => onChange(e.target.value || undefined)}
|
|
576
|
+
className="input"
|
|
577
|
+
>
|
|
578
|
+
<option value="">(none)</option>
|
|
579
|
+
{options.map((opt) => (
|
|
580
|
+
<option key={opt} value={opt}>
|
|
581
|
+
{opt}
|
|
582
|
+
</option>
|
|
583
|
+
))}
|
|
584
|
+
</select>
|
|
585
|
+
);
|
|
586
|
+
}
|
|
587
|
+
|
|
500
588
|
return (
|
|
501
589
|
<input
|
|
502
590
|
type="text"
|
|
@@ -507,6 +595,7 @@ export function Field({
|
|
|
507
595
|
className="input"
|
|
508
596
|
/>
|
|
509
597
|
);
|
|
598
|
+
}
|
|
510
599
|
case 'title':
|
|
511
600
|
return (
|
|
512
601
|
<input
|
|
@@ -3,6 +3,7 @@ import type { ProjectColors } from '../types/Project';
|
|
|
3
3
|
import type { ViewPropsGenerated } from '../build-components/View/ViewProps.generated';
|
|
4
4
|
import type { Fonts } from '../types/Fonts';
|
|
5
5
|
import type { LayoutContext, SchemaEntry } from './types';
|
|
6
|
+
import type { ProjectOptions } from '../utils/nodeTree';
|
|
6
7
|
|
|
7
8
|
export type TabId = 'style' | 'container' | 'other';
|
|
8
9
|
|
|
@@ -10,6 +11,7 @@ export type AttributesEditorProps = {
|
|
|
10
11
|
node: Node;
|
|
11
12
|
onChange: (next: Node) => void;
|
|
12
13
|
projectColors?: ProjectColors;
|
|
14
|
+
projectRoot?: Node;
|
|
13
15
|
};
|
|
14
16
|
|
|
15
17
|
export type AttributesEditorTabConfig = {
|
|
@@ -60,6 +62,7 @@ export type AttributesEditorModel = {
|
|
|
60
62
|
projectColorsForPicker?: ProjectColors;
|
|
61
63
|
viewAttributes?: Partial<ViewPropsGenerated['attributes']>;
|
|
62
64
|
layoutContext: LayoutContext;
|
|
65
|
+
projectOptions: ProjectOptions;
|
|
63
66
|
getAttributeValue: (name: string) => unknown;
|
|
64
67
|
handleAttributeChange: (name: string, val: unknown) => void;
|
|
65
68
|
handleChildrenChange: (val: string) => void;
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
} from '../utils/patterns';
|
|
14
14
|
import { useRenderStore } from '../store';
|
|
15
15
|
import type { LayoutContext, SchemaEntry } from './types';
|
|
16
|
+
import { collectProjectMetadata } from '../utils/nodeTree';
|
|
16
17
|
import {
|
|
17
18
|
buildAttributesEditorEntries,
|
|
18
19
|
findLegacyFlatStyleKeys,
|
|
@@ -36,6 +37,7 @@ export function useAttributesEditorModel({
|
|
|
36
37
|
node,
|
|
37
38
|
onChange,
|
|
38
39
|
projectColors,
|
|
40
|
+
projectRoot,
|
|
39
41
|
}: AttributesEditorProps): AttributesEditorModel {
|
|
40
42
|
const isInvalidNode = !node || isNodeString(node);
|
|
41
43
|
// Memoize baseData to prevent it from changing on every render
|
|
@@ -141,6 +143,11 @@ export function useAttributesEditorModel({
|
|
|
141
143
|
[projectColors],
|
|
142
144
|
);
|
|
143
145
|
|
|
146
|
+
const projectOptions = useMemo(
|
|
147
|
+
() => collectProjectMetadata(projectRoot || baseData),
|
|
148
|
+
[projectRoot, baseData],
|
|
149
|
+
);
|
|
150
|
+
|
|
144
151
|
const viewAttributes = useMemo<
|
|
145
152
|
Partial<ViewPropsGenerated['attributes']> | undefined
|
|
146
153
|
>(
|
|
@@ -428,6 +435,7 @@ export function useAttributesEditorModel({
|
|
|
428
435
|
projectColorsForPicker,
|
|
429
436
|
viewAttributes,
|
|
430
437
|
layoutContext,
|
|
438
|
+
projectOptions,
|
|
431
439
|
getAttributeValue,
|
|
432
440
|
handleAttributeChange,
|
|
433
441
|
handleChildrenChange,
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import React, { useState, useId } from 'react';
|
|
2
|
+
import type { NodeData } from '../../types/Node';
|
|
3
|
+
import type { ViewPropsGenerated } from '../View/ViewProps.generated';
|
|
4
|
+
import { CheckboxComponentProps } from './CheckboxProps.generated';
|
|
5
|
+
import useNode from '../useNode';
|
|
6
|
+
import { useLogRender } from '../../utils/useLogRender';
|
|
7
|
+
import { useExtractViewStyle } from '../../attribute-analyser/style/web/useExtractViewStyle';
|
|
8
|
+
import { parseColor, type ParseColorOptions } from '../../utils/parseColor';
|
|
9
|
+
import { useBuilderParams } from '../../components/BuilderProvider';
|
|
10
|
+
import { useLocalize } from '../../hooks/useLocalize';
|
|
11
|
+
import { Icon } from '../../components/Icon.generated';
|
|
12
|
+
import { useMergedStyle } from '../../utils/useMergedStyle';
|
|
13
|
+
import { getStyleBag, toAttributeRecord } from '../../utils/attributeStyle';
|
|
14
|
+
|
|
15
|
+
export interface CheckboxProps extends CheckboxComponentProps {
|
|
16
|
+
checked?: boolean;
|
|
17
|
+
onCheckedChange?: (value: boolean) => void;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function resolveCheckedColor(
|
|
21
|
+
attrRecord: Record<string, unknown>,
|
|
22
|
+
stylesBag: Record<string, unknown> | undefined,
|
|
23
|
+
colorOpts: ParseColorOptions,
|
|
24
|
+
): string {
|
|
25
|
+
const raw =
|
|
26
|
+
(attrRecord.checkedColor as string | undefined) ??
|
|
27
|
+
(attrRecord.color as string | undefined) ??
|
|
28
|
+
(stylesBag?.color as string | undefined);
|
|
29
|
+
const token =
|
|
30
|
+
(typeof raw === 'string' && raw.trim()) ||
|
|
31
|
+
'THEME_COLORS.CHECKBOX_ACTIVE_COLOR';
|
|
32
|
+
return parseColor(token, colorOpts) ?? '#000000';
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function Checkbox({
|
|
36
|
+
node,
|
|
37
|
+
checked: controlledChecked,
|
|
38
|
+
onCheckedChange,
|
|
39
|
+
}: CheckboxProps) {
|
|
40
|
+
useLogRender('Checkbox');
|
|
41
|
+
node = useNode(node);
|
|
42
|
+
const attrs = node.attributes;
|
|
43
|
+
const attrRecord = toAttributeRecord(attrs);
|
|
44
|
+
const stylesBag = getStyleBag(attrs);
|
|
45
|
+
const labelId = useId();
|
|
46
|
+
const viewStyle = useExtractViewStyle(
|
|
47
|
+
node as NodeData<ViewPropsGenerated['attributes']>,
|
|
48
|
+
);
|
|
49
|
+
const { selectedTheme: theme, projectColors } = useBuilderParams();
|
|
50
|
+
const localize = useLocalize();
|
|
51
|
+
const colorOpts: ParseColorOptions = {
|
|
52
|
+
projectColors,
|
|
53
|
+
theme: theme ?? 'light',
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const isControlled =
|
|
57
|
+
controlledChecked !== undefined && onCheckedChange !== undefined;
|
|
58
|
+
const [internalChecked, setInternalChecked] = useState(
|
|
59
|
+
attrs?.checked ?? false,
|
|
60
|
+
);
|
|
61
|
+
const checked = isControlled ? controlledChecked : internalChecked;
|
|
62
|
+
|
|
63
|
+
const activeColor = resolveCheckedColor(attrRecord, stylesBag, colorOpts);
|
|
64
|
+
|
|
65
|
+
const inactiveBorderColor =
|
|
66
|
+
parseColor('THEME_COLORS.LINE', colorOpts) ??
|
|
67
|
+
parseColor('STATIC_COLORS.ONBOARD_SEPARATOR_COLOR', colorOpts);
|
|
68
|
+
|
|
69
|
+
const labelRaw = attrs?.label ?? '';
|
|
70
|
+
const label = localize(labelRaw);
|
|
71
|
+
|
|
72
|
+
const labelFontSize = attrs?.styles?.fontSize ?? 14;
|
|
73
|
+
const labelFontFamily = attrs?.styles?.fontFamily as string | undefined;
|
|
74
|
+
const labelFontWeight = attrs?.styles?.fontWeight as
|
|
75
|
+
| string
|
|
76
|
+
| number
|
|
77
|
+
| undefined;
|
|
78
|
+
const labelTextAlign = attrs?.styles?.textAlign as
|
|
79
|
+
| React.CSSProperties['textAlign']
|
|
80
|
+
| undefined;
|
|
81
|
+
const labelColor =
|
|
82
|
+
parseColor(attrs?.styles?.color as string, colorOpts) ??
|
|
83
|
+
parseColor('THEME_COLORS.TEXT', colorOpts) ??
|
|
84
|
+
parseColor('STATIC_COLORS.BLACK', colorOpts);
|
|
85
|
+
|
|
86
|
+
const checkIconColor =
|
|
87
|
+
parseColor('STATIC_COLORS.WHITE', colorOpts) ?? undefined;
|
|
88
|
+
|
|
89
|
+
const styles = attrs?.styles;
|
|
90
|
+
const boxWidth = styles?.width ?? 20;
|
|
91
|
+
const boxHeight = styles?.height ?? 20;
|
|
92
|
+
const boxBorderRadius = styles?.borderRadius ?? 4;
|
|
93
|
+
const checkIconSize = styles?.checkIconSize ?? 12;
|
|
94
|
+
const checkIconStrokeWidth = styles?.checkIconStrokeWidth ?? 1.7;
|
|
95
|
+
const boxMarginRight = styles?.marginRight ?? 10;
|
|
96
|
+
|
|
97
|
+
const handleToggle = () => {
|
|
98
|
+
const next = !checked;
|
|
99
|
+
if (isControlled) {
|
|
100
|
+
onCheckedChange?.(next);
|
|
101
|
+
} else {
|
|
102
|
+
setInternalChecked(next);
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const handleKeyDown = (e: React.KeyboardEvent) => {
|
|
107
|
+
if (e.key === ' ' || e.key === 'Enter') {
|
|
108
|
+
e.preventDefault();
|
|
109
|
+
handleToggle();
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
const containerStyle = useMergedStyle(viewStyle);
|
|
114
|
+
const boxStyle = {
|
|
115
|
+
width: boxWidth,
|
|
116
|
+
height: boxHeight,
|
|
117
|
+
minWidth: boxWidth,
|
|
118
|
+
minHeight: boxHeight,
|
|
119
|
+
borderRadius: boxBorderRadius,
|
|
120
|
+
border: `2px solid ${checked ? (activeColor ?? 'transparent') : (inactiveBorderColor ?? 'transparent')}`,
|
|
121
|
+
backgroundColor: checked ? (activeColor ?? 'transparent') : 'transparent',
|
|
122
|
+
marginRight: boxMarginRight,
|
|
123
|
+
};
|
|
124
|
+
const labelStyle: React.CSSProperties = {
|
|
125
|
+
fontSize: labelFontSize,
|
|
126
|
+
color: labelColor ?? undefined,
|
|
127
|
+
fontFamily: labelFontFamily,
|
|
128
|
+
fontWeight: labelFontWeight,
|
|
129
|
+
textAlign: labelTextAlign,
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
return (
|
|
133
|
+
<div
|
|
134
|
+
role="checkbox"
|
|
135
|
+
aria-checked={checked}
|
|
136
|
+
aria-labelledby={label ? labelId : undefined}
|
|
137
|
+
aria-label={!label ? 'Checkbox' : undefined}
|
|
138
|
+
tabIndex={0}
|
|
139
|
+
className="rb-checkbox"
|
|
140
|
+
style={containerStyle}
|
|
141
|
+
onClick={handleToggle}
|
|
142
|
+
onKeyDown={handleKeyDown}
|
|
143
|
+
data-testid={attrs?.testID}
|
|
144
|
+
>
|
|
145
|
+
<div className="rb-checkbox__box" style={boxStyle}>
|
|
146
|
+
{checked && (
|
|
147
|
+
<Icon
|
|
148
|
+
iconType="check"
|
|
149
|
+
size={checkIconSize}
|
|
150
|
+
strokeWidth={checkIconStrokeWidth}
|
|
151
|
+
color={
|
|
152
|
+
typeof checkIconColor === 'string' ? checkIconColor : undefined
|
|
153
|
+
}
|
|
154
|
+
alt=""
|
|
155
|
+
/>
|
|
156
|
+
)}
|
|
157
|
+
</div>
|
|
158
|
+
{label ? (
|
|
159
|
+
<span id={labelId} className="rb-checkbox__label" style={labelStyle}>
|
|
160
|
+
{label}
|
|
161
|
+
</span>
|
|
162
|
+
) : null}
|
|
163
|
+
</div>
|
|
164
|
+
);
|
|
165
|
+
}
|