@utilitywarehouse/hearth-react-native 0.11.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (202) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/.turbo/turbo-lint.log +1 -1
  3. package/CHANGELOG.md +16 -0
  4. package/build/components/Accordion/AccordionTrigger.js +1 -1
  5. package/build/components/Banner/Banner.context.d.ts +7 -0
  6. package/build/components/Banner/Banner.context.js +8 -0
  7. package/build/components/Banner/Banner.js +10 -40
  8. package/build/components/Banner/Banner.props.d.ts +3 -5
  9. package/build/components/Banner/BannerIllustration.d.ts +4 -0
  10. package/build/components/Banner/BannerIllustration.js +53 -0
  11. package/build/components/Banner/BannerImage.d.ts +4 -0
  12. package/build/components/Banner/BannerImage.js +53 -0
  13. package/build/components/Banner/index.d.ts +2 -0
  14. package/build/components/Banner/index.js +2 -0
  15. package/build/components/Card/CardAction/CardAction.props.d.ts +2 -3
  16. package/build/components/Card/CardAction/CardActionRoot.js +1 -2
  17. package/build/components/Checkbox/Checkbox.js +1 -2
  18. package/build/components/Checkbox/Checkbox.props.d.ts +3 -3
  19. package/build/components/Checkbox/CheckboxImage.d.ts +2 -1
  20. package/build/components/Checkbox/CheckboxImage.js +8 -1
  21. package/build/components/Checkbox/CheckboxIndicator.js +3 -3
  22. package/build/components/DatePicker/DatePickerDay.js +3 -3
  23. package/build/components/ExpandableCard/ExpandableCard.props.d.ts +1 -2
  24. package/build/components/ExpandableCard/ExpandableCardTrigger.props.d.ts +4 -5
  25. package/build/components/ExpandableCard/ExpandableCardTriggerRoot.js +1 -14
  26. package/build/components/HighlightBanner/HighlightBanner.js +2 -6
  27. package/build/components/HighlightBanner/HighlightBanner.props.d.ts +2 -3
  28. package/build/components/HighlightBanner/HighlightBannerImage.d.ts +4 -0
  29. package/build/components/HighlightBanner/HighlightBannerImage.js +18 -0
  30. package/build/components/HighlightBanner/index.d.ts +1 -0
  31. package/build/components/HighlightBanner/index.js +1 -0
  32. package/build/components/Input/Input.d.ts +5 -7
  33. package/build/components/Input/Input.js +11 -4
  34. package/build/components/Input/InputField.d.ts +4 -7
  35. package/build/components/Input/InputField.js +6 -5
  36. package/build/components/List/ListItem/ListItem.props.d.ts +2 -2
  37. package/build/components/List/ListItem/ListItemRoot.js +1 -2
  38. package/build/components/Modal/Modal.js +2 -6
  39. package/build/components/Modal/Modal.props.d.ts +3 -2
  40. package/build/components/Modal/Modal.web.js +2 -6
  41. package/build/components/Modal/ModalImage.d.ts +4 -0
  42. package/build/components/Modal/ModalImage.js +18 -0
  43. package/build/components/Modal/index.d.ts +1 -0
  44. package/build/components/Modal/index.js +1 -0
  45. package/build/components/PillGroup/Pill.js +2 -2
  46. package/build/components/Radio/Radio.js +1 -2
  47. package/build/components/Radio/Radio.props.d.ts +3 -3
  48. package/build/components/Radio/RadioImage.d.ts +2 -1
  49. package/build/components/Radio/RadioImage.js +8 -1
  50. package/build/components/Radio/RadioIndicator.js +3 -3
  51. package/build/components/RadioCard/RadioCardIndicator.js +3 -3
  52. package/build/components/RadioCard/RadioCardRoot.js +3 -3
  53. package/build/components/Tabs/Tab.js +5 -5
  54. package/build/components/ToggleButton/ToggleButtonRoot.js +2 -2
  55. package/build/components/ToggleButtonCard/ToggleButtonCardRoot.js +3 -3
  56. package/build/components/UnstyledIconButton/UnstyledIconButtonRoot.js +1 -1
  57. package/build/components/VerificationInput/VerificationInput.d.ts +6 -0
  58. package/build/components/VerificationInput/VerificationInput.js +35 -0
  59. package/build/components/VerificationInput/VerificationInput.props.d.ts +49 -0
  60. package/build/components/VerificationInput/VerificationInput.props.js +1 -0
  61. package/build/components/VerificationInput/VerificationInputSlot.d.ts +9 -0
  62. package/build/components/VerificationInput/VerificationInputSlot.js +72 -0
  63. package/build/components/VerificationInput/index.d.ts +4 -0
  64. package/build/components/VerificationInput/index.js +3 -0
  65. package/build/components/VerificationInput/useVerificationInput.d.ts +14 -0
  66. package/build/components/VerificationInput/useVerificationInput.js +58 -0
  67. package/build/components/index.d.ts +1 -0
  68. package/build/components/index.js +1 -0
  69. package/build/utils/index.d.ts +2 -1
  70. package/build/utils/index.js +2 -1
  71. package/build/utils/isThemedImageProps.d.ts +4 -0
  72. package/build/utils/isThemedImageProps.js +4 -0
  73. package/docs/components/AllComponents.web.tsx +9 -0
  74. package/package.json +11 -12
  75. package/src/components/Accordion/Accordion.figma.tsx +23 -0
  76. package/src/components/Accordion/AccordionItemRoot.figma.tsx +47 -0
  77. package/src/components/Accordion/AccordionTrigger.tsx +1 -1
  78. package/src/components/Alert/Alert.figma.tsx +47 -0
  79. package/src/components/Avatar/Avatar.figma.tsx +33 -0
  80. package/src/components/Badge/Badge.figma.tsx +48 -24
  81. package/src/components/Banner/Banner.context.ts +11 -0
  82. package/src/components/Banner/Banner.docs.mdx +55 -37
  83. package/src/components/Banner/Banner.figma.tsx +15 -0
  84. package/src/components/Banner/Banner.props.ts +3 -5
  85. package/src/components/Banner/Banner.stories.tsx +86 -57
  86. package/src/components/Banner/Banner.tsx +24 -67
  87. package/src/components/Banner/BannerIllustration.figma.tsx +30 -0
  88. package/src/components/Banner/BannerIllustration.tsx +63 -0
  89. package/src/components/Banner/BannerImage.tsx +63 -0
  90. package/src/components/Banner/index.ts +2 -0
  91. package/src/components/BottomSheet/BottomSheetModal.figma.tsx +20 -0
  92. package/src/components/Button/Button.figma.tsx +60 -229
  93. package/src/components/Card/Card.docs.mdx +4 -4
  94. package/src/components/Card/Card.figma.tsx +43 -71
  95. package/src/components/Card/CardAction/CardAction.figma.tsx +44 -0
  96. package/src/components/Card/CardAction/CardAction.props.ts +2 -3
  97. package/src/components/Card/CardAction/CardAction.stories.tsx +5 -4
  98. package/src/components/Card/CardAction/CardActionRoot.tsx +4 -5
  99. package/src/components/Carousel/Carousel.figma.tsx +19 -0
  100. package/src/components/Checkbox/Checkbox.docs.mdx +23 -4
  101. package/src/components/Checkbox/Checkbox.figma.tsx +26 -41
  102. package/src/components/Checkbox/Checkbox.props.ts +3 -3
  103. package/src/components/Checkbox/Checkbox.stories.tsx +14 -8
  104. package/src/components/Checkbox/Checkbox.tsx +1 -2
  105. package/src/components/Checkbox/CheckboxGroup.figma.tsx +20 -0
  106. package/src/components/Checkbox/CheckboxImage.figma.tsx +27 -0
  107. package/src/components/Checkbox/CheckboxImage.tsx +8 -3
  108. package/src/components/Checkbox/CheckboxIndicator.tsx +3 -3
  109. package/src/components/Checkbox/CheckboxTileRoot.figma.tsx +32 -0
  110. package/src/components/CurrencyInput/CurrencyInput.figma.tsx +56 -0
  111. package/src/components/DateInput/DateInput.figma.tsx +75 -0
  112. package/src/components/DatePicker/DatePickerCalendar.figma.tsx +34 -0
  113. package/src/components/DatePicker/DatePickerDay.tsx +3 -3
  114. package/src/components/DatePickerInput/DatePickerInput.figma.tsx +62 -0
  115. package/src/components/DescriptionList/DescriptionList.figma.tsx +23 -0
  116. package/src/components/Divider/Divider.figma.tsx +23 -18
  117. package/src/components/ExpandableCard/ExpandableCard.docs.mdx +2 -2
  118. package/src/components/ExpandableCard/ExpandableCard.figma.tsx +54 -0
  119. package/src/components/ExpandableCard/ExpandableCard.props.ts +1 -2
  120. package/src/components/ExpandableCard/ExpandableCard.stories.tsx +3 -3
  121. package/src/components/ExpandableCard/ExpandableCardGroup.figma.tsx +23 -0
  122. package/src/components/ExpandableCard/ExpandableCardTrigger.props.ts +4 -5
  123. package/src/components/ExpandableCard/ExpandableCardTriggerRoot.tsx +2 -17
  124. package/src/components/FormField/FormField.figma.tsx +23 -0
  125. package/src/components/Helper/HelperText.figma.tsx +23 -0
  126. package/src/components/HighlightBanner/HighlightBanner.docs.mdx +73 -42
  127. package/src/components/HighlightBanner/HighlightBanner.props.ts +2 -3
  128. package/src/components/HighlightBanner/HighlightBanner.stories.tsx +85 -60
  129. package/src/components/HighlightBanner/HighlightBanner.tsx +3 -10
  130. package/src/components/HighlightBanner/HighlightBannerImage.tsx +20 -0
  131. package/src/components/HighlightBanner/index.ts +1 -0
  132. package/src/components/IconButton/IconButton.figma.tsx +55 -161
  133. package/src/components/IconContainer/IconContainer.figma.tsx +50 -0
  134. package/src/components/InlineLink/InlineLink.figma.tsx +33 -0
  135. package/src/components/Input/Input.figma.tsx +52 -110
  136. package/src/components/Input/Input.stories.tsx +76 -3
  137. package/src/components/Input/Input.tsx +110 -98
  138. package/src/components/Input/InputField.tsx +27 -26
  139. package/src/components/Label/Label.figma.tsx +24 -0
  140. package/src/components/Link/Link.figma.tsx +42 -0
  141. package/src/components/List/List.docs.mdx +15 -9
  142. package/src/components/List/List.figma.tsx +29 -108
  143. package/src/components/List/List.stories.tsx +2 -2
  144. package/src/components/List/ListAction/ListAction.figma.tsx +29 -0
  145. package/src/components/List/ListItem/ListItem.figma.tsx +40 -220
  146. package/src/components/List/ListItem/ListItem.props.ts +2 -2
  147. package/src/components/List/ListItem/ListItemLeadingContent.figma.tsx +29 -0
  148. package/src/components/List/ListItem/ListItemRoot.tsx +2 -3
  149. package/src/components/List/ListItem/ListItemTrailingContent.figma.tsx +27 -0
  150. package/src/components/Menu/Menu.figma.tsx +30 -0
  151. package/src/components/Menu/MenuItem.figma.tsx +31 -0
  152. package/src/components/Modal/Modal.docs.mdx +16 -4
  153. package/src/components/Modal/Modal.figma.tsx +56 -0
  154. package/src/components/Modal/Modal.props.ts +3 -2
  155. package/src/components/Modal/Modal.stories.tsx +2 -5
  156. package/src/components/Modal/Modal.tsx +2 -6
  157. package/src/components/Modal/Modal.web.tsx +2 -6
  158. package/src/components/Modal/ModalImage.tsx +20 -0
  159. package/src/components/Modal/index.ts +1 -0
  160. package/src/components/PillGroup/Pill.figma.tsx +25 -0
  161. package/src/components/PillGroup/Pill.tsx +3 -3
  162. package/src/components/PillGroup/PillGroup.figma.tsx +21 -0
  163. package/src/components/PillGroup/PillGroup.stories.tsx +1 -1
  164. package/src/components/ProgressStepper/ProgressStep.figma.tsx +30 -0
  165. package/src/components/ProgressStepper/ProgressStepper.figma.tsx +20 -0
  166. package/src/components/Radio/Radio.docs.mdx +21 -8
  167. package/src/components/Radio/Radio.figma.tsx +22 -42
  168. package/src/components/Radio/Radio.props.ts +3 -3
  169. package/src/components/Radio/Radio.stories.tsx +15 -11
  170. package/src/components/Radio/Radio.tsx +1 -2
  171. package/src/components/Radio/RadioGroup.figma.tsx +54 -0
  172. package/src/components/Radio/RadioImage.figma.tsx +27 -0
  173. package/src/components/Radio/RadioImage.tsx +8 -3
  174. package/src/components/Radio/RadioIndicator.tsx +3 -3
  175. package/src/components/Radio/RadioTileRoot.figma.tsx +31 -0
  176. package/src/components/RadioCard/RadioCardIndicator.tsx +3 -3
  177. package/src/components/RadioCard/RadioCardRoot.tsx +3 -3
  178. package/src/components/SectionHeader/SectionHeader.figma.tsx +30 -16
  179. package/src/components/Select/Select.figma.tsx +55 -0
  180. package/src/components/Select/SelectOption.figma.tsx +36 -0
  181. package/src/components/Spinner/Spinner.figma.tsx +20 -12
  182. package/src/components/Switch/Switch.figma.tsx +31 -23
  183. package/src/components/Tabs/Tab.tsx +5 -5
  184. package/src/components/Tabs/Tabs.figma.tsx +29 -0
  185. package/src/components/ThemedImage/ThemedImage.stories.tsx +1 -1
  186. package/src/components/Toast/ToastItem.figma.tsx +22 -0
  187. package/src/components/ToggleButton/ToggleButtonRoot.tsx +2 -2
  188. package/src/components/ToggleButtonCard/ToggleButtonCardRoot.tsx +3 -3
  189. package/src/components/UnstyledIconButton/UnstyledIconButton.figma.tsx +49 -0
  190. package/src/components/UnstyledIconButton/UnstyledIconButtonRoot.tsx +1 -1
  191. package/src/components/VerificationInput/VerificationInput.docs.mdx +68 -0
  192. package/src/components/VerificationInput/VerificationInput.props.ts +52 -0
  193. package/src/components/VerificationInput/VerificationInput.stories.tsx +140 -0
  194. package/src/components/VerificationInput/VerificationInput.tsx +89 -0
  195. package/src/components/VerificationInput/VerificationInputSlot.tsx +94 -0
  196. package/src/components/VerificationInput/index.ts +5 -0
  197. package/src/components/VerificationInput/useVerificationInput.ts +72 -0
  198. package/src/components/index.ts +1 -0
  199. package/src/utils/index.ts +2 -1
  200. package/src/utils/isThemedImageProps.ts +8 -0
  201. package/src/components/Checkbox/CheckboxIndicator.figma.tsx +0 -19
  202. package/src/components/Radio/RadioIndicator.figma.tsx +0 -21
@@ -1,115 +1,57 @@
1
- // import { Input } from './';
2
- // import figma from '@figma/code-connect';
3
- // import { EyeMediumIcon } from '@utilitywarehouse/hearth-react-native-icons';
1
+ import figma from '@figma/code-connect';
2
+ import Input from './Input';
4
3
 
5
4
  /**
6
5
  * -- This file was auto-generated by Code Connect --
7
- * `props` includes a mapping from Figma properties and variants to
8
- * suggested values. You should update this to match the props of your
9
- * code component, and update the `example` function to return the
10
- * code example you'd like to see in Figma
6
+ * `props` includes a mapping from your code props to Figma properties.
7
+ * You should check this is correct, and update the `example` function
8
+ * to return the code example you'd like to see in Figma
11
9
  */
12
10
 
13
- // figma.connect(
14
- // Input,
15
- // 'https://www.figma.com/design/3RY3OvLA88yZksRjOfjQJm/UW-App-UI?node-id=6990-3022&m=dev',
16
- // {
17
- // props: {
18
- // state: figma.enum('state', {
19
- // initial: 'initial',
20
- // focus: 'focus',
21
- // filled: 'filled',
22
- // }),
23
- // placeholder: figma.boolean('placeholder', {
24
- // true: figma.nestedProps('.Parts/Input value', {
25
- // text: figma.string('Text'),
26
- // }),
27
- // false: { text: undefined },
28
- // }),
29
- // validationStatus: figma.enum('validationStatus', {
30
- // initial: undefined,
31
- // invalid: 'invalid',
32
- // valid: 'valid',
33
- // }),
34
- // disabled: figma.boolean('disabled'),
35
- // readOnly: figma.boolean('readOnly'),
36
- // iconLeft: figma.boolean('Icon Left?', {
37
- // true: figma.nestedProps('.Parts/Content Left', {
38
- // icon: figma.instance('Icon'),
39
- // }),
40
- // false: {
41
- // icon: undefined,
42
- // },
43
- // }),
44
- // value: figma.nestedProps('.Parts/Input value', {
45
- // text: figma.boolean('placeholder', {
46
- // true: undefined,
47
- // false: figma.string('Text'),
48
- // }),
49
- // }),
50
- // },
51
- // example: props => (
52
- // <Input
53
- // validationStatus={props.validationStatus}
54
- // placeholder={props.placeholder.text}
55
- // readonly={props.readOnly}
56
- // value={props.value.text}
57
- // disabled={props.disabled}
58
- // leadingIcon={props.iconLeft.icon}
59
- // />
60
- // ),
61
- // }
62
- // );
63
-
64
- // // Password Input
65
- // figma.connect(
66
- // Input,
67
- // 'https://www.figma.com/design/3RY3OvLA88yZksRjOfjQJm/UW-App-UI?node-id=7928-5958&m=dev',
68
- // {
69
- // props: {
70
- // state: figma.enum('state', {
71
- // initial: 'initial',
72
- // focus: 'focus',
73
- // filled: 'filled',
74
- // }),
75
- // placeholder: figma.boolean('placeholder', {
76
- // true: figma.nestedProps('.Parts/Input value', {
77
- // text: figma.string('Text'),
78
- // }),
79
- // false: { text: undefined },
80
- // }),
81
- // validationStatus: figma.enum('validationStatus', {
82
- // initial: undefined,
83
- // invalid: 'invalid',
84
- // valid: 'valid',
85
- // }),
86
- // disabled: figma.boolean('disabled'),
87
- // readOnly: figma.boolean('readOnly'),
88
- // iconLeft: figma.boolean('Icon Left?', {
89
- // true: figma.nestedProps('.Parts/Content Left', {
90
- // icon: figma.instance('Icon'),
91
- // }),
92
- // false: {
93
- // icon: undefined,
94
- // },
95
- // }),
96
- // value: figma.nestedProps('.Parts/Input value', {
97
- // text: figma.boolean('placeholder', {
98
- // true: undefined,
99
- // false: figma.string('Text'),
100
- // }),
101
- // }),
102
- // },
103
- // example: props => (
104
- // <Input
105
- // validationStatus={props.validationStatus}
106
- // placeholder={props.placeholder.text}
107
- // readonly={props.readOnly}
108
- // value={props.value.text}
109
- // disabled={props.disabled}
110
- // leadingIcon={props.iconLeft.icon}
111
- // trailingIcon={EyeMediumIcon}
112
- // />
113
- // ),
114
- // }
115
- // );
11
+ figma.connect(Input, 'https://www.figma.com/design/6NKZXZhFSExXrcbBgc6zTR?node-id=2685%3A7021', {
12
+ props: {
13
+ // These props were automatically mapped based on your linked code:
14
+ disabled: figma.enum('State', {
15
+ Disabled: true,
16
+ }),
17
+ readonly: figma.enum('State', {
18
+ 'Read-only': true,
19
+ }),
20
+ focused: figma.boolean('Focus?'),
21
+ placeholder: figma.string('Suffix'),
22
+ focusable: figma.boolean('Focus?'),
23
+ hasTVPreferredFocus: figma.boolean('Focus?'),
24
+ 'aria-disabled': figma.enum('State', {
25
+ Disabled: true,
26
+ }),
27
+ // No matching props could be found for these Figma properties:
28
+ // "helperText": figma.boolean('Helper text?'),
29
+ // "label": figma.string('Label'),
30
+ // "validation": figma.string('Validation'),
31
+ // "helperText": figma.string('Helper text'),
32
+ // "value": figma.string('Value'),
33
+ // "suffix": figma.boolean('Suffix?'),
34
+ // "prefix": figma.boolean('Prefix?'),
35
+ // "prefix": figma.string('Prefix'),
36
+ // "suffix": figma.string('Suffix'),
37
+ // "optional": figma.boolean('Optional?'),
38
+ // "valueType": figma.enum('Value type', {
39
+ // "Empty": "empty",
40
+ // "Placeholder": "placeholder",
41
+ // "Filled": "filled"
42
+ // }),
43
+ // "labelVariant": figma.enum('Label variant', {
44
+ // "Body": "body",
45
+ // "Heading": "heading"
46
+ // })
47
+ },
48
+ example: props => (
49
+ <Input
50
+ disabled={props.disabled}
51
+ readonly={props.readonly}
52
+ focused={props.focused}
53
+ placeholder={props.placeholder}
54
+ focusable={props.focusable}
55
+ />
56
+ ),
57
+ });
@@ -1,10 +1,13 @@
1
- import { Meta, StoryObj } from '@storybook/react-vite';
1
+ import { Meta, StoryObj } from '@storybook/react-native';
2
2
  import * as Icons from '@utilitywarehouse/hearth-react-native-icons';
3
3
  import { EmailMediumIcon } from '@utilitywarehouse/hearth-react-native-icons';
4
- import { useState } from 'react';
5
- import { NativeSyntheticEvent, TextInputChangeEventData } from 'react-native';
4
+ import { useRef, useState } from 'react';
5
+ import { NativeSyntheticEvent, TextInput, TextInputChangeEventData, View } from 'react-native';
6
6
  import { Input } from '.';
7
7
  import { VariantTitle } from '../../../docs/components';
8
+ import { useTheme } from '../../hooks';
9
+ import { BodyText } from '../BodyText';
10
+ import { Button } from '../Button';
8
11
  import { Flex } from '../Flex';
9
12
 
10
13
  const meta = {
@@ -73,6 +76,7 @@ export default meta;
73
76
  type Story = StoryObj<typeof meta>;
74
77
 
75
78
  export const Playground: Story = {
79
+ // @ts-expect-error - This is a playground
76
80
  render: ({ leadingIcon: leading, trailingIcon: trailing, ...args }) => {
77
81
  // @ts-expect-error - This is a playground
78
82
  const leadingIcon = leading === 'none' ? undefined : Icons[leading];
@@ -152,3 +156,72 @@ export const Variants: Story = {
152
156
  );
153
157
  },
154
158
  };
159
+
160
+ export const RefTest: Story = {
161
+ parameters: {
162
+ controls: { include: [] },
163
+ },
164
+ render: () => {
165
+ const inputRef = useRef<TextInput>(null);
166
+ const [refStatus, setRefStatus] = useState('Ref not tested yet');
167
+ const theme = useTheme();
168
+
169
+ const handleFocus = () => {
170
+ if (inputRef.current) {
171
+ inputRef.current.focus();
172
+ setRefStatus('✅ Ref works! Input focused programmatically');
173
+ } else {
174
+ setRefStatus('❌ Ref is null');
175
+ }
176
+ };
177
+
178
+ const handleBlur = () => {
179
+ if (inputRef.current) {
180
+ inputRef.current.blur();
181
+ setRefStatus('✅ Ref works! Input blurred programmatically');
182
+ } else {
183
+ setRefStatus('❌ Ref is null');
184
+ }
185
+ };
186
+
187
+ const handleClear = () => {
188
+ if (inputRef.current) {
189
+ inputRef.current.clear();
190
+ setRefStatus('✅ Ref works! Input cleared programmatically');
191
+ } else {
192
+ setRefStatus('❌ Ref is null');
193
+ }
194
+ };
195
+
196
+ return (
197
+ <Flex direction="column" space="lg">
198
+ <VariantTitle title="Ref Test">
199
+ <Input
200
+ ref={inputRef}
201
+ placeholder="Test ref functionality"
202
+ defaultValue="Try the buttons below"
203
+ />
204
+ </VariantTitle>
205
+ <VariantTitle title="Status">
206
+ <Flex direction="column" space="sm">
207
+ <Flex direction="row" space="sm">
208
+ <Button onPress={handleFocus}>Focus Input</Button>
209
+ <Button onPress={handleBlur}>Blur Input</Button>
210
+ <Button onPress={handleClear}>Clear Input</Button>
211
+ </Flex>
212
+ <View
213
+ style={{
214
+ marginTop: 8,
215
+ padding: 8,
216
+ backgroundColor: theme.color.background.secondary,
217
+ borderRadius: 4,
218
+ }}
219
+ >
220
+ <BodyText>{refStatus}</BodyText>
221
+ </View>
222
+ </Flex>
223
+ </VariantTitle>
224
+ </Flex>
225
+ );
226
+ },
227
+ };
@@ -1,5 +1,6 @@
1
1
  import { createInput } from '@gluestack-ui/input';
2
- import { ComponentType, useState } from 'react';
2
+ import { ComponentType, forwardRef, useImperativeHandle, useRef, useState } from 'react';
3
+ import { TextInput } from 'react-native';
3
4
  import type InputProps from './Input.props';
4
5
 
5
6
  import {
@@ -29,108 +30,119 @@ export const InputSlot = InputComponent.Slot;
29
30
  export const InputField = InputComponent.Input;
30
31
  export const InputIcon = InputComponent.Icon;
31
32
 
32
- const Input = ({
33
- validationStatus = 'initial',
34
- children,
35
- disabled,
36
- focused,
37
- readonly,
38
- leadingIcon,
39
- trailingIcon,
40
- type,
41
- showPasswordToggle = true,
42
- onClear,
43
- format,
44
- loading,
45
- clearable = false,
46
- required,
47
- inBottomSheet = false,
48
- ...props
49
- }: InputProps) => {
50
- const formFieldContext = useFormFieldContext();
51
- const { disabled: formFieldDisabled } = formFieldContext;
52
- const validationStatusFromContext = formFieldContext?.validationStatus ?? validationStatus;
53
- const isRequired = formFieldContext?.required ?? required;
54
- const [fieldType, setFieldType] = useState<'password' | 'text'>(
55
- type === 'password' ? 'password' : 'text'
56
- );
57
- const { color } = useTheme();
33
+ const Input = forwardRef<TextInput, InputProps>(
34
+ (
35
+ {
36
+ validationStatus = 'initial',
37
+ children,
38
+ disabled,
39
+ focused,
40
+ readonly,
41
+ leadingIcon,
42
+ trailingIcon,
43
+ type,
44
+ showPasswordToggle = true,
45
+ onClear,
46
+ format,
47
+ loading,
48
+ clearable = false,
49
+ required,
50
+ inBottomSheet = false,
51
+ ...props
52
+ },
53
+ ref
54
+ ) => {
55
+ const formFieldContext = useFormFieldContext();
56
+ const { disabled: formFieldDisabled } = formFieldContext;
57
+ const validationStatusFromContext = formFieldContext?.validationStatus ?? validationStatus;
58
+ const isRequired = formFieldContext?.required ?? required;
59
+ const [fieldType, setFieldType] = useState<'password' | 'text'>(
60
+ type === 'password' ? 'password' : 'text'
61
+ );
62
+ const { color } = useTheme();
63
+ const inputRef = useRef<TextInput>(null);
58
64
 
59
- const shouldShowPasswordToggle = type === 'password' && showPasswordToggle;
60
- const shouldShowClear = clearable && !!(props as InputWithoutChildrenProps)?.value;
65
+ // Expose TextInput methods to parent components
66
+ useImperativeHandle(ref, () => inputRef.current as TextInput, []);
61
67
 
62
- const toggleFieldType = () => {
63
- setFieldType(fieldType === 'password' ? 'text' : 'password');
64
- };
68
+ const shouldShowPasswordToggle = type === 'password' && showPasswordToggle;
69
+ const shouldShowClear = clearable && !!(props as InputWithoutChildrenProps)?.value;
65
70
 
66
- const leadingIconComponent = ((): ComponentType | undefined => {
67
- if (type === 'search') {
68
- return SearchMediumIcon;
69
- }
70
- return leadingIcon;
71
- })();
71
+ const toggleFieldType = () => {
72
+ setFieldType(fieldType === 'password' ? 'text' : 'password');
73
+ };
72
74
 
73
- const getInputMode = (() => {
74
- if (type === 'search') {
75
- return 'search';
76
- }
77
- return undefined;
78
- })();
75
+ const leadingIconComponent = ((): ComponentType | undefined => {
76
+ if (type === 'search') {
77
+ return SearchMediumIcon;
78
+ }
79
+ return leadingIcon;
80
+ })();
79
81
 
80
- return (
81
- <InputComponent
82
- {...(children ? props : {})}
83
- validationStatus={validationStatusFromContext}
84
- isInvalid={validationStatusFromContext === 'invalid'}
85
- isReadOnly={readonly}
86
- isDisabled={formFieldDisabled ?? disabled}
87
- isFocused={focused}
88
- type={type as undefined}
89
- isRequired={isRequired}
90
- >
91
- {children ? (
92
- <>{children}</>
93
- ) : (
94
- <>
95
- {!!leadingIconComponent && (
96
- <InputSlot>
97
- <InputIcon as={leadingIconComponent} />
98
- </InputSlot>
99
- )}
100
- <InputField
101
- type={fieldType}
102
- inputMode={getInputMode}
103
- inBottomSheet={inBottomSheet}
104
- {...props}
105
- />
106
- {shouldShowClear && (
107
- <InputSlot>
108
- <UnstyledIconButton onPress={onClear} icon={CloseSmallIcon} />
109
- </InputSlot>
110
- )}
111
- {loading && (
112
- <InputSlot>
113
- <Spinner size="xs" color={color.icon.primary} />
114
- </InputSlot>
115
- )}
116
- {shouldShowPasswordToggle && (
117
- <InputSlot>
118
- <UnstyledIconButton
119
- onPress={toggleFieldType}
120
- icon={fieldType === 'password' ? EyeSmallIcon : EyeOffSmallIcon}
121
- />
122
- </InputSlot>
123
- )}
124
- {!!trailingIcon && (
125
- <InputSlot>
126
- <InputIcon as={trailingIcon} />
127
- </InputSlot>
128
- )}
129
- </>
130
- )}
131
- </InputComponent>
132
- );
133
- };
82
+ const getInputMode = (() => {
83
+ if (type === 'search') {
84
+ return 'search';
85
+ }
86
+ return undefined;
87
+ })();
88
+
89
+ return (
90
+ <InputComponent
91
+ {...(children ? props : {})}
92
+ validationStatus={validationStatusFromContext}
93
+ isInvalid={validationStatusFromContext === 'invalid'}
94
+ isReadOnly={readonly}
95
+ isDisabled={formFieldDisabled ?? disabled}
96
+ isFocused={focused}
97
+ type={type as undefined}
98
+ isRequired={isRequired}
99
+ >
100
+ {children ? (
101
+ <>{children}</>
102
+ ) : (
103
+ <>
104
+ {!!leadingIconComponent && (
105
+ <InputSlot>
106
+ <InputIcon as={leadingIconComponent} />
107
+ </InputSlot>
108
+ )}
109
+ <InputField
110
+ // @ts-expect-error - ref forwarding issue
111
+ ref={inputRef}
112
+ type={fieldType}
113
+ inputMode={getInputMode}
114
+ inBottomSheet={inBottomSheet}
115
+ {...props}
116
+ />
117
+ {shouldShowClear && (
118
+ <InputSlot>
119
+ <UnstyledIconButton onPress={onClear} icon={CloseSmallIcon} />
120
+ </InputSlot>
121
+ )}
122
+ {loading && (
123
+ <InputSlot>
124
+ <Spinner size="xs" color={color.icon.primary} />
125
+ </InputSlot>
126
+ )}
127
+ {shouldShowPasswordToggle && (
128
+ <InputSlot>
129
+ <UnstyledIconButton
130
+ onPress={toggleFieldType}
131
+ icon={fieldType === 'password' ? EyeSmallIcon : EyeOffSmallIcon}
132
+ />
133
+ </InputSlot>
134
+ )}
135
+ {!!trailingIcon && (
136
+ <InputSlot>
137
+ <InputIcon as={trailingIcon} />
138
+ </InputSlot>
139
+ )}
140
+ </>
141
+ )}
142
+ </InputComponent>
143
+ );
144
+ }
145
+ );
134
146
 
135
147
  Input.displayName = 'Input';
136
148
 
@@ -1,25 +1,38 @@
1
1
  import { BottomSheetTextInput } from '@gorhom/bottom-sheet';
2
+ import { forwardRef } from 'react';
2
3
  import { TextInput as RNTextInput, TextInputProps } from 'react-native';
3
4
  import { StyleSheet } from 'react-native-unistyles';
4
5
  import { useTheme } from '../../hooks';
5
6
  import { useInputContext } from './Input.context';
6
7
 
7
- const InputField = ({
8
- style,
9
- inBottomSheet = false,
10
- ...props
11
- }: TextInputProps & { inBottomSheet?: boolean }) => {
12
- const { disabled, focused = false, type } = useInputContext();
13
- styles.useVariants({ focused, type });
14
- const { color } = useTheme();
8
+ const InputField = forwardRef<RNTextInput, TextInputProps & { inBottomSheet?: boolean }>(
9
+ ({ style, inBottomSheet = false, ...props }, ref) => {
10
+ const { disabled, focused = false, type } = useInputContext();
11
+ styles.useVariants({ focused, type });
12
+ const { color } = useTheme();
13
+
14
+ if (inBottomSheet) {
15
+ return (
16
+ // @ts-expect-error - BottomSheetTextInput has incompatible event types with TextInput
17
+ <BottomSheetTextInput
18
+ ref={ref as any}
19
+ placeholderTextColor={color.text.secondary}
20
+ selectionColor={color.surface.brand.default}
21
+ cursorColor={color.surface.brand.default}
22
+ verticalAlign="middle"
23
+ aria-disabled={disabled}
24
+ {...props}
25
+ style={[styles.input, style]}
26
+ />
27
+ );
28
+ }
15
29
 
16
- if (inBottomSheet) {
17
30
  return (
18
- // @ts-expect-error - BottomSheetTextInput type issue
19
- <BottomSheetTextInput
31
+ <RNTextInput
32
+ ref={ref}
20
33
  placeholderTextColor={color.text.secondary}
21
- selectionColor={color.purple[700]}
22
- cursorColor={color.purple[700]}
34
+ selectionColor={color.surface.brand.default}
35
+ cursorColor={color.surface.brand.default}
23
36
  verticalAlign="middle"
24
37
  aria-disabled={disabled}
25
38
  {...props}
@@ -27,19 +40,7 @@ const InputField = ({
27
40
  />
28
41
  );
29
42
  }
30
-
31
- return (
32
- <RNTextInput
33
- placeholderTextColor={color.text.secondary}
34
- selectionColor={color.purple[700]}
35
- cursorColor={color.purple[700]}
36
- verticalAlign="middle"
37
- aria-disabled={disabled}
38
- {...props}
39
- style={[styles.input, style]}
40
- />
41
- );
42
- };
43
+ );
43
44
 
44
45
  InputField.displayName = 'InputField';
45
46
 
@@ -0,0 +1,24 @@
1
+ import React from "react"
2
+ import Label from "./Label"
3
+ import figma from "@figma/code-connect"
4
+
5
+ /**
6
+ * -- This file was auto-generated by Code Connect --
7
+ * None of your props could be automatically mapped to Figma properties.
8
+ * You should update the `props` object to include a mapping from your
9
+ * code props to Figma properties, and update the `example` function to
10
+ * return the code example you'd like to see in Figma
11
+ */
12
+
13
+ figma.connect(
14
+ Label,
15
+ "https://www.figma.com/design/6NKZXZhFSExXrcbBgc6zTR?node-id=8145%3A617",
16
+ {
17
+ props: {
18
+ // No matching props could be found for these Figma properties:
19
+ // "label": figma.string('Label'),
20
+ // "optional": figma.boolean('Optional?')
21
+ },
22
+ example: (props) => <Label />,
23
+ },
24
+ )
@@ -0,0 +1,42 @@
1
+ import React from "react"
2
+ import Link from "./Link"
3
+ import figma from "@figma/code-connect"
4
+
5
+ /**
6
+ * -- This file was auto-generated by Code Connect --
7
+ * `props` includes a mapping from your code props to Figma properties.
8
+ * You should check this is correct, and update the `example` function
9
+ * to return the code example you'd like to see in Figma
10
+ */
11
+
12
+ figma.connect(
13
+ Link,
14
+ "https://www.figma.com/design/6NKZXZhFSExXrcbBgc6zTR?node-id=163%3A562",
15
+ {
16
+ props: {
17
+ // These props were automatically mapped based on your linked code:
18
+ inverted: figma.boolean("Inverted?"),
19
+ disabled: figma.enum("State", {
20
+ Active: true,
21
+ }),
22
+ showIcon: figma.boolean("Icon right?"),
23
+ focusable: figma.enum("State", {
24
+ Focus: true,
25
+ }),
26
+ // No matching props could be found for these Figma properties:
27
+ // "iconLeft": figma.boolean('Icon left?'),
28
+ // "iconRight": figma.boolean('Icon right?'),
29
+ // "iconRight20": figma.instance('Icon right-20'),
30
+ // "iconLeft20": figma.instance('Icon left-20'),
31
+ // "text": figma.string('Text')
32
+ },
33
+ example: (props) => (
34
+ <Link
35
+ inverted={props.inverted}
36
+ disabled={props.disabled}
37
+ showIcon={props.showIcon}
38
+ focusable={props.focusable}
39
+ />
40
+ ),
41
+ },
42
+ )