@onehat/ui 0.4.72 → 0.4.74

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 -2
  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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@onehat/ui",
3
- "version": "0.4.72",
3
+ "version": "0.4.74",
4
4
  "description": "Base UI for OneHat apps",
5
5
  "main": "src/index.js",
6
6
  "type": "module",
@@ -66,8 +66,8 @@
66
66
  "decimal.js": "^10.5.0",
67
67
  "inflector-js": "^1.0.1",
68
68
  "js-cookie": "^3.0.5",
69
- "native-base": "^3.4.28",
70
69
  "react-hook-form": "^7.55.0",
70
+ "react-native-progress": "^5.0.1",
71
71
  "react-redux": "^9.2.0",
72
72
  "tailwindcss": "^3.4.17",
73
73
  "yup": "^1.6.1"
@@ -16,7 +16,9 @@ const ButtonComponent = forwardRef((props, ref) => {
16
16
  let {
17
17
  self,
18
18
  text, // the text to display on the button
19
+ content, // the content to display on the button
19
20
  isLoading = false, // show a spinner?
21
+ isExpandToFillVertical = false,
20
22
  icon = null, // an actual icon element
21
23
  rightIcon = null, // an actual icon element
22
24
  _spinner = {}, // props for ButtonSpinner
@@ -59,6 +61,10 @@ const ButtonComponent = forwardRef((props, ref) => {
59
61
  'flex-row',
60
62
  'items-center',
61
63
  );
64
+ if (isExpandToFillVertical) {
65
+ // IMPORTANT! Otherwise the button will cut off the vertical content due to size classes automatically added by Gluestack (e.g. h-10)
66
+ className += ' h-auto';
67
+ }
62
68
  if (propsToPass.className) {
63
69
  className += ' ' + propsToPass.className;
64
70
  }
@@ -71,6 +77,7 @@ const ButtonComponent = forwardRef((props, ref) => {
71
77
  {isLoading && <ButtonSpinner className="ButtonSpinner" {..._spinner} />}
72
78
  {icon}
73
79
  {text && <ButtonText className="ButtonText" {..._text}>{text}</ButtonText>}
80
+ {content}
74
81
  {rightIcon}
75
82
  </Button>;
76
83
  });
@@ -6,6 +6,7 @@ import {
6
6
  import clsx from 'clsx';
7
7
  import withComponent from '../Hoc/withComponent.js';
8
8
  import {
9
+ CURRENT_MODE,
9
10
  UI_MODE_WEB,
10
11
  UI_MODE_NATIVE,
11
12
  } from '../../Constants/UiModes.js';
@@ -19,7 +20,7 @@ import _ from 'lodash';
19
20
 
20
21
  function InlineEditor(props) {
21
22
 
22
- if (UiGlobals.mode === UI_MODE_NATIVE) {
23
+ if (CURRENT_MODE === UI_MODE_NATIVE) {
23
24
  throw new Error('Not yet implemented for RN.');
24
25
  }
25
26
 
@@ -8,6 +8,7 @@ import {
8
8
  import clsx from 'clsx';
9
9
  import { SketchPicker } from 'react-color';
10
10
  import {
11
+ CURRENT_MODE,
11
12
  UI_MODE_WEB,
12
13
  } from '../../../Constants/UiModes.js';
13
14
  import UiGlobals from '../../../UiGlobals.js';
@@ -39,7 +40,7 @@ export function ColorElement(props) {
39
40
  return;
40
41
  }
41
42
 
42
- if (UiGlobals.mode === UI_MODE_WEB && triggerRef.current?.getBoundingClientRect) {
43
+ if (CURRENT_MODE === UI_MODE_WEB && triggerRef.current?.getBoundingClientRect) {
43
44
  // For web, ensure it's in the proper place
44
45
  const
45
46
  triggerRect = triggerRef.current.getBoundingClientRect(),
@@ -13,6 +13,7 @@ import {
13
13
  } from '@project-components/Gluestack';
14
14
  import clsx from 'clsx';
15
15
  import {
16
+ CURRENT_MODE,
16
17
  UI_MODE_NATIVE,
17
18
  UI_MODE_WEB,
18
19
  } from '../../../../Constants/UiModes.js';
@@ -44,7 +45,6 @@ const FILTER_NAME = 'q';
44
45
  * @returns boolean
45
46
  */
46
47
  function isEmptyValue(value) {
47
- //
48
48
  return value === null ||
49
49
  value === undefined ||
50
50
  value === '' ||
@@ -52,6 +52,23 @@ function isEmptyValue(value) {
52
52
  (_.isObject(value) && _.isEmpty(value));
53
53
  };
54
54
 
55
+ function getRowProps() {
56
+ return {
57
+ className: clsx(
58
+ 'w-full',
59
+ 'pl-4',
60
+ 'pr-2',
61
+ 'py-1',
62
+ 'border-b-1',
63
+ 'border-grey-300',
64
+ CURRENT_MODE === UI_MODE_NATIVE ? {
65
+ 'min-h-[50px]': true,
66
+ 'h-[50px]': true,
67
+ } : {},
68
+ ),
69
+ };
70
+ }
71
+
55
72
  export const ComboComponent = forwardRef((props, ref) => {
56
73
 
57
74
  const {
@@ -133,7 +150,7 @@ export const ComboComponent = forwardRef((props, ref) => {
133
150
  if (isMenuShown) {
134
151
  return;
135
152
  }
136
- if (UiGlobals.mode === UI_MODE_WEB && inputRef.current?.getBoundingClientRect) {
153
+ if (CURRENT_MODE === UI_MODE_WEB && inputRef.current?.getBoundingClientRect) {
137
154
  // For web, ensure it's in the proper place
138
155
  const
139
156
  rect = inputRef.current.getBoundingClientRect(),
@@ -609,7 +626,7 @@ export const ComboComponent = forwardRef((props, ref) => {
609
626
  className={triggerClassName}
610
627
  />;
611
628
 
612
- if (UiGlobals.mode === UI_MODE_WEB) {
629
+ if (CURRENT_MODE === UI_MODE_WEB) {
613
630
  input = disableDirectEntry ?
614
631
  <Pressable
615
632
  {...testProps('toggleMenuBtn')}
@@ -680,8 +697,7 @@ export const ComboComponent = forwardRef((props, ref) => {
680
697
  {..._input}
681
698
  />;
682
699
  }
683
- if (UiGlobals.mode === UI_MODE_NATIVE) {
684
- throw new Error('Migration to Gluestack not yet implemented on Native');
700
+ if (CURRENT_MODE === UI_MODE_NATIVE) {
685
701
  // This input and trigger are for show
686
702
  // They just show the current getDisplayValue and open the menu
687
703
  const displayValue = getDisplayValue();
@@ -694,6 +710,7 @@ export const ComboComponent = forwardRef((props, ref) => {
694
710
  'flex-row',
695
711
  'justify-center',
696
712
  'items-center',
713
+ 'bg-white',
697
714
  'border',
698
715
  'border-grey-400',
699
716
  'rounded-r-none',
@@ -705,10 +722,10 @@ export const ComboComponent = forwardRef((props, ref) => {
705
722
  numberOfLines={1}
706
723
  ellipsizeMode="head"
707
724
  className={clsx(
708
- 'h-full',
709
- 'flex-1',
725
+ // 'h-full',
726
+ // 'flex-1',
710
727
  'm-0',
711
- 'p-1',
728
+ 'p-2',
712
729
  _.isEmpty(displayValue) ? 'text-grey-400' : 'text-black',
713
730
  styles.FORM_COMBO_INPUT_CLASSNAME,
714
731
  )}
@@ -745,24 +762,20 @@ export const ComboComponent = forwardRef((props, ref) => {
745
762
  }
746
763
  const WhichGrid = isEditor ? WindowedGridEditor : Grid;
747
764
  const gridStyle = {};
748
- if (UiGlobals.mode === UI_MODE_WEB) {
765
+ if (CURRENT_MODE === UI_MODE_WEB) {
749
766
  gridStyle.height = menuHeight || styles.FORM_COMBO_MENU_HEIGHT;
750
767
  }
768
+ let gridClassName = clsx(
769
+ 'h-full',
770
+ 'w-full',
771
+ );
772
+ if (CURRENT_MODE === UI_MODE_NATIVE) {
773
+ gridClassName += ' h-[400px] max-h-[100%]';
774
+ }
751
775
  grid = <WhichGrid
752
776
  showHeaders={false}
753
777
  showHovers={true}
754
- getRowProps={() => {
755
- return {
756
- className: clsx(
757
- 'w-full',
758
- 'pl-4',
759
- 'pr-2',
760
- 'py-1',
761
- 'border-b-1',
762
- 'border-grey-300',
763
- ),
764
- };
765
- }}
778
+ getRowProps={getRowProps}
766
779
  autoAdjustPageSizeToHeight={false}
767
780
  newEntityDisplayValue={newEntityDisplayValue}
768
781
  newEntityDisplayProperty={newEntityDisplayProperty}
@@ -872,14 +885,12 @@ export const ComboComponent = forwardRef((props, ref) => {
872
885
  }}
873
886
  reference="grid"
874
887
  parent={self}
875
- className={clsx(
876
- 'h-full',
877
- )}
888
+ className={gridClassName}
878
889
  style={gridStyle}
879
890
  {...gridProps}
880
891
  {..._editor}
881
892
  />;
882
- if (UiGlobals.mode === UI_MODE_WEB) {
893
+ if (CURRENT_MODE === UI_MODE_WEB) {
883
894
  if (!disableDirectEntry) {
884
895
  inputClone = <Box
885
896
  className="Combo-inputClone-Box"
@@ -959,7 +970,7 @@ export const ComboComponent = forwardRef((props, ref) => {
959
970
  </Box>
960
971
  </Popover>;
961
972
  }
962
- if (UiGlobals.mode === UI_MODE_NATIVE) {
973
+ if (CURRENT_MODE === UI_MODE_NATIVE) {
963
974
  if (isEditor) {
964
975
  // in RN, an editor has no way to accept the selection of the grid, so we need to add a check button to do this
965
976
  checkButton = <IconButton
@@ -981,7 +992,12 @@ export const ComboComponent = forwardRef((props, ref) => {
981
992
  />;
982
993
  }
983
994
  const inputAndTriggerClone = // for RN, this is the actual input and trigger, as we need them to appear up above in the modal
984
- <HStack className="h-[10px]">
995
+ <HStack
996
+ className={clsx(
997
+ 'h-[40px]',
998
+ 'bg-white',
999
+ )}
1000
+ >
985
1001
  {xButton}
986
1002
  {eyeButton}
987
1003
  {disableDirectEntry ?
@@ -993,7 +1009,7 @@ export const ComboComponent = forwardRef((props, ref) => {
993
1009
  'h-full',
994
1010
  'flex-1',
995
1011
  'm-0',
996
- 'p-1',
1012
+ 'p-2',
997
1013
  'border',
998
1014
  'border-grey-400',
999
1015
  'rounded-r-none',
@@ -1054,19 +1070,21 @@ export const ComboComponent = forwardRef((props, ref) => {
1054
1070
  safeAreaTop={true}
1055
1071
  onClose={() => setIsMenuShown(false)}
1056
1072
  className={clsx(
1057
- 'h-[400px]',
1073
+ 'h-full',
1058
1074
  'w-full',
1059
- 'my-auto',
1060
- 'p-[5px]'
1061
1075
  )}
1062
1076
  >
1063
1077
  <ModalBackdrop />
1064
- <ModalContent>
1065
- <ModalBody>
1066
- {inputAndTriggerClone}
1067
- {grid}
1068
- </ModalBody>
1069
- </ModalContent>
1078
+ <VStackNative
1079
+ className={clsx(
1080
+ 'h-[400px]',
1081
+ 'w-[80%]',
1082
+ 'max-w-[400px]',
1083
+ )}
1084
+ >
1085
+ {inputAndTriggerClone}
1086
+ {grid}
1087
+ </VStackNative>
1070
1088
  </Modal>;
1071
1089
  }
1072
1090
  }
@@ -15,6 +15,7 @@ import {
15
15
  DATETIME,
16
16
  } from '../../../Constants/Date.js';
17
17
  import {
18
+ CURRENT_MODE,
18
19
  UI_MODE_NATIVE,
19
20
  UI_MODE_WEB,
20
21
  } from '../../../Constants/UiModes.js';
@@ -103,7 +104,7 @@ export const DateElement = forwardRef((props, ref) => {
103
104
  return value;
104
105
  },
105
106
  showPicker = () => {
106
- if (UiGlobals.mode === UI_MODE_WEB && triggerRef.current?.getBoundingClientRect) {
107
+ if (CURRENT_MODE === UI_MODE_WEB && triggerRef.current?.getBoundingClientRect) {
107
108
  // For web, ensure it's in the proper place
108
109
  const
109
110
  // triggerRect = triggerRef.current.getBoundingClientRect(),
@@ -124,7 +125,7 @@ export const DateElement = forwardRef((props, ref) => {
124
125
  if (disableDirectEntry) {
125
126
  return;
126
127
  }
127
- if (UiGlobals.mode !== UI_MODE_WEB) {
128
+ if (CURRENT_MODE !== UI_MODE_WEB) {
128
129
  return;
129
130
  }
130
131
  switch(e.key) {
@@ -136,7 +137,7 @@ export const DateElement = forwardRef((props, ref) => {
136
137
  }
137
138
  },
138
139
  onInputBlur = (e) => {
139
- // if (UiGlobals.mode !== UI_MODE_WEB) {
140
+ // if (CURRENT_MODE !== UI_MODE_WEB) {
140
141
  // return;
141
142
  // }
142
143
  // const {
@@ -191,7 +192,7 @@ export const DateElement = forwardRef((props, ref) => {
191
192
  inputRef.current?.focus();
192
193
  },
193
194
  onTriggerBlur = (e) => {
194
- if (!isPickerShown || UiGlobals.mode !== UI_MODE_WEB) {
195
+ if (!isPickerShown || CURRENT_MODE !== UI_MODE_WEB) {
195
196
  return;
196
197
  }
197
198
  const {
@@ -327,7 +328,7 @@ export const DateElement = forwardRef((props, ref) => {
327
328
  )}
328
329
  />;
329
330
 
330
- if (UiGlobals.mode === UI_MODE_WEB) {
331
+ if (CURRENT_MODE === UI_MODE_WEB) {
331
332
  input = disableDirectEntry ?
332
333
  <Pressable
333
334
  {...testProps('togglePickerBtn')}
@@ -394,7 +395,7 @@ export const DateElement = forwardRef((props, ref) => {
394
395
  {..._input}
395
396
  />;
396
397
  }
397
- if (UiGlobals.mode === UI_MODE_NATIVE) {
398
+ if (CURRENT_MODE === UI_MODE_NATIVE) {
398
399
  throw new Error('Migration to Gluestack not yet implemented for Native mode');
399
400
  // This input and trigger are for show
400
401
  // The just show the current value and open the menu
@@ -426,7 +427,7 @@ export const DateElement = forwardRef((props, ref) => {
426
427
  }
427
428
 
428
429
  if (isPickerShown) {
429
- if (UiGlobals.mode === UI_MODE_WEB) {
430
+ if (CURRENT_MODE === UI_MODE_WEB) {
430
431
  dropdownMenu = <Popover
431
432
  isOpen={isPickerShown}
432
433
  onClose={() => {
@@ -478,7 +479,7 @@ export const DateElement = forwardRef((props, ref) => {
478
479
  </PopoverContent>
479
480
  </Popover>;
480
481
  }
481
- if (UiGlobals.mode === UI_MODE_NATIVE) {
482
+ if (CURRENT_MODE === UI_MODE_NATIVE) {
482
483
  const inputAndTriggerClone = // for RN, this is the actual input and trigger, as we need them to appear up above in the modal
483
484
  <HStack className="h-[10px]">
484
485
  <IconButton
@@ -4,6 +4,7 @@ import {
4
4
  } from '@project-components/Gluestack';
5
5
  import clsx from 'clsx';
6
6
  import {
7
+ CURRENT_MODE,
7
8
  UI_MODE_NATIVE,
8
9
  UI_MODE_WEB,
9
10
  } from '../../../Constants/UiModes.js';
@@ -36,7 +37,7 @@ export function JsonElement(props) {
36
37
 
37
38
  let assembledComponents = null;
38
39
 
39
- if (UiGlobals.mode === UI_MODE_NATIVE) {
40
+ if (CURRENT_MODE === UI_MODE_NATIVE) {
40
41
  throw new Error('JsonElement not yet implemented for React Native');
41
42
  }
42
43
 
@@ -49,7 +50,7 @@ export function JsonElement(props) {
49
50
  if (props.className) {
50
51
  className += ' ' + propsToPass.className;
51
52
  }
52
- // if (UiGlobals.mode === UI_MODE_WEB) {
53
+ // if (CURRENT_MODE === UI_MODE_WEB) {
53
54
  const src = value ? JSON.parse(value) : {};
54
55
  assembledComponents =
55
56
  <HStack style={propsToPass.style} className={className}>
@@ -89,7 +89,7 @@ const TextAreaElement = forwardRef((props, ref) => {
89
89
  styles.FORM_TEXTAREA_CLASSNAME,
90
90
  );
91
91
  if (className) {
92
- inputClassName += ' ' + className;
92
+ textareaClassName += ' ' + className;
93
93
  }
94
94
  if (minimizeForRow) {
95
95
  textareaClassName += ' h-auto min-h-0 max-h-[40px] overflow-auto';
@@ -89,7 +89,7 @@ export default function FieldSet(props) {
89
89
  styles.FORM_FIELDSET_BG,
90
90
  );
91
91
  if (props.className) {
92
- className += props.className;
92
+ className += ' ' + props.className;
93
93
  }
94
94
 
95
95
 
@@ -1436,7 +1436,10 @@ function Form(props) {
1436
1436
  if (isSaving) {
1437
1437
  footerClassName += ' border-t-2 border-t-[#f00]'
1438
1438
  }
1439
- footer = <Footer className={footerClassName} {...footerProps}>
1439
+ if (footerProps.className) {
1440
+ footerClassName += ' ' + footerProps.className;
1441
+ }
1442
+ footer = <Footer {...footerProps} className={footerClassName}>
1440
1443
  {footerButtons}
1441
1444
  </Footer>;
1442
1445
  }
@@ -50,7 +50,11 @@ const accordionTitleTextStyle = tva({
50
50
  },
51
51
  });
52
52
  const accordionIconStyle = tva({
53
- base: 'text-typography-900 fill-none',
53
+ // BEGIN SKOTE MOD
54
+ // See https://github.com/gluestack/gluestack-ui/issues/2385#issuecomment-3141973446
55
+ // base: 'text-typography-900 fill-none',
56
+ base: 'text-typography-900 fill-black',
57
+ // END SKOTE MOD
54
58
  parentVariants: {
55
59
  size: {
56
60
  '2xs': 'h-3 w-3',
@@ -263,7 +263,11 @@ const actionsheetSectionHeaderTextStyle = tva({
263
263
  });
264
264
 
265
265
  const actionsheetIconStyle = tva({
266
- base: 'text-background-500 fill-none',
266
+ // BEGIN SKOTE MOD
267
+ // See https://github.com/gluestack/gluestack-ui/issues/2385#issuecomment-3141973446
268
+ // base: 'text-background-500 fill-none',
269
+ base: 'text-background-500 fill-black',
270
+ // END SKOTE MOD
267
271
  variants: {
268
272
  size: {
269
273
  '2xs': 'h-3 w-3',
@@ -83,7 +83,11 @@ const alertTextStyle = tva({
83
83
  });
84
84
 
85
85
  const alertIconStyle = tva({
86
- base: 'fill-none',
86
+ // BEGIN SKOTE MOD
87
+ // See https://github.com/gluestack/gluestack-ui/issues/2385#issuecomment-3141973446
88
+ // base: 'fill-none',
89
+ base: 'fill-black',
90
+ // END SKOTE MOD
87
91
  variants: {
88
92
  size: {
89
93
  '2xs': 'h-3 w-3',
@@ -76,7 +76,11 @@ const badgeTextStyle = tva({
76
76
  });
77
77
 
78
78
  const badgeIconStyle = tva({
79
- base: 'fill-none',
79
+ // BEGIN SKOTE MOD
80
+ // See https://github.com/gluestack/gluestack-ui/issues/2385#issuecomment-3141973446
81
+ // base: 'fill-none',
82
+ base: 'fill-black',
83
+ // END SKOTE MOD
80
84
  parentVariants: {
81
85
  action: {
82
86
  error: 'text-error-600',
@@ -282,7 +282,11 @@ const buttonTextStyle = tva({
282
282
  });
283
283
 
284
284
  const buttonIconStyle = tva({
285
- base: 'fill-none',
285
+ // BEGIN SKOTE MOD
286
+ // See https://github.com/gluestack/gluestack-ui/issues/2385#issuecomment-3141973446
287
+ // base: 'fill-none',
288
+ base: 'fill-black',
289
+ // END SKOTE MOD
286
290
  parentVariants: {
287
291
  variant: {
288
292
  link: 'data-[hover=true]:underline data-[active=true]:underline',
@@ -160,7 +160,11 @@ const checkboxLabelStyle = tva({
160
160
  });
161
161
 
162
162
  const checkboxIconStyle = tva({
163
- base: 'text-typography-50 fill-none',
163
+ // BEGIN SKOTE MOD
164
+ // See https://github.com/gluestack/gluestack-ui/issues/2385#issuecomment-3141973446
165
+ // base: 'text-typography-50 fill-none',
166
+ base: 'text-typography-50 fill-black',
167
+ // END SKOTE MOD
164
168
 
165
169
  parentVariants: {
166
170
  size: {
@@ -165,7 +165,11 @@ const fabLabelStyle = tva({
165
165
  });
166
166
 
167
167
  const fabIconStyle = tva({
168
- base: 'text-typography-50 fill-none',
168
+ // BEGIN SKOTE MOD
169
+ // See https://github.com/gluestack/gluestack-ui/issues/2385#issuecomment-3141973446
170
+ // base: 'text-typography-50 fill-none',
171
+ base: 'text-typography-50 fill-black',
172
+ // END SKOTE MOD
169
173
  variants: {
170
174
  size: {
171
175
  '2xs': 'h-3 w-3',
@@ -80,7 +80,11 @@ const formControlStyle = tva({
80
80
  });
81
81
 
82
82
  const formControlErrorIconStyle = tva({
83
- base: 'text-error-700 fill-none',
83
+ // BEGIN SKOTE MOD
84
+ // See https://github.com/gluestack/gluestack-ui/issues/2385#issuecomment-3141973446
85
+ // base: 'text-error-700 fill-none',
86
+ base: 'text-error-700 fill-none fill-black',
87
+ // END SKOTE MOD
84
88
  variants: {
85
89
  size: {
86
90
  '2xs': 'h-3 w-3',
@@ -0,0 +1,74 @@
1
+ import React, { forwardRef } from 'react';
2
+ import { Path, G } from 'react-native-svg';
3
+ const ChildPath = ({ element, fill, stroke: pathStroke }) => {
4
+ const pathStrokeColor = pathStroke || '';
5
+ const fillColor = fill || '';
6
+ if (!element) {
7
+ return null;
8
+ }
9
+ if (element.type === React.Fragment) {
10
+ return element;
11
+ }
12
+ return React.cloneElement(element, {
13
+ fill: fillColor ? fillColor : 'currentColor',
14
+ stroke: pathStrokeColor,
15
+ });
16
+ };
17
+ export function createIcon({ Root, path, d, ...initialProps }) {
18
+ const IconTemp = forwardRef((props, ref) => {
19
+ let children = path;
20
+ if (d && (!path || Object.keys(path).length === 0)) {
21
+ children = <Path fill="currentColor" d={d}/>;
22
+ }
23
+ const finalProps = {
24
+ ...initialProps,
25
+ ...props,
26
+ };
27
+ const {
28
+ stroke = 'currentColor',
29
+ // BEGIN SKOTE MOD
30
+ fill,
31
+ // END SKOTE MOD
32
+ color,
33
+ role = 'img',
34
+ ...resolvedProps
35
+ } = finalProps;
36
+ let type = resolvedProps.type;
37
+ if (type === undefined) {
38
+ type = 'svg';
39
+ }
40
+ let colorProps = {};
41
+ if (color) {
42
+ colorProps = { ...colorProps, color: color };
43
+ }
44
+ if (stroke) {
45
+ colorProps = { ...colorProps, stroke: stroke };
46
+ }
47
+ let sizeProps = {};
48
+ let sizeStyle = {};
49
+ if (type === 'font') {
50
+ if (resolvedProps.sx) {
51
+ sizeProps = { ...sizeProps, fontSize: resolvedProps?.sx?.h };
52
+ }
53
+ if (resolvedProps.size) {
54
+ // sizeProps = { ...sizeProps, fontSize: resolvedProps?.size };
55
+ }
56
+ }
57
+ return (<Root {...resolvedProps} {...colorProps} role={role} ref={ref} {...sizeProps} {...sizeStyle}>
58
+ {React.Children.count(children) > 0 ? (<G>
59
+ {React.Children.map(children, (child, i) => (
60
+ <ChildPath
61
+ key={child?.key ?? i}
62
+ element={child}
63
+ {...child?.props}
64
+ // BEGIN SKOTE MOD
65
+ fill={fill || child?.props?.fill}
66
+ // END SKOTE MOD
67
+ />
68
+ ))}
69
+ </G>) : null}
70
+ </Root>);
71
+ });
72
+ const Icon = IconTemp;
73
+ return Icon;
74
+ }