@onehat/ui 0.4.72 → 0.4.73

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 (39) hide show
  1. package/package.json +2 -1
  2. package/src/Components/Buttons/Button.js +7 -0
  3. package/src/Components/Editor/InlineEditor.js +2 -1
  4. package/src/Components/Form/Field/Color.js +2 -1
  5. package/src/Components/Form/Field/Combo/Combo.js +55 -37
  6. package/src/Components/Form/Field/Date.js +9 -8
  7. package/src/Components/Form/Field/Json.js +3 -2
  8. package/src/Components/Form/Field/TextArea.js +1 -1
  9. package/src/Components/Form/FieldSet.js +1 -1
  10. package/src/Components/Form/Form.js +4 -1
  11. package/src/Components/Gluestack/accordion/index.tsx +5 -1
  12. package/src/Components/Gluestack/actionsheet/index.tsx +5 -1
  13. package/src/Components/Gluestack/alert/index.tsx +5 -1
  14. package/src/Components/Gluestack/badge/index.tsx +5 -1
  15. package/src/Components/Gluestack/button/index.tsx +5 -1
  16. package/src/Components/Gluestack/checkbox/index.tsx +5 -1
  17. package/src/Components/Gluestack/fab/index.tsx +5 -1
  18. package/src/Components/Gluestack/form-control/index.tsx +5 -1
  19. package/src/Components/Gluestack/icon/createIcon.js +74 -0
  20. package/src/Components/Gluestack/icon/index.tsx +46 -88
  21. package/src/Components/Gluestack/input/index.tsx +5 -1
  22. package/src/Components/Gluestack/select/index.tsx +5 -1
  23. package/src/Components/Grid/Grid.js +8 -4
  24. package/src/Components/Grid/GridHeaderRow.js +3 -2
  25. package/src/Components/Grid/GridRow.js +1 -1
  26. package/src/Components/Hoc/withAlert.js +18 -10
  27. package/src/Components/Hoc/withDnd.js +36 -32
  28. package/src/Components/Messages/GlobalModals.js +46 -23
  29. package/src/Components/Messages/Loading.js +2 -2
  30. package/src/Components/Messages/ProgressModal.js +63 -0
  31. package/src/Components/Messages/WaitMessage.js +7 -2
  32. package/src/Components/Report/Report.js +15 -5
  33. package/src/Components/Toolbar/Pagination.js +1 -1
  34. package/src/Components/Toolbar/Toolbar.js +26 -6
  35. package/src/Components/Viewer/TextWithLinks.js +2 -1
  36. package/src/Constants/Dates.js +5 -2
  37. package/src/Functions/downloadInBackground.js +47 -7
  38. package/src/Functions/getReport.js +5 -2
  39. package/src/Functions/trackEngagementHit.js +2 -1
@@ -1,75 +1,29 @@
1
1
  'use client';
2
- import React, { useMemo } from 'react';
3
- import { createIcon } from '@gluestack-ui/icon';
4
- import { Path, Svg } from 'react-native-svg';
2
+ import React from 'react';
3
+ // BEGIN SKOTE MOD
4
+ // See my comment here: https://github.com/gluestack/gluestack-ui/issues/2385#issuecomment-3141973446
5
+ // import { createIcon } from '@gluestack-ui/icon';
6
+ import { createIcon } from './createIcon.js';
7
+ // END SKOTE MOD
8
+ import { Path } from 'react-native-svg';
5
9
  import { tva } from '@gluestack-ui/nativewind-utils/tva';
6
10
  import { cssInterop } from 'nativewind';
7
11
  import { VariantProps } from '@gluestack-ui/nativewind-utils';
8
-
9
- type IPrimitiveIcon = {
10
- height?: number | string;
11
- width?: number | string;
12
- fill?: string;
13
- color?: string;
14
- size?: number | string;
15
- stroke?: string;
16
- as?: React.ElementType;
17
- className?: string;
18
- classNameColor?: string;
19
- };
20
-
21
- const PrimitiveIcon = React.forwardRef<
22
- React.ElementRef<typeof Svg>,
23
- IPrimitiveIcon
24
- >(
25
- (
26
- {
27
- height,
28
- width,
29
- fill,
30
- color,
31
- classNameColor,
32
- size,
33
- stroke,
34
- as: AsComp,
35
- ...props
36
- },
37
- ref
38
- ) => {
39
- color = color ?? classNameColor;
40
- const sizeProps = useMemo(() => {
41
- if (size) return { size };
42
- if (height && width) return { height, width };
43
- if (height) return { height };
44
- if (width) return { width };
45
- return {};
46
- }, [size, height, width]);
47
-
48
- let colorProps = {};
49
- if (fill) {
50
- colorProps = { ...colorProps, fill: fill };
51
- }
52
- if (stroke !== 'currentColor') {
53
- colorProps = { ...colorProps, stroke: stroke };
54
- } else if (stroke === 'currentColor' && color !== undefined) {
55
- colorProps = { ...colorProps, stroke: color };
56
- }
57
-
58
- if (AsComp) {
59
- return <AsComp ref={ref} {...props} {...sizeProps} {...colorProps} />;
60
- }
61
- return (
62
- <Svg ref={ref} height={height} width={width} {...colorProps} {...props} />
63
- );
64
- }
65
- );
12
+ import { PrimitiveIcon, IPrimitiveIcon, Svg } from '@gluestack-ui/icon';
66
13
 
67
14
  export const UIIcon = createIcon({
68
15
  Root: PrimitiveIcon,
69
- });
16
+ }) as React.ForwardRefExoticComponent<
17
+ React.ComponentPropsWithoutRef<typeof PrimitiveIcon> &
18
+ React.RefAttributes<React.ComponentRef<typeof Svg>>
19
+ >;
70
20
 
71
21
  const iconStyle = tva({
72
- base: 'text-typography-950 fill-none pointer-events-none',
22
+ // BEGIN SKOTE MOD
23
+ // See https://github.com/gluestack/gluestack-ui/issues/2385#issuecomment-3141973446
24
+ // base: 'text-typography-950 fill-none pointer-events-none',
25
+ base: 'text-typography-950 fill-black pointer-events-none',
26
+ // END SKOTE MOD
73
27
  variants: {
74
28
  size: {
75
29
  '2xs': 'h-3 w-3',
@@ -82,7 +36,6 @@ const iconStyle = tva({
82
36
  },
83
37
  });
84
38
 
85
- // @ts-expect-error
86
39
  cssInterop(UIIcon, {
87
40
  className: {
88
41
  target: 'style',
@@ -100,8 +53,8 @@ type IIConProps = IPrimitiveIcon &
100
53
  VariantProps<typeof iconStyle> &
101
54
  React.ComponentPropsWithoutRef<typeof UIIcon>;
102
55
 
103
- export const Icon = React.forwardRef<React.ElementRef<typeof Svg>, IIConProps>(
104
- ({ size = 'md', className, ...props }, ref) => {
56
+ const Icon = React.forwardRef<React.ComponentRef<typeof UIIcon>, IIConProps>(
57
+ function Icon({ size = 'md', className, ...props }, ref) {
105
58
  if (typeof size === 'number') {
106
59
  return (
107
60
  <UIIcon
@@ -133,31 +86,36 @@ export const Icon = React.forwardRef<React.ElementRef<typeof Svg>, IIConProps>(
133
86
  }
134
87
  );
135
88
 
89
+ export { Icon };
90
+
136
91
  type ParameterTypes = Omit<Parameters<typeof createIcon>[0], 'Root'>;
137
92
 
138
93
  const createIconUI = ({ ...props }: ParameterTypes) => {
139
- const UIIconCreateIcon = createIcon({ Root: Svg, ...props });
140
-
141
- return React.forwardRef<React.ElementRef<typeof Svg>>(
142
- (
143
- {
144
- className,
145
- size,
146
- ...props
147
- }: VariantProps<typeof iconStyle> &
148
- React.ComponentPropsWithoutRef<typeof UIIconCreateIcon>,
149
- ref
150
- ) => {
151
- return (
152
- <UIIconCreateIcon
153
- // @ts-ignore
154
- ref={ref}
155
- {...props}
156
- className={iconStyle({ size, class: className })}
157
- />
158
- );
159
- }
160
- );
94
+ const UIIconCreateIcon = createIcon({
95
+ Root: Svg,
96
+ ...props,
97
+ }) as React.ForwardRefExoticComponent<
98
+ React.ComponentPropsWithoutRef<typeof PrimitiveIcon> &
99
+ React.RefAttributes<React.ComponentRef<typeof Svg>>
100
+ >;
101
+
102
+ return React.forwardRef<React.ComponentRef<typeof Svg>>(function UIIcon(
103
+ {
104
+ className,
105
+ size,
106
+ ...inComingProps
107
+ }: VariantProps<typeof iconStyle> &
108
+ React.ComponentPropsWithoutRef<typeof UIIconCreateIcon>,
109
+ ref
110
+ ) {
111
+ return (
112
+ <UIIconCreateIcon
113
+ ref={ref}
114
+ {...inComingProps}
115
+ className={iconStyle({ size, class: className })}
116
+ />
117
+ );
118
+ });
161
119
  };
162
120
  export { createIconUI as createIcon };
163
121
  // All Icons
@@ -115,7 +115,11 @@ const inputStyle = tva({
115
115
  });
116
116
 
117
117
  const inputIconStyle = tva({
118
- base: 'justify-center items-center text-typography-400 fill-none',
118
+ // BEGIN SKOTE MOD
119
+ // See https://github.com/gluestack/gluestack-ui/issues/2385#issuecomment-3141973446
120
+ // base: 'justify-center items-center text-typography-400 fill-none',
121
+ base: 'justify-center items-center text-typography-400 fill-black',
122
+ // END SKOTE MOD
119
123
  parentVariants: {
120
124
  size: {
121
125
  '2xs': 'h-3 w-3',
@@ -33,7 +33,11 @@ const SelectTriggerWrapper = React.forwardRef<
33
33
  });
34
34
 
35
35
  const selectIconStyle = tva({
36
- base: 'text-background-500 fill-none',
36
+ // BEGIN SKOTE MOD
37
+ // See https://github.com/gluestack/gluestack-ui/issues/2385#issuecomment-3141973446
38
+ // base: 'text-background-500 fill-none',
39
+ base: 'text-background-500 fill-black',
40
+ // END SKOTE MOD
37
41
  parentVariants: {
38
42
  size: {
39
43
  '2xs': 'h-3 w-3',
@@ -112,11 +112,15 @@ function GridComponent(props) {
112
112
  columnProps = {},
113
113
  defaultHiddenColumns = [],
114
114
  getRowProps = (item) => {
115
+ let className = clsx(
116
+ 'border-bottom-1',
117
+ 'border-bottom-grey-500',
118
+ );
119
+ if (CURRENT_MODE === UI_MODE_NATIVE) {
120
+ className += ' py-4';
121
+ }
115
122
  return {
116
- className: clsx(
117
- 'border-bottom-1',
118
- 'border-bottom-grey-500',
119
- ),
123
+ className,
120
124
  };
121
125
  },
122
126
  flatListProps = {},
@@ -15,6 +15,7 @@ import {
15
15
  HORIZONTAL,
16
16
  } from '../../Constants/Directions.js';
17
17
  import {
18
+ CURRENT_MODE,
18
19
  UI_MODE_WEB,
19
20
  } from '../../Constants/UiModes.js';
20
21
  import UiGlobals from '../../UiGlobals.js';
@@ -280,7 +281,7 @@ export default function GridHeaderRow(props) {
280
281
  }
281
282
  }, [columnsConfig]);
282
283
 
283
- if (UiGlobals.mode !== UI_MODE_WEB) {
284
+ if (CURRENT_MODE !== UI_MODE_WEB) {
284
285
  canColumnsReorder = false;
285
286
  canColumnsResize = false;
286
287
  }
@@ -425,7 +426,7 @@ export default function GridHeaderRow(props) {
425
426
  )}
426
427
  />}
427
428
 
428
- {isOver && UiGlobals.mode === UI_MODE_WEB && // only works for web for now
429
+ {isOver && CURRENT_MODE === UI_MODE_WEB && // only works for web for now
429
430
  <HeaderColumnSelectorHandle
430
431
  key="HeaderColumnSelectorHandle"
431
432
  showColumnsSelector={showColumnsSelector}
@@ -100,7 +100,7 @@ function GridRow(props) {
100
100
  actualCanDrop = validateDrop(draggedItem);
101
101
  }
102
102
 
103
- if (showSelectHandle && isSelected) {
103
+ if (isSelected) {
104
104
  if (showHovers && isHovered) {
105
105
  mixWith = styles.GRID_ROW_SELECTED_BG_HOVER;
106
106
  } else {
@@ -29,9 +29,10 @@ function withAlert(WrappedComponent) {
29
29
  } = props,
30
30
  getBody = (args) => {
31
31
  const {
32
- icon,
32
+ icon = TriangleExclamation,
33
33
  message,
34
- color = 'black',
34
+ textColor = 'text-black',
35
+ fillColor = 'fill-black',
35
36
  } = args;
36
37
  return <HStack className="withAlert-HStack flex-1 w-full">
37
38
  <Box className={clsx(
@@ -43,12 +44,15 @@ function withAlert(WrappedComponent) {
43
44
  'justify-center',
44
45
  'pr-3',
45
46
  )}>
46
- <Icon as={icon} className={clsx(
47
- 'withAlert-Icon',
48
- 'h-[40px]',
49
- 'w-[40px]',
50
- `text-${color}`,
51
- )} />
47
+ <Icon
48
+ as={icon}
49
+ className={clsx(
50
+ 'withAlert-Icon',
51
+ 'h-[40px]',
52
+ 'w-[40px]',
53
+ fillColor,
54
+ )}
55
+ />
52
56
  </Box>
53
57
  <Box className={clsx(
54
58
  'withAlert-Box2',
@@ -60,7 +64,7 @@ function withAlert(WrappedComponent) {
60
64
  )}>
61
65
  <Text className={clsx(
62
66
  'withAlert-Text',
63
- `text-${color}`,
67
+ textColor,
64
68
  'text-[18px]',
65
69
  'flex-none',
66
70
  'mr-2',
@@ -108,7 +112,7 @@ function withAlert(WrappedComponent) {
108
112
  body: getBody({
109
113
  icon: TriangleExclamation,
110
114
  message,
111
- color: 'red',
115
+ fillColor: 'fill-red-500',
112
116
  }),
113
117
  onOk: () => {
114
118
  hideModal();
@@ -121,6 +125,7 @@ function withAlert(WrappedComponent) {
121
125
  customButtons: buttons ?? null,
122
126
  h: 250,
123
127
  w: 400,
128
+ whichModal: 'alert',
124
129
  });
125
130
  },
126
131
  onConfirm = (message, onYes, includeCancel = false, onNo) => {
@@ -145,6 +150,7 @@ function withAlert(WrappedComponent) {
145
150
  includeCancel,
146
151
  h: 250,
147
152
  w: 400,
153
+ whichModal: 'confirm',
148
154
  });
149
155
  },
150
156
  onInfo = (message) => {
@@ -160,6 +166,7 @@ function withAlert(WrappedComponent) {
160
166
  canClose: true,
161
167
  h: 200,
162
168
  w: 400,
169
+ whichModal: 'info',
163
170
  });
164
171
  };
165
172
 
@@ -173,6 +180,7 @@ function withAlert(WrappedComponent) {
173
180
  disableWithAlert={false}
174
181
  alreadyHasWithAlert={true}
175
182
  alert={onAlert}
183
+ getAlertBody={getBody}
176
184
  confirm={onConfirm}
177
185
  hideAlert={hideModal}
178
186
  showInfo={onInfo}
@@ -16,6 +16,23 @@ import {
16
16
  // If you need constraints, you can potentially use a CustomDragLayer (see code at bottom)
17
17
  // but it will lag behind, compared to what the native drag layer can do
18
18
 
19
+ function defaultDragCollect(monitor, props2) { // Optional. The collecting function. It should return a plain object of the props to return for injection into your component. It receives two parameters, monitor and props. Read the overview for an introduction to the monitors and the collecting function. See the collecting function described in detail in the next section.
20
+ // monitor fn determines which props from dnd state get passed
21
+ return {
22
+ // canDrag: !!monitor.canDrag(), // Returns trueif no drag operation is in progress, and the owner's canDrag() returns true or is not defined.
23
+ isDragging: !!monitor.isDragging(), // Returns trueif a drag operation is in progress, and either the owner initiated the drag, or its isDragging() is defined and returns true.
24
+ type: monitor.getItemType(), // Returns a string or a symbol identifying the type of the current dragged item. Returns null if no item is being dragged.
25
+ item: monitor.getItem(), // Returns a plain object representing the currently dragged item. Every drag source must specify it by returning an object from its beginDrag() method. Returns nullif no item is being dragged.
26
+ dropResult: monitor.getDropResult(), // Returns a plain object representing the last recorded drop result. The drop targets may optionally specify it by returning an object from their drop()methods. When a chain of drop()is dispatched for the nested targets, bottom up, any parent that explicitly returns its own result from drop()overrides the child drop result previously set by the child. Returns nullif called outside endDrag().
27
+ didDrop: !!monitor.didDrop(), // Returns trueif some drop target has handled the drop event, falseotherwise. Even if a target did not return a drop result, didDrop() returns true. Use it inside endDrag()to test whether any drop target has handled the drop. Returns falseif called outside endDrag().
28
+ initialClientOffset: monitor.getInitialClientOffset(), // Returns the { x, y }client offset of the pointer at the time when the current drag operation has started. Returns nullif no item is being dragged.
29
+ initialSourceClientOffset: monitor.getInitialSourceClientOffset(), // Returns the { x, y }client offset of the drag source component's root DOM node at the time when the current drag operation has started. Returns nullif no item is being dragged.
30
+ clientOffset: monitor.getClientOffset(), // Returns the last recorded { x, y }client offset of the pointer while a drag operation is in progress. Returns nullif no item is being dragged.
31
+ differenceFromInitialOffset: monitor.getDifferenceFromInitialOffset(), // Returns the { x, y }difference between the last recorded client offset of the pointer and the client offset when the current drag operation has started. Returns nullif no item is being dragged.
32
+ sourceClientOffset: monitor.getSourceClientOffset(), // Returns the projected { x, y }client offset of the drag source component's root DOM node, based on its position at the time when the current drag operation has started, and the movement difference. Returns nullif no item is being dragged.
33
+ };
34
+ };
35
+
19
36
  export function withDragSource(WrappedComponent) {
20
37
  return forwardRef((props, ref) => {
21
38
 
@@ -42,22 +59,7 @@ export function withDragSource(WrappedComponent) {
42
59
  canDrag = null,
43
60
  isDragging = null,
44
61
  getDragProxy,
45
- dragCollect = (monitor, props2) => { // Optional. The collecting function. It should return a plain object of the props to return for injection into your component. It receives two parameters, monitor and props. Read the overview for an introduction to the monitors and the collecting function. See the collecting function described in detail in the next section.
46
- // monitor fn determines which props from dnd state get passed
47
- return {
48
- // canDrag: !!monitor.canDrag(), // Returns trueif no drag operation is in progress, and the owner's canDrag() returns true or is not defined.
49
- isDragging: !!monitor.isDragging(), // Returns trueif a drag operation is in progress, and either the owner initiated the drag, or its isDragging() is defined and returns true.
50
- type: monitor.getItemType(), // Returns a string or a symbol identifying the type of the current dragged item. Returns null if no item is being dragged.
51
- item: monitor.getItem(), // Returns a plain object representing the currently dragged item. Every drag source must specify it by returning an object from its beginDrag() method. Returns nullif no item is being dragged.
52
- dropResult: monitor.getDropResult(), // Returns a plain object representing the last recorded drop result. The drop targets may optionally specify it by returning an object from their drop()methods. When a chain of drop()is dispatched for the nested targets, bottom up, any parent that explicitly returns its own result from drop()overrides the child drop result previously set by the child. Returns nullif called outside endDrag().
53
- didDrop: !!monitor.didDrop(), // Returns trueif some drop target has handled the drop event, falseotherwise. Even if a target did not return a drop result, didDrop() returns true. Use it inside endDrag()to test whether any drop target has handled the drop. Returns falseif called outside endDrag().
54
- initialClientOffset: monitor.getInitialClientOffset(), // Returns the { x, y }client offset of the pointer at the time when the current drag operation has started. Returns nullif no item is being dragged.
55
- initialSourceClientOffset: monitor.getInitialSourceClientOffset(), // Returns the { x, y }client offset of the drag source component's root DOM node at the time when the current drag operation has started. Returns nullif no item is being dragged.
56
- clientOffset: monitor.getClientOffset(), // Returns the last recorded { x, y }client offset of the pointer while a drag operation is in progress. Returns nullif no item is being dragged.
57
- differenceFromInitialOffset: monitor.getDifferenceFromInitialOffset(), // Returns the { x, y }difference between the last recorded client offset of the pointer and the client offset when the current drag operation has started. Returns nullif no item is being dragged.
58
- sourceClientOffset: monitor.getSourceClientOffset(), // Returns the projected { x, y }client offset of the drag source component's root DOM node, based on its position at the time when the current drag operation has started, and the movement difference. Returns nullif no item is being dragged.
59
- };
60
- },
62
+ dragCollect = defaultDragCollect,
61
63
  } = props,
62
64
  [dragState, dragSourceRef, dragPreviewRef] = useDrag(() => { // A specification object or a function that creates a specification object.
63
65
  // The useDrag hook provides a way to wire your component into the DnD system as a drag source. By passing in a specification into useDrag, you declaratively describe the typeof draggable being generated, the itemobject representing the drag source, what props to collect, and more. The useDraghooks returns a few key items: a set of collected props, and refs that may be attached to drag source and drag preview elements
@@ -98,7 +100,7 @@ export function withDragSource(WrappedComponent) {
98
100
  };
99
101
  },*/
100
102
  };
101
- }),
103
+ }, [dragSourceItem, getDragProxy, dragSourceType, dragPreviewOptions, dragOptions, dropEffect, onDragEnd, canDrag, isDragging, dragCollect]),
102
104
  {
103
105
  canDrag: stateCanDrag,
104
106
  isDragging: stateIsDragging,
@@ -120,7 +122,7 @@ export function withDragSource(WrappedComponent) {
120
122
  if (layer.isDragging && dragSourceItem?.id === layer.item.id) {
121
123
  dragSourceItem.onDrag(layer);
122
124
  }
123
- }, [layer]);
125
+ }, [layer, dragSourceItem]);
124
126
  }
125
127
 
126
128
  return <WrappedComponent
@@ -136,7 +138,13 @@ export function withDragSource(WrappedComponent) {
136
138
  });
137
139
  }
138
140
 
139
-
141
+ function defaultDropCollect(monitor, props) {
142
+ return {
143
+ canDrop: !!monitor.canDrop(),
144
+ isOver: !!monitor.isOver(),
145
+ draggedItem: monitor.getItem(), // Pass the dragged item so TreeNode can evaluate custom logic
146
+ };
147
+ }
140
148
  export function withDropTarget(WrappedComponent) {
141
149
  return forwardRef((props, ref) => {
142
150
 
@@ -154,13 +162,7 @@ export function withDropTarget(WrappedComponent) {
154
162
  onDrop = null,
155
163
  onDropHover = null,
156
164
  canDrop = null,
157
- dropCollect = (monitor, props) => {
158
- return {
159
- canDrop: !!monitor.canDrop(),
160
- isOver: !!monitor.isOver(),
161
- draggedItem: monitor.getItem(), // Pass the dragged item so TreeNode can evaluate custom logic
162
- };
163
- },
165
+ dropCollect = defaultDropCollect,
164
166
  } = props,
165
167
  localTargetRef = useRef(null),
166
168
  [dropState, dropTargetRef] = useDrop(() => { // A specification object or a function that creates a specification object.
@@ -187,7 +189,7 @@ export function withDropTarget(WrappedComponent) {
187
189
  };
188
190
  },*/
189
191
  };
190
- }),
192
+ }, [dropTargetAccept, dropOptions, onDrop, onDropHover, canDrop, dropCollect]),
191
193
  {
192
194
  canDrop: stateCanDrop,
193
195
  isOver,
@@ -221,11 +223,13 @@ export function GlobalDragProxy() {
221
223
  isDragging,
222
224
  item,
223
225
  currentOffset,
224
- } = useDragLayer((monitor) => ({
225
- isDragging: monitor.isDragging(),
226
- item: monitor.getItem(),
227
- currentOffset: monitor.getSourceClientOffset(),
228
- }));
226
+ } = useDragLayer((monitor) => {
227
+ return {
228
+ isDragging: monitor.isDragging(),
229
+ item: monitor.getItem(),
230
+ currentOffset: monitor.getSourceClientOffset(),
231
+ };
232
+ });
229
233
 
230
234
  if (!isDragging || !currentOffset || CURRENT_MODE !== UI_MODE_WEB) { // Native uses a native drag layer, so we don't need to render a custom proxy
231
235
  return null;
@@ -9,39 +9,62 @@ import {
9
9
  setAlertMessage,
10
10
  setDebugMessage,
11
11
  setInfoMessage,
12
+ selectProgressMessage,
13
+ selectProgressPercentage,
12
14
  } from '@src/models/Slices/DebugSlice';
13
15
  import WaitMessage from './WaitMessage';
14
16
  import ErrorMessage from './ErrorMessage';
17
+ import ProgressModal from './ProgressModal';
15
18
 
16
19
 
17
20
 
18
- export default function GlobalModals() {
19
- const
21
+ export default function GlobalModals(props) {
22
+ const {
23
+ progressColor = '#666',
24
+ } = props,
20
25
  dispatch = useDispatch(),
21
26
  isWaitModalShown = useSelector(selectIsWaitModalShown),
22
27
  alertMessage = useSelector(selectAlertMessage),
23
28
  debugMessage = useSelector(selectDebugMessage),
24
29
  infoMessage = useSelector(selectInfoMessage),
25
- waitMessage = useSelector(selectWaitMessage);
30
+ waitMessage = useSelector(selectWaitMessage),
31
+ progressMessage = useSelector(selectProgressMessage),
32
+ progressPercentage = useSelector(selectProgressPercentage);
26
33
 
27
- return <>
28
- {isWaitModalShown && <WaitMessage text={waitMessage} />}
29
- {!isWaitModalShown && alertMessage &&
30
- <ErrorMessage
31
- text={alertMessage}
32
- onOk={() => dispatch(setAlertMessage(null))}
33
- />}
34
- {!isWaitModalShown && debugMessage &&
35
- <ErrorMessage
36
- text={debugMessage}
37
- color="green"
38
- onOk={() => dispatch(setDebugMessage(null))}
39
- />}
40
- {!isWaitModalShown && infoMessage &&
41
- <ErrorMessage
42
- text={infoMessage}
43
- color="#000"
44
- onOk={() => dispatch(setInfoMessage(null))}
45
- />}
46
- </>;
34
+ let moduleToShow = null;
35
+
36
+ if (debugMessage) {
37
+ moduleToShow =
38
+ <ErrorMessage
39
+ text={debugMessage}
40
+ onOk={() => dispatch(setDebugMessage(null))}
41
+ color="green"
42
+ />;
43
+ } else if (alertMessage) {
44
+ moduleToShow =
45
+ <ErrorMessage
46
+ text={alertMessage}
47
+ onOk={() => dispatch(setAlertMessage(null))}
48
+ />;
49
+ } else if (infoMessage) {
50
+ moduleToShow =
51
+ <ErrorMessage
52
+ text={infoMessage}
53
+ onOk={() => dispatch(setInfoMessage(null))}
54
+ color="#000"
55
+ />;
56
+ }
57
+ if (isWaitModalShown) {
58
+ moduleToShow = <WaitMessage text={waitMessage} />;
59
+ }
60
+ if (progressMessage && progressPercentage < 100) {
61
+ moduleToShow = <ProgressModal
62
+ progressMessage={progressMessage}
63
+ progressPercentage={progressPercentage}
64
+ color={progressColor}
65
+ />;
66
+ }
67
+
68
+ return moduleToShow;
47
69
  }
70
+
@@ -10,14 +10,14 @@ import ScreenContainer from '../Container/ScreenContainer.js';
10
10
  export default function Loading(props) {
11
11
 
12
12
  if (props.isScreen) {
13
- return <ScreenContainer {...props}>
13
+ return <ScreenContainer className="h-full w-full" {...props}>
14
14
  <HStack className="flex-1 justify-center items-center">
15
15
  <Spinner className="text-primary-500 mr-1" />
16
16
  <Text>Loading</Text>
17
17
  </HStack>
18
18
  </ScreenContainer>;
19
19
  }
20
- return <HStackNative {...props} className="justify-center min-h-[100px]">
20
+ return <HStackNative {...props} className="justify-center min-h-[100px] h-full w-full">
21
21
  <Spinner className="flex-1 text-primary-500" />
22
22
  </HStackNative>;
23
23
  }
@@ -0,0 +1,63 @@
1
+ import { useState, useEffect, } from 'react';import {
2
+ HStack,
3
+ Modal, ModalBackdrop, ModalHeader, ModalContent, ModalCloseButton, ModalBody, ModalFooter,
4
+ Spinner,
5
+ Text,
6
+ VStack,
7
+ } from '@project-components/Gluestack';
8
+ import clsx from 'clsx';
9
+ import { useSelector } from 'react-redux';
10
+ import * as Progress from 'react-native-progress';
11
+ import testProps from '../../Functions/testProps';
12
+
13
+ let progressTimeout = null;
14
+
15
+ export default function ProgressModal(props) {
16
+ const {
17
+ progressMessage,
18
+ progressPercentage,
19
+ color = '#666',
20
+ } = props,
21
+ [progressBarWidth, setProgressBarWidth] = useState(175),
22
+ [isInited, setIsInited] = useState(false);
23
+
24
+ return <Modal
25
+ {...testProps('ProgressModal')}
26
+ isOpen={true}
27
+ className="Modal"
28
+ aria-disabled={true}
29
+ >
30
+ <ModalBackdrop />
31
+ <ModalContent
32
+ className={clsx(
33
+ 'ModalContent',
34
+ 'max-w-[400px]',
35
+ 'shadow-lg',
36
+ )}
37
+ >
38
+ <VStack
39
+ className={clsx(
40
+ 'VStack',
41
+ 'w-[90%]',
42
+ 'items-center',
43
+ 'justify-center',
44
+ 'self-center',
45
+ )}
46
+ onLayout={(e) => {
47
+ setProgressBarWidth(e.nativeEvent.layout.width);
48
+ setIsInited(true);
49
+ }}
50
+ >
51
+ <Text className="text-black mb-2">{progressMessage}</Text>
52
+ {isInited &&
53
+ <Progress.Bar
54
+ animated={false}
55
+ progress={progressPercentage / 100}
56
+ width={progressBarWidth}
57
+ height={20}
58
+ color={color}
59
+ />}
60
+ </VStack>
61
+ </ModalContent>
62
+ </Modal>;
63
+ }
@@ -5,6 +5,11 @@ import {
5
5
  Text,
6
6
  } from '@project-components/Gluestack';
7
7
  import clsx from 'clsx';
8
+ import {
9
+ CURRENT_MODE,
10
+ UI_MODE_WEB,
11
+ UI_MODE_NATIVE,
12
+ } from '../../Constants/UiModes.js';
8
13
  import testProps from '../../Functions/testProps.js';
9
14
 
10
15
  export default function WaitMessage(props) {
@@ -19,14 +24,14 @@ export default function WaitMessage(props) {
19
24
  {...testProps('WaitMessage')}
20
25
  isOpen={true}
21
26
  className="Modal"
22
- aria-disabled="true"
27
+ aria-disabled={true}
23
28
  >
24
29
  <ModalBackdrop />
25
30
  <ModalContent
26
31
  className={clsx(
27
32
  'ModalContent',
28
33
  'w-[200px]',
29
- 'h-[50px]',
34
+ CURRENT_MODE === UI_MODE_WEB ? 'h-[50px]' : '',
30
35
  'shadow-lg',
31
36
  )}
32
37
  >