react-crud-mobile 1.1.2 → 1.3.1

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