@hero-design/rn 8.56.1 → 8.57.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +1 -1
- package/CHANGELOG.md +31 -0
- package/assets/fonts/hero-icons-mobile.ttf +0 -0
- package/es/index.js +5240 -4333
- package/lib/assets/fonts/hero-icons-mobile.ttf +0 -0
- package/lib/index.js +5239 -4332
- package/package.json +7 -6
- package/src/components/Button/StyledButton.tsx +16 -30
- package/src/components/Calendar/__tests__/index.spec.tsx +5 -5
- package/src/components/Carousel/CardCarousel.tsx +7 -10
- package/src/components/Carousel/__tests__/index.spec.tsx +14 -0
- package/src/components/DatePicker/__tests__/DatePickerCalendar.spec.tsx +32 -29
- package/src/components/Empty/__tests__/__snapshots__/index.spec.tsx.snap +2 -2
- package/src/components/Error/__tests__/__snapshots__/index.spec.tsx.snap +4 -4
- package/src/components/Icon/HeroIcon/glyphMap.json +1 -1
- package/src/components/Icon/IconList.ts +4 -0
- package/src/components/PinInput/index.tsx +1 -1
- package/src/components/Tabs/SceneView.tsx +6 -4
- package/src/components/Tabs/ScrollableTabs.tsx +8 -2
- package/src/components/Tabs/{ScrollableTabsHeader.tsx → ScrollableTabsHeader/ScrollableTabsHeader.tsx} +73 -42
- package/src/components/Tabs/ScrollableTabsHeader/hooks/useInitHighlightedAnimation.ts +45 -0
- package/src/components/Tabs/ScrollableTabsHeader/hooks/useInitUnderlinedAnimation.ts +91 -0
- package/src/components/Tabs/StyledScrollableTabs.tsx +14 -3
- package/src/components/Tabs/__tests__/ScrollableTabsHeader.spec.tsx +7 -3
- package/src/components/Tabs/__tests__/__snapshots__/ScrollableTabs.spec.tsx.snap +42 -6
- package/src/components/Tabs/__tests__/__snapshots__/ScrollableTabsHeader.spec.tsx.snap +623 -3
- package/src/components/Tabs/__tests__/useInitHighlightedAnimation.spec.tsx +56 -0
- package/src/components/Tabs/__tests__/useInitUnderlinedAnimation.spec.tsx +65 -0
- package/src/components/TextInput/__tests__/index.spec.tsx +148 -1
- package/src/components/TextInput/index.tsx +135 -57
- package/src/components/Toast/ToastContext.ts +20 -2
- package/src/components/Toast/ToastProvider.tsx +7 -4
- package/src/components/Typography/Body/__tests__/__snapshots__/StyledBody.tsx.snap +2 -2
- package/src/components/Typography/Body/__tests__/__snapshots__/index.spec.tsx.snap +2 -2
- package/src/theme/__tests__/__snapshots__/index.spec.ts.snap +1 -1
- package/src/theme/components/typography.ts +1 -1
- package/types/components/Carousel/CardCarousel.d.ts +1 -0
- package/types/components/Icon/IconList.d.ts +1 -1
- package/types/components/Icon/index.d.ts +1 -1
- package/types/components/Icon/utils.d.ts +1 -1
- package/types/components/Tabs/ScrollableTabs.d.ts +4 -1
- package/types/components/Tabs/{ScrollableTabsHeader.d.ts → ScrollableTabsHeader/ScrollableTabsHeader.d.ts} +7 -3
- package/types/components/Tabs/ScrollableTabsHeader/hooks/useInitHighlightedAnimation.d.ts +9 -0
- package/types/components/Tabs/ScrollableTabsHeader/hooks/useInitUnderlinedAnimation.d.ts +10 -0
- package/types/components/Tabs/StyledScrollableTabs.d.ts +5 -1
- package/types/components/Tabs/index.d.ts +1 -1
- package/types/components/TextInput/index.d.ts +29 -1
- package/types/components/Toast/ToastContext.d.ts +1 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/* eslint-disable no-underscore-dangle */
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import Typography from '../../Typography';
|
|
4
|
+
import useInitHighlightedAnimation from '../ScrollableTabsHeader/hooks/useInitHighlightedAnimation';
|
|
5
|
+
import renderWithTheme from '../../../testHelpers/renderWithTheme';
|
|
6
|
+
import { theme } from '../../..';
|
|
7
|
+
import HeroDesignProvider from '../../HeroDesignProvider';
|
|
8
|
+
|
|
9
|
+
const TestComponent = ({
|
|
10
|
+
tabsLength,
|
|
11
|
+
variant,
|
|
12
|
+
selectedIndex,
|
|
13
|
+
}: {
|
|
14
|
+
tabsLength: number;
|
|
15
|
+
variant: 'highlighted' | 'underlined';
|
|
16
|
+
selectedIndex?: number;
|
|
17
|
+
}) => {
|
|
18
|
+
const { tabsAnims } = useInitHighlightedAnimation({
|
|
19
|
+
tabsLength,
|
|
20
|
+
variant,
|
|
21
|
+
selectedIndex,
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<Typography.Body>
|
|
26
|
+
{/* @ts-expect-error: _value is private */}
|
|
27
|
+
{tabsAnims.map((item) => item._value).toString()}
|
|
28
|
+
</Typography.Body>
|
|
29
|
+
);
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
describe('useCounter', () => {
|
|
33
|
+
test('should return correct anims array', () => {
|
|
34
|
+
const { getByText } = renderWithTheme(
|
|
35
|
+
<TestComponent tabsLength={3} variant="highlighted" selectedIndex={2} />
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
expect(getByText('0,0,1')).toBeDefined();
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test('should not update anims array values if variant is not highlighted', () => {
|
|
42
|
+
const { getByText, rerender } = renderWithTheme(
|
|
43
|
+
<TestComponent tabsLength={3} variant="underlined" selectedIndex={2} />
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
expect(getByText('0,0,1')).toBeDefined();
|
|
47
|
+
|
|
48
|
+
rerender(
|
|
49
|
+
<HeroDesignProvider theme={theme}>
|
|
50
|
+
<TestComponent tabsLength={3} variant="underlined" selectedIndex={0} />
|
|
51
|
+
</HeroDesignProvider>
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
expect(getByText('0,0,1')).toBeDefined();
|
|
55
|
+
});
|
|
56
|
+
});
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/* eslint-disable no-underscore-dangle */
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import renderWithTheme from '../../../testHelpers/renderWithTheme';
|
|
4
|
+
import Typography from '../../Typography';
|
|
5
|
+
import useInitUnderlinedAnimation from '../ScrollableTabsHeader/hooks/useInitUnderlinedAnimation';
|
|
6
|
+
import HeroDesignProvider from '../../HeroDesignProvider';
|
|
7
|
+
import { theme } from '../../..';
|
|
8
|
+
|
|
9
|
+
const TestComponent = ({
|
|
10
|
+
tabsLength,
|
|
11
|
+
variant,
|
|
12
|
+
selectedIndex = 0,
|
|
13
|
+
}: {
|
|
14
|
+
tabsLength: number;
|
|
15
|
+
variant: 'highlighted' | 'underlined';
|
|
16
|
+
selectedIndex?: number;
|
|
17
|
+
}) => {
|
|
18
|
+
const { underlinedTranslateX, underlinedOpacity } =
|
|
19
|
+
useInitUnderlinedAnimation({
|
|
20
|
+
tabsLength,
|
|
21
|
+
variant,
|
|
22
|
+
selectedIndex,
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
return (
|
|
26
|
+
<>
|
|
27
|
+
<Typography.Body>
|
|
28
|
+
{/* @ts-expect-error: _value is private */}
|
|
29
|
+
{underlinedTranslateX.map((item) => item._parent._value).toString()}
|
|
30
|
+
</Typography.Body>
|
|
31
|
+
|
|
32
|
+
<Typography.Body>
|
|
33
|
+
{/* @ts-expect-error: _value is private */}
|
|
34
|
+
{underlinedOpacity.map((item) => item._parent._value).toString()}
|
|
35
|
+
</Typography.Body>
|
|
36
|
+
</>
|
|
37
|
+
);
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
describe('useCounter', () => {
|
|
41
|
+
test('should return correct anims arrays', () => {
|
|
42
|
+
const { getByText } = renderWithTheme(
|
|
43
|
+
<TestComponent tabsLength={3} variant="underlined" selectedIndex={1} />
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
expect(getByText('0,1,0')).toBeDefined();
|
|
47
|
+
expect(getByText('0,1,0')).toBeDefined();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
test('should not update translatX anims array values if variant is not underlined', () => {
|
|
51
|
+
const { getByText, rerender } = renderWithTheme(
|
|
52
|
+
<TestComponent tabsLength={3} variant="highlighted" selectedIndex={1} />
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
expect(getByText('0,0,0')).toBeDefined();
|
|
56
|
+
|
|
57
|
+
rerender(
|
|
58
|
+
<HeroDesignProvider theme={theme}>
|
|
59
|
+
<TestComponent tabsLength={3} variant="highlighted" selectedIndex={2} />
|
|
60
|
+
</HeroDesignProvider>
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
expect(getByText('0,0,0')).toBeDefined();
|
|
64
|
+
});
|
|
65
|
+
});
|
|
@@ -4,7 +4,15 @@ import { TextInput as RNTextInput } from 'react-native';
|
|
|
4
4
|
import { theme } from '../../..';
|
|
5
5
|
import renderWithTheme from '../../../testHelpers/renderWithTheme';
|
|
6
6
|
import Icon from '../../Icon';
|
|
7
|
-
import TextInput, {
|
|
7
|
+
import TextInput, {
|
|
8
|
+
getState,
|
|
9
|
+
renderErrorOrHelpText,
|
|
10
|
+
renderInput,
|
|
11
|
+
renderMaxLengthMessage,
|
|
12
|
+
renderPrefix,
|
|
13
|
+
renderSuffix,
|
|
14
|
+
TextInputHandles,
|
|
15
|
+
} from '../index';
|
|
8
16
|
|
|
9
17
|
describe('getState', () => {
|
|
10
18
|
it.each`
|
|
@@ -496,3 +504,142 @@ describe('TextInput', () => {
|
|
|
496
504
|
});
|
|
497
505
|
});
|
|
498
506
|
});
|
|
507
|
+
|
|
508
|
+
describe('renderErrorOrHelpText', () => {
|
|
509
|
+
it('renders correctly with error', () => {
|
|
510
|
+
const { queryAllByText } = renderWithTheme(
|
|
511
|
+
<>
|
|
512
|
+
{renderErrorOrHelpText({
|
|
513
|
+
error: 'This is error',
|
|
514
|
+
helpText: 'This is help text',
|
|
515
|
+
})}
|
|
516
|
+
</>
|
|
517
|
+
);
|
|
518
|
+
|
|
519
|
+
expect(queryAllByText('This is error')).toHaveLength(1);
|
|
520
|
+
expect(queryAllByText('This is help text')).toHaveLength(0);
|
|
521
|
+
});
|
|
522
|
+
|
|
523
|
+
it('renders correctly with help text', () => {
|
|
524
|
+
const { queryAllByText } = renderWithTheme(
|
|
525
|
+
<>
|
|
526
|
+
{renderErrorOrHelpText({
|
|
527
|
+
error: '',
|
|
528
|
+
helpText: 'This is help text',
|
|
529
|
+
})}
|
|
530
|
+
</>
|
|
531
|
+
);
|
|
532
|
+
|
|
533
|
+
expect(queryAllByText('This is help text')).toHaveLength(1);
|
|
534
|
+
});
|
|
535
|
+
});
|
|
536
|
+
|
|
537
|
+
describe('renderInput', () => {
|
|
538
|
+
it('renders correctly with renderInputValue', () => {
|
|
539
|
+
const wrapper = renderWithTheme(
|
|
540
|
+
<>
|
|
541
|
+
{renderInput({
|
|
542
|
+
variant: 'textarea',
|
|
543
|
+
nativeInputProps: {},
|
|
544
|
+
renderInputValue: (props) => {
|
|
545
|
+
return (
|
|
546
|
+
<RNTextInput
|
|
547
|
+
{...props}
|
|
548
|
+
value="customised text"
|
|
549
|
+
testID="custom-text-input"
|
|
550
|
+
/>
|
|
551
|
+
);
|
|
552
|
+
},
|
|
553
|
+
})}
|
|
554
|
+
</>
|
|
555
|
+
);
|
|
556
|
+
|
|
557
|
+
expect(wrapper.queryAllByTestId('custom-text-input')).toHaveLength(1);
|
|
558
|
+
expect(wrapper.queryAllByDisplayValue('customised text')).toHaveLength(1);
|
|
559
|
+
});
|
|
560
|
+
|
|
561
|
+
it('renders correctly without renderInputValue', () => {
|
|
562
|
+
const wrapper = renderWithTheme(
|
|
563
|
+
<>
|
|
564
|
+
{renderInput({
|
|
565
|
+
variant: 'textarea',
|
|
566
|
+
nativeInputProps: {
|
|
567
|
+
testID: 'text-input',
|
|
568
|
+
value: 'text input value',
|
|
569
|
+
},
|
|
570
|
+
})}
|
|
571
|
+
</>
|
|
572
|
+
);
|
|
573
|
+
|
|
574
|
+
expect(wrapper.queryAllByTestId('text-input')).toHaveLength(1);
|
|
575
|
+
expect(wrapper.queryAllByDisplayValue('text input value')).toHaveLength(1);
|
|
576
|
+
});
|
|
577
|
+
});
|
|
578
|
+
describe('renderSuffix', () => {
|
|
579
|
+
it('renders loading icon with loading', () => {
|
|
580
|
+
const wrapper = renderWithTheme(
|
|
581
|
+
<>
|
|
582
|
+
{renderSuffix({
|
|
583
|
+
loading: true,
|
|
584
|
+
suffix: 'dollar-sign',
|
|
585
|
+
state: 'default',
|
|
586
|
+
})}
|
|
587
|
+
</>
|
|
588
|
+
);
|
|
589
|
+
|
|
590
|
+
expect(wrapper.getByTestId('input-suffix')).toHaveProp('name', 'loading');
|
|
591
|
+
});
|
|
592
|
+
|
|
593
|
+
it('renders suffix icon', () => {
|
|
594
|
+
const wrapper = renderWithTheme(
|
|
595
|
+
<>
|
|
596
|
+
{renderSuffix({
|
|
597
|
+
loading: false,
|
|
598
|
+
suffix: 'dollar-sign',
|
|
599
|
+
state: 'default',
|
|
600
|
+
})}
|
|
601
|
+
</>
|
|
602
|
+
);
|
|
603
|
+
|
|
604
|
+
// verify element has prop name = icon
|
|
605
|
+
expect(wrapper.getByTestId('input-suffix')).toHaveProp(
|
|
606
|
+
'name',
|
|
607
|
+
'dollar-sign'
|
|
608
|
+
);
|
|
609
|
+
});
|
|
610
|
+
});
|
|
611
|
+
|
|
612
|
+
describe('renderPrefix', () => {
|
|
613
|
+
it('renders prefix icon', () => {
|
|
614
|
+
const wrapper = renderWithTheme(
|
|
615
|
+
<>
|
|
616
|
+
{renderPrefix({
|
|
617
|
+
prefix: 'dollar-sign',
|
|
618
|
+
state: 'default',
|
|
619
|
+
})}
|
|
620
|
+
</>
|
|
621
|
+
);
|
|
622
|
+
|
|
623
|
+
expect(wrapper.getByTestId('input-prefix')).toHaveProp(
|
|
624
|
+
'name',
|
|
625
|
+
'dollar-sign'
|
|
626
|
+
);
|
|
627
|
+
});
|
|
628
|
+
});
|
|
629
|
+
|
|
630
|
+
describe('renderMaxLengthMessage', () => {
|
|
631
|
+
it('renders correctly with maxLength', () => {
|
|
632
|
+
const { queryAllByText } = renderWithTheme(
|
|
633
|
+
<>
|
|
634
|
+
{renderMaxLengthMessage({
|
|
635
|
+
maxLength: 10,
|
|
636
|
+
state: 'default',
|
|
637
|
+
currentLength: 5,
|
|
638
|
+
hideCharacterCount: false,
|
|
639
|
+
})}
|
|
640
|
+
</>
|
|
641
|
+
);
|
|
642
|
+
|
|
643
|
+
expect(queryAllByText('5/10')).toHaveLength(1);
|
|
644
|
+
});
|
|
645
|
+
});
|
|
@@ -46,6 +46,8 @@ export type TextInputHandles = Pick<
|
|
|
46
46
|
'focus' | 'clear' | 'blur' | 'isFocused' | 'setNativeProps'
|
|
47
47
|
>;
|
|
48
48
|
|
|
49
|
+
export type TextInputVariant = 'text' | 'textarea';
|
|
50
|
+
|
|
49
51
|
export interface TextInputProps extends NativeTextInputProps {
|
|
50
52
|
/**
|
|
51
53
|
* Field label.
|
|
@@ -123,7 +125,7 @@ export interface TextInputProps extends NativeTextInputProps {
|
|
|
123
125
|
/**
|
|
124
126
|
* Component variant.
|
|
125
127
|
*/
|
|
126
|
-
variant?:
|
|
128
|
+
variant?: TextInputVariant;
|
|
127
129
|
}
|
|
128
130
|
|
|
129
131
|
export const getState = ({
|
|
@@ -161,6 +163,120 @@ const EMPTY_PLACEHOLDER_VALUE = ' ';
|
|
|
161
163
|
|
|
162
164
|
export const LABEL_ANIMATION_DURATION = 150;
|
|
163
165
|
|
|
166
|
+
export const renderErrorOrHelpText = ({
|
|
167
|
+
error,
|
|
168
|
+
helpText,
|
|
169
|
+
}: {
|
|
170
|
+
error?: string;
|
|
171
|
+
helpText?: string;
|
|
172
|
+
}) => {
|
|
173
|
+
return error ? (
|
|
174
|
+
<StyledErrorContainer>
|
|
175
|
+
<Icon
|
|
176
|
+
testID="input-error-icon"
|
|
177
|
+
icon="circle-info"
|
|
178
|
+
size="xsmall"
|
|
179
|
+
intent="danger"
|
|
180
|
+
/>
|
|
181
|
+
|
|
182
|
+
<StyledError testID="input-error-message">{error}</StyledError>
|
|
183
|
+
</StyledErrorContainer>
|
|
184
|
+
) : (
|
|
185
|
+
!!helpText && <StyledHelperText>{helpText}</StyledHelperText>
|
|
186
|
+
);
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
export const renderInput = ({
|
|
190
|
+
variant,
|
|
191
|
+
nativeInputProps,
|
|
192
|
+
renderInputValue,
|
|
193
|
+
ref,
|
|
194
|
+
}: {
|
|
195
|
+
variant: TextInputVariant;
|
|
196
|
+
nativeInputProps: NativeTextInputProps;
|
|
197
|
+
multiline?: boolean;
|
|
198
|
+
renderInputValue?: (inputProps: NativeTextInputProps) => React.ReactNode;
|
|
199
|
+
ref?: React.Ref<RNTextInput>;
|
|
200
|
+
}) => {
|
|
201
|
+
return renderInputValue ? (
|
|
202
|
+
renderInputValue(nativeInputProps)
|
|
203
|
+
) : (
|
|
204
|
+
<StyledTextInput
|
|
205
|
+
{...nativeInputProps}
|
|
206
|
+
themeVariant={variant}
|
|
207
|
+
multiline={variant === 'textarea' || nativeInputProps.multiline}
|
|
208
|
+
ref={ref}
|
|
209
|
+
/>
|
|
210
|
+
);
|
|
211
|
+
};
|
|
212
|
+
|
|
213
|
+
export const renderSuffix = ({
|
|
214
|
+
state,
|
|
215
|
+
loading,
|
|
216
|
+
suffix,
|
|
217
|
+
}: {
|
|
218
|
+
state: State;
|
|
219
|
+
loading: boolean;
|
|
220
|
+
suffix?: IconName | React.ReactElement;
|
|
221
|
+
}) => {
|
|
222
|
+
const actualSuffix = loading ? 'loading' : suffix;
|
|
223
|
+
return typeof actualSuffix === 'string' ? (
|
|
224
|
+
<Icon
|
|
225
|
+
intent={state === 'disabled' ? 'disabled-text' : 'text'}
|
|
226
|
+
testID="input-suffix"
|
|
227
|
+
icon={actualSuffix}
|
|
228
|
+
spin={actualSuffix === 'loading'}
|
|
229
|
+
size="medium"
|
|
230
|
+
/>
|
|
231
|
+
) : (
|
|
232
|
+
suffix
|
|
233
|
+
);
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
export const renderPrefix = ({
|
|
237
|
+
state,
|
|
238
|
+
prefix,
|
|
239
|
+
}: {
|
|
240
|
+
state: State;
|
|
241
|
+
prefix?: IconName | React.ReactElement;
|
|
242
|
+
}) => {
|
|
243
|
+
return typeof prefix === 'string' ? (
|
|
244
|
+
<Icon
|
|
245
|
+
intent={state === 'disabled' ? 'disabled-text' : 'text'}
|
|
246
|
+
testID="input-prefix"
|
|
247
|
+
icon={prefix}
|
|
248
|
+
size="xsmall"
|
|
249
|
+
/>
|
|
250
|
+
) : (
|
|
251
|
+
prefix
|
|
252
|
+
);
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
export const renderMaxLengthMessage = ({
|
|
256
|
+
maxLength,
|
|
257
|
+
state,
|
|
258
|
+
currentLength,
|
|
259
|
+
hideCharacterCount,
|
|
260
|
+
}: {
|
|
261
|
+
state: State;
|
|
262
|
+
currentLength: number;
|
|
263
|
+
maxLength?: number;
|
|
264
|
+
hideCharacterCount: boolean;
|
|
265
|
+
}) => {
|
|
266
|
+
const shouldShowMaxLength = maxLength !== undefined && !hideCharacterCount;
|
|
267
|
+
return (
|
|
268
|
+
shouldShowMaxLength && (
|
|
269
|
+
<StyledMaxLengthMessage themeState={state}>
|
|
270
|
+
{currentLength}/{maxLength}
|
|
271
|
+
</StyledMaxLengthMessage>
|
|
272
|
+
)
|
|
273
|
+
);
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
export const getDisplayText = (value?: string, defaultValue?: string) => {
|
|
277
|
+
return (value !== undefined ? value : defaultValue) ?? '';
|
|
278
|
+
};
|
|
279
|
+
|
|
164
280
|
const TextInput = forwardRef<TextInputHandles, TextInputProps>(
|
|
165
281
|
(
|
|
166
282
|
{
|
|
@@ -188,9 +304,8 @@ const TextInput = forwardRef<TextInputHandles, TextInputProps>(
|
|
|
188
304
|
}: TextInputProps,
|
|
189
305
|
ref?: React.Ref<TextInputHandles>
|
|
190
306
|
) => {
|
|
191
|
-
const displayText = (value
|
|
307
|
+
const displayText = getDisplayText(value, defaultValue);
|
|
192
308
|
const isEmptyValue = displayText.length === 0;
|
|
193
|
-
const actualSuffix = loading ? 'loading' : suffix;
|
|
194
309
|
|
|
195
310
|
const [inputSize, setInputSize] = React.useState<{
|
|
196
311
|
height: number;
|
|
@@ -210,8 +325,6 @@ const TextInput = forwardRef<TextInputHandles, TextInputProps>(
|
|
|
210
325
|
isEmptyValue,
|
|
211
326
|
});
|
|
212
327
|
|
|
213
|
-
const shouldShowMaxLength = maxLength !== undefined && !hideCharacterCount;
|
|
214
|
-
|
|
215
328
|
const theme = useTheme();
|
|
216
329
|
|
|
217
330
|
const focusAnimation = useRef(new Animated.Value(0)).current;
|
|
@@ -346,16 +459,7 @@ const TextInput = forwardRef<TextInputHandles, TextInputProps>(
|
|
|
346
459
|
/>
|
|
347
460
|
|
|
348
461
|
<View onLayout={onPrefixLayout}>
|
|
349
|
-
{
|
|
350
|
-
<Icon
|
|
351
|
-
intent={state === 'disabled' ? 'disabled-text' : 'text'}
|
|
352
|
-
testID="input-prefix"
|
|
353
|
-
icon={prefix}
|
|
354
|
-
size="xsmall"
|
|
355
|
-
/>
|
|
356
|
-
) : (
|
|
357
|
-
prefix
|
|
358
|
-
)}
|
|
462
|
+
{renderPrefix({ state, prefix })}
|
|
359
463
|
</View>
|
|
360
464
|
<StyledLabelContainerInsideTextInput
|
|
361
465
|
themeVariant={variant}
|
|
@@ -424,52 +528,26 @@ const TextInput = forwardRef<TextInputHandles, TextInputProps>(
|
|
|
424
528
|
</StyledLabelContainerInsideTextInput>
|
|
425
529
|
|
|
426
530
|
<StyledTextInputAndLabelContainer>
|
|
427
|
-
{
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
innerTextInput.current = reference;
|
|
436
|
-
}}
|
|
437
|
-
/>
|
|
438
|
-
)}
|
|
531
|
+
{renderInput({
|
|
532
|
+
variant,
|
|
533
|
+
nativeInputProps,
|
|
534
|
+
renderInputValue,
|
|
535
|
+
ref: (rnTextInputRef) => {
|
|
536
|
+
innerTextInput.current = rnTextInputRef;
|
|
537
|
+
},
|
|
538
|
+
})}
|
|
439
539
|
</StyledTextInputAndLabelContainer>
|
|
440
|
-
{
|
|
441
|
-
<Icon
|
|
442
|
-
intent={state === 'disabled' ? 'disabled-text' : 'text'}
|
|
443
|
-
testID="input-suffix"
|
|
444
|
-
icon={actualSuffix}
|
|
445
|
-
spin={actualSuffix === 'loading'}
|
|
446
|
-
size="medium"
|
|
447
|
-
/>
|
|
448
|
-
) : (
|
|
449
|
-
suffix
|
|
450
|
-
)}
|
|
540
|
+
{renderSuffix({ state, loading, suffix })}
|
|
451
541
|
</StyledTextInputContainer>
|
|
452
542
|
<StyledErrorAndHelpTextContainer>
|
|
453
543
|
<StyledErrorAndMaxLengthContainer>
|
|
454
|
-
{error
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
/>
|
|
462
|
-
|
|
463
|
-
<StyledError testID="input-error-message">{error}</StyledError>
|
|
464
|
-
</StyledErrorContainer>
|
|
465
|
-
) : (
|
|
466
|
-
!!helpText && <StyledHelperText>{helpText}</StyledHelperText>
|
|
467
|
-
)}
|
|
468
|
-
{shouldShowMaxLength && (
|
|
469
|
-
<StyledMaxLengthMessage themeState={state}>
|
|
470
|
-
{displayText.length}/{maxLength}
|
|
471
|
-
</StyledMaxLengthMessage>
|
|
472
|
-
)}
|
|
544
|
+
{renderErrorOrHelpText({ error, helpText })}
|
|
545
|
+
{renderMaxLengthMessage({
|
|
546
|
+
state,
|
|
547
|
+
currentLength: displayText.length,
|
|
548
|
+
maxLength,
|
|
549
|
+
hideCharacterCount,
|
|
550
|
+
})}
|
|
473
551
|
</StyledErrorAndMaxLengthContainer>
|
|
474
552
|
</StyledErrorAndHelpTextContainer>
|
|
475
553
|
</StyledContainer>
|
|
@@ -7,8 +7,18 @@ export type ToastControllerContextType = {
|
|
|
7
7
|
clearAll: () => void;
|
|
8
8
|
};
|
|
9
9
|
|
|
10
|
+
export const fallbackToastControlContext: ToastControllerContextType = {
|
|
11
|
+
show: (_: Omit<ToastProps, 'position'>) => '',
|
|
12
|
+
hide: (_: string) => {
|
|
13
|
+
// Fallback empty function
|
|
14
|
+
},
|
|
15
|
+
clearAll: () => {
|
|
16
|
+
// Fallback empty function
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
|
|
10
20
|
export const ToastContext = createContext<ToastControllerContextType>(
|
|
11
|
-
|
|
21
|
+
fallbackToastControlContext
|
|
12
22
|
);
|
|
13
23
|
|
|
14
24
|
export type ToastConfigContextType = Pick<
|
|
@@ -22,4 +32,12 @@ export const ToastConfigContext = createContext<ToastConfigContextType>(
|
|
|
22
32
|
|
|
23
33
|
export const useToastConfig = () => useContext(ToastConfigContext);
|
|
24
34
|
|
|
25
|
-
export const useToast = () =>
|
|
35
|
+
export const useToast = () => {
|
|
36
|
+
const context = useContext<ToastControllerContextType>(ToastContext);
|
|
37
|
+
if (!context) {
|
|
38
|
+
// eslint-disable-next-line no-console
|
|
39
|
+
console.warn('Toast was used without ToastProvider');
|
|
40
|
+
return fallbackToastControlContext;
|
|
41
|
+
}
|
|
42
|
+
return context;
|
|
43
|
+
};
|
|
@@ -3,7 +3,11 @@ import { View } from 'react-native';
|
|
|
3
3
|
|
|
4
4
|
import type { ReactNode } from 'react';
|
|
5
5
|
import ToastContainer from './ToastContainer';
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
ToastConfigContext,
|
|
8
|
+
ToastContext,
|
|
9
|
+
fallbackToastControlContext,
|
|
10
|
+
} from './ToastContext';
|
|
7
11
|
import type { ToastControllerContextType } from './ToastContext';
|
|
8
12
|
import type { ToastContainerProps } from './types';
|
|
9
13
|
import { useDeprecation } from '../../utils/hooks';
|
|
@@ -29,8 +33,7 @@ const ToastProvider = ({
|
|
|
29
33
|
);
|
|
30
34
|
|
|
31
35
|
const toastRef = useRef<ToastControllerContextType>(null);
|
|
32
|
-
|
|
33
|
-
const [refState, setRefState] = useState<ToastControllerContextType>(null);
|
|
36
|
+
const [refState, setRefState] = useState<ToastControllerContextType>();
|
|
34
37
|
|
|
35
38
|
useEffect(() => {
|
|
36
39
|
if (toastRef.current) {
|
|
@@ -44,7 +47,7 @@ const ToastProvider = ({
|
|
|
44
47
|
);
|
|
45
48
|
|
|
46
49
|
return (
|
|
47
|
-
<ToastContext.Provider value={refState}>
|
|
50
|
+
<ToastContext.Provider value={refState || fallbackToastControlContext}>
|
|
48
51
|
<View style={{ flex: 1 }}>
|
|
49
52
|
{refState ? children : null}
|
|
50
53
|
<ToastConfigContext.Provider value={config}>
|
|
@@ -313,7 +313,7 @@ exports[`StyledBody has regular variant and playful typeface and $fontWeight fon
|
|
|
313
313
|
[
|
|
314
314
|
{
|
|
315
315
|
"color": "#001f23",
|
|
316
|
-
"fontFamily": "
|
|
316
|
+
"fontFamily": "RebondGrotesque",
|
|
317
317
|
"fontSize": 18,
|
|
318
318
|
"letterSpacing": 0.54,
|
|
319
319
|
"lineHeight": 26,
|
|
@@ -513,7 +513,7 @@ exports[`StyledBody has small variant and playful typeface and $fontWeight fontW
|
|
|
513
513
|
[
|
|
514
514
|
{
|
|
515
515
|
"color": "#001f23",
|
|
516
|
-
"fontFamily": "
|
|
516
|
+
"fontFamily": "RebondGrotesque",
|
|
517
517
|
"fontSize": 16,
|
|
518
518
|
"letterSpacing": 0.54,
|
|
519
519
|
"lineHeight": 24,
|
|
@@ -422,7 +422,7 @@ exports[`Body has regular variant and playful typeface and $fontWeight fontWeigh
|
|
|
422
422
|
[
|
|
423
423
|
{
|
|
424
424
|
"color": "#001f23",
|
|
425
|
-
"fontFamily": "
|
|
425
|
+
"fontFamily": "RebondGrotesque",
|
|
426
426
|
"fontSize": 18,
|
|
427
427
|
"letterSpacing": 0.54,
|
|
428
428
|
"lineHeight": 26,
|
|
@@ -677,7 +677,7 @@ exports[`Body has small variant and playful typeface and $fontWeight fontWeight
|
|
|
677
677
|
[
|
|
678
678
|
{
|
|
679
679
|
"color": "#001f23",
|
|
680
|
-
"fontFamily": "
|
|
680
|
+
"fontFamily": "RebondGrotesque",
|
|
681
681
|
"fontSize": 16,
|
|
682
682
|
"letterSpacing": 0.54,
|
|
683
683
|
"lineHeight": 24,
|
|
@@ -1203,7 +1203,7 @@ exports[`theme returns correct theme object 1`] = `
|
|
|
1203
1203
|
"semiBold": "BeVietnamPro-SemiBold",
|
|
1204
1204
|
},
|
|
1205
1205
|
"playful": {
|
|
1206
|
-
"regular": "
|
|
1206
|
+
"regular": "RebondGrotesque",
|
|
1207
1207
|
"semiBold": "RebondGrotesque-SemiBold",
|
|
1208
1208
|
},
|
|
1209
1209
|
},
|
|
@@ -38,4 +38,5 @@ export interface CardCarouselProps {
|
|
|
38
38
|
ref?: React.Ref<CardCarouselHandles>;
|
|
39
39
|
onLayout?: (event: LayoutChangeEvent) => void;
|
|
40
40
|
}
|
|
41
|
+
export declare const getCardCarouselValidIndex: (index: number, length: number) => number;
|
|
41
42
|
export declare const CardCarousel: React.ForwardRefExoticComponent<Omit<CardCarouselProps, "ref"> & React.RefAttributes<CardCarouselHandles>>;
|