@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.
Files changed (115) hide show
  1. package/dist/attributes-editor/Field.d.ts +3 -1
  2. package/dist/attributes-editor/attributesEditorModelTypes.d.ts +3 -0
  3. package/dist/attributes-editor/useAttributesEditorModel.d.ts +1 -1
  4. package/dist/build-components/Checkbox/Checkbox.d.ts +6 -0
  5. package/dist/build-components/Checkbox/CheckboxProps.generated.d.ts +67 -0
  6. package/dist/build-components/FormCheckbox/FormCheckbox.d.ts +3 -0
  7. package/dist/build-components/FormCheckbox/FormCheckboxProps.generated.d.ts +69 -0
  8. package/dist/build-components/FormErrorText/FormErrorText.d.ts +3 -0
  9. package/dist/build-components/FormErrorText/FormErrorTextProps.generated.d.ts +61 -0
  10. package/dist/build-components/FormProvider/FormProvider.d.ts +11 -0
  11. package/dist/build-components/FormProvider/FormProviderProps.generated.d.ts +55 -0
  12. package/dist/build-components/FormSubmitButton/FormSubmitButton.d.ts +2 -0
  13. package/dist/build-components/FormSubmitButton/FormSubmitButtonProps.generated.d.ts +78 -0
  14. package/dist/build-components/GlobalProvider/GlobalContext.d.ts +28 -0
  15. package/dist/build-components/GlobalProvider/GlobalProvider.d.ts +5 -0
  16. package/dist/build-components/GlobalProvider/GlobalProviderProps.generated.d.ts +60 -0
  17. package/dist/build-components/GlobalProvider/globalProviderUtils.d.ts +28 -0
  18. package/dist/build-components/GlobalProvider/useGlobalNavigation.d.ts +19 -0
  19. package/dist/build-components/GlobalProvider/useGlobalProviderLogic.d.ts +15 -0
  20. package/dist/build-components/OnboardButton/OnboardButtonProps.generated.d.ts +22 -10
  21. package/dist/build-components/OnboardProvider/OnboardProviderProps.generated.d.ts +2 -0
  22. package/dist/build-components/PaywallProvider/PaywallProviderProps.generated.d.ts +2 -0
  23. package/dist/build-components/SystemButton/SystemButton.d.ts +7 -0
  24. package/dist/build-components/SystemButton/SystemButtonProps.generated.d.ts +76 -0
  25. package/dist/build-components/SystemButton/usePlacementButtonEvents.d.ts +35 -0
  26. package/dist/build-components/TermsProvider/TermsProvider.d.ts +5 -0
  27. package/dist/build-components/TermsProvider/TermsProviderProps.generated.d.ts +55 -0
  28. package/dist/build-components/WebView/WebView.d.ts +2 -0
  29. package/dist/build-components/WebView/WebViewProps.generated.d.ts +59 -0
  30. package/dist/build-components/index.d.ts +10 -1
  31. package/dist/build-components/patterns.generated.d.ts +5645 -1686
  32. package/dist/index.cjs.js +1 -1
  33. package/dist/index.cjs.js.map +1 -1
  34. package/dist/index.esm.js +1 -1
  35. package/dist/index.esm.js.map +1 -1
  36. package/dist/index.web.cjs.js +5 -5
  37. package/dist/index.web.cjs.js.map +1 -1
  38. package/dist/index.web.d.ts +1 -0
  39. package/dist/index.web.esm.js +4 -4
  40. package/dist/index.web.esm.js.map +1 -1
  41. package/dist/mockOS/context/MockOSContextBase.d.ts +3 -1
  42. package/dist/styles.css +1 -1
  43. package/dist/types/PreviewConfig.d.ts +1 -1
  44. package/dist/utils/nodeTree.d.ts +18 -0
  45. package/package.json +2 -1
  46. package/scripts/prebuild/utils/validateAllComponentsOrThrow.js +68 -4
  47. package/src/assets/meta.json +1 -1
  48. package/src/assets/prompt-scheme-onboard.generated.ts +1 -1
  49. package/src/assets/prompt-scheme-paywall.generated.ts +1 -1
  50. package/src/assets/samples/getSamples.ts +7 -0
  51. package/src/assets/samples/global-onboard-flow.json +735 -0
  52. package/src/assets/samples/terms-and-privacy-no-form.json +108 -0
  53. package/src/assets/samples/terms-and-privacy.json +130 -0
  54. package/src/attributes-editor/AttributesEditorView.tsx +3 -0
  55. package/src/attributes-editor/Field.tsx +91 -2
  56. package/src/attributes-editor/attributesEditorModelTypes.ts +3 -0
  57. package/src/attributes-editor/useAttributesEditorModel.ts +8 -0
  58. package/src/build-components/Checkbox/Checkbox.tsx +165 -0
  59. package/src/build-components/Checkbox/CheckboxProps.generated.ts +84 -0
  60. package/src/build-components/Checkbox/pattern.json +83 -0
  61. package/src/build-components/FormCheckbox/FormCheckbox.tsx +108 -0
  62. package/src/build-components/FormCheckbox/FormCheckboxProps.generated.ts +86 -0
  63. package/src/build-components/FormCheckbox/pattern.json +39 -0
  64. package/src/build-components/FormErrorText/FormErrorText.tsx +34 -0
  65. package/src/build-components/FormErrorText/FormErrorTextProps.generated.ts +78 -0
  66. package/src/build-components/FormErrorText/pattern.json +21 -0
  67. package/src/build-components/FormProvider/FormProvider.tsx +131 -0
  68. package/src/build-components/FormProvider/FormProviderProps.generated.ts +72 -0
  69. package/src/build-components/FormProvider/pattern.json +33 -0
  70. package/src/build-components/FormSubmitButton/FormSubmitButton.tsx +52 -0
  71. package/src/build-components/FormSubmitButton/FormSubmitButtonProps.generated.ts +114 -0
  72. package/src/build-components/FormSubmitButton/pattern.json +33 -0
  73. package/src/build-components/GlobalProvider/GlobalContext.ts +48 -0
  74. package/src/build-components/GlobalProvider/GlobalProvider.tsx +51 -0
  75. package/src/build-components/GlobalProvider/GlobalProviderProps.generated.ts +78 -0
  76. package/src/build-components/GlobalProvider/globalProviderUtils.ts +204 -0
  77. package/src/build-components/GlobalProvider/pattern.json +55 -0
  78. package/src/build-components/GlobalProvider/useGlobalNavigation.ts +65 -0
  79. package/src/build-components/GlobalProvider/useGlobalProviderLogic.ts +172 -0
  80. package/src/build-components/OnboardButton/OnboardButton.tsx +44 -36
  81. package/src/build-components/OnboardButton/OnboardButtonProps.generated.ts +40 -10
  82. package/src/build-components/OnboardButton/pattern.json +7 -4
  83. package/src/build-components/OnboardProvider/OnboardProviderProps.generated.ts +12 -0
  84. package/src/build-components/OnboardProvider/pattern.json +9 -1
  85. package/src/build-components/PaywallProvider/PaywallProviderProps.generated.ts +12 -0
  86. package/src/build-components/PaywallProvider/pattern.json +9 -1
  87. package/src/build-components/RenderNode.generated.tsx +46 -1
  88. package/src/build-components/SystemButton/SystemButton.tsx +74 -0
  89. package/src/build-components/SystemButton/SystemButtonProps.generated.ts +112 -0
  90. package/src/build-components/SystemButton/pattern.json +63 -0
  91. package/src/build-components/SystemButton/usePlacementButtonEvents.ts +114 -0
  92. package/src/build-components/TermsProvider/TermsProvider.tsx +45 -0
  93. package/src/build-components/TermsProvider/TermsProviderProps.generated.ts +82 -0
  94. package/src/build-components/TermsProvider/pattern.json +35 -0
  95. package/src/build-components/WebView/WebView.tsx +149 -0
  96. package/src/build-components/WebView/WebViewProps.generated.ts +76 -0
  97. package/src/build-components/WebView/pattern.json +71 -0
  98. package/src/build-components/index.ts +45 -0
  99. package/src/build-components/patterns.generated.ts +5735 -1557
  100. package/src/components/AttributesEditorPanel.tsx +1 -0
  101. package/src/index.web.ts +3 -0
  102. package/src/mockOS/components/MockOSRouter.tsx +21 -0
  103. package/src/mockOS/context/MockOSContext.tsx +7 -0
  104. package/src/mockOS/context/MockOSContextBase.ts +4 -0
  105. package/src/patterns/event-constants.json +19 -0
  106. package/src/styles/components/_checkbox.scss +19 -0
  107. package/src/styles/components/_global-provider.scss +131 -0
  108. package/src/styles/components/_webview.scss +52 -0
  109. package/src/styles/index.scss +4 -0
  110. package/src/types/PreviewConfig.ts +19 -0
  111. package/src/utils/analyseNodeByPatterns.ts +5 -2
  112. package/src/utils/nodeTree.ts +115 -0
  113. package/src/utils/projectColors.ts +4 -0
  114. package/src/.DS_Store +0 -0
  115. package/src/assets/.DS_Store +0 -0
@@ -21,7 +21,13 @@ import type { CarouselButtonsComponentProps } from './CarouselButtons/CarouselBu
21
21
  import type { CarouselDotsComponentProps } from './CarouselDots/CarouselDotsProps.generated';
22
22
  import type { CarouselItemComponentProps } from './CarouselItem/CarouselItemProps.generated';
23
23
  import type { CarouselProviderComponentProps } from './CarouselProvider/CarouselProviderProps.generated';
24
+ import type { CheckboxComponentProps } from './Checkbox/CheckboxProps.generated';
24
25
  import type { CountDownComponentProps } from './CountDown/CountDownProps.generated';
26
+ import type { FormCheckboxComponentProps } from './FormCheckbox/FormCheckboxProps.generated';
27
+ import type { FormErrorTextComponentProps } from './FormErrorText/FormErrorTextProps.generated';
28
+ import type { FormProviderComponentProps } from './FormProvider/FormProviderProps.generated';
29
+ import type { FormSubmitButtonComponentProps } from './FormSubmitButton/FormSubmitButtonProps.generated';
30
+ import type { GlobalProviderComponentProps } from './GlobalProvider/GlobalProviderProps.generated';
25
31
  import type { ImageComponentProps } from './Image/ImageProps.generated';
26
32
  import type { MainComponentProps } from './Main/MainProps.generated';
27
33
  import type { NavigationBarColorComponentProps } from './NavigationBarColor/NavigationBarColorProps.generated';
@@ -47,8 +53,11 @@ import type { PromoComponentProps } from './Promo/PromoProps.generated';
47
53
  import type { RadioButtonComponentProps } from './RadioButton/RadioButtonProps.generated';
48
54
  import type { SeparatorComponentProps } from './Separator/SeparatorProps.generated';
49
55
  import type { StatusBarColorComponentProps } from './StatusBarColor/StatusBarColorProps.generated';
56
+ import type { SystemButtonComponentProps } from './SystemButton/SystemButtonProps.generated';
57
+ import type { TermsProviderComponentProps } from './TermsProvider/TermsProviderProps.generated';
50
58
  import type { TextComponentProps } from './Text/TextProps.generated';
51
59
  import type { ViewComponentProps } from './View/ViewProps.generated';
60
+ import type { WebViewComponentProps } from './WebView/WebViewProps.generated';
52
61
  import { BIcon } from './BIcon/BIcon';
53
62
  import { BackgroundImage } from './BackgroundImage/BackgroundImage';
54
63
  import { Button } from './Button/Button';
@@ -57,7 +66,13 @@ import CarouselButtons from './CarouselButtons/CarouselButtons';
57
66
  import CarouselDots from './CarouselDots/CarouselDots';
58
67
  import { CarouselItem } from './CarouselItem/CarouselItem';
59
68
  import CarouselProvider from './CarouselProvider/CarouselProvider';
69
+ import { Checkbox } from './Checkbox/Checkbox';
60
70
  import { CountDown } from './CountDown/CountDown';
71
+ import { FormCheckbox } from './FormCheckbox/FormCheckbox';
72
+ import { FormErrorText } from './FormErrorText/FormErrorText';
73
+ import { FormProvider } from './FormProvider/FormProvider';
74
+ import { FormSubmitButton } from './FormSubmitButton/FormSubmitButton';
75
+ import GlobalProvider from './GlobalProvider/GlobalProvider';
61
76
  import Image from './Image/Image';
62
77
  import Main from './Main/Main';
63
78
  import NavigationBarColor from './NavigationBarColor/NavigationBarColor';
@@ -83,8 +98,11 @@ import Promo from './Promo/Promo';
83
98
  import RadioButton from './RadioButton/RadioButton';
84
99
  import Separator from './Separator/Separator';
85
100
  import StatusBarColor from './StatusBarColor/StatusBarColor';
101
+ import { SystemButton } from './SystemButton/SystemButton';
102
+ import TermsProvider from './TermsProvider/TermsProvider';
86
103
  import { Text } from './Text/Text';
87
104
  import View from './View/View';
105
+ import { WebView } from './WebView/WebView';
88
106
 
89
107
  type BuilderNode =
90
108
  | (BIconComponentProps['node'] & { type: 'BIcon' })
@@ -95,7 +113,13 @@ type BuilderNode =
95
113
  | (CarouselDotsComponentProps['node'] & { type: 'CarouselDots' })
96
114
  | (CarouselItemComponentProps['node'] & { type: 'CarouselItem' })
97
115
  | (CarouselProviderComponentProps['node'] & { type: 'CarouselProvider' })
116
+ | (CheckboxComponentProps['node'] & { type: 'Checkbox' })
98
117
  | (CountDownComponentProps['node'] & { type: 'CountDown' })
118
+ | (FormCheckboxComponentProps['node'] & { type: 'FormCheckbox' })
119
+ | (FormErrorTextComponentProps['node'] & { type: 'FormErrorText' })
120
+ | (FormProviderComponentProps['node'] & { type: 'FormProvider' })
121
+ | (FormSubmitButtonComponentProps['node'] & { type: 'FormSubmitButton' })
122
+ | (GlobalProviderComponentProps['node'] & { type: 'GlobalProvider' })
99
123
  | (ImageComponentProps['node'] & { type: 'Image' })
100
124
  | (MainComponentProps['node'] & { type: 'Main' })
101
125
  | (NavigationBarColorComponentProps['node'] & { type: 'NavigationBarColor' })
@@ -123,8 +147,11 @@ type BuilderNode =
123
147
  | (RadioButtonComponentProps['node'] & { type: 'RadioButton' })
124
148
  | (SeparatorComponentProps['node'] & { type: 'Separator' })
125
149
  | (StatusBarColorComponentProps['node'] & { type: 'StatusBarColor' })
150
+ | (SystemButtonComponentProps['node'] & { type: 'SystemButton' })
151
+ | (TermsProviderComponentProps['node'] & { type: 'TermsProvider' })
126
152
  | (TextComponentProps['node'] & { type: 'Text' })
127
- | (ViewComponentProps['node'] & { type: 'View' });
153
+ | (ViewComponentProps['node'] & { type: 'View' })
154
+ | (WebViewComponentProps['node'] & { type: 'WebView' });
128
155
 
129
156
  function RenderNode({ node }: { node: Node }) {
130
157
  if (isNodeNullOrUndefined(node)) {
@@ -172,8 +199,20 @@ function RenderNode({ node }: { node: Node }) {
172
199
  return <CarouselItem node={normalizedNode} />;
173
200
  case 'CarouselProvider':
174
201
  return <CarouselProvider node={normalizedNode} />;
202
+ case 'Checkbox':
203
+ return <Checkbox node={normalizedNode} />;
175
204
  case 'CountDown':
176
205
  return <CountDown node={normalizedNode} />;
206
+ case 'FormCheckbox':
207
+ return <FormCheckbox node={normalizedNode} />;
208
+ case 'FormErrorText':
209
+ return <FormErrorText node={normalizedNode} />;
210
+ case 'FormProvider':
211
+ return <FormProvider node={normalizedNode} />;
212
+ case 'FormSubmitButton':
213
+ return <FormSubmitButton node={normalizedNode} />;
214
+ case 'GlobalProvider':
215
+ return <GlobalProvider node={normalizedNode} />;
177
216
  case 'Image':
178
217
  return <Image node={normalizedNode} />;
179
218
  case 'Main':
@@ -224,10 +263,16 @@ function RenderNode({ node }: { node: Node }) {
224
263
  return <Separator node={normalizedNode} />;
225
264
  case 'StatusBarColor':
226
265
  return <StatusBarColor node={normalizedNode} />;
266
+ case 'SystemButton':
267
+ return <SystemButton node={normalizedNode} />;
268
+ case 'TermsProvider':
269
+ return <TermsProvider node={normalizedNode} />;
227
270
  case 'Text':
228
271
  return <Text node={normalizedNode} />;
229
272
  case 'View':
230
273
  return <View node={normalizedNode} />;
274
+ case 'WebView':
275
+ return <WebView node={normalizedNode} />;
231
276
  default:
232
277
  return other(nodeType, node);
233
278
  }
@@ -0,0 +1,74 @@
1
+ import React, { useId } from 'react';
2
+ import type { SystemButtonComponentProps } from './SystemButtonProps.generated';
3
+ import useNode from '../useNode';
4
+ import { useLogRender } from '../../utils/useLogRender';
5
+ import { useExtractViewStyle } from '../../attribute-analyser/style/web/useExtractViewStyle';
6
+ import { useExtractTextStyle } from '../../attribute-analyser/style/web/useExtractTextStyle';
7
+ import { useMergedStyle } from '../../utils/useMergedStyle';
8
+ import { useMockOSContext, useMockPermission } from '../../mockOS';
9
+ import { useLocalize } from '../../hooks/useLocalize';
10
+ import { usePlacementButtonEvents } from './usePlacementButtonEvents';
11
+ import { useGlobalNavigation } from '../GlobalProvider/useGlobalNavigation';
12
+ import { useGlobalContext } from '../GlobalProvider/GlobalContext';
13
+
14
+ export type SystemButtonOptionalProps = {
15
+ onClick?: () => void;
16
+ disabled?: boolean;
17
+ };
18
+
19
+ export function SystemButton({
20
+ node,
21
+ onClick: onClickProp,
22
+ disabled = false,
23
+ }: SystemButtonComponentProps & SystemButtonOptionalProps) {
24
+ useLogRender('SystemButton');
25
+ node = useNode(node);
26
+ const attributeName = node.sourceType ?? node.type ?? 'SystemButton';
27
+ const context = useMockOSContext();
28
+ const mockPermissionManager = useMockPermission(context);
29
+ const globalNavigate = useGlobalNavigation();
30
+ const globalCtx = useGlobalContext();
31
+ const generatedId = useId();
32
+ const attributeKey = node.key ?? generatedId;
33
+ const attrs = node.attributes;
34
+ const labelRaw = attrs?.labelKey ?? '';
35
+ const localize = useLocalize();
36
+ const label = localize(labelRaw);
37
+ const viewStyle = useExtractViewStyle(node as any);
38
+ const textStyle = useExtractTextStyle(node as any);
39
+
40
+ const placementClick = usePlacementButtonEvents(attrs?.events, {
41
+ context,
42
+ requestPermission: (permission) =>
43
+ mockPermissionManager.requestPermission(permission),
44
+ globalNavigate,
45
+ setCondition: globalCtx?.setCondition,
46
+ });
47
+
48
+ const handleClick = onClickProp ?? placementClick;
49
+
50
+ const buttonStyle = useMergedStyle(viewStyle, textStyle, {
51
+ border: 'none',
52
+ display: 'flex',
53
+ justifyContent: 'center',
54
+ alignItems: 'center',
55
+ cursor: disabled ? 'not-allowed' : 'pointer',
56
+ opacity: disabled ? 0.6 : 1,
57
+ });
58
+
59
+ return (
60
+ <button
61
+ {...(attrs?.testID ? { 'data-testid': attrs.testID } : {})}
62
+ attribute-name={attributeName}
63
+ attribute-key={attributeKey}
64
+ onClick={handleClick}
65
+ disabled={disabled}
66
+ type="button"
67
+ style={buttonStyle}
68
+ >
69
+ {label || 'Button'}
70
+ </button>
71
+ );
72
+ }
73
+
74
+ export default SystemButton;
@@ -0,0 +1,112 @@
1
+ /* AUTO-GENERATED FILE - DO NOT EDIT */
2
+
3
+ import type { NodeData } from '../../types/Node';
4
+
5
+ export type TypeOptionType =
6
+ | 'Permission'
7
+ | 'Navigate'
8
+ | 'Placement'
9
+ | 'SetCondition';
10
+ export type PermissionOptionType =
11
+ | 'notification'
12
+ | 'camera'
13
+ | 'microphone'
14
+ | 'location'
15
+ | 'photos'
16
+ | 'contacts'
17
+ | 'att'
18
+ | 'rating'
19
+ | 'GDPR';
20
+ export type PlacementKeyOptionType =
21
+ | 'terms'
22
+ | 'onboard'
23
+ | 'paywall'
24
+ | 'subscription'
25
+ | 'home';
26
+ export type ConditionKeyOptionType = 'termsAccepted';
27
+ export type FlexDirectionOptionType = 'row' | 'column';
28
+ export type FlexWrapOptionType = 'nowrap' | 'wrap' | 'wrap-reverse';
29
+ export type AlignItemsOptionType =
30
+ | 'flex-start'
31
+ | 'center'
32
+ | 'flex-end'
33
+ | 'stretch'
34
+ | 'baseline';
35
+ export type JustifyContentOptionType =
36
+ | 'flex-start'
37
+ | 'center'
38
+ | 'flex-end'
39
+ | 'space-between'
40
+ | 'space-around'
41
+ | 'space-evenly';
42
+ export type PositionOptionType = 'relative' | 'absolute';
43
+
44
+ export interface EventObjectGenerated {
45
+ type?: TypeOptionType;
46
+ permission?: PermissionOptionType;
47
+ navigate_to?: string;
48
+ targetIndex?: number;
49
+ placementKey?: PlacementKeyOptionType;
50
+ conditionKey?: ConditionKeyOptionType;
51
+ value?: boolean;
52
+ }
53
+
54
+ export interface SystemButtonStyleGenerated {
55
+ color?: string;
56
+ fontSize?: number;
57
+ fontFamily?: string;
58
+ fontWeight?: string;
59
+ textAlign?: string;
60
+ flexDirection?: FlexDirectionOptionType;
61
+ flexWrap?: FlexWrapOptionType;
62
+ alignItems?: AlignItemsOptionType;
63
+ justifyContent?: JustifyContentOptionType;
64
+ gap?: string;
65
+ padding?: string;
66
+ paddingHorizontal?: string;
67
+ paddingVertical?: string;
68
+ paddingTop?: string;
69
+ paddingBottom?: string;
70
+ paddingLeft?: string;
71
+ paddingRight?: string;
72
+ margin?: string;
73
+ marginHorizontal?: string;
74
+ marginVertical?: string;
75
+ marginTop?: string;
76
+ marginBottom?: string;
77
+ marginLeft?: string;
78
+ marginRight?: string;
79
+ backgroundColor?: string;
80
+ borderRadius?: number;
81
+ width?: string;
82
+ minWidth?: string;
83
+ maxWidth?: string;
84
+ height?: number;
85
+ minHeight?: string;
86
+ maxHeight?: string;
87
+ flex?: number;
88
+ position?: PositionOptionType;
89
+ top?: string;
90
+ bottom?: string;
91
+ left?: string;
92
+ right?: string;
93
+ zIndex?: number;
94
+ }
95
+
96
+ export interface SystemButtonPropsGenerated {
97
+ child: string;
98
+ attributes: {
99
+ styles?: SystemButtonStyleGenerated;
100
+ adjustsFontSizeToFit?: boolean;
101
+ numberOfLines?: number;
102
+ translateCounter?: number;
103
+ scrollable?: boolean;
104
+ testID?: string;
105
+ labelKey?: string;
106
+ events?: EventObjectGenerated[];
107
+ };
108
+ }
109
+
110
+ export interface SystemButtonComponentProps {
111
+ node: NodeData<SystemButtonPropsGenerated['attributes']>;
112
+ }
@@ -0,0 +1,63 @@
1
+ {
2
+ "schemaVersion": 2,
3
+ "pattern": {
4
+ "type": "SystemButton",
5
+ "title": "SystemButton",
6
+ "description": "A reusable button component for system actions.",
7
+ "children": "never",
8
+ "extends": "Text",
9
+ "attributes": {
10
+ "labelKey": "string",
11
+ "events": "EventObject[]",
12
+ "testID": "string",
13
+ "styles": {
14
+ "color": "color",
15
+ "backgroundColor": "color",
16
+ "height": "number",
17
+ "borderRadius": "number",
18
+ "fontSize": "number",
19
+ "fontWeight": "string"
20
+ }
21
+ }
22
+ },
23
+ "defaults": {
24
+ "attributes": {
25
+ "labelKey": "Button"
26
+ },
27
+ "styles": {
28
+ "height": 48,
29
+ "borderRadius": 8,
30
+ "backgroundColor": "THEME_COLORS.SYSTEM_BUTTON_BACKGROUND",
31
+ "color": "THEME_COLORS.SYSTEM_BUTTON_TEXT"
32
+ }
33
+ },
34
+ "types": {
35
+ "EventObject": {
36
+ "type": "$ref:event-constants.eventTypes",
37
+ "permission": "$ref:event-constants.permissionTypes",
38
+ "navigate_to": "string",
39
+ "targetIndex": "number",
40
+ "placementKey": "$ref:event-constants.placementKeys",
41
+ "conditionKey": "$ref:event-constants.conditionKeys",
42
+ "value": "boolean"
43
+ }
44
+ },
45
+ "meta": {
46
+ "label": "System Button",
47
+ "description": "Versatile button for navigation, permissions, and more.",
48
+ "attributes": {
49
+ "labelKey": {
50
+ "label": "Label Key",
51
+ "description": "Localization key for button text.",
52
+ "category": "other",
53
+ "sort": 1
54
+ },
55
+ "events": {
56
+ "label": "Events",
57
+ "description": "Actions to perform on click.",
58
+ "category": "other",
59
+ "sort": 2
60
+ }
61
+ }
62
+ }
63
+ }
@@ -0,0 +1,114 @@
1
+ import { useRef, useCallback } from 'react';
2
+ import type { MockOSContextValue } from '../../mockOS/context/MockOSContextBase';
3
+ import type { PermissionStatus } from '../../mockOS/managers/mockPermissionManager';
4
+
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
+ export interface PlacementEventObject {
7
+ type?: 'Permission' | 'Navigate' | 'Placement' | 'SetCondition';
8
+ permission?: string | null;
9
+ placementKey?: string;
10
+ navigate_to?: string;
11
+ targetIndex?: number;
12
+ conditionKey?: string;
13
+ value?: boolean;
14
+ }
15
+
16
+ export interface UsePlacementButtonEventsOptions {
17
+ context: MockOSContextValue | null;
18
+ requestPermission: (permission: string) => Promise<PermissionStatus>;
19
+ /** Called for Navigate events when placementKey is not set (e.g. carousel or navigate_to). Return true if handled. */
20
+ onNavigateWithoutPlacement?: (
21
+ e: PlacementEventObject,
22
+ ) => Promise<boolean> | boolean;
23
+ /**
24
+ * Optional global navigate function (from useGlobalNavigation).
25
+ * When provided, Navigate/Placement events try this first before falling back
26
+ * to MockOSContext. Return true if the navigation was handled.
27
+ */
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;
34
+ }
35
+
36
+ /**
37
+ * Shared hook for Permission + Navigate(placementKey / navigate_to) used by SystemButton and OnboardButton.
38
+ * OnboardButton can pass onNavigateWithoutPlacement to handle carousel (targetIndex) and navigate_to.
39
+ * Onboard events are pushed to handledEventsRef too: double-click is ignored; "back to terms then click again" still works because the terms screen remounts and the ref is fresh.
40
+ */
41
+ export function usePlacementButtonEvents(
42
+ events: PlacementEventObject[] | undefined,
43
+ options: UsePlacementButtonEventsOptions,
44
+ ): () => Promise<void> {
45
+ const {
46
+ context,
47
+ requestPermission,
48
+ onNavigateWithoutPlacement,
49
+ globalNavigate,
50
+ setCondition,
51
+ } = options;
52
+ const handledEventsRef = useRef<PlacementEventObject[]>([]);
53
+
54
+ /**
55
+ * Attempts to navigate to a target. Tries globalNavigate first (GlobalProvider),
56
+ * then falls back to MockOSContext.
57
+ */
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
+ );
65
+
66
+ const handleClick = useCallback(async () => {
67
+ const list = events ?? [];
68
+
69
+ for (const e of list) {
70
+ if (handledEventsRef.current.includes(e)) {
71
+ continue;
72
+ }
73
+
74
+ if (e.type === 'Permission') {
75
+ const permission = e.permission ?? 'camera';
76
+ await requestPermission(permission);
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);
81
+ } else if (e.type === 'Placement' && e.placementKey) {
82
+ const target =
83
+ e.placementKey === 'paywall' ? 'paywall' : e.placementKey;
84
+ navigateTo(target);
85
+ handledEventsRef.current.push(e);
86
+ } else if (e.type === 'Navigate') {
87
+ if (e.placementKey) {
88
+ const target =
89
+ e.placementKey === 'paywall' ? 'paywall' : e.placementKey;
90
+ navigateTo(target);
91
+ handledEventsRef.current.push(e);
92
+ } else {
93
+ const handled =
94
+ onNavigateWithoutPlacement != null &&
95
+ (await Promise.resolve(onNavigateWithoutPlacement(e)));
96
+ if (handled) {
97
+ handledEventsRef.current.push(e);
98
+ } else if (e.navigate_to && typeof e.navigate_to === 'string') {
99
+ navigateTo(e.navigate_to);
100
+ handledEventsRef.current.push(e);
101
+ }
102
+ }
103
+ }
104
+ }
105
+ }, [
106
+ events,
107
+ requestPermission,
108
+ setCondition,
109
+ navigateTo,
110
+ onNavigateWithoutPlacement,
111
+ ]);
112
+
113
+ return handleClick;
114
+ }
@@ -0,0 +1,45 @@
1
+ import React, { useId } from 'react';
2
+ import type { TermsProviderComponentProps } from './TermsProviderProps.generated';
3
+ import RenderNode from '../RenderNode.generated';
4
+ import type { Node } from '../../types/Node';
5
+ import useNode from '../useNode';
6
+ import { useBuilderParams } from '../../components/BuilderProvider';
7
+ import { useExtractViewStyle } from '../../attribute-analyser/style/web/useExtractViewStyle';
8
+ import { useLogRender } from '../../utils/useLogRender';
9
+ import { isNodeSelected, SELECTED_OUTLINE_STYLE } from '../../utils/selection';
10
+ import { useMergedStyle } from '../../utils/useMergedStyle';
11
+
12
+ function TermsProvider({ node }: TermsProviderComponentProps) {
13
+ useLogRender('TermsProvider');
14
+ node = useNode(node);
15
+
16
+ const generatedId = useId();
17
+ const attributeName = node.sourceType ?? node.type ?? 'TermsProvider';
18
+ const attributeKey = node.key ?? generatedId;
19
+
20
+ const { previewMode, selectedKey } = useBuilderParams();
21
+
22
+ const baseStyle = useExtractViewStyle(node);
23
+
24
+ const isSelected = isNodeSelected({
25
+ previewMode: !!previewMode,
26
+ current: selectedKey ? { key: selectedKey } : undefined,
27
+ node,
28
+ });
29
+ const style = useMergedStyle(
30
+ baseStyle,
31
+ isSelected ? SELECTED_OUTLINE_STYLE : undefined,
32
+ );
33
+
34
+ return (
35
+ <div
36
+ attribute-name={attributeName}
37
+ attribute-key={attributeKey}
38
+ style={style}
39
+ >
40
+ {node.children && <RenderNode node={node.children as Node} />}
41
+ </div>
42
+ );
43
+ }
44
+
45
+ export default React.memo(TermsProvider);
@@ -0,0 +1,82 @@
1
+ /* AUTO-GENERATED FILE - DO NOT EDIT */
2
+
3
+ import type { NodeData } from '../../types/Node';
4
+
5
+ export type AnimationOptionType =
6
+ | 'default'
7
+ | 'fade'
8
+ | 'fade_from_bottom'
9
+ | 'fade_from_right'
10
+ | 'reveal_from_bottom'
11
+ | 'scale_from_center'
12
+ | 'slide_from_right'
13
+ | 'slide_from_left'
14
+ | 'slide_from_bottom'
15
+ | 'none';
16
+ export type FlexDirectionOptionType = 'row' | 'column';
17
+ export type FlexWrapOptionType = 'nowrap' | 'wrap' | 'wrap-reverse';
18
+ export type AlignItemsOptionType =
19
+ | 'flex-start'
20
+ | 'center'
21
+ | 'flex-end'
22
+ | 'stretch'
23
+ | 'baseline';
24
+ export type JustifyContentOptionType =
25
+ | 'flex-start'
26
+ | 'center'
27
+ | 'flex-end'
28
+ | 'space-between'
29
+ | 'space-around'
30
+ | 'space-evenly';
31
+ export type PositionOptionType = 'relative' | 'absolute';
32
+
33
+ export interface TermsProviderStyleGenerated {
34
+ flexDirection?: FlexDirectionOptionType;
35
+ flexWrap?: FlexWrapOptionType;
36
+ alignItems?: AlignItemsOptionType;
37
+ justifyContent?: JustifyContentOptionType;
38
+ gap?: string;
39
+ padding?: string;
40
+ paddingHorizontal?: string;
41
+ paddingVertical?: string;
42
+ paddingTop?: string;
43
+ paddingBottom?: string;
44
+ paddingLeft?: string;
45
+ paddingRight?: string;
46
+ margin?: string;
47
+ marginHorizontal?: string;
48
+ marginVertical?: string;
49
+ marginTop?: string;
50
+ marginBottom?: string;
51
+ marginLeft?: string;
52
+ marginRight?: string;
53
+ backgroundColor?: string;
54
+ borderRadius?: string;
55
+ width?: string;
56
+ minWidth?: string;
57
+ maxWidth?: string;
58
+ height?: string;
59
+ minHeight?: string;
60
+ maxHeight?: string;
61
+ flex?: number;
62
+ position?: PositionOptionType;
63
+ top?: string;
64
+ bottom?: string;
65
+ left?: string;
66
+ right?: string;
67
+ zIndex?: number;
68
+ }
69
+
70
+ export interface TermsProviderPropsGenerated {
71
+ child: string;
72
+ attributes: {
73
+ styles?: TermsProviderStyleGenerated;
74
+ scrollable?: boolean;
75
+ testID?: string;
76
+ animation?: AnimationOptionType;
77
+ };
78
+ }
79
+
80
+ export interface TermsProviderComponentProps {
81
+ node: NodeData<TermsProviderPropsGenerated['attributes']>;
82
+ }
@@ -0,0 +1,35 @@
1
+ {
2
+ "schemaVersion": 2,
3
+ "pattern": {
4
+ "type": "TermsProvider",
5
+ "title": "title",
6
+ "description": "description",
7
+ "children": "node",
8
+ "extends": "View",
9
+ "attributes": {
10
+ "animation": ["default", "fade", "fade_from_bottom", "fade_from_right", "reveal_from_bottom", "scale_from_center", "slide_from_right", "slide_from_left", "slide_from_bottom", "none"]
11
+ }
12
+ },
13
+ "defaults": {
14
+ "styles": {
15
+ "width": "100%",
16
+ "height": "100%",
17
+ "flex": 1
18
+ }
19
+ },
20
+ "meta": {
21
+ "desiredParent": ["root", "GlobalProvider"],
22
+ "label": "Terms Provider",
23
+ "description": "Provider for terms & privacy page (e.g. WebView + form). Use as a GlobalProvider page.",
24
+ "attributes": {
25
+ "animation": {
26
+ "label": "Page transition animation",
27
+ "description": "When this component is a GlobalProvider page: animation used when navigating to this screen.",
28
+ "category": "other",
29
+ "specialCategory": null,
30
+ "sort": 1
31
+ }
32
+ },
33
+ "styles": {}
34
+ }
35
+ }