@utilitywarehouse/hearth-react-native 0.16.2 → 0.17.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.
- package/.turbo/turbo-build.log +1 -1
- package/.turbo/turbo-lint.log +14 -14
- package/CHANGELOG.md +132 -0
- package/build/components/Card/CardAction/CardActionRoot.js +12 -2
- package/build/components/Card/CardActions.context.d.ts +6 -0
- package/build/components/Card/CardActions.context.js +5 -0
- package/build/components/Card/CardActions.d.ts +7 -0
- package/build/components/Card/CardActions.js +29 -0
- package/build/components/Card/CardRoot.js +16 -104
- package/build/components/Card/helpers.d.ts +8 -0
- package/build/components/Card/helpers.js +146 -0
- package/build/components/Card/index.d.ts +2 -0
- package/build/components/Card/index.js +2 -0
- package/build/components/ExpandableCard/ExpandableCardGroup.d.ts +1 -1
- package/build/components/ExpandableCard/ExpandableCardGroup.js +2 -2
- package/build/components/ExpandableCard/ExpandableCardGroup.props.d.ts +4 -0
- package/build/components/Input/Input.js +4 -3
- package/build/components/Input/Input.props.d.ts +9 -0
- package/build/components/List/List.context.d.ts +4 -2
- package/build/components/List/List.context.js +0 -2
- package/build/components/List/List.d.ts +1 -1
- package/build/components/List/List.js +25 -38
- package/build/components/List/List.props.d.ts +1 -0
- package/build/components/List/ListAction/ListAction.js +24 -7
- package/build/components/List/ListAction/ListAction.props.d.ts +1 -0
- package/build/components/List/ListItem/ListItemRoot.js +12 -4
- package/build/utils/isThemedImageProps.d.ts +1 -1
- package/package.json +3 -3
- package/src/components/Card/Card.docs.mdx +224 -66
- package/src/components/Card/Card.stories.tsx +29 -25
- package/src/components/Card/CardAction/CardAction.stories.tsx +239 -93
- package/src/components/Card/CardAction/CardActionRoot.tsx +15 -2
- package/src/components/Card/CardActions.context.ts +12 -0
- package/src/components/Card/CardActions.tsx +40 -0
- package/src/components/Card/CardRoot.tsx +27 -132
- package/src/components/Card/helpers.tsx +195 -0
- package/src/components/Card/index.ts +2 -0
- package/src/components/ExpandableCard/ExpandableCard.figma.tsx +33 -38
- package/src/components/ExpandableCard/ExpandableCardGroup.figma.tsx +34 -17
- package/src/components/ExpandableCard/ExpandableCardGroup.props.ts +5 -0
- package/src/components/ExpandableCard/ExpandableCardGroup.tsx +2 -0
- package/src/components/HighlightBanner/HighlightBanner.figma.tsx +46 -0
- package/src/components/IconButton/IconButton.figma.tsx +20 -30
- package/src/components/IconContainer/IconContainer.figma.tsx +7 -13
- package/src/components/IndicatorIconButton/IndicatorIconButton.figma.tsx +16 -0
- package/src/components/Input/Input.docs.mdx +55 -15
- package/src/components/Input/Input.figma.tsx +106 -40
- package/src/components/Input/Input.props.ts +9 -0
- package/src/components/Input/Input.tsx +21 -0
- package/src/components/Link/Link.figma.tsx +31 -38
- package/src/components/List/List.context.ts +2 -4
- package/src/components/List/List.docs.mdx +10 -5
- package/src/components/List/List.figma.tsx +42 -28
- package/src/components/List/List.props.ts +1 -0
- package/src/components/List/List.stories.tsx +43 -0
- package/src/components/List/List.tsx +38 -51
- package/src/components/List/ListAction/ListAction.figma.tsx +5 -13
- package/src/components/List/ListAction/ListAction.props.ts +1 -0
- package/src/components/List/ListAction/ListAction.tsx +40 -10
- package/src/components/List/ListItem/ListItem.figma.tsx +43 -27
- package/src/components/List/ListItem/ListItemRoot.tsx +15 -4
- package/src/utils/isThemedImageProps.ts +1 -1
- package/src/components/InlineLink/InlineLink.figma.tsx +0 -33
|
@@ -1,16 +1,8 @@
|
|
|
1
1
|
import figma from '@figma/code-connect';
|
|
2
|
-
import IconButton from '
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* -- This file was auto-generated by Code Connect --
|
|
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
|
|
9
|
-
*/
|
|
2
|
+
import { IconButton } from '../';
|
|
10
3
|
|
|
11
4
|
figma.connect(IconButton, 'https://www.figma.com/design/6NKZXZhFSExXrcbBgc6zTR?node-id=90%3A1455', {
|
|
12
5
|
props: {
|
|
13
|
-
// These props were automatically mapped based on your linked code:
|
|
14
6
|
disabled: figma.enum('State', {
|
|
15
7
|
Disabled: true,
|
|
16
8
|
}),
|
|
@@ -18,38 +10,36 @@ figma.connect(IconButton, 'https://www.figma.com/design/6NKZXZhFSExXrcbBgc6zTR?n
|
|
|
18
10
|
'SM-32': 'sm',
|
|
19
11
|
'MD-48': 'md',
|
|
20
12
|
}),
|
|
13
|
+
colorScheme: figma.enum('Color Scheme', {
|
|
14
|
+
Affirmative: 'affirmative',
|
|
15
|
+
Destructive: 'destructive',
|
|
16
|
+
Functional: 'functional',
|
|
17
|
+
Highlight: 'highlight',
|
|
18
|
+
}),
|
|
21
19
|
loading: figma.enum('State', {
|
|
22
20
|
Loading: true,
|
|
23
21
|
}),
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
'aria-disabled': figma.enum('State', {
|
|
28
|
-
Disabled: true,
|
|
22
|
+
icon: figma.enum('Size', {
|
|
23
|
+
'SM-32': figma.instance('Icon-20'),
|
|
24
|
+
'MD-48': figma.instance('Icon-24'),
|
|
29
25
|
}),
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
26
|
+
variant: figma.enum('Variant', {
|
|
27
|
+
Emphasis: 'emphasis',
|
|
28
|
+
Solid: 'solid',
|
|
29
|
+
Outline: 'outline',
|
|
30
|
+
Ghost: 'ghost',
|
|
33
31
|
}),
|
|
34
|
-
|
|
35
|
-
// "icon24": figma.instance('Icon-24'),
|
|
36
|
-
// "icon20": figma.instance('Icon-20'),
|
|
37
|
-
// "variant": figma.enum('Variant', {
|
|
38
|
-
// "Emphasis": "emphasis",
|
|
39
|
-
// "Solid": "solid",
|
|
40
|
-
// "Outline": "outline",
|
|
41
|
-
// "Ghost": "ghost"
|
|
42
|
-
// }),
|
|
43
|
-
// "inverted": figma.boolean('Inverted?')
|
|
32
|
+
inverted: figma.boolean('Inverted?'),
|
|
44
33
|
},
|
|
45
34
|
example: props => (
|
|
46
35
|
<IconButton
|
|
47
36
|
disabled={props.disabled}
|
|
48
37
|
size={props.size}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
focusable={props.focusable}
|
|
38
|
+
variant={props.variant}
|
|
39
|
+
inverted={props.inverted}
|
|
52
40
|
colorScheme={props.colorScheme}
|
|
41
|
+
loading={props.loading}
|
|
42
|
+
icon={props.icon}
|
|
53
43
|
/>
|
|
54
44
|
),
|
|
55
45
|
});
|
|
@@ -1,19 +1,11 @@
|
|
|
1
1
|
import figma from '@figma/code-connect';
|
|
2
|
-
import IconContainer from '
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* -- This file was auto-generated by Code Connect --
|
|
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
|
|
9
|
-
*/
|
|
2
|
+
import { IconContainer } from '../';
|
|
10
3
|
|
|
11
4
|
figma.connect(
|
|
12
5
|
IconContainer,
|
|
13
6
|
'https://www.figma.com/design/6NKZXZhFSExXrcbBgc6zTR?node-id=5462%3A9728',
|
|
14
7
|
{
|
|
15
8
|
props: {
|
|
16
|
-
// These props were automatically mapped based on your linked code:
|
|
17
9
|
size: figma.enum('Size', {
|
|
18
10
|
'SM-32': 'sm',
|
|
19
11
|
'MD-48': 'md',
|
|
@@ -33,13 +25,15 @@ figma.connect(
|
|
|
33
25
|
Cashback: 'cashback',
|
|
34
26
|
Highlight: 'highlight',
|
|
35
27
|
}),
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
28
|
+
icon: figma.enum('Size', {
|
|
29
|
+
'SM-32': figma.instance('Icon-20'),
|
|
30
|
+
'MD-48': figma.instance('Icon-24'),
|
|
31
|
+
'LG-64': figma.instance('Icon-24'),
|
|
32
|
+
}),
|
|
39
33
|
},
|
|
40
34
|
example: props => (
|
|
41
35
|
<IconContainer
|
|
42
|
-
icon={
|
|
36
|
+
icon={props.icon}
|
|
43
37
|
size={props.size}
|
|
44
38
|
radiusNone={props.radiusNone}
|
|
45
39
|
variant={props.variant}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import figma from '@figma/code-connect';
|
|
2
|
+
import { IndicatorIconButton } from '..';
|
|
3
|
+
|
|
4
|
+
figma.connect(
|
|
5
|
+
IndicatorIconButton,
|
|
6
|
+
'https://www.figma.com/design/6NKZXZhFSExXrcbBgc6zTR/Hearth-Components---Tokens?node-id=6778-10672&t=3uUSBVdxldgG5uz3-4',
|
|
7
|
+
{
|
|
8
|
+
props: {
|
|
9
|
+
indicator: figma.boolean('Indicator?'),
|
|
10
|
+
icon: figma.nestedProps('Icon Button/Unstyled', {
|
|
11
|
+
icon: figma.instance('Icon-24'),
|
|
12
|
+
}),
|
|
13
|
+
},
|
|
14
|
+
example: props => <IndicatorIconButton icon={props.icon.icon} indicator={props.indicator} />,
|
|
15
|
+
}
|
|
16
|
+
);
|
|
@@ -29,6 +29,8 @@ The input component is a text field that allows users to enter text, numbers, or
|
|
|
29
29
|
- [Advanced Usage](#advanced-usage)
|
|
30
30
|
- [Variants](#variants)
|
|
31
31
|
- [Examples](#examples)
|
|
32
|
+
- [With Label and Helper Text](#with-label-and-helper-text)
|
|
33
|
+
- [With `prefix` and `suffix`](#with-prefix-and-suffix)
|
|
32
34
|
- [With `FormField`](#with-formfield)
|
|
33
35
|
- [Accessibility](#accessibility)
|
|
34
36
|
|
|
@@ -46,7 +48,7 @@ The input component is a text field that allows users to enter text, numbers, or
|
|
|
46
48
|
<InputSlot>
|
|
47
49
|
<InputIcon as={EmailMediumIcon} />
|
|
48
50
|
</InputSlot>
|
|
49
|
-
<InputField placeholder="Placeholder"
|
|
51
|
+
<InputField placeholder="Placeholder" onChangeText={() => console.log('###')} />
|
|
50
52
|
</Input>
|
|
51
53
|
</Center>
|
|
52
54
|
</UsageWrap>
|
|
@@ -95,8 +97,10 @@ all of the React Native [`View` props](https://reactnative.dev/docs/view).
|
|
|
95
97
|
| required | `boolean` | `true` | Indicates that the input is required. **(Only to be used if the input has no children)** |
|
|
96
98
|
| leadingIcon | `React.ComponentType` | `-` | The leading icon of the input. **(Only to be used if the input has no children)** |
|
|
97
99
|
| trailingIcon | `React.ComponentType` | `-` | The trailing icon of the input. **(Only to be used if the input has no children)** |
|
|
100
|
+
| prefix | `string \| React.ReactNode` | `-` | Content to display before the input field. **(Only to be used if the input has no children)** |
|
|
101
|
+
| suffix | `string \| React.ReactNode` | `-` | Content to display after the input field. **(Only to be used if the input has no children)** |
|
|
98
102
|
| value | `string` | `-` | The value of the input. **(Only to be used if the input has no children)** |
|
|
99
|
-
|
|
|
103
|
+
| onChangeText | `function` | `-` | Callback function that is triggered when the input value changes. **(Only to be used if the input has no children)** **(Only to be used if the input has no children)** |
|
|
100
104
|
| onBlur | `function` | `-` | Callback function that is triggered when the input loses focus. **(Only to be used if the input has no children)** |
|
|
101
105
|
| onFocus | `function` | `-` | Callback function that is triggered when the input gains focus. **(Only to be used if the input has no children)** |
|
|
102
106
|
| placeholder | `string` | `-` | The placeholder text for the input. **(Only to be used if the input has no children)** |
|
|
@@ -113,7 +117,7 @@ The `InputField` inherits all of the React Native [`TextInput` props](https://re
|
|
|
113
117
|
| ------------- | ---------------------- | -------- | ----------------------------------------------------------------- |
|
|
114
118
|
| type | `'text' \| 'password'` | `'text'` | The type of the input. |
|
|
115
119
|
| value | `string` | `-` | The value of the input. |
|
|
116
|
-
|
|
|
120
|
+
| onChangeText | `function` | `-` | Callback function that is triggered when the input value changes. |
|
|
117
121
|
| onBlur | `function` | `-` | Callback function that is triggered when the input loses focus. |
|
|
118
122
|
| onFocus | `function` | `-` | Callback function that is triggered when the input gains focus. |
|
|
119
123
|
| placeholder | `string` | `-` | The placeholder text for the input. |
|
|
@@ -156,13 +160,12 @@ import {
|
|
|
156
160
|
EyeOffMediumIcon,
|
|
157
161
|
} from '@utilitywarehouse/hearth-react-native-icons';
|
|
158
162
|
import { useState } from 'react';
|
|
159
|
-
import { NativeSyntheticEvent, TextInputChangeEventData } from 'react-native';
|
|
160
163
|
|
|
161
164
|
const AdvancedExample = () => {
|
|
162
165
|
const [value, setValue] = useState<string>('');
|
|
163
166
|
const [fieldType, setFieldType] = useState<'password' | 'text'>('password');
|
|
164
|
-
const handleChange = (
|
|
165
|
-
setValue(
|
|
167
|
+
const handleChange = (text: string) => {
|
|
168
|
+
setValue(text);
|
|
166
169
|
};
|
|
167
170
|
const handleToggleFieldType = () => {
|
|
168
171
|
setFieldType(fieldType === 'password' ? 'text' : 'password');
|
|
@@ -173,7 +176,7 @@ const AdvancedExample = () => {
|
|
|
173
176
|
<InputIcon as={EmailMediumIcon} />
|
|
174
177
|
</InputSlot>
|
|
175
178
|
<InputField
|
|
176
|
-
|
|
179
|
+
onChangeText={handleChange}
|
|
177
180
|
type={fieldType}
|
|
178
181
|
value={value}
|
|
179
182
|
placeholder="Secret email address"
|
|
@@ -207,7 +210,7 @@ The `Input` component can be used with a label and helper text by passing the `l
|
|
|
207
210
|
<Input
|
|
208
211
|
label="Label"
|
|
209
212
|
helperText="Helper text"
|
|
210
|
-
|
|
213
|
+
onChangeText={() => console.log('###')}
|
|
211
214
|
placeholder="Placeholder"
|
|
212
215
|
/>
|
|
213
216
|
</Center>
|
|
@@ -218,14 +221,14 @@ import { Input } from '@utilitywarehouse/hearth-react-native';
|
|
|
218
221
|
|
|
219
222
|
const MyComponent = () => {
|
|
220
223
|
const [value, setValue] = useState('');
|
|
221
|
-
const handleChange =
|
|
222
|
-
setValue(
|
|
224
|
+
const handleChange = text => {
|
|
225
|
+
setValue(text);
|
|
223
226
|
};
|
|
224
227
|
return (
|
|
225
228
|
<Input
|
|
226
229
|
label="Label"
|
|
227
230
|
helperText="Helper text"
|
|
228
|
-
|
|
231
|
+
onChangeText={handleChange}
|
|
229
232
|
value={value}
|
|
230
233
|
placeholder="Placeholder"
|
|
231
234
|
/>
|
|
@@ -233,6 +236,43 @@ const MyComponent = () => {
|
|
|
233
236
|
};
|
|
234
237
|
```
|
|
235
238
|
|
|
239
|
+
## With `prefix` and `suffix`
|
|
240
|
+
|
|
241
|
+
The `Input` component can be customised with `prefix` and `suffix` props to add content before or after the input field.
|
|
242
|
+
|
|
243
|
+
<UsageWrap>
|
|
244
|
+
<Center>
|
|
245
|
+
<Input
|
|
246
|
+
label="Amount"
|
|
247
|
+
prefix="£"
|
|
248
|
+
suffix="GBP"
|
|
249
|
+
onChangeText={() => console.log('###')}
|
|
250
|
+
placeholder="0.00"
|
|
251
|
+
/>
|
|
252
|
+
</Center>
|
|
253
|
+
</UsageWrap>
|
|
254
|
+
|
|
255
|
+
```tsx
|
|
256
|
+
import { Input } from '@utilitywarehouse/hearth-react-native';
|
|
257
|
+
|
|
258
|
+
const MyComponent = () => {
|
|
259
|
+
const [value, setValue] = useState('');
|
|
260
|
+
const handleChange = text => {
|
|
261
|
+
setValue(text);
|
|
262
|
+
};
|
|
263
|
+
return (
|
|
264
|
+
<Input
|
|
265
|
+
label="Amount"
|
|
266
|
+
prefix="£"
|
|
267
|
+
suffix="GBP"
|
|
268
|
+
onChangeText={handleChange}
|
|
269
|
+
value={value}
|
|
270
|
+
placeholder="0.00"
|
|
271
|
+
/>
|
|
272
|
+
);
|
|
273
|
+
};
|
|
274
|
+
```
|
|
275
|
+
|
|
236
276
|
### With `FormField`
|
|
237
277
|
|
|
238
278
|
The `Input` component can be used with the `FormField` component to create a custom input field.
|
|
@@ -241,7 +281,7 @@ For more information on the `FormField` componment view the [docs here](/docs/co
|
|
|
241
281
|
<UsageWrap>
|
|
242
282
|
<Center>
|
|
243
283
|
<FormField label="Label" helperText="Helper text" helperPosition="bottom">
|
|
244
|
-
<Input
|
|
284
|
+
<Input onChangeText={() => console.log('###')} placeholder="Placeholder" />
|
|
245
285
|
</FormField>
|
|
246
286
|
</Center>
|
|
247
287
|
</UsageWrap>
|
|
@@ -251,12 +291,12 @@ import { FormField, Input } from '@utilitywarehouse/hearth-react-native';
|
|
|
251
291
|
|
|
252
292
|
const MyComponent = () => {
|
|
253
293
|
const [value, setValue] = useState('');
|
|
254
|
-
const handleChange =
|
|
255
|
-
setValue(
|
|
294
|
+
const handleChange = text => {
|
|
295
|
+
setValue(text);
|
|
256
296
|
};
|
|
257
297
|
return (
|
|
258
298
|
<FormField label="Label" helperText="Helper text" helperPosition="bottom">
|
|
259
|
-
<Input
|
|
299
|
+
<Input onChangeText={handleChange} value={value} placeholder="Placeholder" />
|
|
260
300
|
</FormField>
|
|
261
301
|
);
|
|
262
302
|
};
|
|
@@ -1,57 +1,123 @@
|
|
|
1
1
|
import figma from '@figma/code-connect';
|
|
2
|
-
import Input from '
|
|
2
|
+
import { Input } from '../';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
const props = {
|
|
5
|
+
disabled: figma.enum('State', {
|
|
6
|
+
Disabled: true,
|
|
7
|
+
}),
|
|
8
|
+
readonly: figma.enum('State', {
|
|
9
|
+
'Read-only': true,
|
|
10
|
+
}),
|
|
11
|
+
placeholder: figma.enum('Value type', {
|
|
12
|
+
Placeholder: figma.string('Value'),
|
|
13
|
+
}),
|
|
14
|
+
value: figma.enum('Value type', {
|
|
15
|
+
Filled: figma.string('Value'),
|
|
16
|
+
}),
|
|
17
|
+
label: figma.string('Label'),
|
|
18
|
+
labelVariant: figma.enum('Label variant', {
|
|
19
|
+
Body: 'body',
|
|
20
|
+
Heading: 'heading',
|
|
21
|
+
}),
|
|
22
|
+
helperText: figma.boolean('Helper text?', {
|
|
23
|
+
true: figma.string('Helper text'),
|
|
24
|
+
}),
|
|
25
|
+
validationStatus: figma.enum('State', {
|
|
26
|
+
Invalid: 'invalid',
|
|
27
|
+
Valid: 'valid',
|
|
28
|
+
}),
|
|
29
|
+
invalidText: figma.enum('State', {
|
|
30
|
+
Invalid: figma.string('Validation'),
|
|
31
|
+
}),
|
|
32
|
+
validText: figma.enum('State', {
|
|
33
|
+
Valid: figma.string('Validation'),
|
|
34
|
+
}),
|
|
35
|
+
};
|
|
10
36
|
|
|
11
37
|
figma.connect(Input, 'https://www.figma.com/design/6NKZXZhFSExXrcbBgc6zTR?node-id=2685%3A7021', {
|
|
12
38
|
props: {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
39
|
+
...props,
|
|
40
|
+
required: figma.boolean('Optional?', {
|
|
41
|
+
true: false,
|
|
42
|
+
false: true,
|
|
16
43
|
}),
|
|
17
|
-
|
|
18
|
-
'
|
|
44
|
+
prefix: figma.boolean('Prefix?', {
|
|
45
|
+
true: figma.string('Prefix'),
|
|
19
46
|
}),
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
focusable: figma.boolean('Focus?'),
|
|
23
|
-
hasTVPreferredFocus: figma.boolean('Focus?'),
|
|
24
|
-
'aria-disabled': figma.enum('State', {
|
|
25
|
-
Disabled: true,
|
|
47
|
+
suffix: figma.boolean('Suffix?', {
|
|
48
|
+
true: figma.string('Suffix'),
|
|
26
49
|
}),
|
|
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
50
|
},
|
|
48
51
|
example: props => (
|
|
49
52
|
<Input
|
|
50
53
|
disabled={props.disabled}
|
|
51
54
|
readonly={props.readonly}
|
|
52
|
-
focused={props.focused}
|
|
53
55
|
placeholder={props.placeholder}
|
|
54
|
-
|
|
56
|
+
value={props.value}
|
|
57
|
+
label={props.label}
|
|
58
|
+
labelVariant={props.labelVariant}
|
|
59
|
+
helperText={props.helperText}
|
|
60
|
+
required={props.required}
|
|
61
|
+
prefix={props.prefix}
|
|
62
|
+
suffix={props.suffix}
|
|
63
|
+
validationStatus={props.validationStatus}
|
|
64
|
+
invalidText={props.invalidText}
|
|
65
|
+
validText={props.validText}
|
|
55
66
|
/>
|
|
56
67
|
),
|
|
57
68
|
});
|
|
69
|
+
|
|
70
|
+
figma.connect(
|
|
71
|
+
Input,
|
|
72
|
+
'https://www.figma.com/design/6NKZXZhFSExXrcbBgc6zTR/Hearth-Components---Tokens?node-id=2251-10106&t=3uUSBVdxldgG5uz3-4',
|
|
73
|
+
{
|
|
74
|
+
props,
|
|
75
|
+
example: props => (
|
|
76
|
+
<Input
|
|
77
|
+
type="password"
|
|
78
|
+
disabled={props.disabled}
|
|
79
|
+
readonly={props.readonly}
|
|
80
|
+
placeholder={props.placeholder}
|
|
81
|
+
value={props.value}
|
|
82
|
+
label={props.label}
|
|
83
|
+
labelVariant={props.labelVariant}
|
|
84
|
+
helperText={props.helperText}
|
|
85
|
+
validationStatus={props.validationStatus}
|
|
86
|
+
invalidText={props.invalidText}
|
|
87
|
+
validText={props.validText}
|
|
88
|
+
/>
|
|
89
|
+
),
|
|
90
|
+
}
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
figma.connect(
|
|
94
|
+
Input,
|
|
95
|
+
'https://www.figma.com/design/6NKZXZhFSExXrcbBgc6zTR/Hearth-Components---Tokens?node-id=2161-1311&t=3uUSBVdxldgG5uz3-4',
|
|
96
|
+
{
|
|
97
|
+
props: {
|
|
98
|
+
loading: figma.enum('State', {
|
|
99
|
+
Loading: true,
|
|
100
|
+
}),
|
|
101
|
+
placeholder: figma.enum('State', {
|
|
102
|
+
Placeholder: figma.string('Value'),
|
|
103
|
+
}),
|
|
104
|
+
value: figma.enum('State', {
|
|
105
|
+
Filled: figma.string('Value'),
|
|
106
|
+
}),
|
|
107
|
+
label: figma.string('Label'),
|
|
108
|
+
helperText: figma.boolean('Helper text?', {
|
|
109
|
+
true: figma.string('Helper text'),
|
|
110
|
+
}),
|
|
111
|
+
},
|
|
112
|
+
example: props => (
|
|
113
|
+
<Input
|
|
114
|
+
type="search"
|
|
115
|
+
loading={props.loading}
|
|
116
|
+
placeholder={props.placeholder}
|
|
117
|
+
value={props.value}
|
|
118
|
+
label={props.label}
|
|
119
|
+
helperText={props.helperText}
|
|
120
|
+
/>
|
|
121
|
+
),
|
|
122
|
+
}
|
|
123
|
+
);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ComponentType } from 'react';
|
|
2
|
+
import React from 'react';
|
|
2
3
|
import type { TextInputProps, ViewProps } from 'react-native';
|
|
3
4
|
|
|
4
5
|
// Base props common to all input types
|
|
@@ -47,6 +48,8 @@ export interface InputWithChildrenProps extends InputBaseProps, ViewProps {
|
|
|
47
48
|
onClear?: never;
|
|
48
49
|
leadingIcon?: never;
|
|
49
50
|
trailingIcon?: never;
|
|
51
|
+
prefix?: never;
|
|
52
|
+
suffix?: never;
|
|
50
53
|
}
|
|
51
54
|
|
|
52
55
|
// Base for inputs without children
|
|
@@ -55,6 +58,8 @@ interface InputWithoutChildrenBaseProps extends InputBaseProps, Omit<TextInputPr
|
|
|
55
58
|
leadingIcon?: ComponentType;
|
|
56
59
|
trailingIcon?: ComponentType;
|
|
57
60
|
required?: boolean;
|
|
61
|
+
prefix?: string | number | React.ReactNode;
|
|
62
|
+
suffix?: string | number | React.ReactNode;
|
|
58
63
|
}
|
|
59
64
|
|
|
60
65
|
// Specific input types with their unique props
|
|
@@ -74,6 +79,8 @@ interface PasswordInputSpecificProps extends InputWithoutChildrenBaseProps {
|
|
|
74
79
|
loading?: never;
|
|
75
80
|
clearable?: never;
|
|
76
81
|
onClear?: never;
|
|
82
|
+
prefix?: never;
|
|
83
|
+
suffix?: never;
|
|
77
84
|
}
|
|
78
85
|
|
|
79
86
|
interface SearchInputSpecificProps extends InputWithoutChildrenBaseProps {
|
|
@@ -83,6 +90,8 @@ interface SearchInputSpecificProps extends InputWithoutChildrenBaseProps {
|
|
|
83
90
|
onClear?: () => void;
|
|
84
91
|
showPasswordToggle?: never;
|
|
85
92
|
format?: never;
|
|
93
|
+
prefix?: never;
|
|
94
|
+
suffix?: never;
|
|
86
95
|
}
|
|
87
96
|
|
|
88
97
|
// Union of all input types
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
SearchMediumIcon,
|
|
11
11
|
} from '@utilitywarehouse/hearth-react-native-icons';
|
|
12
12
|
import { useTheme } from '../../hooks';
|
|
13
|
+
import { BodyText } from '../BodyText';
|
|
13
14
|
import { FormField, useFormFieldContext } from '../FormField';
|
|
14
15
|
import { Spinner } from '../Spinner';
|
|
15
16
|
import { UnstyledIconButton } from '../UnstyledIconButton';
|
|
@@ -54,6 +55,8 @@ const Input = forwardRef<TextInput, InputProps>(
|
|
|
54
55
|
helperIcon,
|
|
55
56
|
validText,
|
|
56
57
|
invalidText,
|
|
58
|
+
prefix,
|
|
59
|
+
suffix,
|
|
57
60
|
...props
|
|
58
61
|
},
|
|
59
62
|
ref
|
|
@@ -169,6 +172,15 @@ const Input = forwardRef<TextInput, InputProps>(
|
|
|
169
172
|
<InputIcon as={leadingIconComponent} />
|
|
170
173
|
</InputSlot>
|
|
171
174
|
)}
|
|
175
|
+
{!!prefix && (
|
|
176
|
+
<InputSlot>
|
|
177
|
+
{typeof prefix === 'string' || typeof prefix === 'number' ? (
|
|
178
|
+
<BodyText>{prefix}</BodyText>
|
|
179
|
+
) : (
|
|
180
|
+
prefix
|
|
181
|
+
)}
|
|
182
|
+
</InputSlot>
|
|
183
|
+
)}
|
|
172
184
|
<InputField
|
|
173
185
|
// @ts-expect-error - ref forwarding issue
|
|
174
186
|
ref={inputRef}
|
|
@@ -197,6 +209,15 @@ const Input = forwardRef<TextInput, InputProps>(
|
|
|
197
209
|
/>
|
|
198
210
|
</InputSlot>
|
|
199
211
|
)}
|
|
212
|
+
{!!suffix && (
|
|
213
|
+
<InputSlot>
|
|
214
|
+
{typeof suffix === 'string' || typeof suffix === 'number' ? (
|
|
215
|
+
<BodyText>{suffix}</BodyText>
|
|
216
|
+
) : (
|
|
217
|
+
suffix
|
|
218
|
+
)}
|
|
219
|
+
</InputSlot>
|
|
220
|
+
)}
|
|
200
221
|
{!!trailingIcon && (
|
|
201
222
|
<InputSlot>
|
|
202
223
|
<InputIcon as={trailingIcon} />
|
|
@@ -1,42 +1,35 @@
|
|
|
1
|
-
import
|
|
2
|
-
import Link from
|
|
3
|
-
import figma from "@figma/code-connect"
|
|
1
|
+
import figma from '@figma/code-connect';
|
|
2
|
+
import { Link } from '../';
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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,
|
|
4
|
+
figma.connect(Link, 'https://www.figma.com/design/6NKZXZhFSExXrcbBgc6zTR?node-id=163%3A562', {
|
|
5
|
+
props: {
|
|
6
|
+
inverted: figma.boolean('Inverted?'),
|
|
7
|
+
showIcon: figma.boolean('Icon right?', {
|
|
8
|
+
false: figma.boolean('Icon left?', {
|
|
9
|
+
false: false,
|
|
10
|
+
}),
|
|
11
|
+
}),
|
|
12
|
+
iconPosition: figma.boolean('Icon right?', {
|
|
13
|
+
false: figma.boolean('Icon left?', {
|
|
14
|
+
true: 'left',
|
|
21
15
|
}),
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
16
|
+
}),
|
|
17
|
+
text: figma.string('Text'),
|
|
18
|
+
icon: figma.boolean('Icon right?', {
|
|
19
|
+
true: figma.instance('Icon right-20'),
|
|
20
|
+
false: figma.boolean('Icon left?', {
|
|
21
|
+
true: figma.instance('Icon left-20'),
|
|
25
22
|
}),
|
|
26
|
-
|
|
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
|
-
),
|
|
23
|
+
}),
|
|
41
24
|
},
|
|
42
|
-
|
|
25
|
+
example: props => (
|
|
26
|
+
<Link
|
|
27
|
+
icon={props.icon}
|
|
28
|
+
showIcon={props.showIcon}
|
|
29
|
+
iconPosition={props.iconPosition}
|
|
30
|
+
inverted={props.inverted}
|
|
31
|
+
>
|
|
32
|
+
{props.text}
|
|
33
|
+
</Link>
|
|
34
|
+
),
|
|
35
|
+
});
|
|
@@ -5,6 +5,8 @@ export const ListContext = createContext<{
|
|
|
5
5
|
loading?: ListProps['loading'];
|
|
6
6
|
disabled?: ListProps['disabled'];
|
|
7
7
|
container?: ListProps['container'];
|
|
8
|
+
firstItemId?: string;
|
|
9
|
+
registerItem?: (id: string) => () => void;
|
|
8
10
|
}>({});
|
|
9
11
|
|
|
10
12
|
export const useListContext = () => {
|
|
@@ -12,7 +14,3 @@ export const useListContext = () => {
|
|
|
12
14
|
|
|
13
15
|
return context;
|
|
14
16
|
};
|
|
15
|
-
|
|
16
|
-
export const ListFirstItemContext = createContext<boolean>(false);
|
|
17
|
-
|
|
18
|
-
export const useListFirstItemContext = () => useContext(ListFirstItemContext);
|
|
@@ -100,6 +100,7 @@ const MyComponent = () => (
|
|
|
100
100
|
| heading | `string` | | The text to display in the heading of the list. |
|
|
101
101
|
| helperText | `string` | | The supporting text to display in the heading of the list. |
|
|
102
102
|
| headerTrailingContent | `ReactNode` | | Optional content to display on the right side of the header. |
|
|
103
|
+
| invalidText | `string` | | Validation error text to display in the heading of the list. |
|
|
103
104
|
| loading | `boolean` | `false` | Whether to show the list items in loading state. |
|
|
104
105
|
| disabled | `boolean` | `false` | Whether to disable the list. |
|
|
105
106
|
|
|
@@ -121,13 +122,17 @@ const MyComponent = () => (
|
|
|
121
122
|
| truncateHeading | `boolean` | `false` | Whether to truncate the heading text if it overflows. |
|
|
122
123
|
| truncateHelperText | `boolean` | `false` | Whether to truncate the helper text if it overflows. |
|
|
123
124
|
|
|
125
|
+
First-item styling is applied to the first rendered `ListItem` or `ListAction`. Wrapper components that render `null`
|
|
126
|
+
are ignored, so conditional list items will not affect which item loses the top border.
|
|
127
|
+
|
|
124
128
|
### `ListAction`
|
|
125
129
|
|
|
126
|
-
| Name | Type | Default | Description
|
|
127
|
-
| -------- | ------------ | ------- |
|
|
128
|
-
| heading | `string` | | The text to display in the list action item.
|
|
129
|
-
| onPress | `() => void` | | A callback function to be called
|
|
130
|
-
| disabled | `boolean` | `false` | Whether to disable the list action item.
|
|
130
|
+
| Name | Type | Default | Description |
|
|
131
|
+
| -------- | ------------ | ------- | ---------------------------------------------------------------------- |
|
|
132
|
+
| heading | `string` | | The text to display in the list action item. |
|
|
133
|
+
| onPress | `() => void` | | A callback function to be called when the list action item is pressed. |
|
|
134
|
+
| disabled | `boolean` | `false` | Whether to disable the list action item. |
|
|
135
|
+
| loading | `boolean` | `false` | Whether to show the list action in loading state. |
|
|
131
136
|
|
|
132
137
|
#### - `ListItemLeadingContent`
|
|
133
138
|
|