formio-react-native 1.0.0

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 (162) hide show
  1. package/README.md +384 -0
  2. package/lib/commonjs/components/CheckboxField.js +2 -0
  3. package/lib/commonjs/components/DataGrid.js +2 -0
  4. package/lib/commonjs/components/DatePicker.js +2 -0
  5. package/lib/commonjs/components/EditGrid.js +2 -0
  6. package/lib/commonjs/components/FileUpload.js +2 -0
  7. package/lib/commonjs/components/FormioField.js +2 -0
  8. package/lib/commonjs/components/FormioForm.js +2 -0
  9. package/lib/commonjs/components/ResourceSelect.js +2 -0
  10. package/lib/commonjs/components/Wizard.js +2 -0
  11. package/lib/commonjs/components/renderers/CheckboxRenderer.js +2 -0
  12. package/lib/commonjs/components/renderers/EmailRenderer.js +2 -0
  13. package/lib/commonjs/components/renderers/FallbackRenderer.js +2 -0
  14. package/lib/commonjs/components/renderers/NumberRenderer.js +2 -0
  15. package/lib/commonjs/components/renderers/PasswordRenderer.js +2 -0
  16. package/lib/commonjs/components/renderers/PhoneNumberRenderer.js +2 -0
  17. package/lib/commonjs/components/renderers/RadioRenderer.js +2 -0
  18. package/lib/commonjs/components/renderers/SelectRenderer.js +2 -0
  19. package/lib/commonjs/components/renderers/SelectboxesRenderer.js +2 -0
  20. package/lib/commonjs/components/renderers/TextAreaRenderer.js +2 -0
  21. package/lib/commonjs/components/renderers/TextfieldRenderer.js +2 -0
  22. package/lib/commonjs/components/renderers/URLRenderer.js +2 -0
  23. package/lib/commonjs/components/renderers/index.js +2 -0
  24. package/lib/commonjs/constants/colors.js +2 -0
  25. package/lib/commonjs/constants/componentTypes.js +2 -0
  26. package/lib/commonjs/constants/index.js +2 -0
  27. package/lib/commonjs/constants/spacing.js +2 -0
  28. package/lib/commonjs/constants/typography.js +2 -0
  29. package/lib/commonjs/constants/validationMessages.js +2 -0
  30. package/lib/commonjs/context/FormioContext.js +2 -0
  31. package/lib/commonjs/errors/ErrorBoundary.js +2 -0
  32. package/lib/commonjs/errors/FormioError.js +2 -0
  33. package/lib/commonjs/errors/errorUtils.js +2 -0
  34. package/lib/commonjs/errors/index.js +2 -0
  35. package/lib/commonjs/hooks/useTheme.js +2 -0
  36. package/lib/commonjs/i18n/I18nContext.js +2 -0
  37. package/lib/commonjs/i18n/locales/ar/index.js +2 -0
  38. package/lib/commonjs/i18n/locales/fr/index.js +2 -0
  39. package/lib/commonjs/i18n/messages.js +2 -0
  40. package/lib/commonjs/i18n/translations/en.js +2 -0
  41. package/lib/commonjs/i18n/types.js +2 -0
  42. package/lib/commonjs/index.js +2 -0
  43. package/lib/commonjs/package.json +1 -0
  44. package/lib/commonjs/registry/ComponentRegistry.js +2 -0
  45. package/lib/commonjs/registry/index.js +2 -0
  46. package/lib/commonjs/types.js +2 -0
  47. package/lib/commonjs/utils/a11yUtils.js +2 -0
  48. package/lib/commonjs/utils/componentUtils.js +2 -0
  49. package/lib/commonjs/utils/index.js +2 -0
  50. package/lib/commonjs/utils/logger.js +2 -0
  51. package/lib/commonjs/utils/performanceUtils.js +2 -0
  52. package/lib/commonjs/utils/rtlUtils.js +2 -0
  53. package/lib/commonjs/utils/safeEval.js +21 -0
  54. package/lib/commonjs/utils/styleUtils.js +2 -0
  55. package/lib/commonjs/validation.js +2 -0
  56. package/lib/module/components/CheckboxField.js +2 -0
  57. package/lib/module/components/DataGrid.js +2 -0
  58. package/lib/module/components/DatePicker.js +2 -0
  59. package/lib/module/components/EditGrid.js +2 -0
  60. package/lib/module/components/FileUpload.js +2 -0
  61. package/lib/module/components/FormioField.js +2 -0
  62. package/lib/module/components/FormioForm.js +2 -0
  63. package/lib/module/components/ResourceSelect.js +2 -0
  64. package/lib/module/components/Wizard.js +2 -0
  65. package/lib/module/components/renderers/CheckboxRenderer.js +2 -0
  66. package/lib/module/components/renderers/EmailRenderer.js +2 -0
  67. package/lib/module/components/renderers/FallbackRenderer.js +2 -0
  68. package/lib/module/components/renderers/NumberRenderer.js +2 -0
  69. package/lib/module/components/renderers/PasswordRenderer.js +2 -0
  70. package/lib/module/components/renderers/PhoneNumberRenderer.js +2 -0
  71. package/lib/module/components/renderers/RadioRenderer.js +2 -0
  72. package/lib/module/components/renderers/SelectRenderer.js +2 -0
  73. package/lib/module/components/renderers/SelectboxesRenderer.js +2 -0
  74. package/lib/module/components/renderers/TextAreaRenderer.js +2 -0
  75. package/lib/module/components/renderers/TextfieldRenderer.js +2 -0
  76. package/lib/module/components/renderers/URLRenderer.js +2 -0
  77. package/lib/module/components/renderers/index.js +2 -0
  78. package/lib/module/constants/colors.js +2 -0
  79. package/lib/module/constants/componentTypes.js +2 -0
  80. package/lib/module/constants/index.js +2 -0
  81. package/lib/module/constants/spacing.js +2 -0
  82. package/lib/module/constants/typography.js +2 -0
  83. package/lib/module/constants/validationMessages.js +2 -0
  84. package/lib/module/context/FormioContext.js +2 -0
  85. package/lib/module/errors/ErrorBoundary.js +2 -0
  86. package/lib/module/errors/FormioError.js +2 -0
  87. package/lib/module/errors/errorUtils.js +2 -0
  88. package/lib/module/errors/index.js +2 -0
  89. package/lib/module/hooks/useTheme.js +2 -0
  90. package/lib/module/i18n/I18nContext.js +2 -0
  91. package/lib/module/i18n/locales/ar/index.js +2 -0
  92. package/lib/module/i18n/locales/fr/index.js +2 -0
  93. package/lib/module/i18n/messages.js +2 -0
  94. package/lib/module/i18n/translations/en.js +2 -0
  95. package/lib/module/i18n/types.js +2 -0
  96. package/lib/module/index.js +2 -0
  97. package/lib/module/package.json +1 -0
  98. package/lib/module/registry/ComponentRegistry.js +2 -0
  99. package/lib/module/registry/index.js +2 -0
  100. package/lib/module/types.js +2 -0
  101. package/lib/module/utils/a11yUtils.js +2 -0
  102. package/lib/module/utils/componentUtils.js +2 -0
  103. package/lib/module/utils/index.js +2 -0
  104. package/lib/module/utils/logger.js +2 -0
  105. package/lib/module/utils/performanceUtils.js +2 -0
  106. package/lib/module/utils/rtlUtils.js +2 -0
  107. package/lib/module/utils/safeEval.js +21 -0
  108. package/lib/module/utils/styleUtils.js +2 -0
  109. package/lib/module/validation.js +2 -0
  110. package/lib/typescript/commonjs/components/CheckboxField.d.ts +11 -0
  111. package/lib/typescript/commonjs/components/DataGrid.d.ts +20 -0
  112. package/lib/typescript/commonjs/components/DatePicker.d.ts +25 -0
  113. package/lib/typescript/commonjs/components/EditGrid.d.ts +18 -0
  114. package/lib/typescript/commonjs/components/FileUpload.d.ts +35 -0
  115. package/lib/typescript/commonjs/components/FormioField.d.ts +11 -0
  116. package/lib/typescript/commonjs/components/FormioForm.d.ts +4 -0
  117. package/lib/typescript/commonjs/components/ResourceSelect.d.ts +38 -0
  118. package/lib/typescript/commonjs/components/Wizard.d.ts +31 -0
  119. package/lib/typescript/commonjs/components/renderers/CheckboxRenderer.d.ts +4 -0
  120. package/lib/typescript/commonjs/components/renderers/EmailRenderer.d.ts +4 -0
  121. package/lib/typescript/commonjs/components/renderers/FallbackRenderer.d.ts +4 -0
  122. package/lib/typescript/commonjs/components/renderers/NumberRenderer.d.ts +4 -0
  123. package/lib/typescript/commonjs/components/renderers/PasswordRenderer.d.ts +4 -0
  124. package/lib/typescript/commonjs/components/renderers/PhoneNumberRenderer.d.ts +4 -0
  125. package/lib/typescript/commonjs/components/renderers/RadioRenderer.d.ts +4 -0
  126. package/lib/typescript/commonjs/components/renderers/SelectRenderer.d.ts +4 -0
  127. package/lib/typescript/commonjs/components/renderers/SelectboxesRenderer.d.ts +4 -0
  128. package/lib/typescript/commonjs/components/renderers/TextAreaRenderer.d.ts +4 -0
  129. package/lib/typescript/commonjs/components/renderers/TextfieldRenderer.d.ts +4 -0
  130. package/lib/typescript/commonjs/components/renderers/URLRenderer.d.ts +4 -0
  131. package/lib/typescript/commonjs/components/renderers/index.d.ts +27 -0
  132. package/lib/typescript/commonjs/constants/colors.d.ts +18 -0
  133. package/lib/typescript/commonjs/constants/componentTypes.d.ts +42 -0
  134. package/lib/typescript/commonjs/constants/index.d.ts +53 -0
  135. package/lib/typescript/commonjs/constants/spacing.d.ts +10 -0
  136. package/lib/typescript/commonjs/constants/typography.d.ts +24 -0
  137. package/lib/typescript/commonjs/constants/validationMessages.d.ts +17 -0
  138. package/lib/typescript/commonjs/context/FormioContext.d.ts +151 -0
  139. package/lib/typescript/commonjs/errors/ErrorBoundary.d.ts +23 -0
  140. package/lib/typescript/commonjs/errors/FormioError.d.ts +28 -0
  141. package/lib/typescript/commonjs/errors/errorUtils.d.ts +8 -0
  142. package/lib/typescript/commonjs/errors/index.d.ts +5 -0
  143. package/lib/typescript/commonjs/hooks/useTheme.d.ts +10 -0
  144. package/lib/typescript/commonjs/i18n/I18nContext.d.ts +10 -0
  145. package/lib/typescript/commonjs/i18n/locales/ar/index.d.ts +3 -0
  146. package/lib/typescript/commonjs/i18n/locales/fr/index.d.ts +3 -0
  147. package/lib/typescript/commonjs/i18n/messages.d.ts +10 -0
  148. package/lib/typescript/commonjs/i18n/translations/en.d.ts +4 -0
  149. package/lib/typescript/commonjs/i18n/types.d.ts +12 -0
  150. package/lib/typescript/commonjs/index.d.ts +35 -0
  151. package/lib/typescript/commonjs/package.json +1 -0
  152. package/lib/typescript/commonjs/registry/ComponentRegistry.d.ts +32 -0
  153. package/lib/typescript/commonjs/registry/index.d.ts +3 -0
  154. package/lib/typescript/commonjs/types.d.ts +142 -0
  155. package/lib/typescript/commonjs/utils/a11yUtils.d.ts +31 -0
  156. package/lib/typescript/commonjs/utils/index.d.ts +9 -0
  157. package/lib/typescript/commonjs/utils/logger.d.ts +25 -0
  158. package/lib/typescript/commonjs/utils/rtlUtils.d.ts +18 -0
  159. package/lib/typescript/commonjs/utils/safeEval.d.ts +20 -0
  160. package/lib/typescript/commonjs/utils/styleUtils.d.ts +13 -0
  161. package/lib/typescript/commonjs/validation.d.ts +8 -0
  162. package/package.json +80 -0
package/README.md ADDED
@@ -0,0 +1,384 @@
1
+ # formio-react-native
2
+
3
+ React Native renderer for Form.io forms using native components with theming and customization support.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install formio-react-native @react-native-picker/picker
9
+ ```
10
+
11
+ ## Basic Usage
12
+
13
+ ```tsx
14
+ import React from 'react';
15
+ import { FormioForm } from 'formio-react-native';
16
+
17
+ const formSchema = {
18
+ components: [
19
+ {
20
+ type: 'textfield',
21
+ key: 'firstName',
22
+ label: 'First Name',
23
+ placeholder: 'Enter your first name',
24
+ required: true,
25
+ input: true
26
+ },
27
+ {
28
+ type: 'email',
29
+ key: 'email',
30
+ label: 'Email',
31
+ placeholder: 'Enter your email',
32
+ required: true,
33
+ input: true
34
+ },
35
+ {
36
+ type: 'button',
37
+ key: 'submit',
38
+ label: 'Submit'
39
+ }
40
+ ]
41
+ };
42
+
43
+ export default function App() {
44
+ const handleSubmit = (data) => {
45
+ console.log('Form submitted:', data);
46
+ };
47
+
48
+ return (
49
+ <FormioForm
50
+ form={formSchema}
51
+ onSubmit={handleSubmit}
52
+ />
53
+ );
54
+ }
55
+ ```
56
+
57
+ ## Theming and Customization
58
+
59
+ ### Using FormioProvider for Global Theming
60
+
61
+ ```tsx
62
+ import React from 'react';
63
+ import { FormioProvider, FormioForm } from 'formio-react-native';
64
+
65
+ const App = () => {
66
+ return (
67
+ <FormioProvider
68
+ theme={{
69
+ colors: {
70
+ primary: '#007AFF',
71
+ error: '#FF3B30',
72
+ border: '#C7C7CC',
73
+ text: '#000',
74
+ background: '#fff',
75
+ },
76
+ input: {
77
+ borderRadius: 8,
78
+ padding: 12,
79
+ fontSize: 16,
80
+ },
81
+ label: {
82
+ fontSize: 16,
83
+ fontWeight: '600',
84
+ marginBottom: 8,
85
+ },
86
+ }}
87
+ >
88
+ <FormioForm form={formSchema} onSubmit={handleSubmit} />
89
+ </FormioProvider>
90
+ );
91
+ };
92
+ ```
93
+
94
+ ### Custom Component Overrides
95
+
96
+ ```tsx
97
+ import React from 'react';
98
+ import { FormioProvider, ComponentRenderer } from 'formio-react-native';
99
+ import { TextInput, Text, View } from 'react-native';
100
+
101
+ const CustomTextField: ComponentRenderer = (component, props) => {
102
+ return (
103
+ <View style={{ marginBottom: 16 }}>
104
+ <Text style={{ fontSize: 18, fontWeight: 'bold' }}>
105
+ {component.label}
106
+ </Text>
107
+ <TextInput
108
+ style={{
109
+ borderWidth: 2,
110
+ borderColor: '#3498db',
111
+ borderRadius: 12,
112
+ padding: 16,
113
+ backgroundColor: '#ecf0f1',
114
+ }}
115
+ value={props.value || ''}
116
+ onChangeText={props.onChange}
117
+ placeholder={component.placeholder}
118
+ />
119
+ {props.error && (
120
+ <Text style={{ color: '#e74c3c', marginTop: 4 }}>
121
+ {props.error}
122
+ </Text>
123
+ )}
124
+ </View>
125
+ );
126
+ };
127
+
128
+ const App = () => {
129
+ return (
130
+ <FormioProvider
131
+ components={{
132
+ textfield: CustomTextField,
133
+ }}
134
+ >
135
+ <FormioForm form={formSchema} onSubmit={handleSubmit} />
136
+ </FormioProvider>
137
+ );
138
+ };
139
+ ```
140
+
141
+ ### Per-Form Component Overrides
142
+
143
+ ```tsx
144
+ // Override components for specific forms
145
+ <FormioForm
146
+ form={formSchema}
147
+ components={{
148
+ email: CustomEmailField, // Only for this form
149
+ }}
150
+ onSubmit={handleSubmit}
151
+ />
152
+ ```
153
+
154
+ ### Dynamic Component Registration
155
+
156
+ ```tsx
157
+ import { useFormioContext } from 'formio-react-native';
158
+
159
+ const MyComponent = () => {
160
+ const { registerComponent } = useFormioContext();
161
+
162
+ useEffect(() => {
163
+ registerComponent('customWidget', (component, props) => (
164
+ <CustomWidget {...component} {...props} />
165
+ ));
166
+ }, []);
167
+
168
+ return <FormioForm form={schema} />;
169
+ };
170
+ ```
171
+
172
+ ## Supported Field Types
173
+
174
+ ### Input Components
175
+ - `textfield` / `text` - Text input
176
+ - `email` - Email input with validation
177
+ - `password` - Password input (masked) with show/hide toggle
178
+ - `number` - Numeric input with min/max constraints
179
+ - `textarea` - Multi-line text input
180
+ - `url` - URL input with URL keyboard
181
+ - `phoneNumber` - Phone number input with phone keyboard
182
+
183
+ ### Selection Components
184
+ - `select` - Dropdown picker with search
185
+ - `checkbox` - Single checkbox/toggle
186
+ - `radio` - Radio button group
187
+ - `selectboxes` - Multi-select checkboxes
188
+
189
+ ### Date/Time Components
190
+ - `date` - Date picker (text-based, ready for native integration)
191
+ - `datetime` - Date and time picker
192
+ - `time` - Time picker
193
+
194
+ ### File Components
195
+ - `file` - File upload with callback support
196
+
197
+ ### Layout Components
198
+ - `panel` - Container panel
199
+ - `columns` - Column layout
200
+ - `datagrid` - Data grid with add/remove rows
201
+ - `editgrid` - Editable grid with inline editing
202
+
203
+ ### Advanced Components
204
+ - `wizard` - Multi-step wizard form
205
+ - `button` - Submit button
206
+
207
+ ## API
208
+
209
+ ### FormioForm Props
210
+
211
+ - `form` - Form.io JSON schema
212
+ - `data` - Initial form data (optional)
213
+ - `components` - Component overrides for this form
214
+ - `onSubmit` - Called when form is submitted with valid data
215
+ - `onChange` - Called when any field value changes
216
+ - `onValidation` - Called when validation state changes
217
+
218
+ ### FormioProvider Props
219
+
220
+ - `theme` - Global theme configuration
221
+ - `components` - Global component overrides
222
+ - `children` - React children
223
+
224
+ ### ComponentRenderer Type
225
+
226
+ ```tsx
227
+ type ComponentRenderer = (
228
+ component: FormioComponent,
229
+ props: ComponentRenderProps
230
+ ) => ReactNode;
231
+
232
+ interface ComponentRenderProps {
233
+ value: any;
234
+ onChange: (value: any) => void;
235
+ error?: string;
236
+ disabled?: boolean;
237
+ readOnly?: boolean;
238
+ formData?: Record<string, any>;
239
+ }
240
+ ```
241
+
242
+ ## Override Precedence
243
+
244
+ 1. **Form-level components** (via `components` prop) - Highest priority
245
+ 2. **Context components** (via `FormioProvider`) - Medium priority
246
+ 3. **Built-in components** - Lowest priority (fallback)
247
+
248
+ This allows you to set global defaults while still overriding specific forms when needed.
249
+
250
+ ## Internationalization (i18n)
251
+
252
+ The library includes built-in support for multiple languages with automatic RTL detection.
253
+
254
+ ### Supported Languages
255
+
256
+ - **English** (en) - Default
257
+ - **Arabic** (ar) - RTL
258
+ - **French** (fr)
259
+
260
+ ### Basic Usage
261
+
262
+ ```tsx
263
+ import { FormioProvider, FormioForm } from 'formio-react-native';
264
+
265
+ const App = () => {
266
+ return (
267
+ <FormioProvider
268
+ i18n={{
269
+ language: 'ar', // Set to Arabic
270
+ translations: {
271
+ // Use default translations or provide custom ones
272
+ },
273
+ }}
274
+ >
275
+ <FormioForm form={formSchema} onSubmit={handleSubmit} />
276
+ </FormioProvider>
277
+ );
278
+ };
279
+ ```
280
+
281
+ ### Custom Translations
282
+
283
+ ```tsx
284
+ const customTranslations = {
285
+ en: {
286
+ 'validation.REQUIRED': 'This field is mandatory',
287
+ 'Submit': 'Send Form',
288
+ 'First Name': 'Given Name',
289
+ },
290
+ ar: {
291
+ 'validation.REQUIRED': 'هذا الحقل إلزامي',
292
+ 'Submit': 'إرسال النموذج',
293
+ 'First Name': 'الاسم الأول',
294
+ },
295
+ };
296
+
297
+ <FormioProvider
298
+ i18n={{
299
+ language: 'ar',
300
+ translations: customTranslations,
301
+ }}
302
+ >
303
+ <FormioForm form={formSchema} onSubmit={handleSubmit} />
304
+ </FormioProvider>
305
+ ```
306
+
307
+ ### Language Switching
308
+
309
+ ```tsx
310
+ import { useI18n } from 'formio-react-native';
311
+
312
+ const LanguageSwitcher = () => {
313
+ const { language, setLanguage } = useI18n();
314
+
315
+ return (
316
+ <View>
317
+ <TouchableOpacity onPress={() => setLanguage('en')}>
318
+ <Text>English</Text>
319
+ </TouchableOpacity>
320
+ <TouchableOpacity onPress={() => setLanguage('ar')}>
321
+ <Text>العربية</Text>
322
+ </TouchableOpacity>
323
+ <TouchableOpacity onPress={() => setLanguage('fr')}>
324
+ <Text>Français</Text>
325
+ </TouchableOpacity>
326
+ </View>
327
+ );
328
+ };
329
+ ```
330
+
331
+ ### RTL Support
332
+
333
+ RTL (Right-to-Left) is automatically enabled for Arabic and Hebrew. The library handles:
334
+
335
+ - Text direction
336
+ - Component alignment
337
+ - Icon positioning
338
+ - Margin/padding reversal
339
+
340
+ ```tsx
341
+ import { useI18n } from 'formio-react-native';
342
+
343
+ const MyComponent = () => {
344
+ const { isRTL } = useI18n();
345
+
346
+ return (
347
+ <View style={{ flexDirection: isRTL ? 'row-reverse' : 'row' }}>
348
+ {/* Your content */}
349
+ </View>
350
+ );
351
+ };
352
+ ```
353
+
354
+ ### Translation Keys
355
+
356
+ #### Validation Messages
357
+ - `validation.REQUIRED` - Field is required
358
+ - `validation.MIN_LENGTH` - Minimum length validation
359
+ - `validation.MAX_LENGTH` - Maximum length validation
360
+ - `validation.PATTERN` - Pattern validation
361
+ - `validation.MIN_VALUE` - Minimum value validation
362
+ - `validation.MAX_VALUE` - Maximum value validation
363
+ - `validation.INVALID_EMAIL` - Email validation
364
+ - `validation.INVALID_URL` - URL validation
365
+ - `validation.INVALID_PHONE` - Phone validation
366
+ - `validation.INVALID_DATE` - Date validation
367
+ - `validation.FILE_TYPE_INVALID` - File type validation
368
+ - `validation.FILE_SIZE_TOO_LARGE` - File size validation
369
+ - `validation.CUSTOM_ERROR` - Custom validation error
370
+
371
+ #### Common UI Strings
372
+ - `Submit` - Submit button
373
+ - `Previous` - Previous button
374
+ - `Next` - Next button
375
+ - `Finish` - Finish button
376
+ - `Loading...` - Loading indicator
377
+ - `Search...` - Search placeholder
378
+ - `No options available` - Empty options message
379
+ - `Select...` - Select placeholder
380
+ - `No wizard pages found` - Wizard error message
381
+
382
+ #### Component Labels
383
+ - `First Name`, `Last Name`, `Email`, `Phone`, `Address`, `City`, `State`, `Zip Code`, `Country`
384
+ - `Message`, `Comments`, `Agree`, `Yes`, `No`, `OK`, `Cancel`, `Delete`, `Edit`, `Add`, `Remove`, `Save`, `Close`, `Done`
@@ -0,0 +1,2 @@
1
+ import React from'react';import{View,Text,TouchableOpacity,StyleSheet}from'react-native';import{useI18n}from'../i18n/I18nContext';export const CheckboxField=({label,value,onChange,required,error})=>{const{translate,isRTL}=useI18n();return React.createElement(View,{style:styles.container},React.createElement(TouchableOpacity,{style:styles.checkboxContainer,onPress:()=>onChange(!value)},React.createElement(View,{style:[styles.checkbox,value&&styles.checkboxChecked]},value&&React.createElement(Text,{style:styles.checkmark},"\u2713")),React.createElement(Text,{style:[styles.label,{textAlign:isRTL?'right':'left'}]},translate(label,label),required&&React.createElement(Text,{style:styles.required}," *"))),error&&React.createElement(Text,{style:[styles.errorText,{textAlign:isRTL?'right':'left'}]},translate(error,error)));};const styles=StyleSheet.create({container:{marginBottom:16},checkboxContainer:{flexDirection:'row',alignItems:'center'},checkbox:{width:20,height:20,borderWidth:2,borderColor:'#ddd',borderRadius:4,marginRight:12,alignItems:'center',justifyContent:'center',backgroundColor:'#fff'},checkboxChecked:{backgroundColor:'#007bff',borderColor:'#007bff'},checkmark:{color:'#fff',fontSize:14,fontWeight:'bold'},label:{fontSize:16,color:'#333',flex:1},required:{color:'#e74c3c'},errorText:{color:'#e74c3c',fontSize:14,marginTop:4,marginLeft:32}});
2
+ //# sourceMappingURL=CheckboxField.js.map
@@ -0,0 +1,2 @@
1
+ import React from'react';import{View,Text,TouchableOpacity,StyleSheet}from'react-native';import{FormioField}from'./FormioField';export const DataGrid=({component,value=[],disabled,readOnly,error,onChange})=>{const addRow=()=>{const row={};component.components.forEach(c=>{var _c$defaultValue;if(c.key)row[c.key]=(_c$defaultValue=c.defaultValue)!=null?_c$defaultValue:undefined;});onChange([...value,row]);};const removeRow=index=>{const next=value.filter((_,i)=>i!==index);onChange(next);};const updateCell=(rowIndex,key,cellValue)=>{const next=value.map((row,i)=>i===rowIndex?{...row,[key]:cellValue}:row);onChange(next);};return React.createElement(View,null,value.map((row,rIdx)=>React.createElement(View,{key:rIdx,style:styles.row},component.components.map(col=>React.createElement(View,{key:col.key,style:styles.cell},React.createElement(FormioField,{component:col,value:row[col.key],onChange:(k,v)=>updateCell(rIdx,col.key,v),error:undefined}))),!disabled&&!readOnly&&React.createElement(TouchableOpacity,{style:styles.removeBtn,onPress:()=>removeRow(rIdx)},React.createElement(Text,{style:styles.removeText},"Remove")))),!disabled&&!readOnly&&React.createElement(TouchableOpacity,{style:styles.addBtn,onPress:addRow},React.createElement(Text,{style:styles.addText},"Add Row")),error?React.createElement(Text,{style:styles.errorText},error):null);};const styles=StyleSheet.create({row:{borderWidth:1,borderColor:'#ddd',borderRadius:8,padding:8,marginBottom:8,backgroundColor:'#fff'},cell:{marginBottom:8},removeBtn:{alignSelf:'flex-end'},removeText:{color:'#e74c3c'},addBtn:{backgroundColor:'#007bff',padding:10,borderRadius:8,alignItems:'center'},addText:{color:'#fff',fontSize:14},errorText:{color:'#e74c3c',fontSize:14,marginTop:4}});
2
+ //# sourceMappingURL=DataGrid.js.map
@@ -0,0 +1,2 @@
1
+ import React,{useState}from'react';import{View,Text,TouchableOpacity,StyleSheet,Modal,ScrollView}from'react-native';import{useI18n}from'../i18n/I18nContext';export const DatePicker=({component,value,disabled,readOnly,error,onChange})=>{const[opened,setOpened]=useState(false);const[inputValue,setInputValue]=useState(value||'');const{translate}=useI18n();const handleConfirm=()=>{onChange(inputValue||null);setOpened(false);};const handleCancel=()=>{setInputValue(value||'');setOpened(false);};const getPlaceholder=()=>{switch(component.type){case'time':return'HH:mm';case'datetime':return'yyyy-MM-dd HH:mm';case'date':default:return'yyyy-MM-dd';}};return React.createElement(View,null,React.createElement(TouchableOpacity,{style:[styles.input,error&&styles.inputError,(disabled||readOnly)&&styles.disabled],onPress:()=>!disabled&&!readOnly&&setOpened(true),disabled:disabled||readOnly},React.createElement(Text,{style:[styles.valueText,!value&&styles.placeholder]},value||getPlaceholder())),error?React.createElement(Text,{style:styles.errorText},error):null,React.createElement(Modal,{visible:opened&&!disabled&&!readOnly,transparent:true,animationType:"slide"},React.createElement(View,{style:styles.modalOverlay},React.createElement(View,{style:styles.modalContent},React.createElement(View,{style:styles.modalHeader},React.createElement(Text,{style:styles.modalTitle},translate(component.label||'Select Date',component.label||'Select Date'))),React.createElement(ScrollView,{style:styles.modalBody},React.createElement(Text,{style:styles.instructionText},translate('Enter date in format:','Enter date in format:')," ",getPlaceholder()),React.createElement(Text,{style:styles.exampleText},translate('Example:','Example:')," ",getExampleDate(component.type))),React.createElement(View,{style:styles.modalFooter},React.createElement(TouchableOpacity,{style:[styles.button,styles.cancelButton],onPress:handleCancel},React.createElement(Text,{style:styles.buttonText},translate('Cancel','Cancel'))),React.createElement(TouchableOpacity,{style:[styles.button,styles.confirmButton],onPress:handleConfirm},React.createElement(Text,{style:styles.buttonText},translate('OK','OK'))))))));};function getExampleDate(type){const now=new Date();const year=now.getFullYear();const month=String(now.getMonth()+1).padStart(2,'0');const day=String(now.getDate()).padStart(2,'0');const hours=String(now.getHours()).padStart(2,'0');const minutes=String(now.getMinutes()).padStart(2,'0');switch(type){case'time':return`${hours}:${minutes}`;case'datetime':return`${year}-${month}-${day} ${hours}:${minutes}`;case'date':default:return`${year}-${month}-${day}`;}}const styles=StyleSheet.create({input:{borderWidth:1,borderColor:'#ddd',borderRadius:8,padding:12,backgroundColor:'#fff',marginBottom:8},inputError:{borderColor:'#e74c3c'},disabled:{backgroundColor:'#f0f0f0',opacity:0.6},valueText:{fontSize:16,color:'#333'},placeholder:{color:'#999'},errorText:{color:'#e74c3c',fontSize:14,marginTop:4},modalOverlay:{flex:1,backgroundColor:'rgba(0, 0, 0, 0.5)',justifyContent:'flex-end'},modalContent:{backgroundColor:'#fff',borderTopLeftRadius:12,borderTopRightRadius:12,maxHeight:'80%'},modalHeader:{paddingHorizontal:16,paddingVertical:12,borderBottomWidth:1,borderBottomColor:'#eee'},modalTitle:{fontSize:18,fontWeight:'600',color:'#333'},modalBody:{paddingHorizontal:16,paddingVertical:12},instructionText:{fontSize:14,color:'#666',marginBottom:8},exampleText:{fontSize:14,color:'#999',fontStyle:'italic'},modalFooter:{flexDirection:'row',justifyContent:'flex-end',paddingHorizontal:16,paddingVertical:12,borderTopWidth:1,borderTopColor:'#eee',gap:8},button:{paddingHorizontal:16,paddingVertical:10,borderRadius:6,minWidth:80,alignItems:'center'},cancelButton:{backgroundColor:'#f0f0f0'},confirmButton:{backgroundColor:'#007bff'},buttonText:{fontSize:14,fontWeight:'600',color:'#333'}});
2
+ //# sourceMappingURL=DatePicker.js.map
@@ -0,0 +1,2 @@
1
+ import React,{useState}from'react';import{View,Text,TouchableOpacity,StyleSheet}from'react-native';import{FormioField}from'./FormioField';export const EditGrid=({component,value=[],disabled,readOnly,error,onChange})=>{const[editing,setEditing]=useState(null);const addRow=()=>{const row={};component.components.forEach(c=>{var _c$defaultValue;if(c.key)row[c.key]=(_c$defaultValue=c.defaultValue)!=null?_c$defaultValue:undefined;});onChange([...value,row]);setEditing(value.length);};const removeRow=index=>{const next=value.filter((_,i)=>i!==index);onChange(next);};const updateCell=(rowIndex,key,cellValue)=>{const next=value.map((row,i)=>i===rowIndex?{...row,[key]:cellValue}:row);onChange(next);};const finalizeRow=()=>setEditing(null);return React.createElement(View,null,value.map((row,rIdx)=>React.createElement(View,{key:rIdx,style:styles.row},component.components.map(col=>React.createElement(View,{key:col.key,style:styles.cell},React.createElement(FormioField,{component:col,value:row[col.key],onChange:(k,v)=>updateCell(rIdx,col.key,v),error:undefined}))),!disabled&&!readOnly&&React.createElement(View,{style:styles.rowActions},editing===rIdx?React.createElement(TouchableOpacity,{onPress:finalizeRow},React.createElement(Text,{style:styles.actionText},"Done")):React.createElement(TouchableOpacity,{onPress:()=>setEditing(rIdx)},React.createElement(Text,{style:styles.actionText},"Edit")),React.createElement(TouchableOpacity,{onPress:()=>removeRow(rIdx)},React.createElement(Text,{style:[styles.actionText,styles.delete]},"Delete"))))),!disabled&&!readOnly&&React.createElement(TouchableOpacity,{style:styles.addBtn,onPress:addRow},React.createElement(Text,{style:styles.addText},"Add Row")),error?React.createElement(Text,{style:styles.errorText},error):null);};const styles=StyleSheet.create({row:{borderWidth:1,borderColor:'#ddd',borderRadius:8,padding:8,marginBottom:8,backgroundColor:'#fff'},cell:{marginBottom:8},rowActions:{flexDirection:'row',justifyContent:'flex-end',gap:16},actionText:{color:'#007bff'},delete:{color:'#e74c3c'},addBtn:{backgroundColor:'#007bff',padding:10,borderRadius:8,alignItems:'center'},addText:{color:'#fff',fontSize:14},errorText:{color:'#e74c3c',fontSize:14,marginTop:4}});
2
+ //# sourceMappingURL=EditGrid.js.map
@@ -0,0 +1,2 @@
1
+ import React from'react';import{View,Text,Image,TouchableOpacity,StyleSheet}from'react-native';import{useI18n}from'../i18n/I18nContext';export const FileUpload=({component,value=[],disabled,readOnly,error,onChange,onPickFile})=>{const{translate}=useI18n();const pickFile=async()=>{if(disabled||readOnly||!onPickFile)return;try{const newFiles=await onPickFile();const next=component.multiple?[...value,...newFiles]:newFiles;onChange(next);}catch(err){console.warn('File pick error:',err);}};const removeFile=index=>{const next=value.filter((_,i)=>i!==index);onChange(next);};return React.createElement(View,{style:styles.container},value.length>0&&React.createElement(View,{style:styles.filesRow},value.map((file,idx)=>React.createElement(View,{key:idx,style:styles.fileItem},file.url||file.base64?React.createElement(Image,{source:{uri:file.url||file.base64},style:styles.thumbnail}):React.createElement(View,{style:styles.thumbnailPlaceholder},React.createElement(Text,{style:styles.fileIcon},"\uD83D\uDCC4")),React.createElement(Text,{style:styles.fileName,numberOfLines:1},file.name),!disabled&&!readOnly&&React.createElement(TouchableOpacity,{onPress:()=>removeFile(idx),style:styles.removeButton},React.createElement(Text,{style:styles.removeText},translate('Remove','Remove')))))),!disabled&&!readOnly&&React.createElement(TouchableOpacity,{onPress:pickFile,style:styles.addButton},React.createElement(Text,{style:styles.addButtonText},translate(component.multiple?'Add Files':'Add File',component.multiple?'Add Files':'Add File'))),error?React.createElement(Text,{style:styles.errorText},error):null);};const styles=StyleSheet.create({container:{marginBottom:16},filesRow:{flexDirection:'row',flexWrap:'wrap',gap:12,marginBottom:12},fileItem:{width:100,alignItems:'center'},thumbnail:{width:80,height:80,borderRadius:8,backgroundColor:'#f5f5f5'},thumbnailPlaceholder:{width:80,height:80,borderRadius:8,backgroundColor:'#eee',justifyContent:'center',alignItems:'center'},fileIcon:{fontSize:32},fileName:{marginTop:6,fontSize:12,color:'#333'},removeButton:{marginTop:4},removeText:{color:'#e74c3c',fontSize:12},addButton:{padding:10,backgroundColor:'#007bff',borderRadius:8,alignItems:'center'},addButtonText:{color:'#fff',fontSize:14},errorText:{color:'#e74c3c',fontSize:14,marginTop:4}});
2
+ //# sourceMappingURL=FileUpload.js.map
@@ -0,0 +1,2 @@
1
+ import React from'react';import{View,Text,StyleSheet}from'react-native';import{useTheme}from'../hooks/useTheme';import{useI18n}from'../i18n/I18nContext';import{useFormioContext}from'../context/FormioContext';import{createRegistryWithComponents}from'../registry';import{DEFAULT_RENDERERS,FallbackRenderer}from'../components/renderers';let Picker=null;try{Picker=require('@react-native-picker/picker').Picker;}catch(e){Picker=null;}const getOptions=component=>{const ds=component.data;if(!ds)return[];if(ds.values)return ds.values;if(ds.json&&Array.isArray(ds.json))return ds.json;return[];};export const FormioField=({component,value,onChange,error})=>{const{type,key,label,placeholder,required,disabled}=component;const{createStyles,getColor,getComponent}=useTheme();const{translate,isRTL}=useI18n();const formioContext=useFormioContext();const translatedLabel=translate(label||'',label);const translatedPlaceholder=translate(placeholder||'',placeholder);const translatedError=translate(error||'',error);const themedStyles=createStyles(theme=>({fieldContainer:{marginBottom:getComponent('container.marginBottom',16)},label:{fontSize:getComponent('label.fontSize',16),fontWeight:getComponent('label.fontWeight','500'),marginBottom:getComponent('label.marginBottom',8),color:getComponent('label.color')||getColor('text','#333'),textAlign:isRTL?'right':'left'},input:{borderWidth:getComponent('input.borderWidth',1),borderColor:error?getColor('error','#e74c3c'):getColor('border','#ddd'),borderRadius:getComponent('input.borderRadius',8),padding:getComponent('input.padding',12),fontSize:getComponent('input.fontSize',16),minHeight:getComponent('input.minHeight',44),backgroundColor:disabled?getColor('disabled','#f0f0f0'):getColor('background','#fff'),textAlign:isRTL?'right':'left',writingDirection:isRTL?'rtl':'ltr'},errorText:{color:getColor('error','#e74c3c'),fontSize:getComponent('error.fontSize',14),marginTop:getComponent('error.marginTop',4)}}));const registry=React.useMemo(()=>{const reg=createRegistryWithComponents(DEFAULT_RENDERERS);const overrides=formioContext==null?void 0:formioContext.componentOverrides;if(overrides){Object.entries(overrides).forEach(([t,override])=>{if(override&&typeof override==='function'){reg.register(t,props=>{return override(props.component,{value:props.value,onChange:props.onChange,error:props.error,disabled:props.disabled,readOnly:props.readOnly,formData:props.formData,validationErrors:props.validationErrors});});}});}return reg;},[formioContext==null?void 0:formioContext.componentOverrides]);const renderField=()=>{const renderer=registry.get(type);if(renderer){return React.createElement(React.Fragment,null,renderer({component,value,onChange:val=>onChange(key,val),error:translatedError,disabled,readOnly:!!component.readOnly}));}return React.createElement(FallbackRenderer,{component:component,value:value,onChange:v=>onChange(key,v),error:translatedError,disabled:disabled});};if(component.input===false)return null;if(type==='checkbox'){return renderField();}return React.createElement(View,{style:themedStyles.fieldContainer},translatedLabel&&React.createElement(Text,{style:themedStyles.label},translatedLabel,required&&React.createElement(Text,{style:[styles.required,{color:getColor('error')}]}," *")),renderField(),component.description?React.createElement(Text,{style:[styles.description,{color:getColor('textSecondary'),textAlign:isRTL?'right':'left'}]},translate(component.description,component.description)):null,translatedError&&React.createElement(Text,{style:themedStyles.errorText},translatedError));};const styles=StyleSheet.create({fieldContainer:{marginBottom:16},label:{fontSize:16,fontWeight:'500',marginBottom:8,color:'#333'},required:{color:'#e74c3c'},input:{borderWidth:1,borderColor:'#ddd',borderRadius:8,padding:12,fontSize:16,backgroundColor:'#fff'},disabled:{backgroundColor:'#f0f0f0',color:'#999'},textarea:{height:100,textAlignVertical:'top'},selectPlaceholder:{padding:12,fontSize:16,color:'#999',fontStyle:'italic'},inputError:{borderColor:'#e74c3c'},description:{color:'#666',fontSize:13,marginTop:4},errorText:{color:'#e74c3c',fontSize:14,marginTop:4},pickerWrapper:{borderWidth:1,borderColor:'#ddd',borderRadius:8,overflow:'hidden',backgroundColor:'#fff'},radioGroup:{gap:8},radioItem:{fontSize:16,paddingVertical:6},switchRow:{flexDirection:'row',alignItems:'center',gap:8},switchLabel:{fontSize:16}});
2
+ //# sourceMappingURL=FormioField.js.map
@@ -0,0 +1,2 @@
1
+ import React,{useState,useEffect}from'react';import{ScrollView,View,Text,TouchableOpacity,StyleSheet}from'react-native';import{useI18n}from'../i18n/I18nContext';import{FormioField}from'./FormioField';import{DatePicker}from'./DatePicker';import{FileUpload}from'./FileUpload';import{ResourceSelect}from'./ResourceSelect';import{DataGrid}from'./DataGrid';import{EditGrid}from'./EditGrid';import{Wizard}from'./Wizard';import{validateForm}from'../validation';import{useFormioContext}from'../context/FormioContext';import{safeEvalConditional,safeEvalValue}from'../utils';const traverseComponents=(components,cb)=>{const walk=comp=>{cb(comp);if(comp.components)comp.components.forEach(walk);if(comp.type==='columns'&&Array.isArray(comp.columns)){comp.columns.forEach(col=>{if(Array.isArray(col.components))col.components.forEach(walk);});}};components.forEach(walk);};const flatten=components=>{const out=[];traverseComponents(components,c=>out.push(c));return out;};const initDefaults=(components,data)=>{const flat=flatten(components);const next={...data};for(const c of flat){if(c.input!==false&&c.key&&next[c.key]===undefined){if(c.defaultValue!==undefined)next[c.key]=c.defaultValue;}}return next;};const isHidden=(component,data)=>{if(component.hidden)return true;const value=data[component.key];if(component.customConditional){const res=safeEvalConditional(component.customConditional,{data,value,row:data,util:{}});return!res;}if(component.conditional&&component.conditional.when){const whenVal=data[component.conditional.when];const eq=component.conditional.eq;const show=component.conditional.show!==false;const match=whenVal===eq;return show?!match:match;}return false;};const applyCalculations=(components,data)=>{const flat=flatten(components);let changed=true;let guard=0;let next={...data};while(changed&&guard<5){changed=false;guard++;for(const c of flat){if(c.calculateValue){const current=next[c.key];const calc=safeEvalValue(c.calculateValue,{data:next,value:current,row:next,util:{}});if(calc!==undefined&&calc!==current){next={...next,[c.key]:calc};changed=true;}}}}return next;};export const FormioForm=({form,data:initialData={},options,components:propComponents,onSubmit,onChange,onValidation})=>{const context=useFormioContext();const{translate,isRTL}=useI18n();const componentOverrides={...(context==null?void 0:context.componentOverrides),...propComponents};const theme=context==null?void 0:context.theme;const[formData,setFormData]=useState(initialData);const[errors,setErrors]=useState([]);if(form.display==='wizard'){return React.createElement(ScrollView,{style:styles.form},form.title&&React.createElement(Text,{style:styles.title},form.title),React.createElement(Wizard,{form:form,component:{type:'wizard',key:'wizard',pages:form.components},data:formData,setData:setFormData,errors:errors,onValidation:setErrors,onFinish:()=>{const validationErrors=validateForm(form.components,formData,{translate});if(validationErrors.length===0){onSubmit==null||onSubmit(formData);}else{setErrors(validationErrors);}}}));}useEffect(()=>{let next=initDefaults(form.components,initialData);next=applyCalculations(form.components,next);setFormData(next);const validationErrors=validateForm(form.components,next,{translate});setErrors(validationErrors);onValidation==null||onValidation(validationErrors);},[form]);useEffect(()=>{const validationErrors=validateForm(form.components,formData,{translate});setErrors(validationErrors);onValidation==null||onValidation(validationErrors);},[formData]);const handleFieldChange=(key,value)=>{let next={...formData,[key]:value};next=applyCalculations(form.components,next);setFormData(next);onChange==null||onChange(next);};const handleSubmit=()=>{const validationErrors=validateForm(form.components,formData,{translate});if(validationErrors.length===0){onSubmit==null||onSubmit(formData);}else{setErrors(validationErrors);}};const getFieldError=key=>{var _errors$find;return(_errors$find=errors.find(e=>e.field===key))==null?void 0:_errors$find.message;};const renderComponent=component=>{if(isHidden(component,formData))return null;const customRenderer=(componentOverrides==null?void 0:componentOverrides[component.type])||(componentOverrides==null?void 0:componentOverrides[component.key]);if(customRenderer){return customRenderer(component,{value:formData[component.key],onChange:value=>handleFieldChange(component.key,value),error:getFieldError(component.key),disabled:component.disabled||false,readOnly:(options==null?void 0:options.readOnly)||false,formData});}if(component.type==='button'&&component.key==='submit'){var _theme$colors;return React.createElement(TouchableOpacity,{key:component.key,style:[styles.submitButton,(theme==null||(_theme$colors=theme.colors)==null?void 0:_theme$colors.primary)&&{backgroundColor:theme.colors.primary}],onPress:handleSubmit},React.createElement(Text,{style:styles.submitButtonText},translate(component.label||'Submit',component.label||'Submit')));}if(component.type==='wizard'||form.display==='wizard'){const wizardPages=component.pages||form.components||[];return React.createElement(Wizard,{key:component.key||'wizard',form:form,component:{...component,pages:wizardPages,type:'wizard'},data:formData,setData:d=>setFormData(d),errors:errors,onFinish:handleSubmit});}if(component.type==='columns'&&Array.isArray(component.columns)){const cols=component.columns;const shouldShowLabel=component.label&&!component.hideLabel;return React.createElement(View,{key:component.key,style:styles.columnsContainer},shouldShowLabel?React.createElement(Text,{style:[styles.containerLabel,{textAlign:isRTL?'right':'left'}]},translate(component.label,component.label)):null,React.createElement(View,{style:styles.columnsRow},cols.map((col,i)=>React.createElement(View,{key:`${component.key}-col-${i}`,style:styles.column},Array.isArray(col.components)?col.components.map(renderComponent):null))));}if(component.components&&component.components.length&&component.type!=='wizard'){const children=component.components.map(renderComponent).filter(Boolean);if(children.length===0)return null;const displayText=component.title||component.label;const shouldShowLabel=displayText&&!component.hideLabel;return React.createElement(View,{key:component.key,style:styles.container},shouldShowLabel?React.createElement(Text,{style:[styles.containerLabel,{textAlign:isRTL?'right':'left'}]},translate(displayText,displayText)):null,children);}if(component.input===false)return null;switch(component.type){case'date':case'datetime':case'time':return React.createElement(DatePicker,{key:component.key,component:component,value:formData[component.key],onChange:val=>handleFieldChange(component.key,val),error:getFieldError(component.key),disabled:component.disabled,readOnly:options==null?void 0:options.readOnly});case'file':return React.createElement(FileUpload,{key:component.key,component:component,value:formData[component.key],onChange:val=>handleFieldChange(component.key,val),error:getFieldError(component.key),disabled:component.disabled,readOnly:options==null?void 0:options.readOnly});case'datagrid':return React.createElement(DataGrid,{key:component.key,component:component,value:formData[component.key],onChange:val=>handleFieldChange(component.key,val),error:getFieldError(component.key),disabled:component.disabled,readOnly:options==null?void 0:options.readOnly});case'editgrid':return React.createElement(EditGrid,{key:component.key,component:component,value:formData[component.key],onChange:val=>handleFieldChange(component.key,val),error:getFieldError(component.key),disabled:component.disabled,readOnly:options==null?void 0:options.readOnly});case'select':{return React.createElement(ResourceSelect,{key:component.key,component:component,value:formData[component.key],onChange:val=>handleFieldChange(component.key,val),error:getFieldError(component.key),disabled:component.disabled,readOnly:options==null?void 0:options.readOnly});}case'PlatformFileInput':return React.createElement(FileUpload,{key:component.key,component:component,value:formData[component.key],onChange:val=>handleFieldChange(component.key,val),error:getFieldError(component.key),disabled:component.disabled,readOnly:options==null?void 0:options.readOnly});}return React.createElement(FormioField,{key:component.key,component:component,value:formData[component.key],onChange:handleFieldChange,error:getFieldError(component.key)});};return React.createElement(ScrollView,{style:[styles.form,{direction:isRTL?'rtl':'ltr'}]},form.components.map((c,index)=>React.createElement(React.Fragment,{key:c.key||index},renderComponent(c))));};const styles=StyleSheet.create({form:{flex:1,padding:16,backgroundColor:'#f5f5f5'},title:{fontSize:24,fontWeight:'bold',marginBottom:24,textAlign:'center',color:'#333'},container:{marginBottom:16},columnsContainer:{marginBottom:16},columnsRow:{flexDirection:'row',gap:12},column:{flex:1},containerLabel:{fontSize:18,fontWeight:'600',marginBottom:12,color:'#333'},submitButton:{backgroundColor:'#007bff',padding:16,borderRadius:8,alignItems:'center',marginTop:24},submitButtonText:{color:'#fff',fontSize:16,fontWeight:'600'}});
2
+ //# sourceMappingURL=FormioForm.js.map
@@ -0,0 +1,2 @@
1
+ import React,{useState,useEffect}from'react';import{View,Text,TouchableOpacity,FlatList,TextInput,StyleSheet,ActivityIndicator}from'react-native';import{useI18n}from'../i18n/I18nContext';export const ResourceSelect=({component,value,disabled,readOnly,error,onChange,fetcher})=>{var _component$searchEnab;const[items,setItems]=useState([]);const[search,setSearch]=useState('');const[showList,setShowList]=useState(false);const[loading,setLoading]=useState(false);const{translate,isRTL}=useI18n();const getOptions=()=>{const data=component.data;if(!data)return[];if(data.values)return data.values;if(data.json&&Array.isArray(data.json))return data.json;return items;};useEffect(()=>{const data=component.data;if(data&&(data.dataSrc==='url'||data.dataSrc==='resource'||data.url)){setLoading(true);const doFetch=async()=>{try{var _data$url;let base=(_data$url=data.url)!=null?_data$url:'';let labelProp=data.labelProperty||'title';let valueProp=data.valueProperty||'id';let sep=base.includes('?')?'&':'?';let q=search?`${sep}${data.searchField||'search'}=${encodeURIComponent(search)}`:'';let url=`${base}${q}`;const res=fetcher?await fetcher(url):await fetch(url).then(r=>r.json());const dataArray=Array.isArray(res)?res:res.data||res.items||[];const mapped=dataArray.map(item=>{const originalLabel=item[labelProp]||item.name||item.label||item.title||item._id||item.id||String(item);return{label:translate(originalLabel,originalLabel),value:item[valueProp]||item._id||item.id||item.value||item};});setItems(mapped);}catch(err){setItems([]);}finally{setLoading(false);}};doFetch();}else{setItems(getOptions());}},[component.data,search,fetcher]);const options=getOptions();const filteredItems=options&&Array.isArray(options)?options.filter(item=>(item.label||'').toLowerCase().includes((search||'').toLowerCase())):[];const selectedItem=options.find(item=>item.value===value);if(disabled||readOnly){return React.createElement(View,{style:styles.container},React.createElement(Text,{style:[styles.label,{textAlign:isRTL?'right':'left'}]},translate(component.label||'',component.label)),React.createElement(View,{style:[styles.selector,styles.disabled]},React.createElement(Text,{style:styles.selectorText},(selectedItem==null?void 0:selectedItem.label)||component.placeholder||'Select...')),error&&React.createElement(Text,{style:styles.error},error));}const useSearch=((_component$searchEnab=component.searchEnabled)!=null?_component$searchEnab:true)&&options.length>5;return React.createElement(View,{style:styles.container},React.createElement(Text,{style:[styles.label,{textAlign:isRTL?'right':'left'}]},translate(component.label||'',component.label),component.required&&React.createElement(Text,{style:styles.required}," *")),React.createElement(TouchableOpacity,{style:[styles.selector,error&&styles.selectorError],onPress:()=>setShowList(!showList),disabled:disabled||readOnly},React.createElement(Text,{style:[styles.selectorText,!selectedItem&&styles.placeholder,{textAlign:isRTL?'right':'left'}]},loading?translate('Loading...','Loading...'):(selectedItem==null?void 0:selectedItem.label)||translate(component.placeholder||'Select...',component.placeholder||'Select...')),React.createElement(Text,{style:styles.arrow},showList?'▲':'▼')),showList&&React.createElement(View,{style:styles.dropdownWrapper},React.createElement(View,{style:styles.dropdown},useSearch&&React.createElement(TextInput,{style:[styles.searchInput,{textAlign:isRTL?'right':'left'}],placeholder:translate('Search...','Search...'),value:search,onChangeText:setSearch,autoFocus:true,editable:!disabled&&!readOnly}),loading?React.createElement(ActivityIndicator,{style:{margin:12}}):React.createElement(FlatList,{data:filteredItems,keyExtractor:item=>{var _item$label;const v=typeof item.value==='object'?JSON.stringify(item.value):String(item.value);const l=String((_item$label=item.label)!=null?_item$label:'');return`${v}-${l}`;},renderItem:({item})=>React.createElement(TouchableOpacity,{key:(_item$label2=>{const v=typeof item.value==='object'?JSON.stringify(item.value):String(item.value);const l=String((_item$label2=item.label)!=null?_item$label2:'');return`${v}-${l}`;})(),style:[styles.item,item.value===value&&styles.selectedItem],onPress:()=>{onChange(item.value);setShowList(false);setSearch('');}},React.createElement(Text,{style:[styles.itemText,item.value===value&&styles.selectedText]},item.label)),ListEmptyComponent:React.createElement(Text,{style:[styles.emptyText,{textAlign:isRTL?'right':'left'}]},loading?translate('Loading...','Loading...'):translate('No options available','No options available')),keyboardShouldPersistTaps:"handled",style:styles.flatList,contentContainerStyle:{flexGrow:1},nestedScrollEnabled:true}))),error&&React.createElement(Text,{style:[styles.error,{textAlign:isRTL?'right':'left'}]},translate(error,error)));};const styles=StyleSheet.create({container:{marginBottom:16},label:{fontSize:16,fontWeight:'600',marginBottom:8,color:'#333'},required:{color:'#e74c3c'},selector:{borderWidth:1,borderColor:'#ddd',borderRadius:8,padding:12,backgroundColor:'#fff',flexDirection:'row',justifyContent:'space-between',alignItems:'center'},selectorError:{borderColor:'#e74c3c'},disabled:{backgroundColor:'#f5f5f5',opacity:0.6},selectorText:{fontSize:16,color:'#333',flex:1},placeholder:{color:'#999'},arrow:{fontSize:12,color:'#666'},dropdownWrapper:{position:'relative',zIndex:1000},dropdown:{borderWidth:1,borderColor:'#ddd',borderRadius:8,backgroundColor:'#fff',maxHeight:200,minHeight:10,marginTop:4,overflow:'hidden'},flatList:{flexGrow:1},searchInput:{borderBottomWidth:1,borderBottomColor:'#eee',padding:12,fontSize:16},item:{padding:12,borderBottomWidth:1,borderBottomColor:'#eee'},selectedItem:{backgroundColor:'#e3f2fd'},itemText:{fontSize:16,color:'#333'},selectedText:{fontWeight:'600',color:'#1976d2'},emptyText:{padding:12,textAlign:'center',color:'#999',fontStyle:'italic'},error:{color:'#e74c3c',fontSize:14,marginTop:4}});
2
+ //# sourceMappingURL=ResourceSelect.js.map
@@ -0,0 +1,2 @@
1
+ import React,{useState,useEffect}from'react';import{View,Text,TouchableOpacity}from'react-native';import{FormioField}from'./FormioField';import{validateForm}from'../validation';import{useTheme}from'../hooks/useTheme';import{useI18n}from'../i18n/I18nContext';const safeEval=(code,ctx)=>{try{var _ctx$row,_ctx$util;const fn=new Function('data','row','value','util','show',`return (function(){\n${code}\nreturn typeof show !== 'undefined' ? show : undefined;\n})();`);return fn(ctx.data,(_ctx$row=ctx.row)!=null?_ctx$row:ctx.data,ctx.value,(_ctx$util=ctx.util)!=null?_ctx$util:{},undefined);}catch(e){return undefined;}};const isHidden=(component,data)=>{if(component.hidden)return true;const value=data[component.key];if(component.customConditional){const res=safeEval(component.customConditional,{data,value,row:data,util:{}});if(typeof res==='boolean')return!res;if(res!==undefined)return!Boolean(res);}if(component.conditional&&component.conditional.when){const whenVal=data[component.conditional.when];const eq=component.conditional.eq;const show=component.conditional.show!==false;const match=whenVal===eq;return show?!match:match;}return false;};const applyCalculations=(components,data)=>{let changed=true;let guard=0;let next={...data};while(changed&&guard<5){changed=false;guard++;for(const c of components){if(c.calculateValue){const current=next[c.key];const calc=safeEval(c.calculateValue,{data:next,value:current,row:next,util:{}});if(calc!==undefined&&calc!==current){next={...next,[c.key]:calc};changed=true;}}}}return next;};export const Wizard=({form,component,data,setData,errors,onValidation,onNext,onPrev,onFinish})=>{const[currentPage,setCurrentPage]=useState(0);const{createStyles,getColor,getComponent}=useTheme();const{translate,isRTL}=useI18n();const pages=component.pages||[];const currentPageData=pages[currentPage];const getError=key=>{var _errors$find;return(_errors$find=errors.find(e=>e.field===key))==null?void 0:_errors$find.message;};const handleChange=(key,value)=>{let next={...data,[key]:value};const allComponents=pages.flatMap(p=>p.components||[]);next=applyCalculations(allComponents,next);setData(next);};useEffect(()=>{if(currentPageData!=null&&currentPageData.components){const allComponents=pages.flatMap(p=>p.components||[]);const allErrors=validateForm(allComponents,data,{translate});onValidation==null||onValidation(allErrors);}},[data,currentPageData,pages,onValidation]);const nextPage=()=>{if(currentPage<pages.length-1){setCurrentPage(currentPage+1);onNext==null||onNext();}else{onFinish==null||onFinish();}};const prevPage=()=>{if(currentPage>0){setCurrentPage(currentPage-1);onPrev==null||onPrev();}};if(!currentPageData||pages.length===0){return React.createElement(Text,null,"No wizard pages found");}const themedStyles=createStyles(()=>({wizardContainer:{flex:1},pageIndicator:{alignItems:'center',marginBottom:getComponent('container.marginBottom',16)},pageText:{fontSize:getComponent('label.fontSize',14),color:getColor('textSecondary','#666')},pageTitle:{fontSize:getComponent('button.fontSize',20),fontWeight:getComponent('button.fontWeight','bold'),marginBottom:getComponent('container.marginBottom',16),textAlign:'center',color:getColor('text','#333')},pageContent:{flex:1,marginBottom:getComponent('container.marginBottom',20)},navRow:{flexDirection:'row',justifyContent:'space-between',paddingTop:getComponent('container.padding',16),borderTopWidth:1,borderTopColor:getColor('border','#eee')},navBtn:{padding:getComponent('button.padding',12),borderRadius:getComponent('button.borderRadius',8),minWidth:100,alignItems:'center',minHeight:getComponent('button.minHeight',44)},prevBtn:{backgroundColor:getColor('textSecondary','#6c757d')},nextBtn:{backgroundColor:getColor('primary','#007bff')},navText:{color:getColor('background','#fff'),fontWeight:getComponent('button.fontWeight','600'),fontSize:getComponent('button.fontSize',16)},disabled:{opacity:0.4}}));return React.createElement(View,{style:themedStyles.wizardContainer},React.createElement(View,{style:themedStyles.pageIndicator},React.createElement(Text,{style:themedStyles.pageText},"Page ",currentPage+1," of ",pages.length)),currentPageData.title&&React.createElement(Text,{style:[themedStyles.pageTitle,{textAlign:isRTL?'right':'left'}]},translate(currentPageData.title,currentPageData.title)),React.createElement(View,{style:themedStyles.pageContent},(currentPageData.components||[]).map(c=>{if(isHidden(c,data))return null;return React.createElement(FormioField,{key:c.key,component:c,value:data[c.key],onChange:handleChange,error:getError(c.key)});})),React.createElement(View,{style:themedStyles.navRow},React.createElement(TouchableOpacity,{onPress:prevPage,style:[themedStyles.navBtn,themedStyles.prevBtn,currentPage===0&&themedStyles.disabled],disabled:currentPage===0},React.createElement(Text,{style:themedStyles.navText},translate('Previous','Previous'))),React.createElement(TouchableOpacity,{onPress:nextPage,style:[themedStyles.navBtn,themedStyles.nextBtn]},React.createElement(Text,{style:themedStyles.navText},currentPage<pages.length-1?translate('Next','Next'):translate('Finish','Finish')))));};
2
+ //# sourceMappingURL=Wizard.js.map
@@ -0,0 +1,2 @@
1
+ import React from'react';import{Switch,StyleSheet,View,Text}from'react-native';import{COLORS,SPACING,TYPOGRAPHY}from'../../constants';import{useI18n}from'../../i18n/I18nContext';import{getTextAlign,getFlexDirection}from'../../utils/rtlUtils';import{getCheckboxAriaAttributes}from'../../utils/a11yUtils';const styles=StyleSheet.create({container:{marginBottom:SPACING.md},checkboxContainer:{flexDirection:'row',alignItems:'center',paddingVertical:SPACING.sm},label:{fontSize:TYPOGRAPHY.fontSize.md,color:COLORS.text,marginLeft:SPACING.sm,flex:1},labelDisabled:{color:COLORS.disabled},errorText:{color:COLORS.error,fontSize:TYPOGRAPHY.fontSize.xs,marginTop:SPACING.xs}});const CheckboxRendererComponent=({component,value,onChange,error,disabled=false,readOnly=false})=>{const{label}=component;const{isRTL}=useI18n();const isChecked=Boolean(value);return React.createElement(View,{style:styles.container},React.createElement(View,{style:[styles.checkboxContainer,{flexDirection:getFlexDirection(isRTL)}]},React.createElement(View,getCheckboxAriaAttributes(label||'',isChecked,disabled||readOnly),React.createElement(Switch,{value:isChecked,onValueChange:onChange,disabled:disabled||readOnly,trackColor:{false:COLORS.border,true:COLORS.primary},thumbColor:isChecked?COLORS.primary:COLORS.disabled})),label&&React.createElement(Text,{style:[styles.label,(disabled||readOnly)&&styles.labelDisabled,{textAlign:getTextAlign(isRTL)}]},label)),error&&React.createElement(Text,{style:[styles.errorText,{textAlign:getTextAlign(isRTL)}]},error));};export const CheckboxRenderer=React.memo(CheckboxRendererComponent);
2
+ //# sourceMappingURL=CheckboxRenderer.js.map
@@ -0,0 +1,2 @@
1
+ import React from'react';import{TextInput,StyleSheet,View}from'react-native';import{COLORS,SPACING,TYPOGRAPHY}from'../../constants';const styles=StyleSheet.create({container:{marginBottom:SPACING.md},input:{borderWidth:1,borderColor:COLORS.border,borderRadius:4,paddingHorizontal:SPACING.sm,paddingVertical:SPACING.sm,fontSize:TYPOGRAPHY.fontSize.md,color:COLORS.text,minHeight:40},inputFocused:{borderColor:COLORS.primary},inputError:{borderColor:COLORS.error},inputDisabled:{backgroundColor:COLORS.disabled,color:COLORS.disabled}});export const EmailRenderer=({component,value,onChange,error,disabled=false,readOnly=false})=>{const[state,setState]=React.useState({isFocused:false});const{placeholder}=component;const inputStyle=[styles.input,state.isFocused&&styles.inputFocused,error&&styles.inputError,disabled&&styles.inputDisabled];return React.createElement(View,{style:styles.container},React.createElement(TextInput,{style:inputStyle,placeholder:placeholder||'Enter email address',placeholderTextColor:COLORS.placeholder,value:String(value||''),onChangeText:onChange,editable:!disabled&&!readOnly,onFocus:()=>setState({isFocused:true}),onBlur:()=>setState({isFocused:false}),keyboardType:"email-address",autoCapitalize:"none",autoCorrect:false,autoComplete:"email"}));};
2
+ //# sourceMappingURL=EmailRenderer.js.map
@@ -0,0 +1,2 @@
1
+ import React from'react';import{StyleSheet,View,Text}from'react-native';import{COLORS,SPACING,TYPOGRAPHY}from'../../constants';import{Logger}from'../../utils/logger';const logger=new Logger('FallbackRenderer');const styles=StyleSheet.create({container:{marginBottom:SPACING.md,padding:SPACING.md,backgroundColor:COLORS.warningLight,borderLeftWidth:4,borderLeftColor:COLORS.warning,borderRadius:4},title:{fontSize:TYPOGRAPHY.fontSize.md,fontWeight:TYPOGRAPHY.fontWeight.semibold,color:COLORS.warning,marginBottom:SPACING.xs},message:{fontSize:TYPOGRAPHY.fontSize.sm,color:COLORS.text,marginBottom:SPACING.sm},details:{fontSize:TYPOGRAPHY.fontSize.xs,color:COLORS.textSecondary,backgroundColor:COLORS.background,padding:SPACING.sm,borderRadius:3,fontFamily:'monospace'}});export const FallbackRenderer=({component})=>{const{type,label,key}=component;React.useEffect(()=>{logger.warn(`Unknown component type: "${type}" (${label||key||'unknown'})`);},[type,label,key]);return React.createElement(View,{style:styles.container},React.createElement(Text,{style:styles.title},"Unsupported Component Type"),React.createElement(Text,{style:styles.message},"Component type \"",type,"\" is not supported or not registered."),label&&React.createElement(Text,{style:styles.message},"Label: ",label),React.createElement(Text,{style:styles.details},key||'no-key'));};
2
+ //# sourceMappingURL=FallbackRenderer.js.map
@@ -0,0 +1,2 @@
1
+ import React from'react';import{TextInput,StyleSheet,View}from'react-native';import{COLORS,SPACING,TYPOGRAPHY}from'../../constants';const styles=StyleSheet.create({container:{marginBottom:SPACING.md},input:{borderWidth:1,borderColor:COLORS.border,borderRadius:4,paddingHorizontal:SPACING.sm,paddingVertical:SPACING.sm,fontSize:TYPOGRAPHY.fontSize.md,color:COLORS.text,minHeight:40},inputFocused:{borderColor:COLORS.primary},inputError:{borderColor:COLORS.error},inputDisabled:{backgroundColor:COLORS.disabled,color:COLORS.disabled}});export const NumberRenderer=({component,value,onChange,error,disabled=false,readOnly=false})=>{const[state,setState]=React.useState({isFocused:false});const{placeholder,min,max}=component;const inputStyle=[styles.input,state.isFocused&&styles.inputFocused,error&&styles.inputError,disabled&&styles.inputDisabled];const handleChange=text=>{if(text===''){onChange(null);return;}const numValue=parseFloat(text);if(!isNaN(numValue)){let constrainedValue=numValue;if(min!==undefined&&constrainedValue<min){constrainedValue=min;}if(max!==undefined&&constrainedValue>max){constrainedValue=max;}onChange(constrainedValue);}};return React.createElement(View,{style:styles.container},React.createElement(TextInput,{style:inputStyle,placeholder:placeholder||'Enter a number',placeholderTextColor:COLORS.placeholder,value:value!==null&&value!==undefined?String(value):'',onChangeText:handleChange,editable:!disabled&&!readOnly,onFocus:()=>setState({isFocused:true}),onBlur:()=>setState({isFocused:false}),keyboardType:"decimal-pad"}));};
2
+ //# sourceMappingURL=NumberRenderer.js.map
@@ -0,0 +1,2 @@
1
+ import React,{useState}from'react';import{TextInput,StyleSheet,View,Text,TouchableOpacity}from'react-native';import{COLORS,SPACING,TYPOGRAPHY}from'../../constants';const styles=StyleSheet.create({container:{marginBottom:SPACING.md},inputWrapper:{flexDirection:'row',alignItems:'center',borderWidth:1,borderColor:COLORS.border,borderRadius:4,paddingHorizontal:SPACING.sm,backgroundColor:COLORS.background},inputWrapperFocused:{borderColor:COLORS.primary},inputWrapperError:{borderColor:COLORS.error},inputWrapperDisabled:{backgroundColor:COLORS.disabled},input:{flex:1,paddingVertical:SPACING.sm,fontSize:TYPOGRAPHY.fontSize.md,color:COLORS.text,minHeight:40},toggleButton:{padding:SPACING.xs,marginLeft:SPACING.xs},toggleText:{fontSize:18,color:COLORS.primary}});export const PasswordRenderer=({component,value,onChange,error,disabled=false,readOnly=false})=>{const[state,setState]=useState({isFocused:false,showPassword:false});const{placeholder}=component;const inputWrapperStyle=[styles.inputWrapper,state.isFocused&&styles.inputWrapperFocused,error&&styles.inputWrapperError,disabled&&styles.inputWrapperDisabled];return React.createElement(View,{style:styles.container},React.createElement(View,{style:inputWrapperStyle},React.createElement(TextInput,{style:styles.input,placeholder:placeholder||'Enter password',placeholderTextColor:COLORS.placeholder,value:String(value||''),onChangeText:onChange,editable:!disabled&&!readOnly,onFocus:()=>setState(prev=>({...prev,isFocused:true})),onBlur:()=>setState(prev=>({...prev,isFocused:false})),secureTextEntry:!state.showPassword,autoCapitalize:"none",autoCorrect:false}),React.createElement(TouchableOpacity,{style:styles.toggleButton,onPress:()=>setState(prev=>({...prev,showPassword:!prev.showPassword})),disabled:disabled||readOnly},React.createElement(Text,{style:styles.toggleText},state.showPassword?'🐵':'🙈'))));};
2
+ //# sourceMappingURL=PasswordRenderer.js.map
@@ -0,0 +1,2 @@
1
+ import React from'react';import{TextInput,StyleSheet,View}from'react-native';import{COLORS,SPACING,TYPOGRAPHY}from'../../constants';const styles=StyleSheet.create({container:{marginBottom:SPACING.md},input:{borderWidth:1,borderColor:COLORS.border,borderRadius:4,paddingHorizontal:SPACING.sm,paddingVertical:SPACING.sm,fontSize:TYPOGRAPHY.fontSize.md,color:COLORS.text,minHeight:40},inputFocused:{borderColor:COLORS.primary},inputError:{borderColor:COLORS.error},inputDisabled:{backgroundColor:COLORS.disabled,color:COLORS.disabled}});export const PhoneNumberRenderer=({component,value,onChange,error,disabled=false,readOnly=false})=>{const[state,setState]=React.useState({isFocused:false});const{placeholder}=component;const inputStyle=[styles.input,state.isFocused&&styles.inputFocused,error&&styles.inputError,disabled&&styles.inputDisabled];return React.createElement(View,{style:styles.container},React.createElement(TextInput,{style:inputStyle,placeholder:placeholder||'Enter phone number',placeholderTextColor:COLORS.placeholder,value:String(value||''),onChangeText:onChange,editable:!disabled&&!readOnly,onFocus:()=>setState({isFocused:true}),onBlur:()=>setState({isFocused:false}),keyboardType:"phone-pad",autoCapitalize:"none",autoCorrect:false}));};
2
+ //# sourceMappingURL=PhoneNumberRenderer.js.map
@@ -0,0 +1,2 @@
1
+ import _extends from"@babel/runtime/helpers/esm/extends";import React from'react';import{View,Text,TouchableOpacity,StyleSheet}from'react-native';import{COLORS,SPACING,TYPOGRAPHY}from'../../constants';import{useI18n}from'../../i18n/I18nContext';import{getTextAlign,getFlexDirection}from'../../utils/rtlUtils';import{getRadioAriaAttributes}from'../../utils/a11yUtils';const styles=StyleSheet.create({container:{marginBottom:SPACING.md},radioGroup:{gap:SPACING.sm},radioItem:{flexDirection:'row',alignItems:'center',paddingVertical:SPACING.xs},radioButton:{width:20,height:20,borderRadius:10,borderWidth:2,borderColor:COLORS.border,justifyContent:'center',alignItems:'center',marginRight:SPACING.sm},radioButtonSelected:{borderColor:COLORS.primary,backgroundColor:COLORS.primary},radioButtonDisabled:{borderColor:COLORS.disabled,backgroundColor:COLORS.disabled},radioInner:{width:8,height:8,borderRadius:4,backgroundColor:COLORS.background},radioLabel:{fontSize:TYPOGRAPHY.fontSize.md,color:COLORS.text,flex:1},radioLabelDisabled:{color:COLORS.disabled}});const RadioRendererComponent=({component,value,onChange,error,disabled=false,readOnly=false})=>{var _component$data;const{isRTL}=useI18n();const options=parseOptions(((_component$data=component.data)==null?void 0:_component$data.values)||component.values||[]);return React.createElement(View,{style:styles.container},React.createElement(View,{style:[styles.radioGroup,{flexDirection:getFlexDirection(isRTL)}]},options.map((option,index)=>React.createElement(TouchableOpacity,_extends({key:String(option.value),style:styles.radioItem,onPress:()=>!disabled&&!readOnly&&onChange(option.value),disabled:disabled||readOnly},getRadioAriaAttributes(option.label,value===option.value,disabled||readOnly)),React.createElement(View,{style:[styles.radioButton,value===option.value&&styles.radioButtonSelected,(disabled||readOnly)&&styles.radioButtonDisabled]},value===option.value&&React.createElement(View,{style:styles.radioInner})),React.createElement(Text,{style:[styles.radioLabel,(disabled||readOnly)&&styles.radioLabelDisabled,{textAlign:getTextAlign(isRTL)}]},option.label)))));};function parseOptions(data){if(!Array.isArray(data)){return[];}return data.map(item=>{if(typeof item==='string'){return{label:item,value:item};}if(typeof item==='object'&&item!==null){return{label:item.label||String(item.value),value:item.value};}return{label:String(item),value:item};});}export const RadioRenderer=React.memo(RadioRendererComponent);
2
+ //# sourceMappingURL=RadioRenderer.js.map
@@ -0,0 +1,2 @@
1
+ import React from'react';import{StyleSheet,View,Text,TouchableOpacity,Modal,FlatList}from'react-native';import{COLORS,SPACING,TYPOGRAPHY}from'../../constants';const styles=StyleSheet.create({container:{marginBottom:SPACING.md},label:{fontSize:TYPOGRAPHY.fontSize.sm,fontWeight:TYPOGRAPHY.fontWeight.semibold,color:COLORS.text,marginBottom:SPACING.xs},selectButton:{borderWidth:1,borderColor:COLORS.border,borderRadius:4,paddingHorizontal:SPACING.sm,paddingVertical:SPACING.sm,minHeight:40,justifyContent:'center'},selectButtonFocused:{borderColor:COLORS.primary},selectButtonError:{borderColor:COLORS.error},selectButtonDisabled:{backgroundColor:COLORS.disabled},selectText:{fontSize:TYPOGRAPHY.fontSize.md,color:COLORS.text},selectTextPlaceholder:{color:COLORS.placeholder},selectTextDisabled:{color:COLORS.disabled},modalOverlay:{flex:1,backgroundColor:'rgba(0, 0, 0, 0.5)',justifyContent:'flex-end'},modalContent:{backgroundColor:COLORS.background,borderTopLeftRadius:12,borderTopRightRadius:12,maxHeight:'80%'},modalHeader:{paddingHorizontal:SPACING.md,paddingVertical:SPACING.md,borderBottomWidth:1,borderBottomColor:COLORS.border,flexDirection:'row',justifyContent:'space-between',alignItems:'center'},modalTitle:{fontSize:TYPOGRAPHY.fontSize.lg,fontWeight:TYPOGRAPHY.fontWeight.bold,color:COLORS.text},closeButton:{padding:SPACING.sm},closeButtonText:{fontSize:TYPOGRAPHY.fontSize.lg,color:COLORS.primary,fontWeight:TYPOGRAPHY.fontWeight.bold},optionItem:{paddingHorizontal:SPACING.md,paddingVertical:SPACING.md,borderBottomWidth:1,borderBottomColor:COLORS.border},optionItemSelected:{backgroundColor:COLORS.primaryLight},optionText:{fontSize:TYPOGRAPHY.fontSize.md,color:COLORS.text},optionTextSelected:{fontWeight:TYPOGRAPHY.fontWeight.semibold,color:COLORS.primary},errorText:{color:COLORS.error,fontSize:TYPOGRAPHY.fontSize.xs,marginTop:SPACING.xs}});export const SelectRenderer=({component,value,onChange,error,disabled=false,readOnly=false})=>{var _component$data;const[state,setState]=React.useState({isOpen:false,isFocused:false,options:parseOptions(((_component$data=component.data)==null?void 0:_component$data.values)||component.values||[])});const{label,placeholder}=component;const selectedOption=state.options.find(opt=>opt.value===value);const displayText=(selectedOption==null?void 0:selectedOption.label)||placeholder||'Select an option';const selectButtonStyle=[styles.selectButton,state.isFocused&&styles.selectButtonFocused,error&&styles.selectButtonError,(disabled||readOnly)&&styles.selectButtonDisabled];const selectTextStyle=[styles.selectText,!selectedOption&&styles.selectTextPlaceholder,(disabled||readOnly)&&styles.selectTextDisabled];const handleSelect=selectedValue=>{onChange(selectedValue);setState(prev=>({...prev,isOpen:false}));};const handleOpenClose=()=>{if(!disabled&&!readOnly){setState(prev=>({...prev,isOpen:!prev.isOpen,isFocused:!prev.isOpen}));}};return React.createElement(View,{style:styles.container},label&&React.createElement(Text,{style:styles.label},label),React.createElement(TouchableOpacity,{style:selectButtonStyle,onPress:handleOpenClose,disabled:disabled||readOnly},React.createElement(Text,{style:selectTextStyle},displayText)),React.createElement(Modal,{visible:state.isOpen&&!disabled&&!readOnly,transparent:true,animationType:"slide"},React.createElement(View,{style:styles.modalOverlay},React.createElement(View,{style:styles.modalContent},React.createElement(View,{style:styles.modalHeader},React.createElement(Text,{style:styles.modalTitle},label||'Select'),React.createElement(TouchableOpacity,{style:styles.closeButton,onPress:handleOpenClose},React.createElement(Text,{style:styles.closeButtonText},"Done"))),React.createElement(FlatList,{data:state.options,keyExtractor:(item,idx)=>String(idx),renderItem:({item})=>React.createElement(TouchableOpacity,{style:[styles.optionItem,item.value===value&&styles.optionItemSelected],onPress:()=>handleSelect(item.value)},React.createElement(Text,{style:[styles.optionText,item.value===value&&styles.optionTextSelected]},item.label))})))),error&&React.createElement(Text,{style:styles.errorText},error));};function parseOptions(data){if(!Array.isArray(data)){return[];}return data.map(item=>{if(typeof item==='string'){return{label:item,value:item};}if(typeof item==='object'&&item!==null){return{label:item.label||String(item.value),value:item.value};}return{label:String(item),value:item};});}
2
+ //# sourceMappingURL=SelectRenderer.js.map
@@ -0,0 +1,2 @@
1
+ import React from'react';import{View,Text,TouchableOpacity,StyleSheet}from'react-native';import{COLORS,SPACING,TYPOGRAPHY}from'../../constants';const styles=StyleSheet.create({container:{marginBottom:SPACING.md},label:{fontSize:TYPOGRAPHY.fontSize.sm,fontWeight:TYPOGRAPHY.fontWeight.semibold,color:COLORS.text,marginBottom:SPACING.sm},checkboxGroup:{gap:SPACING.sm},checkboxItem:{flexDirection:'row',alignItems:'center',paddingVertical:SPACING.xs},checkbox:{width:20,height:20,borderRadius:3,borderWidth:2,borderColor:COLORS.border,justifyContent:'center',alignItems:'center',marginRight:SPACING.sm},checkboxSelected:{borderColor:COLORS.primary,backgroundColor:COLORS.primary},checkboxDisabled:{borderColor:COLORS.disabled,backgroundColor:COLORS.disabled},checkmark:{fontSize:14,color:COLORS.background,fontWeight:'bold'},checkboxLabel:{fontSize:TYPOGRAPHY.fontSize.md,color:COLORS.text,flex:1},checkboxLabelDisabled:{color:COLORS.disabled},errorText:{color:COLORS.error,fontSize:TYPOGRAPHY.fontSize.xs,marginTop:SPACING.sm}});export const SelectboxesRenderer=({component,value={},onChange,error,disabled=false,readOnly=false})=>{var _component$data;const{label}=component;const options=parseOptions(((_component$data=component.data)==null?void 0:_component$data.values)||component.values||[]);const selectedValues=value||{};const handleToggle=optionValue=>{if(disabled||readOnly)return;const newValue={...selectedValues,[String(optionValue)]:!selectedValues[String(optionValue)]};onChange(newValue);};return React.createElement(View,{style:styles.container},label&&React.createElement(Text,{style:styles.label},label),React.createElement(View,{style:styles.checkboxGroup},options.map(option=>{const isSelected=selectedValues[String(option.value)];return React.createElement(TouchableOpacity,{key:String(option.value),style:styles.checkboxItem,onPress:()=>handleToggle(option.value),disabled:disabled||readOnly},React.createElement(View,{style:[styles.checkbox,isSelected&&styles.checkboxSelected,(disabled||readOnly)&&styles.checkboxDisabled]},isSelected&&React.createElement(Text,{style:styles.checkmark},"\u2713")),React.createElement(Text,{style:[styles.checkboxLabel,(disabled||readOnly)&&styles.checkboxLabelDisabled]},option.label));})),error&&React.createElement(Text,{style:styles.errorText},error));};function parseOptions(data){if(!Array.isArray(data)){return[];}return data.map(item=>{if(typeof item==='string'){return{label:item,value:item};}if(typeof item==='object'&&item!==null){return{label:item.label||String(item.value),value:item.value};}return{label:String(item),value:item};});}
2
+ //# sourceMappingURL=SelectboxesRenderer.js.map
@@ -0,0 +1,2 @@
1
+ import React from'react';import{TextInput,StyleSheet,View,Text}from'react-native';import{COLORS,SPACING,TYPOGRAPHY}from'../../constants';const styles=StyleSheet.create({container:{marginBottom:SPACING.md},label:{fontSize:TYPOGRAPHY.fontSize.sm,fontWeight:TYPOGRAPHY.fontWeight.semibold,color:COLORS.text,marginBottom:SPACING.xs},input:{borderWidth:1,borderColor:COLORS.border,borderRadius:4,paddingHorizontal:SPACING.sm,paddingVertical:SPACING.sm,fontSize:TYPOGRAPHY.fontSize.md,color:COLORS.text,minHeight:100,textAlignVertical:'top'},inputFocused:{borderColor:COLORS.primary},inputError:{borderColor:COLORS.error},inputDisabled:{backgroundColor:COLORS.disabled,color:COLORS.disabled},errorText:{color:COLORS.error,fontSize:TYPOGRAPHY.fontSize.xs,marginTop:SPACING.xs},charCount:{fontSize:TYPOGRAPHY.fontSize.xs,color:COLORS.textSecondary,marginTop:SPACING.xs}});export const TextAreaRenderer=({component,value,onChange,error,disabled=false,readOnly=false})=>{const[state,setState]=React.useState({isFocused:false});const{label,placeholder,maxLength}=component;const currentLength=String(value||'').length;const inputStyle=[styles.input,state.isFocused&&styles.inputFocused,error&&styles.inputError,disabled&&styles.inputDisabled];return React.createElement(View,{style:styles.container},label&&React.createElement(Text,{style:styles.label},label),React.createElement(TextInput,{style:inputStyle,placeholder:placeholder,placeholderTextColor:COLORS.placeholder,value:String(value||''),onChangeText:onChange,editable:!disabled&&!readOnly,onFocus:()=>setState({isFocused:true}),onBlur:()=>setState({isFocused:false}),multiline:true,numberOfLines:4,maxLength:maxLength}),maxLength&&React.createElement(Text,{style:styles.charCount},currentLength," / ",maxLength),error&&React.createElement(Text,{style:styles.errorText},error));};
2
+ //# sourceMappingURL=TextAreaRenderer.js.map
@@ -0,0 +1,2 @@
1
+ import React from'react';import{TextInput,StyleSheet,View}from'react-native';import{COLORS,SPACING,TYPOGRAPHY}from'../../constants';const styles=StyleSheet.create({container:{marginBottom:SPACING.md},input:{borderWidth:1,borderColor:COLORS.border,borderRadius:4,paddingHorizontal:SPACING.sm,paddingVertical:SPACING.sm,fontSize:TYPOGRAPHY.fontSize.md,color:COLORS.text,minHeight:40},inputFocused:{borderColor:COLORS.primary},inputError:{borderColor:COLORS.error},inputDisabled:{backgroundColor:COLORS.disabled,color:COLORS.disabled}});export const TextfieldRenderer=({component,value,onChange,error,disabled=false,readOnly=false})=>{const[state,setState]=React.useState({isFocused:false});const{placeholder,type='text'}=component;const inputStyle=[styles.input,state.isFocused&&styles.inputFocused,error&&styles.inputError,disabled&&styles.inputDisabled];return React.createElement(View,{style:styles.container},React.createElement(TextInput,{style:inputStyle,placeholder:placeholder,placeholderTextColor:COLORS.placeholder,value:String(value||''),onChangeText:onChange,editable:!disabled&&!readOnly,onFocus:()=>setState({isFocused:true}),onBlur:()=>setState({isFocused:false}),keyboardType:getKeyboardType(type),secureTextEntry:type==='password',autoCapitalize:getAutoCapitalize(type),autoCorrect:type!=='email'&&type!=='url'}));};function getKeyboardType(type){const keyboardMap={email:'email-address',url:'url',number:'numeric',tel:'phone-pad',text:'default'};return keyboardMap[type]||'default';}function getAutoCapitalize(type){const capitalizeMap={email:'none',url:'none',text:'sentences'};return capitalizeMap[type]||'none';}
2
+ //# sourceMappingURL=TextfieldRenderer.js.map
@@ -0,0 +1,2 @@
1
+ import React from'react';import{TextInput,StyleSheet,View}from'react-native';import{COLORS,SPACING,TYPOGRAPHY}from'../../constants';const styles=StyleSheet.create({container:{marginBottom:SPACING.md},input:{borderWidth:1,borderColor:COLORS.border,borderRadius:4,paddingHorizontal:SPACING.sm,paddingVertical:SPACING.sm,fontSize:TYPOGRAPHY.fontSize.md,color:COLORS.text,minHeight:40},inputFocused:{borderColor:COLORS.primary},inputError:{borderColor:COLORS.error},inputDisabled:{backgroundColor:COLORS.disabled,color:COLORS.disabled}});export const URLRenderer=({component,value,onChange,error,disabled=false,readOnly=false})=>{const[state,setState]=React.useState({isFocused:false});const{label,placeholder}=component;const inputStyle=[styles.input,state.isFocused&&styles.inputFocused,error&&styles.inputError,disabled&&styles.inputDisabled];return React.createElement(View,{style:styles.container},React.createElement(TextInput,{style:inputStyle,placeholder:placeholder||'Enter URL',placeholderTextColor:COLORS.placeholder,value:String(value||''),onChangeText:onChange,editable:!disabled&&!readOnly,onFocus:()=>setState({isFocused:true}),onBlur:()=>setState({isFocused:false}),keyboardType:"default",autoCapitalize:"none",autoCorrect:false}));};
2
+ //# sourceMappingURL=URLRenderer.js.map
@@ -0,0 +1,2 @@
1
+ export{TextfieldRenderer}from'./TextfieldRenderer';export{EmailRenderer}from'./EmailRenderer';export{NumberRenderer}from'./NumberRenderer';export{CheckboxRenderer}from'./CheckboxRenderer';export{RadioRenderer}from'./RadioRenderer';export{SelectRenderer}from'./SelectRenderer';export{SelectboxesRenderer}from'./SelectboxesRenderer';export{TextAreaRenderer}from'./TextAreaRenderer';export{PasswordRenderer}from'./PasswordRenderer';export{URLRenderer}from'./URLRenderer';export{PhoneNumberRenderer}from'./PhoneNumberRenderer';export{FallbackRenderer}from'./FallbackRenderer';export const DEFAULT_RENDERERS={textfield:require('./TextfieldRenderer').TextfieldRenderer,text:require('./TextfieldRenderer').TextfieldRenderer,email:require('./EmailRenderer').EmailRenderer,number:require('./NumberRenderer').NumberRenderer,checkbox:require('./CheckboxRenderer').CheckboxRenderer,radio:require('./RadioRenderer').RadioRenderer,select:require('./SelectRenderer').SelectRenderer,selectboxes:require('./SelectboxesRenderer').SelectboxesRenderer,textarea:require('./TextAreaRenderer').TextAreaRenderer,password:require('./PasswordRenderer').PasswordRenderer,url:require('./URLRenderer').URLRenderer,phoneNumber:require('./PhoneNumberRenderer').PhoneNumberRenderer};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,2 @@
1
+ export const DEFAULT_COLORS={PRIMARY:'#007AFF',SECONDARY:'#5856D6',ERROR:'#FF3B30',SUCCESS:'#34C759',WARNING:'#FF9500',INFO:'#00B0FF',BACKGROUND:'#FFFFFF',SURFACE:'#F2F2F7',TEXT:'#333333',TEXT_SECONDARY:'#8E8E93',BORDER:'#C7C7CC',BORDER_FOCUS:'#007AFF',DISABLED:'#F0F0F0',PLACEHOLDER:'#C7C7CC'};
2
+ //# sourceMappingURL=colors.js.map
@@ -0,0 +1,2 @@
1
+ export const COMPONENT_TYPES={TEXTFIELD:'textfield',EMAIL:'email',PASSWORD:'password',NUMBER:'number',TEXTAREA:'textarea',URL:'url',PHONE_NUMBER:'phoneNumber',SELECT:'select',CHECKBOX:'checkbox',RADIO:'radio',SELECTBOXES:'selectboxes',DATE:'date',DATETIME:'datetime',TIME:'time',DAY:'day',FILE:'file',PANEL:'panel',CONTAINER:'container',COLUMNS:'columns',FIELDSET:'fieldset',WELL:'well',TABS:'tabs',TABLE:'table',BUTTON:'button',HTML:'html',LABEL:'label',HIDDEN:'hidden',CONTENT:'content',DATAGRID:'datagrid',EDITGRID:'editgrid',TREE:'tree',WIZARD:'wizard',SIGNATURE:'signature',RESOURCE:'resource',CUSTOM:'custom'};export const INPUT_COMPONENT_TYPES=[COMPONENT_TYPES.TEXTFIELD,COMPONENT_TYPES.EMAIL,COMPONENT_TYPES.PASSWORD,COMPONENT_TYPES.NUMBER,COMPONENT_TYPES.TEXTAREA,COMPONENT_TYPES.URL,COMPONENT_TYPES.PHONE_NUMBER,COMPONENT_TYPES.SELECT,COMPONENT_TYPES.CHECKBOX,COMPONENT_TYPES.RADIO,COMPONENT_TYPES.SELECTBOXES,COMPONENT_TYPES.DATE,COMPONENT_TYPES.DATETIME,COMPONENT_TYPES.TIME,COMPONENT_TYPES.DAY,COMPONENT_TYPES.FILE,COMPONENT_TYPES.DATAGRID,COMPONENT_TYPES.EDITGRID];export const CONTAINER_COMPONENT_TYPES=[COMPONENT_TYPES.PANEL,COMPONENT_TYPES.CONTAINER,COMPONENT_TYPES.COLUMNS,COMPONENT_TYPES.FIELDSET,COMPONENT_TYPES.WELL,COMPONENT_TYPES.TABS,COMPONENT_TYPES.TABLE];export const DISPLAY_COMPONENT_TYPES=[COMPONENT_TYPES.BUTTON,COMPONENT_TYPES.HTML,COMPONENT_TYPES.LABEL,COMPONENT_TYPES.HIDDEN,COMPONENT_TYPES.CONTENT];
2
+ //# sourceMappingURL=componentTypes.js.map
@@ -0,0 +1,2 @@
1
+ import{DEFAULT_COLORS}from'./colors';import{FONT_SIZES,FONT_WEIGHTS}from'./typography';export{DEFAULT_COLORS}from'./colors';export const SPACING={xs:4,sm:8,md:12,lg:16,xl:24,xxl:32};export{FONT_SIZES,FONT_WEIGHTS,LINE_HEIGHTS}from'./typography';export{COMPONENT_TYPES,INPUT_COMPONENT_TYPES,CONTAINER_COMPONENT_TYPES,DISPLAY_COMPONENT_TYPES}from'./componentTypes';export{VALIDATION_MESSAGES}from'./validationMessages';export const COLORS={primary:DEFAULT_COLORS.PRIMARY,secondary:DEFAULT_COLORS.SECONDARY,error:DEFAULT_COLORS.ERROR,success:DEFAULT_COLORS.SUCCESS,warning:DEFAULT_COLORS.WARNING,info:DEFAULT_COLORS.INFO,background:DEFAULT_COLORS.BACKGROUND,surface:DEFAULT_COLORS.SURFACE,text:DEFAULT_COLORS.TEXT,textSecondary:DEFAULT_COLORS.TEXT_SECONDARY,border:DEFAULT_COLORS.BORDER,borderFocus:DEFAULT_COLORS.BORDER_FOCUS,disabled:DEFAULT_COLORS.DISABLED,placeholder:DEFAULT_COLORS.PLACEHOLDER,warningLight:'#FFF3CD',primaryLight:'#E3F2FD'};export const TYPOGRAPHY={fontSize:{xs:FONT_SIZES.XS,sm:FONT_SIZES.SM,md:FONT_SIZES.MD,lg:FONT_SIZES.LG,xl:FONT_SIZES.XL,xxl:FONT_SIZES.XXL},fontWeight:{light:FONT_WEIGHTS.LIGHT,normal:FONT_WEIGHTS.NORMAL,medium:FONT_WEIGHTS.MEDIUM,semibold:FONT_WEIGHTS.SEMI_BOLD,bold:FONT_WEIGHTS.BOLD}};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,2 @@
1
+ export const SPACING={XS:4,SM:8,MD:12,LG:16,XL:24,XXL:32};
2
+ //# sourceMappingURL=spacing.js.map
@@ -0,0 +1,2 @@
1
+ export const FONT_SIZES={XS:12,SM:14,MD:16,LG:18,XL:20,XXL:24};export const FONT_WEIGHTS={LIGHT:'300',NORMAL:'400',MEDIUM:'500',SEMI_BOLD:'600',BOLD:'700'};export const LINE_HEIGHTS={TIGHT:1.2,NORMAL:1.5,RELAXED:1.8};
2
+ //# sourceMappingURL=typography.js.map
@@ -0,0 +1,2 @@
1
+ export const VALIDATION_MESSAGES={REQUIRED:'This field is required',MIN_LENGTH:'Minimum length is {min}',MAX_LENGTH:'Maximum length is {max}',PATTERN:'Invalid format',MIN_VALUE:'Minimum value is {min}',MAX_VALUE:'Maximum value is {max}',INVALID_EMAIL:'Invalid email address',INVALID_URL:'Invalid URL',INVALID_PHONE:'Invalid phone number',INVALID_DATE:'Invalid date',FILE_TYPE_INVALID:'Invalid file type',FILE_SIZE_TOO_LARGE:'File is too large',CUSTOM_ERROR:'This field is invalid'};
2
+ //# sourceMappingURL=validationMessages.js.map