react-crud-mobile 1.3.52 → 1.3.53

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.
@@ -1,707 +1,707 @@
1
- import React, {
2
- createContext,
3
- useContext,
4
- useEffect,
5
- useLayoutEffect,
6
- useRef,
7
- useState,
8
- } from 'react';
9
- import UIChildren from './UIChildren';
10
- import ElTabs from './tabs/ElTabs';
11
- import ElChart from './charts/ElChart';
12
- import UIComplete from './UIComplete';
13
- import {
14
- Crud,
15
- HtmlUtils,
16
- ScopeUtils,
17
- Utils,
18
- ElementType,
19
- MethodType,
20
- ActionType,
21
- ComponentUtils,
22
- } from 'react-crud-utils';
23
- import UILink from './core/UILink';
24
- import UIIcon from './core/UIIcon';
25
- import UIButton from './core/UIButton';
26
- import UISelect from './core/UISelect';
27
- import UISwitch from './core/UISwitch';
28
- import UISlider from './core/UISlider';
29
- import UIOption from './core/UIOption';
30
- import UIRadio from './core/UIRadio';
31
- import UIInput from './core/UIInput';
32
- import {
33
- Alert,
34
- Image,
35
- Linking,
36
- StyleSheet,
37
- Text,
38
- TouchableHighlight,
39
- View,
40
- } from 'react-native';
41
- import UIList from './core/UIList';
42
- import UIToggle from './core/UIToggle';
43
- import UIQuantity from './core/UIQuantity';
44
- import UIModal from './core/UIModal';
45
- import { Ionicons } from '@expo/vector-icons';
46
- import UIView from './core/UIView';
47
- import Toast from 'react-native-toast-message';
48
- import UIOrder from './core/UIOrder';
49
-
50
- const CrudContext = createContext<any>({});
51
-
52
- export default function UIElement(props: ElementType) {
53
- const ctx = useContext(CrudContext);
54
- const theme = Utils.nvl(props.theme, ctx?.theme);
55
-
56
- let crud: Crud = Utils.nvl(props.crud, ctx?.crud);
57
- let [scope] = useState(ScopeUtils.create({ crud, ...props, theme }));
58
- let [index, setIndex] = useState(0);
59
- let [error, setError]: string | any = useState(null);
60
-
61
- scope.compile(props);
62
-
63
- crud = scope.crud;
64
-
65
- let options: any = scope.getOptions();
66
-
67
- let original = scope.original;
68
- let ref = useRef(null);
69
-
70
- scope.update = () => {
71
- setIndex(++index);
72
- };
73
-
74
- scope.updateElement = () => {
75
- setIndex(++index);
76
- };
77
-
78
- scope.toast = (message: string, type = 'info', args?: any) => {
79
- Toast.show({
80
- type, // 'success' | 'error' | 'info'
81
- text1: message,
82
- position: 'bottom', // 'top' é outra opção
83
- visibilityTime: 3000, // tempo que fica visível em ms
84
- ...args,
85
- });
86
- };
87
-
88
- scope.prompt = (args: MethodType) => {
89
- let event = args.event as ActionType;
90
-
91
- if (event) {
92
- let message = 'Você tem certeza que deseja continuar?';
93
- let title = 'Atenção';
94
- let prompt = event.prompt;
95
-
96
- if (typeof prompt === 'string') {
97
- message = prompt;
98
- }
99
-
100
- if (typeof prompt === 'object') {
101
- message = Utils.nvl(prompt.message, message);
102
- title = Utils.nvl(prompt.title, title);
103
- }
104
-
105
- Alert.alert(
106
- title,
107
- message,
108
- [
109
- {
110
- text: 'Cancelar',
111
- style: 'cancel',
112
- },
113
- {
114
- text: 'Confirmar',
115
- onPress: () => scope.execute(args),
116
- },
117
- ],
118
- { cancelable: false }
119
- );
120
- }
121
- };
122
- const Custom = () => {
123
- let c: any = original.custom;
124
-
125
- if (c) {
126
- if (typeof c === 'string') {
127
- return (
128
- <UIElement
129
- element={{ value: c, type: 'dummy' }}
130
- crud={crud}
131
- ></UIElement>
132
- );
133
- }
134
-
135
- return (
136
- <UIElement
137
- type={c.type}
138
- tag={c.type}
139
- {...c.props}
140
- crud={crud}
141
- ></UIElement>
142
- );
143
- }
144
-
145
- return <></>;
146
- };
147
-
148
- if (scope.is('type', 'dummy')) {
149
- return <>{scope.getDisplayValue()}</>;
150
- }
151
-
152
- let onCheck = () => {
153
- let v = scope.getValue();
154
- let check = !(v === true);
155
-
156
- onChange({ target: { value: check } });
157
- };
158
-
159
- let onChange = (e: any) => {
160
- let val = e.target.value;
161
-
162
- if (scope.isType('integer', 'int', 'number')) {
163
- val = parseInt(val);
164
- } else if (scope.isType('decimal')) {
165
- val = parseFloat(val);
166
- }
167
-
168
- if (scope.isType('select', 'complete')) {
169
- val = scope.getSelectedItem(val);
170
- }
171
-
172
- scope.changeValue(val);
173
- scope.update();
174
- };
175
-
176
- let onClick = (e: any) => {
177
- scope.call('click');
178
- };
179
-
180
- let defaultsInput: any = {
181
- scope,
182
- crud,
183
- onChange: onChange,
184
- };
185
-
186
- if (scope.isType('password')) {
187
- defaultsInput.type = 'password';
188
- }
189
-
190
- let isChecked = () => {
191
- let v = scope.getValue();
192
-
193
- return v === true;
194
- };
195
-
196
- let hasChildren = () => {
197
- if (scope.isInput()) {
198
- return false;
199
- }
200
-
201
- return !Utils.isEmpty(props.children) || !Utils.isEmpty(props.elements);
202
- };
203
-
204
- let isInput = scope.is(
205
- 'type',
206
- 'text',
207
- 'number',
208
- 'integer',
209
- 'int',
210
- 'phone',
211
- 'postalCode',
212
- 'money',
213
- 'password',
214
- 'email'
215
- );
216
-
217
- const getStyle = (part?: string, extra?: any) => {
218
- let type = Utils.nvl(original.type, 'none');
219
- let key = Utils.nvl(part, 'root');
220
- let def = { ...styles[key] };
221
- let hasChild = hasChildren();
222
-
223
- type = Utils.nvl(original.layout, type);
224
-
225
- if (!part && !hasChild) {
226
- def = { ...def };
227
- }
228
-
229
- if (scope.isInput()) {
230
- def = { ...def, ...elementStyle.input[key] };
231
- }
232
-
233
- def = { ...def, ...elementStyle?.[type]?.[key] };
234
-
235
- if (hasChild && part) {
236
- def = { ...def, ...withChildStyles[part] };
237
- }
238
-
239
- return { ...def, ...scope.getStyle(part, { ...def, ...extra }) };
240
- };
241
-
242
- let elStyle = getStyle('element');
243
-
244
- let defaultsUI: any = {
245
- required: scope.isRequired(),
246
- size: 'small',
247
- scope,
248
- crud,
249
- style: elStyle,
250
- placeholder: scope.attr('placeholder', 'Digite aqui'),
251
- };
252
-
253
- scope.error = (msg: string) => {
254
- error = msg;
255
- setError(msg);
256
- };
257
-
258
- if (!original.list?.url && !original.load?.url) {
259
- scope.start();
260
- }
261
-
262
- useEffect(() => {
263
- scope.start();
264
- });
265
-
266
- const CustomIcon = () => {
267
- if (typeof original.icon === 'string') {
268
- return <Ionicons name={original.icon} style={scope.getStyle('icon')} />;
269
- }
270
- return <>{original.icon}</>;
271
- };
272
-
273
- scope.open = (args: any) => {
274
- Linking.openURL(args.url);
275
- };
276
-
277
- useLayoutEffect(() => {
278
- if (ref?.current && scope.is('type', 'card', 'list', 'tabs', 'stepper')) {
279
- let el: any = ref?.current;
280
-
281
- if (el?.classList) {
282
- let bg = HtmlUtils.getBGColor(el);
283
-
284
- if (bg === 'rgb(255, 255, 255)') {
285
- el.classList.add('ui-dark');
286
- } else {
287
- el.classList.add('ui-light');
288
- }
289
- }
290
- }
291
- });
292
-
293
- const isShowLabel = () => {
294
- if (
295
- typeof original.label !== 'undefined' &&
296
- original.label !== false &&
297
- !scope.isType('button', 'dialog', 'modal')
298
- ) {
299
- return true;
300
- }
301
-
302
- return false;
303
- };
304
-
305
- const isShowInner = () => {
306
- if (hasChildren()) {
307
- return false;
308
- }
309
- return true;
310
- };
311
-
312
- if (!scope.isRendered() || scope.is('type', 'define')) {
313
- return <></>;
314
- }
315
-
316
- const isShowChild = () => {
317
- if (
318
- scope.isType(
319
- 'tabs',
320
- 'view',
321
- 'grid',
322
- 'list',
323
- 'define',
324
- 'repeat',
325
- 'modal',
326
- 'dialog',
327
- 'chart'
328
- )
329
- ) {
330
- return false;
331
- }
332
-
333
- return true;
334
- };
335
-
336
- let Tag: any = View;
337
- let custom: any = {};
338
-
339
- if (!scope.isType('input', 'grid', 'list', 'repeat') && original.click) {
340
- Tag = TouchableHighlight;
341
-
342
- custom.underlayColor = 'transparent';
343
- custom.onPress = onClick;
344
- }
345
-
346
- let Inner = () => {
347
- return (
348
- <>
349
- {scope.getPart('render', null, <></>)}
350
- {scope.is('type', 'button') && (
351
- <UIButton
352
- {...defaultsUI}
353
- onClick={onClick}
354
- variant={scope.attr('variant', 'outlined')}
355
- >
356
- {original.icon && <CustomIcon />}
357
- {original.label && (
358
- <Text style={scope.getPart('label', 'button')}>
359
- {scope.getLabel()}
360
- </Text>
361
- )}
362
- </UIButton>
363
- )}
364
- {scope.is('type', 'icon') && (
365
- <UIIcon
366
- {...defaultsUI}
367
- onClick={onClick}
368
- variant={scope.attr('variant', 'outlined')}
369
- >
370
- {scope.getDisplayValue()}
371
- </UIIcon>
372
- )}
373
- {scope.is('type', 'link') && (
374
- <UILink
375
- {...defaultsUI}
376
- onClick={onClick}
377
- variant={scope.attr('variant', 'outlined')}
378
- >
379
- {original.icon && <CustomIcon />}
380
- {original.label && (
381
- <Text style={scope.getPart('label', 'link')}>
382
- {scope.getLabel()}
383
- </Text>
384
- )}
385
- </UILink>
386
- )}
387
- {isInput && (
388
- <UIInput
389
- {...defaultsInput}
390
- {...defaultsUI}
391
- InputProps={{ ...original.inputProps }}
392
- />
393
- )}
394
- {scope.is('type', 'complete', 'autocomplete') && (
395
- <UIComplete
396
- scope={scope}
397
- defaultsInput={defaultsInput}
398
- defaultsUI={defaultsUI}
399
- />
400
- )}
401
- {scope.is('type', 'quantity') && (
402
- <UIQuantity
403
- scope={scope}
404
- defaultsInput={defaultsInput}
405
- defaultsUI={defaultsUI}
406
- />
407
- )}
408
- {scope.is('type', 'checkbox', 'boolean', 'switch') && (
409
- <UISwitch
410
- checked={isChecked()}
411
- {...defaultsInput}
412
- onChange={onCheck}
413
- />
414
- )}
415
- {scope.isType('slider') && (
416
- <UISlider {...defaultsInput} onChange={onCheck} />
417
- )}
418
- {scope.is('type', 'select') && (
419
- <UISelect
420
- {...defaultsInput}
421
- {...defaultsUI}
422
- value={scope.getSelectedValue()}
423
- />
424
- )}
425
- {scope.is('type', 'toggle') && (
426
- <UIToggle
427
- {...defaultsInput}
428
- {...defaultsUI}
429
- value={scope.getSelectedValue()}
430
- />
431
- )}
432
- {scope.is('type', 'radio') && (
433
- <UIRadio {...defaultsInput} {...defaultsUI} row>
434
- {options.map((row: any, i: number) => (
435
- <UIOption
436
- key={'i' + i}
437
- control={<UIRadio {...defaultsUI} />}
438
- label={row.label}
439
- value={row.value}
440
- />
441
- ))}
442
- </UIRadio>
443
- )}
444
- {scope.is('type', 'custom') && <Custom />}
445
- {scope.is('type', 'column') && (
446
- <>
447
- {scope.is('format', 'img') && (
448
- <Image source={scope.getDisplayValue()} />
449
- )}
450
- {scope.is('format', 'icon') && <UIIcon scope={scope} crud={crud} />}
451
- {!scope.is('format', 'icon', 'img') && (
452
- <Text>{scope.getDisplayValue()}</Text>
453
- )}
454
- </>
455
- )}
456
- {scope.is('type', 'output', 'value') && (
457
- <Text style={getStyle('value')}>{scope.getDisplayValue()}</Text>
458
- )}
459
- </>
460
- );
461
- };
462
-
463
- let Include = ({ name, style }: any) => {
464
- if (props[name]) {
465
- let define = ComponentUtils.getDefine(props, name);
466
-
467
- if (!Utils.isEmpty(define)) {
468
- return (
469
- <UIChildren
470
- {...props}
471
- scope={scope}
472
- crud={crud}
473
- style={getStyle(name, style)}
474
- >
475
- {define}
476
- </UIChildren>
477
- );
478
- }
479
- }
480
- return <></>;
481
- };
482
-
483
- let Container = () => {
484
- return (
485
- <>
486
- {isShowLabel() && (
487
- <View
488
- style={getStyle('outerLabel', {
489
- alignSelf: 'flex-start',
490
- flexDirection: 'row',
491
- display: 'flex',
492
- justifyContent: 'space-between',
493
- alignItems: 'center',
494
- width: '100%',
495
- })}
496
- >
497
- <Text style={getStyle('label')}>{scope.getLabel()}</Text>
498
- <Include name="actions" style={{ width: 'auto' }} />
499
- </View>
500
- )}
501
- {isShowInner() && (
502
- <>
503
- <View style={getStyle('inner')}>
504
- <Inner />
505
- </View>
506
- {error && <View style={getStyle('error')}>{error}</View>}
507
- </>
508
- )}
509
- {scope.isType('list', 'repeat') && (
510
- <UIList {...props} scope={scope} crud={crud} />
511
- )}
512
-
513
- {scope.isType('order') && (
514
- <UIOrder {...props} scope={scope} crud={crud} />
515
- )}
516
-
517
- {scope.isType('dialog') && (
518
- <UIModal {...props} scope={scope} crud={crud} />
519
- )}
520
- {scope.isType('chart') && (
521
- <ElChart {...props} scope={scope} crud={crud} />
522
- )}
523
- {scope.isType('tabs') && (
524
- <ElTabs {...props} scope={scope} crud={crud} />
525
- )}
526
-
527
- {scope.isType('view') && (
528
- <UIView {...props} scope={scope} crud={crud} />
529
- )}
530
-
531
- {isShowChild() && (
532
- <UIChildren
533
- {...props}
534
- scope={scope}
535
- crud={crud}
536
- style={getStyle('inner')}
537
- />
538
- )}
539
- </>
540
- );
541
- };
542
-
543
- let Card = (props: any) => {
544
- let isCard = scope.is('type|layout', 'card');
545
-
546
- if (isCard) {
547
- let box = {
548
- ...getStyle('box', { ...boxStyle.box, alignSelf: 'stretch' }),
549
- };
550
-
551
- return (
552
- <View style={getStyle('card', { ...box })}>
553
- <View
554
- style={getStyle('boxInner', {
555
- paddingHorizontal: 15,
556
- paddingVertical: 10,
557
- })}
558
- >
559
- {props.children}
560
- </View>
561
- </View>
562
- );
563
- }
564
-
565
- if (scope.isInput() || original.container) {
566
- return (
567
- <View style={getStyle('container', { padding: 5, width: '100%' })}>
568
- {props.children}
569
- </View>
570
- );
571
- }
572
- return <>{props.children}</>;
573
- };
574
-
575
- return (
576
- <CrudContext.Provider value={{ crud, theme }}>
577
- <Tag ref={ref} style={getStyle()} {...custom}>
578
- <Card>
579
- <Container />
580
- </Card>
581
- </Tag>
582
- </CrudContext.Provider>
583
- );
584
- }
585
-
586
- let boxStyle = StyleSheet.create({
587
- box: {
588
- borderWidth: 0,
589
- borderColor: '#dedede',
590
- borderStyle: 'solid',
591
- backgroundColor: 'white',
592
- borderRadius: 12,
593
- width: '100%',
594
- shadowColor: '#000',
595
- shadowOpacity: 0.1,
596
- shadowRadius: 4,
597
- },
598
- });
599
-
600
- const box: any = {
601
- ...boxStyle.box,
602
- };
603
- //v2
604
- const elementStyle: any = {};
605
-
606
- elementStyle.view = {
607
- inner: {
608
- width: '100%',
609
- alignItems: 'normal',
610
- flex: 1,
611
- },
612
- container: {
613
- width: '100%',
614
- backgroundColor: 'background',
615
- flex: 1,
616
- gap: 10,
617
- },
618
- root: {
619
- width: '100%',
620
- flex: 1,
621
- alignItems: 'normal',
622
- padding: 0,
623
- },
624
- };
625
-
626
- elementStyle.input = StyleSheet.create({
627
- label: {
628
- paddingLeft: 0,
629
- },
630
- inner: {
631
- flex: 1,
632
- width: '100%',
633
- padding: 0,
634
- gap: 10,
635
- alignSelf: 'flex-start',
636
- flexDirection: 'row',
637
- flexWrap: 'wrap',
638
- },
639
- });
640
-
641
- elementStyle.switch = {
642
- inner: {
643
- padding: 5,
644
- },
645
- };
646
-
647
- elementStyle.quantity = {
648
- inner: {
649
- ...box,
650
- backgroundColor: 'primarySoft',
651
- fontWeight: 600,
652
- fontSize: 16,
653
- borderRadius: 25,
654
- borderWidth: 0,
655
- padding: 5,
656
- paddingHorizontal: 5,
657
- paddingVertical: 5,
658
- flexWrap: 'nowrap',
659
- flex: 1,
660
- flexDirection: 'row',
661
- justifyContent: 'center',
662
- alignItems: 'center',
663
- },
664
- };
665
-
666
- elementStyle.toggle = StyleSheet.create({
667
- inner: {
668
- ...box,
669
- flex: 1,
670
- width: '100%',
671
- gap: 10,
672
- justifyContent: 'center',
673
- flexDirection: 'row',
674
- paddingHorizontal: 10,
675
- paddingVertical: 0,
676
- alignSelf: 'flex-start',
677
- flexWrap: 'nowrap',
678
- },
679
- });
680
-
681
- const styles = StyleSheet.create({
682
- root: {
683
- gap: 5,
684
- flexDirection: 'column',
685
- flexWrap: 'wrap',
686
- width: '100%',
687
- alignItems: 'flex-start',
688
- },
689
- label: {
690
- fontWeight: 400,
691
- marginTop: 5,
692
- fontSize: 12,
693
- color: 'labelColor',
694
- },
695
- inner: { width: '100%' },
696
- });
697
-
698
- const withChildStyles = StyleSheet.create({
699
- root: {
700
- gap: 10,
701
- },
702
- label: {
703
- width: '100%',
704
- fontWeight: 500,
705
- fontSize: 24,
706
- },
707
- });
1
+ import React, {
2
+ createContext,
3
+ useContext,
4
+ useEffect,
5
+ useLayoutEffect,
6
+ useRef,
7
+ useState,
8
+ } from 'react';
9
+ import UIChildren from './UIChildren';
10
+ import ElTabs from './tabs/ElTabs';
11
+ import ElChart from './charts/ElChart';
12
+ import UIComplete from './UIComplete';
13
+ import {
14
+ Crud,
15
+ HtmlUtils,
16
+ ScopeUtils,
17
+ Utils,
18
+ ElementType,
19
+ MethodType,
20
+ ActionType,
21
+ ComponentUtils,
22
+ } from 'react-crud-utils';
23
+ import UILink from './core/UILink';
24
+ import UIIcon from './core/UIIcon';
25
+ import UIButton from './core/UIButton';
26
+ import UISelect from './core/UISelect';
27
+ import UISwitch from './core/UISwitch';
28
+ import UISlider from './core/UISlider';
29
+ import UIOption from './core/UIOption';
30
+ import UIRadio from './core/UIRadio';
31
+ import UIInput from './core/UIInput';
32
+ import {
33
+ Alert,
34
+ Image,
35
+ Linking,
36
+ StyleSheet,
37
+ Text,
38
+ TouchableHighlight,
39
+ View,
40
+ } from 'react-native';
41
+ import UIList from './core/UIList';
42
+ import UIToggle from './core/UIToggle';
43
+ import UIQuantity from './core/UIQuantity';
44
+ import UIModal from './core/UIModal';
45
+ import { Ionicons } from '@expo/vector-icons';
46
+ import UIView from './core/UIView';
47
+ import Toast from 'react-native-toast-message';
48
+ import UIOrder from './core/UIOrder';
49
+
50
+ const CrudContext = createContext<any>({});
51
+
52
+ export default function UIElement(props: ElementType) {
53
+ const ctx = useContext(CrudContext);
54
+ const theme = Utils.nvl(props.theme, ctx?.theme);
55
+
56
+ let crud: Crud = Utils.nvl(props.crud, ctx?.crud);
57
+ let [scope] = useState(ScopeUtils.create({ crud, ...props, theme }));
58
+ let [index, setIndex] = useState(0);
59
+ let [error, setError]: string | any = useState(null);
60
+
61
+ scope.compile(props);
62
+
63
+ crud = scope.crud;
64
+
65
+ let options: any = scope.getOptions();
66
+
67
+ let original = scope.original;
68
+ let ref = useRef(null);
69
+
70
+ scope.update = () => {
71
+ setIndex(++index);
72
+ };
73
+
74
+ scope.updateElement = () => {
75
+ setIndex(++index);
76
+ };
77
+
78
+ scope.toast = (message: string, type = 'info', args?: any) => {
79
+ Toast.show({
80
+ type, // 'success' | 'error' | 'info'
81
+ text1: message,
82
+ position: 'bottom', // 'top' é outra opção
83
+ visibilityTime: 3000, // tempo que fica visível em ms
84
+ ...args,
85
+ });
86
+ };
87
+
88
+ scope.prompt = (args: MethodType) => {
89
+ let event = args.event as ActionType;
90
+
91
+ if (event) {
92
+ let message = 'Você tem certeza que deseja continuar?';
93
+ let title = 'Atenção';
94
+ let prompt = event.prompt;
95
+
96
+ if (typeof prompt === 'string') {
97
+ message = prompt;
98
+ }
99
+
100
+ if (typeof prompt === 'object') {
101
+ message = Utils.nvl(prompt.message, message);
102
+ title = Utils.nvl(prompt.title, title);
103
+ }
104
+
105
+ Alert.alert(
106
+ title,
107
+ message,
108
+ [
109
+ {
110
+ text: 'Cancelar',
111
+ style: 'cancel',
112
+ },
113
+ {
114
+ text: 'Confirmar',
115
+ onPress: () => scope.execute(args),
116
+ },
117
+ ],
118
+ { cancelable: false }
119
+ );
120
+ }
121
+ };
122
+ const Custom = () => {
123
+ let c: any = original.custom;
124
+
125
+ if (c) {
126
+ if (typeof c === 'string') {
127
+ return (
128
+ <UIElement
129
+ element={{ value: c, type: 'dummy' }}
130
+ crud={crud}
131
+ ></UIElement>
132
+ );
133
+ }
134
+
135
+ return (
136
+ <UIElement
137
+ type={c.type}
138
+ tag={c.type}
139
+ {...c.props}
140
+ crud={crud}
141
+ ></UIElement>
142
+ );
143
+ }
144
+
145
+ return <></>;
146
+ };
147
+
148
+ if (scope.is('type', 'dummy')) {
149
+ return <>{scope.getDisplayValue()}</>;
150
+ }
151
+
152
+ let onCheck = () => {
153
+ let v = scope.getValue();
154
+ let check = !(v === true);
155
+
156
+ onChange({ target: { value: check } });
157
+ };
158
+
159
+ let onChange = (e: any) => {
160
+ let val = e.target.value;
161
+
162
+ if (scope.isType('integer', 'int', 'number')) {
163
+ val = parseInt(val);
164
+ } else if (scope.isType('decimal')) {
165
+ val = parseFloat(val);
166
+ }
167
+
168
+ if (scope.isType('select', 'complete')) {
169
+ val = scope.getSelectedItem(val);
170
+ }
171
+
172
+ scope.changeValue(val);
173
+ scope.update();
174
+ };
175
+
176
+ let onClick = (e: any) => {
177
+ scope.call('click');
178
+ };
179
+
180
+ let defaultsInput: any = {
181
+ scope,
182
+ crud,
183
+ onChange: onChange,
184
+ };
185
+
186
+ if (scope.isType('password')) {
187
+ defaultsInput.type = 'password';
188
+ }
189
+
190
+ let isChecked = () => {
191
+ let v = scope.getValue();
192
+
193
+ return v === true;
194
+ };
195
+
196
+ let hasChildren = () => {
197
+ if (scope.isInput()) {
198
+ return false;
199
+ }
200
+
201
+ return !Utils.isEmpty(props.children) || !Utils.isEmpty(props.elements);
202
+ };
203
+
204
+ let isInput = scope.is(
205
+ 'type',
206
+ 'text',
207
+ 'number',
208
+ 'integer',
209
+ 'int',
210
+ 'phone',
211
+ 'postalCode',
212
+ 'money',
213
+ 'password',
214
+ 'email'
215
+ );
216
+
217
+ const getStyle = (part?: string, extra?: any) => {
218
+ let type = Utils.nvl(original.type, 'none');
219
+ let key = Utils.nvl(part, 'root');
220
+ let def = { ...styles[key] };
221
+ let hasChild = hasChildren();
222
+
223
+ type = Utils.nvl(original.layout, type);
224
+
225
+ if (!part && !hasChild) {
226
+ def = { ...def };
227
+ }
228
+
229
+ if (scope.isInput()) {
230
+ def = { ...def, ...elementStyle.input[key] };
231
+ }
232
+
233
+ def = { ...def, ...elementStyle?.[type]?.[key] };
234
+
235
+ if (hasChild && part) {
236
+ def = { ...def, ...withChildStyles[part] };
237
+ }
238
+
239
+ return { ...def, ...scope.getStyle(part, { ...def, ...extra }) };
240
+ };
241
+
242
+ let elStyle = getStyle('element');
243
+
244
+ let defaultsUI: any = {
245
+ required: scope.isRequired(),
246
+ size: 'small',
247
+ scope,
248
+ crud,
249
+ style: elStyle,
250
+ placeholder: scope.attr('placeholder', 'Digite aqui'),
251
+ };
252
+
253
+ scope.error = (msg: string) => {
254
+ error = msg;
255
+ setError(msg);
256
+ };
257
+
258
+ if (!original.list?.url && !original.load?.url) {
259
+ scope.start();
260
+ }
261
+
262
+ useEffect(() => {
263
+ scope.start();
264
+ });
265
+
266
+ const CustomIcon = () => {
267
+ if (typeof original.icon === 'string') {
268
+ return <Ionicons name={original.icon} style={scope.getStyle('icon')} />;
269
+ }
270
+ return <>{original.icon}</>;
271
+ };
272
+
273
+ scope.open = (args: any) => {
274
+ Linking.openURL(args.url);
275
+ };
276
+
277
+ useLayoutEffect(() => {
278
+ if (ref?.current && scope.is('type', 'card', 'list', 'tabs', 'stepper')) {
279
+ let el: any = ref?.current;
280
+
281
+ if (el?.classList) {
282
+ let bg = HtmlUtils.getBGColor(el);
283
+
284
+ if (bg === 'rgb(255, 255, 255)') {
285
+ el.classList.add('ui-dark');
286
+ } else {
287
+ el.classList.add('ui-light');
288
+ }
289
+ }
290
+ }
291
+ });
292
+
293
+ const isShowLabel = () => {
294
+ if (
295
+ typeof original.label !== 'undefined' &&
296
+ original.label !== false &&
297
+ !scope.isType('button', 'dialog', 'modal')
298
+ ) {
299
+ return true;
300
+ }
301
+
302
+ return false;
303
+ };
304
+
305
+ const isShowInner = () => {
306
+ if (hasChildren()) {
307
+ return false;
308
+ }
309
+ return true;
310
+ };
311
+
312
+ if (!scope.isRendered() || scope.is('type', 'define')) {
313
+ return <></>;
314
+ }
315
+
316
+ const isShowChild = () => {
317
+ if (
318
+ scope.isType(
319
+ 'tabs',
320
+ 'view',
321
+ 'grid',
322
+ 'list',
323
+ 'define',
324
+ 'repeat',
325
+ 'modal',
326
+ 'dialog',
327
+ 'chart'
328
+ )
329
+ ) {
330
+ return false;
331
+ }
332
+
333
+ return true;
334
+ };
335
+
336
+ let Tag: any = View;
337
+ let custom: any = {};
338
+
339
+ if (!scope.isType('input', 'grid', 'list', 'repeat') && original.click) {
340
+ Tag = TouchableHighlight;
341
+
342
+ custom.underlayColor = 'transparent';
343
+ custom.onPress = onClick;
344
+ }
345
+
346
+ let Inner = () => {
347
+ return (
348
+ <>
349
+ {scope.getPart('render', null, <></>)}
350
+ {scope.is('type', 'button') && (
351
+ <UIButton
352
+ {...defaultsUI}
353
+ onClick={onClick}
354
+ variant={scope.attr('variant', 'outlined')}
355
+ >
356
+ {original.icon && <CustomIcon />}
357
+ {original.label && (
358
+ <Text style={scope.getPart('label', 'button')}>
359
+ {scope.getLabel()}
360
+ </Text>
361
+ )}
362
+ </UIButton>
363
+ )}
364
+ {scope.is('type', 'icon') && (
365
+ <UIIcon
366
+ {...defaultsUI}
367
+ onClick={onClick}
368
+ variant={scope.attr('variant', 'outlined')}
369
+ >
370
+ {scope.getDisplayValue()}
371
+ </UIIcon>
372
+ )}
373
+ {scope.is('type', 'link') && (
374
+ <UILink
375
+ {...defaultsUI}
376
+ onClick={onClick}
377
+ variant={scope.attr('variant', 'outlined')}
378
+ >
379
+ {original.icon && <CustomIcon />}
380
+ {original.label && (
381
+ <Text style={scope.getPart('label', 'link')}>
382
+ {scope.getLabel()}
383
+ </Text>
384
+ )}
385
+ </UILink>
386
+ )}
387
+ {isInput && (
388
+ <UIInput
389
+ {...defaultsInput}
390
+ {...defaultsUI}
391
+ InputProps={{ ...original.inputProps }}
392
+ />
393
+ )}
394
+ {scope.is('type', 'complete', 'autocomplete') && (
395
+ <UIComplete
396
+ scope={scope}
397
+ defaultsInput={defaultsInput}
398
+ defaultsUI={defaultsUI}
399
+ />
400
+ )}
401
+ {scope.is('type', 'quantity') && (
402
+ <UIQuantity
403
+ scope={scope}
404
+ defaultsInput={defaultsInput}
405
+ defaultsUI={defaultsUI}
406
+ />
407
+ )}
408
+ {scope.is('type', 'checkbox', 'boolean', 'switch') && (
409
+ <UISwitch
410
+ checked={isChecked()}
411
+ {...defaultsInput}
412
+ onChange={onCheck}
413
+ />
414
+ )}
415
+ {scope.isType('slider') && (
416
+ <UISlider {...defaultsInput} onChange={onCheck} />
417
+ )}
418
+ {scope.is('type', 'select') && (
419
+ <UISelect
420
+ {...defaultsInput}
421
+ {...defaultsUI}
422
+ value={scope.getSelectedValue()}
423
+ />
424
+ )}
425
+ {scope.is('type', 'toggle') && (
426
+ <UIToggle
427
+ {...defaultsInput}
428
+ {...defaultsUI}
429
+ value={scope.getSelectedValue()}
430
+ />
431
+ )}
432
+ {scope.is('type', 'radio') && (
433
+ <UIRadio {...defaultsInput} {...defaultsUI} row>
434
+ {options.map((row: any, i: number) => (
435
+ <UIOption
436
+ key={'i' + i}
437
+ control={<UIRadio {...defaultsUI} />}
438
+ label={row.label}
439
+ value={row.value}
440
+ />
441
+ ))}
442
+ </UIRadio>
443
+ )}
444
+ {scope.is('type', 'custom') && <Custom />}
445
+ {scope.is('type', 'column') && (
446
+ <>
447
+ {scope.is('format', 'img') && (
448
+ <Image source={scope.getDisplayValue()} />
449
+ )}
450
+ {scope.is('format', 'icon') && <UIIcon scope={scope} crud={crud} />}
451
+ {!scope.is('format', 'icon', 'img') && (
452
+ <Text>{scope.getDisplayValue()}</Text>
453
+ )}
454
+ </>
455
+ )}
456
+ {scope.is('type', 'output', 'value') && (
457
+ <Text style={getStyle('value')}>{scope.getDisplayValue()}</Text>
458
+ )}
459
+ </>
460
+ );
461
+ };
462
+
463
+ let Include = ({ name, style }: any) => {
464
+ if (props[name]) {
465
+ let define = ComponentUtils.getDefine(props, name);
466
+
467
+ if (!Utils.isEmpty(define)) {
468
+ return (
469
+ <UIChildren
470
+ {...props}
471
+ scope={scope}
472
+ crud={crud}
473
+ style={getStyle(name, style)}
474
+ >
475
+ {define}
476
+ </UIChildren>
477
+ );
478
+ }
479
+ }
480
+ return <></>;
481
+ };
482
+
483
+ let Container = () => {
484
+ return (
485
+ <>
486
+ {isShowLabel() && (
487
+ <View
488
+ style={getStyle('outerLabel', {
489
+ alignSelf: 'flex-start',
490
+ flexDirection: 'row',
491
+ display: 'flex',
492
+ justifyContent: 'space-between',
493
+ alignItems: 'center',
494
+ width: '100%',
495
+ })}
496
+ >
497
+ <Text style={getStyle('label')}>{scope.getLabel()}</Text>
498
+ <Include name="actions" style={{ width: 'auto' }} />
499
+ </View>
500
+ )}
501
+ {isShowInner() && (
502
+ <>
503
+ <View style={getStyle('inner')}>
504
+ <Inner />
505
+ </View>
506
+ {error && <View style={getStyle('error')}>{error}</View>}
507
+ </>
508
+ )}
509
+ {scope.isType('list', 'repeat') && (
510
+ <UIList {...props} scope={scope} crud={crud} />
511
+ )}
512
+
513
+ {scope.isType('order') && (
514
+ <UIOrder {...props} scope={scope} crud={crud} />
515
+ )}
516
+
517
+ {scope.isType('dialog') && (
518
+ <UIModal {...props} scope={scope} crud={crud} />
519
+ )}
520
+ {scope.isType('chart') && (
521
+ <ElChart {...props} scope={scope} crud={crud} />
522
+ )}
523
+ {scope.isType('tabs') && (
524
+ <ElTabs {...props} scope={scope} crud={crud} />
525
+ )}
526
+
527
+ {scope.isType('view') && (
528
+ <UIView {...props} scope={scope} crud={crud} />
529
+ )}
530
+
531
+ {isShowChild() && (
532
+ <UIChildren
533
+ {...props}
534
+ scope={scope}
535
+ crud={crud}
536
+ style={getStyle('inner')}
537
+ />
538
+ )}
539
+ </>
540
+ );
541
+ };
542
+
543
+ let Card = (props: any) => {
544
+ let isCard = scope.is('type|layout', 'card');
545
+
546
+ if (isCard) {
547
+ let box = {
548
+ ...getStyle('box', { ...boxStyle.box, alignSelf: 'stretch' }),
549
+ };
550
+
551
+ return (
552
+ <View style={getStyle('card', { ...box })}>
553
+ <View
554
+ style={getStyle('boxInner', {
555
+ paddingHorizontal: 15,
556
+ paddingVertical: 10,
557
+ })}
558
+ >
559
+ {props.children}
560
+ </View>
561
+ </View>
562
+ );
563
+ }
564
+
565
+ if (scope.isInput() || original.container) {
566
+ return (
567
+ <View style={getStyle('container', { padding: 5, width: '100%' })}>
568
+ {props.children}
569
+ </View>
570
+ );
571
+ }
572
+ return <>{props.children}</>;
573
+ };
574
+
575
+ return (
576
+ <CrudContext.Provider value={{ crud, theme }}>
577
+ <Tag ref={ref} style={getStyle()} {...custom}>
578
+ <Card>
579
+ <Container />
580
+ </Card>
581
+ </Tag>
582
+ </CrudContext.Provider>
583
+ );
584
+ }
585
+
586
+ let boxStyle = StyleSheet.create({
587
+ box: {
588
+ borderWidth: 0,
589
+ borderColor: '#dedede',
590
+ borderStyle: 'solid',
591
+ backgroundColor: 'white',
592
+ borderRadius: 12,
593
+ width: '100%',
594
+ shadowColor: '#000',
595
+ shadowOpacity: 0.1,
596
+ shadowRadius: 4,
597
+ },
598
+ });
599
+
600
+ const box: any = {
601
+ ...boxStyle.box,
602
+ };
603
+ //v2
604
+ const elementStyle: any = {};
605
+
606
+ elementStyle.view = {
607
+ inner: {
608
+ width: '100%',
609
+ alignItems: 'normal',
610
+ flex: 1,
611
+ },
612
+ container: {
613
+ width: '100%',
614
+ backgroundColor: 'background',
615
+ flex: 1,
616
+ gap: 10,
617
+ },
618
+ root: {
619
+ width: '100%',
620
+ flex: 1,
621
+ alignItems: 'normal',
622
+ padding: 0,
623
+ },
624
+ };
625
+
626
+ elementStyle.input = StyleSheet.create({
627
+ label: {
628
+ paddingLeft: 0,
629
+ },
630
+ inner: {
631
+ flex: 1,
632
+ width: '100%',
633
+ padding: 0,
634
+ gap: 10,
635
+ alignSelf: 'flex-start',
636
+ flexDirection: 'row',
637
+ flexWrap: 'wrap',
638
+ },
639
+ });
640
+
641
+ elementStyle.switch = {
642
+ inner: {
643
+ padding: 5,
644
+ },
645
+ };
646
+
647
+ elementStyle.quantity = {
648
+ inner: {
649
+ ...box,
650
+ backgroundColor: 'primarySoft',
651
+ fontWeight: 600,
652
+ fontSize: 16,
653
+ borderRadius: 25,
654
+ borderWidth: 0,
655
+ padding: 5,
656
+ paddingHorizontal: 5,
657
+ paddingVertical: 5,
658
+ flexWrap: 'nowrap',
659
+ flex: 1,
660
+ flexDirection: 'row',
661
+ justifyContent: 'center',
662
+ alignItems: 'center',
663
+ },
664
+ };
665
+
666
+ elementStyle.toggle = StyleSheet.create({
667
+ inner: {
668
+ ...box,
669
+ flex: 1,
670
+ width: '100%',
671
+ gap: 10,
672
+ justifyContent: 'center',
673
+ flexDirection: 'row',
674
+ paddingHorizontal: 10,
675
+ paddingVertical: 0,
676
+ alignSelf: 'flex-start',
677
+ flexWrap: 'nowrap',
678
+ },
679
+ });
680
+
681
+ const styles = StyleSheet.create({
682
+ root: {
683
+ gap: 5,
684
+ flexDirection: 'column',
685
+ flexWrap: 'wrap',
686
+ width: '100%',
687
+ alignItems: 'flex-start',
688
+ },
689
+ label: {
690
+ fontWeight: 400,
691
+ marginTop: 5,
692
+ fontSize: 12,
693
+ color: 'labelColor',
694
+ },
695
+ inner: { width: '100%' },
696
+ });
697
+
698
+ const withChildStyles = StyleSheet.create({
699
+ root: {
700
+ gap: 10,
701
+ },
702
+ label: {
703
+ width: '100%',
704
+ fontWeight: 500,
705
+ fontSize: 24,
706
+ },
707
+ });