@developer_tribe/react-builder 1.2.42 → 1.2.44-test.1

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 (131) hide show
  1. package/dist/build-components/BIcon/BIconProps.generated.d.ts +1 -1
  2. package/dist/build-components/Checkbox/Checkbox.d.ts +6 -0
  3. package/dist/build-components/Checkbox/CheckboxProps.generated.d.ts +67 -0
  4. package/dist/build-components/CountDown/CountDownProps.generated.d.ts +1 -1
  5. package/dist/build-components/FormCheckbox/FormCheckbox.d.ts +3 -0
  6. package/dist/build-components/FormCheckbox/FormCheckboxProps.generated.d.ts +69 -0
  7. package/dist/build-components/FormErrorText/FormErrorText.d.ts +3 -0
  8. package/dist/build-components/FormErrorText/FormErrorTextProps.generated.d.ts +61 -0
  9. package/dist/build-components/FormProvider/FormProvider.d.ts +11 -0
  10. package/dist/build-components/FormProvider/FormProviderProps.generated.d.ts +55 -0
  11. package/dist/build-components/FormSubmitButton/FormSubmitButton.d.ts +2 -0
  12. package/dist/build-components/FormSubmitButton/FormSubmitButtonProps.generated.d.ts +73 -0
  13. package/dist/build-components/GlobalProvider/GlobalContext.d.ts +28 -0
  14. package/dist/build-components/GlobalProvider/GlobalProvider.d.ts +5 -0
  15. package/dist/build-components/GlobalProvider/GlobalProviderProps.generated.d.ts +60 -0
  16. package/dist/build-components/GlobalProvider/globalProviderUtils.d.ts +37 -0
  17. package/dist/build-components/GlobalProvider/useGlobalNavigation.d.ts +19 -0
  18. package/dist/build-components/OnboardButton/OnboardButtonProps.generated.d.ts +17 -10
  19. package/dist/build-components/OnboardFooter/OnboardFooterProps.generated.d.ts +1 -1
  20. package/dist/build-components/OnboardProvider/OnboardProviderProps.generated.d.ts +2 -0
  21. package/dist/build-components/OnboardSubtitle/OnboardSubtitleProps.generated.d.ts +1 -1
  22. package/dist/build-components/OnboardTitle/OnboardTitleProps.generated.d.ts +1 -1
  23. package/dist/build-components/PaywallCloseButton/PaywallCloseButtonProps.generated.d.ts +1 -1
  24. package/dist/build-components/PaywallFooter/PaywallFooterProps.generated.d.ts +1 -1
  25. package/dist/build-components/PaywallProvider/PaywallProviderProps.generated.d.ts +2 -0
  26. package/dist/build-components/PriceTag/PriceTagProps.generated.d.ts +1 -1
  27. package/dist/build-components/Pricing/PricingProps.generated.d.ts +1 -1
  28. package/dist/build-components/Promo/PromoProps.generated.d.ts +1 -1
  29. package/dist/build-components/SystemButton/SystemButton.d.ts +7 -0
  30. package/dist/build-components/SystemButton/SystemButtonProps.generated.d.ts +71 -0
  31. package/dist/build-components/SystemButton/usePlacementButtonEvents.d.ts +28 -0
  32. package/dist/build-components/TermsProvider/TermsProvider.d.ts +5 -0
  33. package/dist/build-components/TermsProvider/TermsProviderProps.generated.d.ts +55 -0
  34. package/dist/build-components/Text/TextProps.generated.d.ts +1 -1
  35. package/dist/build-components/WebView/WebView.d.ts +2 -0
  36. package/dist/build-components/WebView/WebViewProps.generated.d.ts +59 -0
  37. package/dist/build-components/index.d.ts +10 -1
  38. package/dist/build-components/patterns.generated.d.ts +5507 -1543
  39. package/dist/index.cjs.js +1 -1
  40. package/dist/index.cjs.js.map +1 -1
  41. package/dist/index.esm.js +1 -1
  42. package/dist/index.esm.js.map +1 -1
  43. package/dist/index.web.cjs.js +5 -5
  44. package/dist/index.web.cjs.js.map +1 -1
  45. package/dist/index.web.d.ts +1 -0
  46. package/dist/index.web.esm.js +4 -4
  47. package/dist/index.web.esm.js.map +1 -1
  48. package/dist/mockOS/context/MockOSContextBase.d.ts +3 -1
  49. package/dist/styles.css +1 -1
  50. package/dist/types/PreviewConfig.d.ts +1 -1
  51. package/package.json +2 -1
  52. package/src/RenderPage.tsx +4 -1
  53. package/src/assets/meta.json +1 -1
  54. package/src/assets/prompt-scheme-onboard.generated.ts +1 -1
  55. package/src/assets/prompt-scheme-paywall.generated.ts +1 -1
  56. package/src/assets/samples/getSamples.ts +7 -0
  57. package/src/assets/samples/global-onboard-flow.json +729 -0
  58. package/src/assets/samples/paywall-1.json +2 -2
  59. package/src/assets/samples/terms-and-privacy-no-form.json +108 -0
  60. package/src/assets/samples/terms-and-privacy.json +130 -0
  61. package/src/attributes-editor/FallbackLocalizationField.tsx +725 -250
  62. package/src/build-components/BIcon/BIconProps.generated.ts +1 -1
  63. package/src/build-components/Checkbox/Checkbox.tsx +165 -0
  64. package/src/build-components/Checkbox/CheckboxProps.generated.ts +84 -0
  65. package/src/build-components/Checkbox/pattern.json +83 -0
  66. package/src/build-components/CountDown/CountDownProps.generated.ts +1 -1
  67. package/src/build-components/FormCheckbox/FormCheckbox.tsx +106 -0
  68. package/src/build-components/FormCheckbox/FormCheckboxProps.generated.ts +86 -0
  69. package/src/build-components/FormCheckbox/pattern.json +39 -0
  70. package/src/build-components/FormErrorText/FormErrorText.tsx +34 -0
  71. package/src/build-components/FormErrorText/FormErrorTextProps.generated.ts +78 -0
  72. package/src/build-components/FormErrorText/pattern.json +21 -0
  73. package/src/build-components/FormProvider/FormProvider.tsx +131 -0
  74. package/src/build-components/FormProvider/FormProviderProps.generated.ts +72 -0
  75. package/src/build-components/FormProvider/pattern.json +33 -0
  76. package/src/build-components/FormSubmitButton/FormSubmitButton.tsx +49 -0
  77. package/src/build-components/FormSubmitButton/FormSubmitButtonProps.generated.ts +91 -0
  78. package/src/build-components/FormSubmitButton/pattern.json +33 -0
  79. package/src/build-components/GlobalProvider/GlobalContext.ts +48 -0
  80. package/src/build-components/GlobalProvider/GlobalProvider.tsx +191 -0
  81. package/src/build-components/GlobalProvider/GlobalProviderProps.generated.ts +78 -0
  82. package/src/build-components/GlobalProvider/globalProviderUtils.ts +163 -0
  83. package/src/build-components/GlobalProvider/pattern.json +55 -0
  84. package/src/build-components/GlobalProvider/useGlobalNavigation.ts +70 -0
  85. package/src/build-components/OnboardButton/OnboardButton.tsx +41 -36
  86. package/src/build-components/OnboardButton/OnboardButtonProps.generated.ts +17 -10
  87. package/src/build-components/OnboardButton/pattern.json +5 -4
  88. package/src/build-components/OnboardFooter/OnboardFooterProps.generated.ts +1 -1
  89. package/src/build-components/OnboardProvider/OnboardProviderProps.generated.ts +12 -0
  90. package/src/build-components/OnboardProvider/pattern.json +9 -1
  91. package/src/build-components/OnboardSubtitle/OnboardSubtitleProps.generated.ts +1 -1
  92. package/src/build-components/OnboardTitle/OnboardTitleProps.generated.ts +1 -1
  93. package/src/build-components/PaywallCloseButton/PaywallCloseButtonProps.generated.ts +1 -1
  94. package/src/build-components/PaywallFooter/PaywallFooterProps.generated.ts +1 -1
  95. package/src/build-components/PaywallProvider/PaywallProviderProps.generated.ts +12 -0
  96. package/src/build-components/PaywallProvider/pattern.json +9 -1
  97. package/src/build-components/PriceTag/PriceTagProps.generated.ts +1 -1
  98. package/src/build-components/Pricing/PricingProps.generated.ts +1 -1
  99. package/src/build-components/Promo/PromoProps.generated.ts +1 -1
  100. package/src/build-components/RenderNode.generated.tsx +46 -1
  101. package/src/build-components/SystemButton/SystemButton.tsx +71 -0
  102. package/src/build-components/SystemButton/SystemButtonProps.generated.ts +89 -0
  103. package/src/build-components/SystemButton/pattern.json +61 -0
  104. package/src/build-components/SystemButton/usePlacementButtonEvents.ts +101 -0
  105. package/src/build-components/TermsProvider/TermsProvider.tsx +45 -0
  106. package/src/build-components/TermsProvider/TermsProviderProps.generated.ts +82 -0
  107. package/src/build-components/TermsProvider/pattern.json +35 -0
  108. package/src/build-components/Text/Text.tsx +5 -4
  109. package/src/build-components/Text/TextProps.generated.ts +1 -1
  110. package/src/build-components/Text/pattern.json +2 -1
  111. package/src/build-components/WebView/WebView.tsx +149 -0
  112. package/src/build-components/WebView/WebViewProps.generated.ts +76 -0
  113. package/src/build-components/WebView/pattern.json +71 -0
  114. package/src/build-components/index.ts +45 -0
  115. package/src/build-components/patterns.generated.ts +5712 -1559
  116. package/src/hooks/useSafeAreaViewStyle.ts +1 -11
  117. package/src/index.web.ts +3 -0
  118. package/src/mockOS/components/MockOSRouter.tsx +21 -0
  119. package/src/mockOS/context/MockOSContext.tsx +7 -0
  120. package/src/mockOS/context/MockOSContextBase.ts +4 -0
  121. package/src/styles/components/_checkbox.scss +19 -0
  122. package/src/styles/components/_global-provider.scss +131 -0
  123. package/src/styles/components/_webview.scss +52 -0
  124. package/src/styles/index.scss +4 -0
  125. package/src/types/PreviewConfig.ts +19 -0
  126. package/src/utils/analyseNodeByPatterns.ts +5 -2
  127. package/src/utils/extractViewStyle/extractViewStyle.ts +0 -1
  128. package/src/utils/projectColors.ts +4 -0
  129. package/src/utils/useMergedStyle.ts +1 -1
  130. package/src/.DS_Store +0 -0
  131. package/src/assets/.DS_Store +0 -0
@@ -66,7 +66,7 @@ export interface BIconPropsGenerated {
66
66
  attributes: {
67
67
  styles?: BIconStyleGenerated;
68
68
  adjustsFontSizeToFit?: boolean;
69
- showEllipsis?: boolean;
69
+ numberOfLines?: number;
70
70
  translateCounter?: number;
71
71
  scrollable?: boolean;
72
72
  testID?: string;
@@ -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
+ }
@@ -0,0 +1,84 @@
1
+ /* AUTO-GENERATED FILE - DO NOT EDIT */
2
+
3
+ import type { NodeData } from '../../types/Node';
4
+
5
+ export type FlexDirectionOptionType = 'row' | 'column';
6
+ export type FlexWrapOptionType = 'nowrap' | 'wrap' | 'wrap-reverse';
7
+ export type AlignItemsOptionType =
8
+ | 'flex-start'
9
+ | 'center'
10
+ | 'flex-end'
11
+ | 'stretch'
12
+ | 'baseline';
13
+ export type JustifyContentOptionType =
14
+ | 'flex-start'
15
+ | 'center'
16
+ | 'flex-end'
17
+ | 'space-between'
18
+ | 'space-around'
19
+ | 'space-evenly';
20
+ export type PositionOptionType = 'relative' | 'absolute';
21
+
22
+ export interface CheckboxStyleGenerated {
23
+ color?: string;
24
+ fontSize?: string;
25
+ fontFamily?: string;
26
+ fontWeight?: string;
27
+ textAlign?: string;
28
+ flexDirection?: FlexDirectionOptionType;
29
+ flexWrap?: FlexWrapOptionType;
30
+ alignItems?: AlignItemsOptionType;
31
+ justifyContent?: JustifyContentOptionType;
32
+ gap?: string;
33
+ padding?: string;
34
+ paddingHorizontal?: string;
35
+ paddingVertical?: string;
36
+ paddingTop?: string;
37
+ paddingBottom?: string;
38
+ paddingLeft?: string;
39
+ paddingRight?: string;
40
+ margin?: string;
41
+ marginHorizontal?: string;
42
+ marginVertical?: string;
43
+ marginTop?: string;
44
+ marginBottom?: string;
45
+ marginLeft?: string;
46
+ marginRight?: string;
47
+ backgroundColor?: string;
48
+ borderRadius?: number;
49
+ width?: string;
50
+ minWidth?: string;
51
+ maxWidth?: string;
52
+ height?: string;
53
+ minHeight?: string;
54
+ maxHeight?: string;
55
+ flex?: number;
56
+ position?: PositionOptionType;
57
+ top?: string;
58
+ bottom?: string;
59
+ left?: string;
60
+ right?: string;
61
+ zIndex?: number;
62
+ checkIconSize?: number;
63
+ checkIconStrokeWidth?: number;
64
+ }
65
+
66
+ export interface CheckboxPropsGenerated {
67
+ child: string;
68
+ attributes: {
69
+ styles?: CheckboxStyleGenerated;
70
+ adjustsFontSizeToFit?: boolean;
71
+ numberOfLines?: number;
72
+ translateCounter?: number;
73
+ scrollable?: boolean;
74
+ testID?: string;
75
+ checked?: boolean;
76
+ label?: string;
77
+ checkedColor?: string;
78
+ syncTermsAccepted?: boolean;
79
+ };
80
+ }
81
+
82
+ export interface CheckboxComponentProps {
83
+ node: NodeData<CheckboxPropsGenerated['attributes']>;
84
+ }
@@ -0,0 +1,83 @@
1
+ {
2
+ "schemaVersion": 2,
3
+ "pattern": {
4
+ "type": "Checkbox",
5
+ "title": "Checkbox",
6
+ "description": "A standard checkbox component.",
7
+ "children": "never",
8
+ "extends": "Text",
9
+ "attributes": {
10
+ "checked": "boolean",
11
+ "label": "string",
12
+ "checkedColor": "color",
13
+ "syncTermsAccepted": "boolean",
14
+ "styles": {
15
+ "borderRadius": "number",
16
+ "checkIconSize": "number",
17
+ "checkIconStrokeWidth": "number"
18
+ }
19
+ },
20
+ "defaults": {
21
+ "checked": false,
22
+ "label": "view.terms.checkbox.label",
23
+ "styles": {
24
+ "borderRadius": 4,
25
+ "checkIconSize": 12,
26
+ "checkIconStrokeWidth": 1.7,
27
+ "flexDirection": "row"
28
+ },
29
+ "checkedColor": "THEME_COLORS.CHECKBOX_ACTIVE_COLOR"
30
+ }
31
+ },
32
+ "meta": {
33
+ "label": "Checkbox",
34
+ "description": "A checkbox with an optional label.",
35
+ "attributes": {
36
+ "checked": {
37
+ "label": "Checked",
38
+ "description": "Whether the checkbox is checked by default.",
39
+ "category": "other",
40
+ "sort": 1
41
+ },
42
+ "label": {
43
+ "label": "Label",
44
+ "description": "The text label next to the checkbox.",
45
+ "category": "other",
46
+ "sort": 2
47
+ },
48
+ "checkedColor": {
49
+ "label": "Checked color",
50
+ "description": "The color of the checkbox when checked.",
51
+ "category": "style",
52
+ "sort": 3
53
+ },
54
+ "styles": {
55
+ "width": {
56
+ "label": "Box Width",
57
+ "description": "Width of the checkbox box (px).",
58
+ "category": "style"
59
+ },
60
+ "height": {
61
+ "label": "Box Height",
62
+ "description": "Height of the checkbox box (px).",
63
+ "category": "style"
64
+ },
65
+ "borderRadius": {
66
+ "label": "Box Border Radius",
67
+ "description": "Border radius of the checkbox box (px).",
68
+ "category": "style"
69
+ },
70
+ "checkIconSize": {
71
+ "label": "Check Icon Size",
72
+ "description": "Size of the check icon inside the box (px).",
73
+ "category": "style"
74
+ },
75
+ "checkIconStrokeWidth": {
76
+ "label": "Check Icon Stroke Width",
77
+ "description": "Stroke width of the check icon inside the box.",
78
+ "category": "style"
79
+ }
80
+ }
81
+ }
82
+ }
83
+ }
@@ -66,7 +66,7 @@ export interface CountDownPropsGenerated {
66
66
  attributes: {
67
67
  styles?: CountDownStyleGenerated;
68
68
  adjustsFontSizeToFit?: boolean;
69
- showEllipsis?: boolean;
69
+ numberOfLines?: number;
70
70
  translateCounter?: number;
71
71
  scrollable?: boolean;
72
72
  testID?: string;
@@ -0,0 +1,106 @@
1
+ import React, { useContext } from 'react';
2
+ import { Controller } from 'react-hook-form';
3
+ import type {
4
+ FieldValues,
5
+ Control,
6
+ ControllerRenderProps,
7
+ } from 'react-hook-form';
8
+ import type { FormCheckboxComponentProps } from './FormCheckboxProps.generated';
9
+ import { formContext } from '../FormProvider/FormProvider';
10
+ import { Checkbox } from '../Checkbox/Checkbox';
11
+ import useNode from '../useNode';
12
+ import { useLogRender } from '../../utils/useLogRender';
13
+
14
+ /**
15
+ * Converts builder validation array to react-hook-form rules.
16
+ * Builder must send validation as key-value pairs; e.g. ['required'] or ['min', 2], ['max', 5].
17
+ * If 'min' or 'max' is the last element (no value following), that rule is skipped (no crash).
18
+ */
19
+ function validationArrayToRules(validation: string[] | undefined): {
20
+ required?: boolean;
21
+ min?: number;
22
+ max?: number;
23
+ } {
24
+ const rules: { required?: boolean; min?: number; max?: number } = {};
25
+ if (!Array.isArray(validation)) return rules;
26
+ if (validation.includes('required')) rules.required = true;
27
+ const minIdx = validation.indexOf('min');
28
+ if (minIdx >= 0) {
29
+ if (validation[minIdx + 1] != null) {
30
+ const minVal = Number(validation[minIdx + 1]);
31
+ if (Number.isFinite(minVal)) rules.min = minVal;
32
+ else {
33
+ console.warn(
34
+ '[FormCheckbox] validation "min" rule skipped: value must be a number.',
35
+ 'Received:',
36
+ validation[minIdx + 1],
37
+ '— Expected e.g. ["min", 2].',
38
+ );
39
+ }
40
+ } else {
41
+ console.warn(
42
+ '[FormCheckbox] validation "min" rule skipped: no value after "min".',
43
+ 'Expected e.g. ["min", 2], got:',
44
+ validation,
45
+ );
46
+ }
47
+ }
48
+ const maxIdx = validation.indexOf('max');
49
+ if (maxIdx >= 0) {
50
+ if (validation[maxIdx + 1] != null) {
51
+ const maxVal = Number(validation[maxIdx + 1]);
52
+ if (Number.isFinite(maxVal)) rules.max = maxVal;
53
+ else {
54
+ console.warn(
55
+ '[FormCheckbox] validation "max" rule skipped: value must be a number.',
56
+ 'Received:',
57
+ validation[maxIdx + 1],
58
+ '— Expected e.g. ["max", 5].',
59
+ );
60
+ }
61
+ } else {
62
+ console.warn(
63
+ '[FormCheckbox] validation "max" rule skipped: no value after "max".',
64
+ 'Expected e.g. ["max", 5], got:',
65
+ validation,
66
+ );
67
+ }
68
+ }
69
+ return rules;
70
+ }
71
+
72
+ /** FormCheckbox wraps Checkbox with RHF; UI and styling come from Checkbox. */
73
+ export function FormCheckbox({ node }: FormCheckboxComponentProps) {
74
+ useLogRender('FormCheckbox');
75
+ node = useNode(node);
76
+ const ctx = useContext(formContext);
77
+ const attrs = node.attributes;
78
+ const name = attrs?.name as string | undefined;
79
+ const validation = attrs?.validation as string[] | undefined;
80
+
81
+ if (!ctx || !name) {
82
+ return <Checkbox node={node as Parameters<typeof Checkbox>[0]['node']} />;
83
+ }
84
+
85
+ const control = ctx.control as Control<FieldValues>;
86
+ const rules = validationArrayToRules(validation);
87
+
88
+ return (
89
+ <Controller
90
+ name={name}
91
+ control={control}
92
+ rules={rules}
93
+ render={({
94
+ field,
95
+ }: {
96
+ field: ControllerRenderProps<FieldValues, string>;
97
+ }) => (
98
+ <Checkbox
99
+ node={node as Parameters<typeof Checkbox>[0]['node']}
100
+ checked={Boolean(field.value)}
101
+ onCheckedChange={(value) => field.onChange(value)}
102
+ />
103
+ )}
104
+ />
105
+ );
106
+ }
@@ -0,0 +1,86 @@
1
+ /* AUTO-GENERATED FILE - DO NOT EDIT */
2
+
3
+ import type { NodeData } from '../../types/Node';
4
+
5
+ export type FlexDirectionOptionType = 'row' | 'column';
6
+ export type FlexWrapOptionType = 'nowrap' | 'wrap' | 'wrap-reverse';
7
+ export type AlignItemsOptionType =
8
+ | 'flex-start'
9
+ | 'center'
10
+ | 'flex-end'
11
+ | 'stretch'
12
+ | 'baseline';
13
+ export type JustifyContentOptionType =
14
+ | 'flex-start'
15
+ | 'center'
16
+ | 'flex-end'
17
+ | 'space-between'
18
+ | 'space-around'
19
+ | 'space-evenly';
20
+ export type PositionOptionType = 'relative' | 'absolute';
21
+
22
+ export interface FormCheckboxStyleGenerated {
23
+ borderRadius?: string;
24
+ checkIconSize?: number;
25
+ checkIconStrokeWidth?: number;
26
+ color?: string;
27
+ fontSize?: string;
28
+ fontFamily?: string;
29
+ fontWeight?: string;
30
+ textAlign?: string;
31
+ flexDirection?: FlexDirectionOptionType;
32
+ flexWrap?: FlexWrapOptionType;
33
+ alignItems?: AlignItemsOptionType;
34
+ justifyContent?: JustifyContentOptionType;
35
+ gap?: string;
36
+ padding?: string;
37
+ paddingHorizontal?: string;
38
+ paddingVertical?: string;
39
+ paddingTop?: string;
40
+ paddingBottom?: string;
41
+ paddingLeft?: string;
42
+ paddingRight?: string;
43
+ margin?: string;
44
+ marginHorizontal?: string;
45
+ marginVertical?: string;
46
+ marginTop?: string;
47
+ marginBottom?: string;
48
+ marginLeft?: string;
49
+ marginRight?: string;
50
+ backgroundColor?: string;
51
+ width?: string;
52
+ minWidth?: string;
53
+ maxWidth?: string;
54
+ height?: string;
55
+ minHeight?: string;
56
+ maxHeight?: string;
57
+ flex?: number;
58
+ position?: PositionOptionType;
59
+ top?: string;
60
+ bottom?: string;
61
+ left?: string;
62
+ right?: string;
63
+ zIndex?: number;
64
+ }
65
+
66
+ export interface FormCheckboxPropsGenerated {
67
+ child: string;
68
+ attributes: {
69
+ styles?: FormCheckboxStyleGenerated;
70
+ checked?: boolean;
71
+ label?: string;
72
+ checkedColor?: string;
73
+ syncTermsAccepted?: boolean;
74
+ adjustsFontSizeToFit?: boolean;
75
+ numberOfLines?: number;
76
+ translateCounter?: number;
77
+ scrollable?: boolean;
78
+ testID?: string;
79
+ name?: string;
80
+ validation?: string[];
81
+ };
82
+ }
83
+
84
+ export interface FormCheckboxComponentProps {
85
+ node: NodeData<FormCheckboxPropsGenerated['attributes']>;
86
+ }
@@ -0,0 +1,39 @@
1
+ {
2
+ "schemaVersion": 2,
3
+ "pattern": {
4
+ "type": "FormCheckbox",
5
+ "title": "FormCheckbox",
6
+ "description": "Checkbox bound to FormProvider; supports validation (required, min, max).",
7
+ "children": "never",
8
+ "extends": "Checkbox",
9
+ "attributes": {
10
+ "name": "string",
11
+ "validation": "string[]"
12
+ }
13
+ },
14
+ "defaults": {
15
+ "styles": {
16
+ "flexDirection": "row",
17
+ "alignItems": "center"
18
+ }
19
+ },
20
+ "meta": {
21
+ "desiredParent": [">FormProvider"],
22
+ "label": "Form Checkbox",
23
+ "description": "Checkbox registered with form context; use name for form field (e.g. termsAccepted).",
24
+ "attributes": {
25
+ "name": {
26
+ "label": "Field name",
27
+ "description": "Form field name for react-hook-form (e.g. termsAccepted).",
28
+ "category": "other",
29
+ "sort": 5
30
+ },
31
+ "validation": {
32
+ "label": "Validation",
33
+ "description": "Validation rules as key-value pairs: e.g. ['required'] or ['min', 2], ['max', 5]. Builder must send min/max with their value in the next array slot.",
34
+ "category": "other",
35
+ "sort": 6
36
+ }
37
+ }
38
+ }
39
+ }
@@ -0,0 +1,34 @@
1
+ import React, { useContext, useMemo } from 'react';
2
+ import type { FormErrorTextComponentProps } from './FormErrorTextProps.generated';
3
+ import { formContext } from '../FormProvider/FormProvider';
4
+ import { Text } from '../Text/Text';
5
+ import useNode from '../useNode';
6
+ import { useLogRender } from '../../utils/useLogRender';
7
+ import { useLocalize } from '../../hooks/useLocalize';
8
+
9
+ /** Renders FormProvider globalError as Text when present; only valid inside FormProvider. */
10
+ export function FormErrorText({ node }: FormErrorTextComponentProps) {
11
+ useLogRender('FormErrorText');
12
+ node = useNode(node);
13
+ const ctx = useContext(formContext);
14
+ const localize = useLocalize();
15
+
16
+ const displayMessage = useMemo(
17
+ () => (ctx?.globalError ? localize(ctx.globalError) : ''),
18
+ [ctx?.globalError, localize],
19
+ );
20
+
21
+ if (!ctx?.globalError || !displayMessage) return null;
22
+
23
+ const textNode = {
24
+ ...node,
25
+ type: 'Text',
26
+ children: displayMessage,
27
+ } as Parameters<typeof Text>[0]['node'];
28
+
29
+ return (
30
+ <div role="alert" aria-live="polite">
31
+ <Text node={textNode} />
32
+ </div>
33
+ );
34
+ }
@@ -0,0 +1,78 @@
1
+ /* AUTO-GENERATED FILE - DO NOT EDIT */
2
+
3
+ import type { NodeData } from '../../types/Node';
4
+
5
+ export type FlexDirectionOptionType = 'row' | 'column';
6
+ export type FlexWrapOptionType = 'nowrap' | 'wrap' | 'wrap-reverse';
7
+ export type AlignItemsOptionType =
8
+ | 'flex-start'
9
+ | 'center'
10
+ | 'flex-end'
11
+ | 'stretch'
12
+ | 'baseline';
13
+ export type JustifyContentOptionType =
14
+ | 'flex-start'
15
+ | 'center'
16
+ | 'flex-end'
17
+ | 'space-between'
18
+ | 'space-around'
19
+ | 'space-evenly';
20
+ export type PositionOptionType = 'relative' | 'absolute';
21
+
22
+ export interface FormErrorTextStyleGenerated {
23
+ color?: string;
24
+ fontSize?: string;
25
+ fontFamily?: string;
26
+ fontWeight?: string;
27
+ textAlign?: string;
28
+ flexDirection?: FlexDirectionOptionType;
29
+ flexWrap?: FlexWrapOptionType;
30
+ alignItems?: AlignItemsOptionType;
31
+ justifyContent?: JustifyContentOptionType;
32
+ gap?: string;
33
+ padding?: string;
34
+ paddingHorizontal?: string;
35
+ paddingVertical?: string;
36
+ paddingTop?: string;
37
+ paddingBottom?: string;
38
+ paddingLeft?: string;
39
+ paddingRight?: string;
40
+ margin?: string;
41
+ marginHorizontal?: string;
42
+ marginVertical?: string;
43
+ marginTop?: string;
44
+ marginBottom?: string;
45
+ marginLeft?: string;
46
+ marginRight?: string;
47
+ backgroundColor?: string;
48
+ borderRadius?: string;
49
+ width?: string;
50
+ minWidth?: string;
51
+ maxWidth?: string;
52
+ height?: string;
53
+ minHeight?: string;
54
+ maxHeight?: string;
55
+ flex?: number;
56
+ position?: PositionOptionType;
57
+ top?: string;
58
+ bottom?: string;
59
+ left?: string;
60
+ right?: string;
61
+ zIndex?: number;
62
+ }
63
+
64
+ export interface FormErrorTextPropsGenerated {
65
+ child: string;
66
+ attributes: {
67
+ styles?: FormErrorTextStyleGenerated;
68
+ adjustsFontSizeToFit?: boolean;
69
+ numberOfLines?: number;
70
+ translateCounter?: number;
71
+ scrollable?: boolean;
72
+ testID?: string;
73
+ };
74
+ }
75
+
76
+ export interface FormErrorTextComponentProps {
77
+ node: NodeData<FormErrorTextPropsGenerated['attributes']>;
78
+ }