@developer_tribe/react-builder 1.2.44-test.1 → 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/FormSubmitButton/FormSubmitButtonProps.generated.d.ts +8 -3
- package/dist/build-components/GlobalProvider/globalProviderUtils.d.ts +4 -13
- package/dist/build-components/GlobalProvider/useGlobalProviderLogic.d.ts +15 -0
- package/dist/build-components/OnboardButton/OnboardButtonProps.generated.d.ts +8 -3
- package/dist/build-components/SystemButton/SystemButtonProps.generated.d.ts +8 -3
- package/dist/build-components/SystemButton/usePlacementButtonEvents.d.ts +9 -2
- package/dist/build-components/patterns.generated.d.ts +15 -9
- 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 +3 -3
- package/dist/index.web.cjs.js.map +1 -1
- package/dist/index.web.esm.js +3 -3
- package/dist/index.web.esm.js.map +1 -1
- package/dist/utils/nodeTree.d.ts +18 -0
- package/package.json +1 -1
- package/scripts/prebuild/utils/validateAllComponentsOrThrow.js +68 -4
- package/src/assets/meta.json +1 -1
- package/src/assets/samples/global-onboard-flow.json +7 -1
- package/src/assets/samples/terms-and-privacy-no-form.json +1 -1
- package/src/assets/samples/terms-and-privacy.json +1 -1
- 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/FormCheckbox/FormCheckbox.tsx +3 -1
- package/src/build-components/FormSubmitButton/FormSubmitButton.tsx +3 -0
- package/src/build-components/FormSubmitButton/FormSubmitButtonProps.generated.ts +26 -3
- package/src/build-components/GlobalProvider/GlobalProvider.tsx +4 -144
- package/src/build-components/GlobalProvider/globalProviderUtils.ts +79 -38
- package/src/build-components/GlobalProvider/useGlobalNavigation.ts +0 -5
- package/src/build-components/GlobalProvider/useGlobalProviderLogic.ts +172 -0
- package/src/build-components/OnboardButton/OnboardButton.tsx +3 -0
- package/src/build-components/OnboardButton/OnboardButtonProps.generated.ts +26 -3
- package/src/build-components/OnboardButton/pattern.json +5 -3
- package/src/build-components/SystemButton/SystemButton.tsx +3 -0
- package/src/build-components/SystemButton/SystemButtonProps.generated.ts +26 -3
- package/src/build-components/SystemButton/pattern.json +5 -3
- package/src/build-components/SystemButton/usePlacementButtonEvents.ts +22 -9
- package/src/build-components/patterns.generated.ts +45 -9
- package/src/components/AttributesEditorPanel.tsx +1 -0
- package/src/patterns/event-constants.json +19 -0
- package/src/utils/nodeTree.ts +115 -0
|
@@ -33,11 +33,13 @@
|
|
|
33
33
|
},
|
|
34
34
|
"types": {
|
|
35
35
|
"EventObject": {
|
|
36
|
-
"type":
|
|
37
|
-
"permission": "
|
|
36
|
+
"type": "$ref:event-constants.eventTypes",
|
|
37
|
+
"permission": "$ref:event-constants.permissionTypes",
|
|
38
38
|
"navigate_to": "string",
|
|
39
39
|
"targetIndex": "number",
|
|
40
|
-
"placementKey": "
|
|
40
|
+
"placementKey": "$ref:event-constants.placementKeys",
|
|
41
|
+
"conditionKey": "$ref:event-constants.conditionKeys",
|
|
42
|
+
"value": "boolean"
|
|
41
43
|
}
|
|
42
44
|
},
|
|
43
45
|
"meta": {
|
|
@@ -2,13 +2,15 @@ import { useRef, useCallback } from 'react';
|
|
|
2
2
|
import type { MockOSContextValue } from '../../mockOS/context/MockOSContextBase';
|
|
3
3
|
import type { PermissionStatus } from '../../mockOS/managers/mockPermissionManager';
|
|
4
4
|
|
|
5
|
-
/** Event shape shared by SystemButton and OnboardButton. Placement = go to placementKey (onboard/terms/paywall); Navigate = navigate_to or carousel. */
|
|
5
|
+
/** Event shape shared by SystemButton and OnboardButton. Placement = go to placementKey (onboard/terms/paywall); Navigate = navigate_to or carousel; SetCondition = update a global boolean condition. */
|
|
6
6
|
export interface PlacementEventObject {
|
|
7
|
-
type?: 'Permission' | 'Navigate' | 'Placement';
|
|
7
|
+
type?: 'Permission' | 'Navigate' | 'Placement' | 'SetCondition';
|
|
8
8
|
permission?: string | null;
|
|
9
9
|
placementKey?: string;
|
|
10
10
|
navigate_to?: string;
|
|
11
11
|
targetIndex?: number;
|
|
12
|
+
conditionKey?: string;
|
|
13
|
+
value?: boolean;
|
|
12
14
|
}
|
|
13
15
|
|
|
14
16
|
export interface UsePlacementButtonEventsOptions {
|
|
@@ -24,6 +26,11 @@ export interface UsePlacementButtonEventsOptions {
|
|
|
24
26
|
* to MockOSContext. Return true if the navigation was handled.
|
|
25
27
|
*/
|
|
26
28
|
globalNavigate?: (target: string) => boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Optional callback to set a global boolean condition (from GlobalContext).
|
|
31
|
+
* Used by SetCondition events.
|
|
32
|
+
*/
|
|
33
|
+
setCondition?: (key: string, value: boolean) => void;
|
|
27
34
|
}
|
|
28
35
|
|
|
29
36
|
/**
|
|
@@ -40,6 +47,7 @@ export function usePlacementButtonEvents(
|
|
|
40
47
|
requestPermission,
|
|
41
48
|
onNavigateWithoutPlacement,
|
|
42
49
|
globalNavigate,
|
|
50
|
+
setCondition,
|
|
43
51
|
} = options;
|
|
44
52
|
const handledEventsRef = useRef<PlacementEventObject[]>([]);
|
|
45
53
|
|
|
@@ -47,10 +55,13 @@ export function usePlacementButtonEvents(
|
|
|
47
55
|
* Attempts to navigate to a target. Tries globalNavigate first (GlobalProvider),
|
|
48
56
|
* then falls back to MockOSContext.
|
|
49
57
|
*/
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
58
|
+
const navigateTo = useCallback(
|
|
59
|
+
(target: string): void => {
|
|
60
|
+
if (globalNavigate?.(target)) return;
|
|
61
|
+
context?.navigation(target as Parameters<typeof context.navigation>[0]);
|
|
62
|
+
},
|
|
63
|
+
[context, globalNavigate],
|
|
64
|
+
);
|
|
54
65
|
|
|
55
66
|
const handleClick = useCallback(async () => {
|
|
56
67
|
const list = events ?? [];
|
|
@@ -64,6 +75,9 @@ export function usePlacementButtonEvents(
|
|
|
64
75
|
const permission = e.permission ?? 'camera';
|
|
65
76
|
await requestPermission(permission);
|
|
66
77
|
handledEventsRef.current.push(e);
|
|
78
|
+
} else if (e.type === 'SetCondition' && e.conditionKey) {
|
|
79
|
+
setCondition?.(e.conditionKey, e.value ?? false);
|
|
80
|
+
handledEventsRef.current.push(e);
|
|
67
81
|
} else if (e.type === 'Placement' && e.placementKey) {
|
|
68
82
|
const target =
|
|
69
83
|
e.placementKey === 'paywall' ? 'paywall' : e.placementKey;
|
|
@@ -88,13 +102,12 @@ export function usePlacementButtonEvents(
|
|
|
88
102
|
}
|
|
89
103
|
}
|
|
90
104
|
}
|
|
91
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
92
105
|
}, [
|
|
93
106
|
events,
|
|
94
|
-
context,
|
|
95
107
|
requestPermission,
|
|
108
|
+
setCondition,
|
|
109
|
+
navigateTo,
|
|
96
110
|
onNavigateWithoutPlacement,
|
|
97
|
-
globalNavigate,
|
|
98
111
|
]);
|
|
99
112
|
|
|
100
113
|
return handleClick;
|
|
@@ -5621,11 +5621,23 @@ export const patterns = [
|
|
|
5621
5621
|
},
|
|
5622
5622
|
types: {
|
|
5623
5623
|
EventObject: {
|
|
5624
|
-
type: ['Permission', 'Navigate', 'Placement'],
|
|
5625
|
-
permission:
|
|
5624
|
+
type: ['Permission', 'Navigate', 'Placement', 'SetCondition'],
|
|
5625
|
+
permission: [
|
|
5626
|
+
'notification',
|
|
5627
|
+
'camera',
|
|
5628
|
+
'microphone',
|
|
5629
|
+
'location',
|
|
5630
|
+
'photos',
|
|
5631
|
+
'contacts',
|
|
5632
|
+
'att',
|
|
5633
|
+
'rating',
|
|
5634
|
+
'GDPR',
|
|
5635
|
+
],
|
|
5626
5636
|
navigate_to: 'string',
|
|
5627
5637
|
targetIndex: 'number',
|
|
5628
|
-
placementKey: '
|
|
5638
|
+
placementKey: ['terms', 'onboard', 'paywall', 'subscription', 'home'],
|
|
5639
|
+
conditionKey: ['termsAccepted'],
|
|
5640
|
+
value: 'boolean',
|
|
5629
5641
|
},
|
|
5630
5642
|
},
|
|
5631
5643
|
meta: {
|
|
@@ -7748,11 +7760,23 @@ export const patterns = [
|
|
|
7748
7760
|
},
|
|
7749
7761
|
types: {
|
|
7750
7762
|
EventObject: {
|
|
7751
|
-
type: ['Permission', 'Navigate', 'Placement'],
|
|
7752
|
-
permission:
|
|
7763
|
+
type: ['Permission', 'Navigate', 'Placement', 'SetCondition'],
|
|
7764
|
+
permission: [
|
|
7765
|
+
'notification',
|
|
7766
|
+
'camera',
|
|
7767
|
+
'microphone',
|
|
7768
|
+
'location',
|
|
7769
|
+
'photos',
|
|
7770
|
+
'contacts',
|
|
7771
|
+
'att',
|
|
7772
|
+
'rating',
|
|
7773
|
+
'GDPR',
|
|
7774
|
+
],
|
|
7753
7775
|
navigate_to: 'string',
|
|
7754
7776
|
targetIndex: 'number',
|
|
7755
|
-
placementKey: '
|
|
7777
|
+
placementKey: ['terms', 'onboard', 'paywall', 'subscription', 'home'],
|
|
7778
|
+
conditionKey: ['termsAccepted'],
|
|
7779
|
+
value: 'boolean',
|
|
7756
7780
|
},
|
|
7757
7781
|
},
|
|
7758
7782
|
meta: {
|
|
@@ -16593,11 +16617,23 @@ export const patterns = [
|
|
|
16593
16617
|
},
|
|
16594
16618
|
types: {
|
|
16595
16619
|
EventObject: {
|
|
16596
|
-
type: ['Permission', 'Navigate', 'Placement'],
|
|
16597
|
-
permission:
|
|
16620
|
+
type: ['Permission', 'Navigate', 'Placement', 'SetCondition'],
|
|
16621
|
+
permission: [
|
|
16622
|
+
'notification',
|
|
16623
|
+
'camera',
|
|
16624
|
+
'microphone',
|
|
16625
|
+
'location',
|
|
16626
|
+
'photos',
|
|
16627
|
+
'contacts',
|
|
16628
|
+
'att',
|
|
16629
|
+
'rating',
|
|
16630
|
+
'GDPR',
|
|
16631
|
+
],
|
|
16598
16632
|
navigate_to: 'string',
|
|
16599
16633
|
targetIndex: 'number',
|
|
16600
|
-
placementKey: '
|
|
16634
|
+
placementKey: ['terms', 'onboard', 'paywall', 'subscription', 'home'],
|
|
16635
|
+
conditionKey: ['termsAccepted'],
|
|
16636
|
+
value: 'boolean',
|
|
16601
16637
|
},
|
|
16602
16638
|
},
|
|
16603
16639
|
},
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$comment": "Central event constants. Referenced via $ref in pattern.json types blocks. Run 'yarn prebuild' after changes.",
|
|
3
|
+
"eventTypes": ["Permission", "Navigate", "Placement", "SetCondition"],
|
|
4
|
+
"placementKeys": ["terms", "onboard", "paywall", "subscription", "home"],
|
|
5
|
+
"conditionKeys": ["termsAccepted"],
|
|
6
|
+
"permissionTypes": [
|
|
7
|
+
"notification",
|
|
8
|
+
"camera",
|
|
9
|
+
"microphone",
|
|
10
|
+
"location",
|
|
11
|
+
"photos",
|
|
12
|
+
"contacts",
|
|
13
|
+
"att",
|
|
14
|
+
"rating",
|
|
15
|
+
"GDPR"
|
|
16
|
+
],
|
|
17
|
+
"validationTypes": ["required", "email", "url", "min", "max"],
|
|
18
|
+
"formFieldNames": ["email", "firstName", "lastName", "phone", "birthday"]
|
|
19
|
+
}
|
package/src/utils/nodeTree.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Node, NodeData } from '../types/Node';
|
|
2
|
+
import eventConstants from '../patterns/event-constants.json';
|
|
2
3
|
|
|
3
4
|
export function deleteNodeFromTree(root: Node, target: Node): Node {
|
|
4
5
|
if (root === null || root === undefined) return root;
|
|
@@ -97,3 +98,117 @@ export function findNodeByKey(root: Node, key?: string): Node | null {
|
|
|
97
98
|
|
|
98
99
|
return null;
|
|
99
100
|
}
|
|
101
|
+
|
|
102
|
+
export type ProjectOptions = {
|
|
103
|
+
pageKeys: string[];
|
|
104
|
+
conditionKeys: string[];
|
|
105
|
+
placementKeys: string[];
|
|
106
|
+
formFieldNames: string[];
|
|
107
|
+
eventTypes: string[];
|
|
108
|
+
validationTypes: string[];
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Traverses the entire node tree to dynamically discover project-level metadata
|
|
113
|
+
* (page keys, condition keys, form field names, etc.) and merges them with
|
|
114
|
+
* central constants from event-constants.json.
|
|
115
|
+
*
|
|
116
|
+
* This enables the Attributes Editor to provide a complete list of valid options
|
|
117
|
+
* for dropdown fields, combining predefined standards with actually used keys
|
|
118
|
+
* in the current design.
|
|
119
|
+
*/
|
|
120
|
+
export function collectProjectMetadata(root: Node): ProjectOptions {
|
|
121
|
+
const pageKeys = new Set<string>();
|
|
122
|
+
const conditionKeys = new Set<string>();
|
|
123
|
+
const placementKeys = new Set<string>();
|
|
124
|
+
const formFieldNames = new Set<string>();
|
|
125
|
+
const eventTypes = new Set<string>();
|
|
126
|
+
|
|
127
|
+
function traverse(node: Node) {
|
|
128
|
+
if (!node || typeof node === 'string') return;
|
|
129
|
+
|
|
130
|
+
if (Array.isArray(node)) {
|
|
131
|
+
node.forEach(traverse);
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const data = node as NodeData;
|
|
136
|
+
const type = data.type;
|
|
137
|
+
const attrs = (data.attributes ?? {}) as Record<string, any>;
|
|
138
|
+
|
|
139
|
+
// Collect Page Keys
|
|
140
|
+
if (type === 'GlobalProvider' && Array.isArray(data.children)) {
|
|
141
|
+
data.children.forEach((child) => {
|
|
142
|
+
if (typeof child === 'object' && child !== null && 'key' in child) {
|
|
143
|
+
if (typeof child.key === 'string') pageKeys.add(child.key);
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
if (attrs.pageKey && typeof attrs.pageKey === 'string') {
|
|
148
|
+
pageKeys.add(attrs.pageKey);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Collect Condition Keys
|
|
152
|
+
if (attrs.conditionKey && typeof attrs.conditionKey === 'string') {
|
|
153
|
+
conditionKeys.add(attrs.conditionKey);
|
|
154
|
+
}
|
|
155
|
+
if (Array.isArray(attrs.skipConditions)) {
|
|
156
|
+
attrs.skipConditions.forEach((entry: any) => {
|
|
157
|
+
if (entry?.conditionKey) conditionKeys.add(entry.conditionKey);
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// Collect Placement Keys
|
|
162
|
+
if (attrs.placementKey && typeof attrs.placementKey === 'string') {
|
|
163
|
+
placementKeys.add(attrs.placementKey);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Collect Form Field Names
|
|
167
|
+
if (type.startsWith('Form') && type !== 'FormProvider' && attrs.name) {
|
|
168
|
+
if (typeof attrs.name === 'string') formFieldNames.add(attrs.name);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Collect from events
|
|
172
|
+
if (Array.isArray(attrs.events)) {
|
|
173
|
+
attrs.events.forEach((evt: any) => {
|
|
174
|
+
if (evt.type && typeof evt.type === 'string') eventTypes.add(evt.type);
|
|
175
|
+
if (evt.navigate_to) pageKeys.add(evt.navigate_to);
|
|
176
|
+
if (evt.placementKey) placementKeys.add(evt.placementKey);
|
|
177
|
+
if (evt.conditionKey) conditionKeys.add(evt.conditionKey);
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (data.children) {
|
|
182
|
+
traverse(data.children as Node);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
traverse(root);
|
|
187
|
+
|
|
188
|
+
// Merge with central constants for a complete set of options
|
|
189
|
+
const result: ProjectOptions = {
|
|
190
|
+
pageKeys: Array.from(
|
|
191
|
+
new Set([...pageKeys, ...eventConstants.placementKeys]),
|
|
192
|
+
).sort(),
|
|
193
|
+
conditionKeys: Array.from(
|
|
194
|
+
new Set([...conditionKeys, ...eventConstants.conditionKeys]),
|
|
195
|
+
).sort(),
|
|
196
|
+
placementKeys: Array.from(
|
|
197
|
+
new Set([...placementKeys, ...eventConstants.placementKeys]),
|
|
198
|
+
).sort(),
|
|
199
|
+
formFieldNames: Array.from(
|
|
200
|
+
new Set([
|
|
201
|
+
...formFieldNames,
|
|
202
|
+
...((eventConstants as any).formFieldNames as string[]),
|
|
203
|
+
]),
|
|
204
|
+
).sort(),
|
|
205
|
+
eventTypes: Array.from(
|
|
206
|
+
new Set([...eventTypes, ...eventConstants.eventTypes]),
|
|
207
|
+
).sort(),
|
|
208
|
+
validationTypes: Array.from(
|
|
209
|
+
new Set((eventConstants as any).validationTypes as string[]),
|
|
210
|
+
).sort(),
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
return result;
|
|
214
|
+
}
|