@transferwise/components 0.0.0-experimental-94a980d → 0.0.0-experimental-afa5e5b
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/build/alert/Alert.js +1 -1
- package/build/alert/Alert.js.map +1 -1
- package/build/alert/Alert.mjs +1 -1
- package/build/alert/Alert.mjs.map +1 -1
- package/build/checkbox/Checkbox.js +1 -1
- package/build/checkbox/Checkbox.js.map +1 -1
- package/build/checkbox/Checkbox.mjs +1 -1
- package/build/checkbox/Checkbox.mjs.map +1 -1
- package/build/field/Field.js +4 -8
- package/build/field/Field.js.map +1 -1
- package/build/field/Field.mjs +4 -8
- package/build/field/Field.mjs.map +1 -1
- package/build/inlineAlert/InlineAlert.js +7 -1
- package/build/inlineAlert/InlineAlert.js.map +1 -1
- package/build/inlineAlert/InlineAlert.mjs +7 -1
- package/build/inlineAlert/InlineAlert.mjs.map +1 -1
- package/build/main.css +1 -17
- package/build/radioGroup/RadioGroup.js +0 -1
- package/build/radioGroup/RadioGroup.js.map +1 -1
- package/build/radioGroup/RadioGroup.mjs +0 -1
- package/build/radioGroup/RadioGroup.mjs.map +1 -1
- package/build/styles/field/Field.css +1 -10
- package/build/styles/main.css +1 -17
- package/build/styles/typeahead/Typeahead.css +0 -4
- package/build/typeahead/Typeahead.js +7 -20
- package/build/typeahead/Typeahead.js.map +1 -1
- package/build/typeahead/Typeahead.mjs +7 -20
- package/build/typeahead/Typeahead.mjs.map +1 -1
- package/build/types/components/src/alert/Alert.d.ts +1 -1
- package/build/types/components/src/alert/Alert.d.ts.map +1 -1
- package/build/types/components/src/field/Field.d.ts +4 -8
- package/build/types/components/src/field/Field.d.ts.map +1 -1
- package/build/types/components/src/inlineAlert/InlineAlert.d.ts +7 -1
- package/build/types/components/src/inlineAlert/InlineAlert.d.ts.map +1 -1
- package/build/types/components/src/radioGroup/RadioGroup.d.ts.map +1 -1
- package/build/types/components/src/typeahead/Typeahead.d.ts +4 -8
- package/build/types/components/src/typeahead/Typeahead.d.ts.map +1 -1
- package/build/types/components/src/upload/Upload.d.ts +1 -1
- package/build/types/components/src/upload/steps/uploadImageStep/uploadImageStep.d.ts.map +1 -1
- package/build/upload/Upload.js.map +1 -1
- package/build/upload/Upload.mjs.map +1 -1
- package/build/upload/steps/uploadImageStep/uploadImageStep.js +4 -5
- package/build/upload/steps/uploadImageStep/uploadImageStep.js.map +1 -1
- package/build/upload/steps/uploadImageStep/uploadImageStep.mjs +4 -5
- package/build/upload/steps/uploadImageStep/uploadImageStep.mjs.map +1 -1
- package/package.json +2 -2
- package/src/alert/Alert.spec.tsx +1 -1
- package/src/alert/Alert.tsx +2 -2
- package/src/checkbox/Checkbox.story.tsx +3 -11
- package/src/checkbox/Checkbox.tsx +1 -1
- package/src/checkbox/__snapshots__/Checkbox.spec.tsx.snap +1 -1
- package/src/field/Field.css +1 -10
- package/src/field/Field.less +2 -13
- package/src/field/Field.spec.tsx +3 -19
- package/src/field/Field.story.tsx +0 -18
- package/src/field/Field.tsx +5 -17
- package/src/inlineAlert/InlineAlert.story.tsx +0 -4
- package/src/inlineAlert/InlineAlert.tsx +7 -1
- package/src/main.css +1 -17
- package/src/main.less +0 -1
- package/src/radioGroup/RadioGroup.story.tsx +0 -2
- package/src/radioGroup/RadioGroup.tsx +1 -6
- package/src/typeahead/Typeahead.css +0 -4
- package/src/typeahead/Typeahead.less +1 -5
- package/src/typeahead/Typeahead.spec.tsx +1 -1
- package/src/typeahead/Typeahead.story.tsx +3 -151
- package/src/typeahead/Typeahead.tsx +9 -33
- package/src/upload/Upload.story.tsx +1 -1
- package/src/upload/Upload.tests.story.tsx +1 -36
- package/src/upload/Upload.tsx +1 -1
- package/src/upload/steps/uploadImageStep/uploadImageStep.tsx +3 -7
- package/build/styles/radioGroup/RadioGroup.css +0 -3
- package/src/radioGroup/RadioGroup.css +0 -3
- package/src/radioGroup/RadioGroup.less +0 -3
- package/src/radioGroup/RadioGroup.test.story.tsx +0 -62
package/src/field/Field.spec.tsx
CHANGED
|
@@ -71,7 +71,7 @@ describe('Field', () => {
|
|
|
71
71
|
expect(screen.getByLabelText(/Phone number/)).toHaveAttribute('aria-describedby');
|
|
72
72
|
});
|
|
73
73
|
|
|
74
|
-
it("should allow for
|
|
74
|
+
it("should allow for InlineAlert's StatusIcon override via `messageIconLabel` prop", () => {
|
|
75
75
|
const customIconLabel = 'My custom icon label';
|
|
76
76
|
|
|
77
77
|
render(
|
|
@@ -86,8 +86,8 @@ describe('Field', () => {
|
|
|
86
86
|
</Field>,
|
|
87
87
|
);
|
|
88
88
|
|
|
89
|
-
expect(screen.
|
|
90
|
-
expect(screen.
|
|
89
|
+
expect(screen.queryByRole('graphics-symbol', { name: 'Error.' })).not.toBeInTheDocument();
|
|
90
|
+
expect(screen.getByRole('graphics-symbol', { name: customIconLabel })).toBeInTheDocument();
|
|
91
91
|
});
|
|
92
92
|
|
|
93
93
|
it('should show or hide (Optional) suffix depending on required prop', () => {
|
|
@@ -147,20 +147,4 @@ describe('Field', () => {
|
|
|
147
147
|
const label = screen.getByText('Phone number');
|
|
148
148
|
await userEvent.click(label);
|
|
149
149
|
});
|
|
150
|
-
|
|
151
|
-
it('should show loading spinner when messageLoading is true', () => {
|
|
152
|
-
render(
|
|
153
|
-
<Field
|
|
154
|
-
label="Phone number"
|
|
155
|
-
message="Processing your request"
|
|
156
|
-
sentiment="neutral"
|
|
157
|
-
messageLoading
|
|
158
|
-
>
|
|
159
|
-
<Input />
|
|
160
|
-
</Field>,
|
|
161
|
-
);
|
|
162
|
-
|
|
163
|
-
expect(screen.getByTestId('InlinePrompt_ProcessIndicator')).toBeInTheDocument();
|
|
164
|
-
expect(screen.getByText('Processing your request')).toBeInTheDocument();
|
|
165
|
-
});
|
|
166
150
|
});
|
|
@@ -46,7 +46,6 @@ export const Basic = (args: FieldProps) => {
|
|
|
46
46
|
sentiment={Sentiment.NEGATIVE}
|
|
47
47
|
message="Validation error, please take a look"
|
|
48
48
|
messageIconLabel={args.messageIconLabel}
|
|
49
|
-
messageLoading={args.messageLoading}
|
|
50
49
|
>
|
|
51
50
|
<Input value={value} onChange={({ target }) => setValue(target.value)} />
|
|
52
51
|
</Field>
|
|
@@ -82,7 +81,6 @@ export const Basic = (args: FieldProps) => {
|
|
|
82
81
|
message={lorem10}
|
|
83
82
|
sentiment="negative"
|
|
84
83
|
messageIconLabel={args.messageIconLabel}
|
|
85
|
-
messageLoading={args.messageLoading}
|
|
86
84
|
>
|
|
87
85
|
<TextArea />
|
|
88
86
|
</Field>
|
|
@@ -111,17 +109,6 @@ export const WithStatusMessages = (args: FieldProps) => {
|
|
|
111
109
|
sentiment={Sentiment.POSITIVE}
|
|
112
110
|
message="Positive message"
|
|
113
111
|
messageIconLabel={args.messageIconLabel}
|
|
114
|
-
messageLoading={args.messageLoading}
|
|
115
|
-
>
|
|
116
|
-
<Input value={value} onChange={({ target }) => setValue(target.value)} />
|
|
117
|
-
</Field>
|
|
118
|
-
|
|
119
|
-
<Field
|
|
120
|
-
label="Text Input with Proposition Message"
|
|
121
|
-
sentiment="proposition"
|
|
122
|
-
message="Proposition message"
|
|
123
|
-
messageIconLabel={args.messageIconLabel}
|
|
124
|
-
messageLoading={args.messageLoading}
|
|
125
112
|
>
|
|
126
113
|
<Input value={value} onChange={({ target }) => setValue(target.value)} />
|
|
127
114
|
</Field>
|
|
@@ -131,7 +118,6 @@ export const WithStatusMessages = (args: FieldProps) => {
|
|
|
131
118
|
sentiment={Sentiment.WARNING}
|
|
132
119
|
message="Warning message"
|
|
133
120
|
messageIconLabel={args.messageIconLabel}
|
|
134
|
-
messageLoading={args.messageLoading}
|
|
135
121
|
>
|
|
136
122
|
<Input value={value} onChange={({ target }) => setValue(target.value)} />
|
|
137
123
|
</Field>
|
|
@@ -141,7 +127,6 @@ export const WithStatusMessages = (args: FieldProps) => {
|
|
|
141
127
|
sentiment={Sentiment.NEGATIVE}
|
|
142
128
|
message="This is a required field"
|
|
143
129
|
messageIconLabel={args.messageIconLabel}
|
|
144
|
-
messageLoading={args.messageLoading}
|
|
145
130
|
>
|
|
146
131
|
<Input value={value} onChange={({ target }) => setValue(target.value)} />
|
|
147
132
|
</Field>
|
|
@@ -153,7 +138,6 @@ export const WithStatusMessages = (args: FieldProps) => {
|
|
|
153
138
|
sentiment={Sentiment.NEGATIVE}
|
|
154
139
|
message="Validation error, please take a look"
|
|
155
140
|
messageIconLabel={args.messageIconLabel}
|
|
156
|
-
messageLoading={args.messageLoading}
|
|
157
141
|
>
|
|
158
142
|
<Input value={value} onChange={({ target }) => setValue(target.value)} />
|
|
159
143
|
</Field>
|
|
@@ -164,7 +148,6 @@ export const WithStatusMessages = (args: FieldProps) => {
|
|
|
164
148
|
hint="This is a helpful message"
|
|
165
149
|
error="Validation error, please take a look"
|
|
166
150
|
messageIconLabel={args.messageIconLabel}
|
|
167
|
-
messageLoading={args.messageLoading}
|
|
168
151
|
>
|
|
169
152
|
<Input value={value} onChange={({ target }) => setValue(target.value)} />
|
|
170
153
|
</Field>
|
|
@@ -174,7 +157,6 @@ export const WithStatusMessages = (args: FieldProps) => {
|
|
|
174
157
|
label="Text Input with Info under the field"
|
|
175
158
|
message="This is a helpful message"
|
|
176
159
|
messageIconLabel={args.messageIconLabel}
|
|
177
|
-
messageLoading={args.messageLoading}
|
|
178
160
|
>
|
|
179
161
|
<Input value={value} onChange={({ target }) => setValue(target.value)} />
|
|
180
162
|
</Field>
|
package/src/field/Field.tsx
CHANGED
|
@@ -2,7 +2,7 @@ import { clsx } from 'clsx';
|
|
|
2
2
|
import { useId, useRef } from 'react';
|
|
3
3
|
|
|
4
4
|
import { Sentiment } from '../common';
|
|
5
|
-
import
|
|
5
|
+
import InlineAlert from '../inlineAlert/InlineAlert';
|
|
6
6
|
import {
|
|
7
7
|
FieldLabelContextProvider,
|
|
8
8
|
InputDescribedByProvider,
|
|
@@ -21,18 +21,14 @@ export type FieldProps = {
|
|
|
21
21
|
hint?: React.ReactNode;
|
|
22
22
|
message?: React.ReactNode;
|
|
23
23
|
/**
|
|
24
|
-
* Override for the [
|
|
24
|
+
* Override for the [InlineAlert icon's default, accessible name](/?path=/docs/other-statusicon-accessibility--docs)
|
|
25
25
|
* announced by the screen readers
|
|
26
26
|
* */
|
|
27
27
|
messageIconLabel?: string;
|
|
28
|
-
/**
|
|
29
|
-
* If true, shows a loading spinner in place of the message icon of the InlinePrompt
|
|
30
|
-
*/
|
|
31
|
-
messageLoading?: boolean;
|
|
32
28
|
description?: React.ReactNode;
|
|
33
29
|
/** @deprecated use `message` and `type={Sentiment.NEGATIVE}` prop instead */
|
|
34
30
|
error?: React.ReactNode;
|
|
35
|
-
sentiment?:
|
|
31
|
+
sentiment?: `${Sentiment.NEGATIVE | Sentiment.NEUTRAL | Sentiment.POSITIVE | Sentiment.WARNING}`;
|
|
36
32
|
className?: string;
|
|
37
33
|
children?: React.ReactNode;
|
|
38
34
|
};
|
|
@@ -43,7 +39,6 @@ export const Field = ({
|
|
|
43
39
|
required = true,
|
|
44
40
|
message: propMessage,
|
|
45
41
|
messageIconLabel,
|
|
46
|
-
messageLoading,
|
|
47
42
|
hint,
|
|
48
43
|
description = hint,
|
|
49
44
|
sentiment: propType = Sentiment.NEUTRAL,
|
|
@@ -109,16 +104,9 @@ export const Field = ({
|
|
|
109
104
|
)}
|
|
110
105
|
|
|
111
106
|
{message && (
|
|
112
|
-
<
|
|
113
|
-
sentiment={sentiment}
|
|
114
|
-
id={messageId}
|
|
115
|
-
mediaLabel={messageIconLabel}
|
|
116
|
-
className="np-field__prompt"
|
|
117
|
-
loading={messageLoading}
|
|
118
|
-
width="full"
|
|
119
|
-
>
|
|
107
|
+
<InlineAlert type={sentiment} id={messageId} iconLabel={messageIconLabel}>
|
|
120
108
|
{message}
|
|
121
|
-
</
|
|
109
|
+
</InlineAlert>
|
|
122
110
|
)}
|
|
123
111
|
</div>
|
|
124
112
|
</InputInvalidProvider>
|
|
@@ -4,13 +4,9 @@ import InlineAlert, { InlineAlertProps } from './InlineAlert';
|
|
|
4
4
|
import { lorem10, lorem40 } from '../test-utils';
|
|
5
5
|
import Link from '../link';
|
|
6
6
|
|
|
7
|
-
/**
|
|
8
|
-
* > **DEPRECATED** Use [InlinePrompt](?path=/docs/prompts-inlineprompt--docs) or [Field](?path=/docs/forms-field--docs) instead.
|
|
9
|
-
*/
|
|
10
7
|
export default {
|
|
11
8
|
component: InlineAlert,
|
|
12
9
|
title: 'Prompts/InlineAlert',
|
|
13
|
-
tags: ['deprecated'],
|
|
14
10
|
} as Meta<InlineAlertProps>;
|
|
15
11
|
|
|
16
12
|
export const Basic = () => {
|
|
@@ -22,7 +22,13 @@ const iconTypes = new Set<NonNullable<InlineAlertProps['type']>>([
|
|
|
22
22
|
]);
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
|
-
*
|
|
25
|
+
* Avoid using `<InlineAlert>` component directly
|
|
26
|
+
* it's for edge cases when `<Field />` isn't suitable for some reasons.
|
|
27
|
+
*
|
|
28
|
+
* Example:
|
|
29
|
+
* ```
|
|
30
|
+
* <Field sentiment={..} message={..}>..</Field>
|
|
31
|
+
* ```
|
|
26
32
|
*/
|
|
27
33
|
export default function InlineAlert({
|
|
28
34
|
id,
|
package/src/main.css
CHANGED
|
@@ -3825,19 +3825,10 @@ html:not([dir="rtl"]) .np-flow-navigation--sm .np-flow-navigation__stepper {
|
|
|
3825
3825
|
stroke-dasharray: calc(12px * 0.5) calc(12px * 0.5);
|
|
3826
3826
|
stroke-dasharray: var(--wds-list-item-spotlight-strokeDashSize) var(--wds-list-item-spotlight-strokeDashSize);
|
|
3827
3827
|
}
|
|
3828
|
-
.np-field-control
|
|
3829
|
-
.np-field__prompt {
|
|
3828
|
+
.np-field-control {
|
|
3830
3829
|
margin-top: 4px;
|
|
3831
3830
|
margin-top: var(--size-4);
|
|
3832
3831
|
}
|
|
3833
|
-
.np-field .form-group--typeahead[class],
|
|
3834
|
-
.np-field .np-checkbox-label[class] {
|
|
3835
|
-
margin-bottom: 0;
|
|
3836
|
-
}
|
|
3837
|
-
.np-field:has(.wds-radio-group) .np-field__prompt {
|
|
3838
|
-
margin-top: 12px;
|
|
3839
|
-
margin-top: var(--size-12);
|
|
3840
|
-
}
|
|
3841
3832
|
.np-input-group {
|
|
3842
3833
|
display: inline-grid;
|
|
3843
3834
|
width: 100%;
|
|
@@ -5406,9 +5397,6 @@ html:not([dir="rtl"]) .np-navigation-option {
|
|
|
5406
5397
|
.np-CardGroup .np-Card.np-Card--promoCard {
|
|
5407
5398
|
max-width: 100%;
|
|
5408
5399
|
}
|
|
5409
|
-
.wds-radio-group .np-radio:last-child label {
|
|
5410
|
-
margin-bottom: 0;
|
|
5411
|
-
}
|
|
5412
5400
|
.np-section {
|
|
5413
5401
|
margin-top: 32px;
|
|
5414
5402
|
margin-top: var(--size-32);
|
|
@@ -6935,10 +6923,6 @@ html:not([dir="rtl"]) .np-navigation-option {
|
|
|
6935
6923
|
padding: 0;
|
|
6936
6924
|
margin: 0;
|
|
6937
6925
|
}
|
|
6938
|
-
.typeahead--prompt {
|
|
6939
|
-
margin-top: 4px;
|
|
6940
|
-
margin-top: var(--size-4);
|
|
6941
|
-
}
|
|
6942
6926
|
.typeahead-sm.typeahead--multiple .typeahead__input-container {
|
|
6943
6927
|
min-height: 32px;
|
|
6944
6928
|
}
|
package/src/main.less
CHANGED
|
@@ -61,7 +61,6 @@
|
|
|
61
61
|
@import "./phoneNumberInput/PhoneNumberInput.less";
|
|
62
62
|
@import "./popover/Popover.less";
|
|
63
63
|
@import "./promoCard/PromoCard.less";
|
|
64
|
-
@import "./radioGroup/RadioGroup.less";
|
|
65
64
|
@import "./section/Section.less";
|
|
66
65
|
@import "./slidingPanel/SlidingPanel.less";
|
|
67
66
|
@import "./snackbar/Snackbar.less";
|
|
@@ -29,12 +29,7 @@ export default function RadioGroup<T extends string | number = never>({
|
|
|
29
29
|
const [uncontrolledValue, setUncontrolledValue] = useState(controlledValue);
|
|
30
30
|
|
|
31
31
|
return radios.length > 0 ? (
|
|
32
|
-
<div
|
|
33
|
-
role="radiogroup"
|
|
34
|
-
{...inputAttributes}
|
|
35
|
-
{...UNSAFE_inputAttributes}
|
|
36
|
-
className="wds-radio-group"
|
|
37
|
-
>
|
|
32
|
+
<div role="radiogroup" {...inputAttributes} {...UNSAFE_inputAttributes}>
|
|
38
33
|
{radios.map(({ value = '' as T, ...restProps }, index) => (
|
|
39
34
|
<Radio
|
|
40
35
|
// eslint-disable-next-line react/no-array-index-key
|
|
@@ -122,10 +122,6 @@
|
|
|
122
122
|
}
|
|
123
123
|
}
|
|
124
124
|
|
|
125
|
-
&--prompt {
|
|
126
|
-
margin-top: var(--size-4);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
125
|
// SIZES
|
|
130
126
|
&-sm {
|
|
131
127
|
&.typeahead--multiple {
|
|
@@ -211,7 +207,7 @@
|
|
|
211
207
|
}
|
|
212
208
|
|
|
213
209
|
.np-theme-personal & {
|
|
214
|
-
.input-group:not(.disabled
|
|
210
|
+
.input-group:not(.disabled,:disabled,.input-group--has-error):focus-within .tw-icon-search {
|
|
215
211
|
color: var(--color-interactive-primary);
|
|
216
212
|
}
|
|
217
213
|
.tw-icon-search {
|
|
@@ -102,7 +102,7 @@ describe('Typeahead', () => {
|
|
|
102
102
|
expect(onChange).toHaveBeenCalledWith([]);
|
|
103
103
|
});
|
|
104
104
|
|
|
105
|
-
it('shows
|
|
105
|
+
it('shows InlineAlert when alert prop is provided', () => {
|
|
106
106
|
render(
|
|
107
107
|
<Typeahead
|
|
108
108
|
id="test"
|
|
@@ -1,18 +1,15 @@
|
|
|
1
1
|
import { Meta, StoryObj } from '@storybook/react-webpack5';
|
|
2
2
|
import { Search as SearchIcon } from '@transferwise/icons';
|
|
3
3
|
import { userEvent, within, fn } from 'storybook/test';
|
|
4
|
-
import { useState } from 'react';
|
|
5
4
|
|
|
6
|
-
import {
|
|
5
|
+
import Typeahead, { type TypeaheadOption } from './Typeahead';
|
|
6
|
+
import { Size } from '../common';
|
|
7
|
+
import { useState } from 'react';
|
|
7
8
|
import { Input } from '../inputs/Input';
|
|
8
9
|
import { Field } from '../field/Field';
|
|
9
10
|
import Button from '../button';
|
|
10
11
|
import Modal from '../modal';
|
|
11
|
-
import { InlinePromptProps } from '../prompt';
|
|
12
|
-
import Typeahead, { type TypeaheadOption } from './Typeahead';
|
|
13
12
|
|
|
14
|
-
// needed for SB to display correct name in the docs
|
|
15
|
-
(Typeahead as React.FC).displayName = 'Typeahead';
|
|
16
13
|
type Story = StoryObj<typeof Typeahead>;
|
|
17
14
|
|
|
18
15
|
/**
|
|
@@ -40,7 +37,6 @@ const meta: Meta<typeof Typeahead> = {
|
|
|
40
37
|
searchDelay: 200,
|
|
41
38
|
showSuggestions: true,
|
|
42
39
|
showNewEntry: true,
|
|
43
|
-
alert: undefined,
|
|
44
40
|
size: Size.MEDIUM,
|
|
45
41
|
initialValue: [],
|
|
46
42
|
id: 'myTypeahead',
|
|
@@ -58,17 +54,6 @@ const meta: Meta<typeof Typeahead> = {
|
|
|
58
54
|
control: 'inline-radio',
|
|
59
55
|
options: [Size.MEDIUM, Size.LARGE],
|
|
60
56
|
},
|
|
61
|
-
alert: {
|
|
62
|
-
description:
|
|
63
|
-
'Displays an [InlinePrompt](?path=/docs/prompts-inlineprompt--docs) below the input when provided. <blockquote class="m-0">**⚠️ DEPRECATED:** Please use [<Field />](?path=/docs/forms-field--docs) component and its `message` and `sentiment` props instead. `error`, `info` and `success` alert types are no longer supported and will be soon removed.</blockquote>',
|
|
64
|
-
control: 'object',
|
|
65
|
-
table: {
|
|
66
|
-
type: {
|
|
67
|
-
summary:
|
|
68
|
-
'{ message: ReactNode; type?: "negative" | "neutral" | "positive" | "warning" | "proposition" }',
|
|
69
|
-
},
|
|
70
|
-
},
|
|
71
|
-
},
|
|
72
57
|
},
|
|
73
58
|
};
|
|
74
59
|
export default meta;
|
|
@@ -252,14 +237,6 @@ export const Search: Story = {
|
|
|
252
237
|
};
|
|
253
238
|
|
|
254
239
|
export const AutoFocusInModal: Story = {
|
|
255
|
-
parameters: {
|
|
256
|
-
docs: {
|
|
257
|
-
story: {
|
|
258
|
-
inline: false,
|
|
259
|
-
iframeHeight: 500,
|
|
260
|
-
},
|
|
261
|
-
},
|
|
262
|
-
},
|
|
263
240
|
render: function Render() {
|
|
264
241
|
const [open, setOpen] = useState<boolean>(true);
|
|
265
242
|
return (
|
|
@@ -302,128 +279,3 @@ export const AutoFocusInModal: Story = {
|
|
|
302
279
|
);
|
|
303
280
|
},
|
|
304
281
|
};
|
|
305
|
-
|
|
306
|
-
export const WithField: Story = {
|
|
307
|
-
args: {
|
|
308
|
-
autoFillOnBlur: undefined,
|
|
309
|
-
chipSeparators: undefined,
|
|
310
|
-
clearable: undefined,
|
|
311
|
-
initialValue: undefined,
|
|
312
|
-
inputAutoComplete: undefined,
|
|
313
|
-
minQueryLength: undefined,
|
|
314
|
-
onBlur: undefined,
|
|
315
|
-
onFocus: undefined,
|
|
316
|
-
onInputChange: undefined,
|
|
317
|
-
onSearch: undefined,
|
|
318
|
-
placeholder: undefined,
|
|
319
|
-
searchDelay: undefined,
|
|
320
|
-
showSuggestions: undefined,
|
|
321
|
-
showNewEntry: undefined,
|
|
322
|
-
size: undefined,
|
|
323
|
-
},
|
|
324
|
-
render: function Render(args) {
|
|
325
|
-
const options = [{ label: 'Option 1' }];
|
|
326
|
-
|
|
327
|
-
const alertTypes: InlinePromptProps['sentiment'][] = [
|
|
328
|
-
Sentiment.NEGATIVE,
|
|
329
|
-
Sentiment.WARNING,
|
|
330
|
-
Sentiment.NEUTRAL,
|
|
331
|
-
Sentiment.POSITIVE,
|
|
332
|
-
'proposition',
|
|
333
|
-
];
|
|
334
|
-
|
|
335
|
-
return (
|
|
336
|
-
<>
|
|
337
|
-
<Field
|
|
338
|
-
id="typeahead"
|
|
339
|
-
label="Field label"
|
|
340
|
-
description="Additional information about the field"
|
|
341
|
-
required
|
|
342
|
-
>
|
|
343
|
-
<Typeahead {...args} name="typeahead" options={options} />
|
|
344
|
-
</Field>
|
|
345
|
-
{alertTypes.map((sentiment) => (
|
|
346
|
-
<Field
|
|
347
|
-
key={sentiment}
|
|
348
|
-
label="Field label"
|
|
349
|
-
id={`typeahead-${sentiment}`}
|
|
350
|
-
message={`This is a ${sentiment} message`}
|
|
351
|
-
sentiment={sentiment}
|
|
352
|
-
>
|
|
353
|
-
<Typeahead {...args} name={`typeahead-${sentiment}`} options={options} />
|
|
354
|
-
</Field>
|
|
355
|
-
))}
|
|
356
|
-
</>
|
|
357
|
-
);
|
|
358
|
-
},
|
|
359
|
-
decorators: (Story) => (
|
|
360
|
-
<div className="d-flex flex-column">
|
|
361
|
-
<Story />
|
|
362
|
-
</div>
|
|
363
|
-
),
|
|
364
|
-
};
|
|
365
|
-
|
|
366
|
-
/**
|
|
367
|
-
* > **⚠️ DEPRECATED:** Please use [<Field />](?path=/docs/forms-field--docs) component and its `message` and `sentiment` props instead. <br/>`error`, `info` and `success` alert types are no longer supported and will be soon removed.
|
|
368
|
-
*/
|
|
369
|
-
export const WithAlert: Story = {
|
|
370
|
-
name: 'With Alert (deprecated)',
|
|
371
|
-
args: {
|
|
372
|
-
autoFillOnBlur: undefined,
|
|
373
|
-
chipSeparators: undefined,
|
|
374
|
-
clearable: undefined,
|
|
375
|
-
initialValue: undefined,
|
|
376
|
-
inputAutoComplete: undefined,
|
|
377
|
-
minQueryLength: undefined,
|
|
378
|
-
onBlur: undefined,
|
|
379
|
-
onFocus: undefined,
|
|
380
|
-
onInputChange: undefined,
|
|
381
|
-
onSearch: undefined,
|
|
382
|
-
placeholder: undefined,
|
|
383
|
-
searchDelay: undefined,
|
|
384
|
-
showSuggestions: undefined,
|
|
385
|
-
showNewEntry: undefined,
|
|
386
|
-
size: undefined,
|
|
387
|
-
},
|
|
388
|
-
parameters: {
|
|
389
|
-
docs: {
|
|
390
|
-
canvas: {
|
|
391
|
-
sourceState: 'hidden',
|
|
392
|
-
},
|
|
393
|
-
},
|
|
394
|
-
},
|
|
395
|
-
render: function Render(args) {
|
|
396
|
-
const options = [{ label: 'Option 1' }];
|
|
397
|
-
|
|
398
|
-
const alertTypes: InlinePromptProps['sentiment'][] = [
|
|
399
|
-
Sentiment.NEGATIVE,
|
|
400
|
-
Sentiment.WARNING,
|
|
401
|
-
Sentiment.NEUTRAL,
|
|
402
|
-
Sentiment.POSITIVE,
|
|
403
|
-
'proposition',
|
|
404
|
-
];
|
|
405
|
-
|
|
406
|
-
return (
|
|
407
|
-
<>
|
|
408
|
-
{alertTypes.map((sentiment) => (
|
|
409
|
-
<Typeahead
|
|
410
|
-
key={sentiment}
|
|
411
|
-
{...args}
|
|
412
|
-
id={`typeahead-${sentiment}`}
|
|
413
|
-
name={`typeahead-${sentiment}`}
|
|
414
|
-
options={options}
|
|
415
|
-
alert={{
|
|
416
|
-
message: `This is a ${sentiment} message`,
|
|
417
|
-
type: sentiment,
|
|
418
|
-
}}
|
|
419
|
-
/>
|
|
420
|
-
))}
|
|
421
|
-
</>
|
|
422
|
-
);
|
|
423
|
-
},
|
|
424
|
-
decorators: (Story) => (
|
|
425
|
-
<div className="d-flex flex-column">
|
|
426
|
-
<Story />
|
|
427
|
-
</div>
|
|
428
|
-
),
|
|
429
|
-
};
|
|
@@ -16,7 +16,8 @@ import {
|
|
|
16
16
|
removeClickClassFromDocumentOnIos,
|
|
17
17
|
stopPropagation,
|
|
18
18
|
} from '../common';
|
|
19
|
-
import
|
|
19
|
+
import InlineAlert from '../inlineAlert';
|
|
20
|
+
import { InlineAlertProps } from '../inlineAlert/InlineAlert';
|
|
20
21
|
import { withInputAttributes, WithInputAttributesProps } from '../inputs/contexts';
|
|
21
22
|
|
|
22
23
|
import TypeaheadInput from './typeaheadInput/TypeaheadInput';
|
|
@@ -39,17 +40,9 @@ export interface TypeaheadProps<T> extends Partial<WrappedComponentProps> {
|
|
|
39
40
|
id: string;
|
|
40
41
|
name: string;
|
|
41
42
|
addon?: ReactNode;
|
|
42
|
-
/**
|
|
43
|
-
* @deprecated Please use [`Field`](?path=/docs/forms-field--docs) component and its `message` and `sentiment` props instead.
|
|
44
|
-
* @deprecated `error`, `info` and `success` are deprecated as alert types and will be soon removed.
|
|
45
|
-
*/
|
|
46
43
|
alert?: {
|
|
47
|
-
message:
|
|
48
|
-
type?:
|
|
49
|
-
| InlinePromptProps['sentiment']
|
|
50
|
-
| `${Sentiment.ERROR}`
|
|
51
|
-
| `${Sentiment.INFO}`
|
|
52
|
-
| `${Sentiment.SUCCESS}`;
|
|
44
|
+
message: InlineAlertProps['children'];
|
|
45
|
+
type?: InlineAlertProps['type'];
|
|
53
46
|
};
|
|
54
47
|
allowNew?: boolean;
|
|
55
48
|
autoFillOnBlur?: boolean;
|
|
@@ -481,20 +474,9 @@ class Typeahead<T> extends Component<TypeaheadPropsWithInputAttributes<T>, Typea
|
|
|
481
474
|
dropdownOpen,
|
|
482
475
|
});
|
|
483
476
|
|
|
484
|
-
const alertType =
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
}
|
|
488
|
-
if (alert.type === Sentiment.ERROR) {
|
|
489
|
-
return Sentiment.NEGATIVE;
|
|
490
|
-
}
|
|
491
|
-
if (alert.type === Sentiment.SUCCESS) {
|
|
492
|
-
return Sentiment.POSITIVE;
|
|
493
|
-
}
|
|
494
|
-
return alert.type;
|
|
495
|
-
})();
|
|
496
|
-
const hasError = errorState || (alert && alertType === Sentiment.NEGATIVE);
|
|
497
|
-
const displayAlert = (!errorState && alert) || (alert && alertType === Sentiment.NEGATIVE);
|
|
477
|
+
const alertType = alert?.type ?? Sentiment.NEUTRAL;
|
|
478
|
+
const hasError = errorState || (alert && alertType === Sentiment.ERROR);
|
|
479
|
+
const displayAlert = (!errorState && alert) || (alert && alertType === Sentiment.ERROR);
|
|
498
480
|
const hasWarning = displayAlert && alertType === Sentiment.WARNING;
|
|
499
481
|
const hasInfo = displayAlert && alertType === Sentiment.NEUTRAL;
|
|
500
482
|
return (
|
|
@@ -512,7 +494,7 @@ class Typeahead<T> extends Component<TypeaheadPropsWithInputAttributes<T>, Typea
|
|
|
512
494
|
onClick={stopPropagation}
|
|
513
495
|
>
|
|
514
496
|
<div
|
|
515
|
-
className={clsx('form-group',
|
|
497
|
+
className={clsx('form-group', {
|
|
516
498
|
'has-error': hasError,
|
|
517
499
|
'has-warning': hasWarning,
|
|
518
500
|
'has-info': hasInfo,
|
|
@@ -564,13 +546,7 @@ class Typeahead<T> extends Component<TypeaheadPropsWithInputAttributes<T>, Typea
|
|
|
564
546
|
</div>
|
|
565
547
|
)}
|
|
566
548
|
</div>
|
|
567
|
-
{displayAlert ?
|
|
568
|
-
<InlinePrompt sentiment={alertType} className="typeahead--prompt" width="full">
|
|
569
|
-
{alert.message}
|
|
570
|
-
</InlinePrompt>
|
|
571
|
-
) : (
|
|
572
|
-
menu
|
|
573
|
-
)}
|
|
549
|
+
{displayAlert ? <InlineAlert type={alert.type}>{alert.message}</InlineAlert> : menu}
|
|
574
550
|
</div>
|
|
575
551
|
</div>
|
|
576
552
|
);
|
|
@@ -71,7 +71,7 @@ const meta = {
|
|
|
71
71
|
},
|
|
72
72
|
errorIconLabel: {
|
|
73
73
|
description:
|
|
74
|
-
"Override for the
|
|
74
|
+
"Override for the InlineAlert icon's default, accessible name announced by the screen readers",
|
|
75
75
|
},
|
|
76
76
|
usHelpImage: {
|
|
77
77
|
control: false,
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import type { Meta
|
|
2
|
-
import { userEvent, within, waitFor } from 'storybook/test';
|
|
1
|
+
import type { Meta } from '@storybook/react-webpack5';
|
|
3
2
|
|
|
4
3
|
import Upload from '.';
|
|
5
4
|
import { Field } from '../field/Field';
|
|
@@ -74,40 +73,6 @@ export const MaxSizes = () => {
|
|
|
74
73
|
);
|
|
75
74
|
};
|
|
76
75
|
|
|
77
|
-
export const WithError: StoryObj<typeof meta> = {
|
|
78
|
-
render: () => (
|
|
79
|
-
<Field label="Upload a file">
|
|
80
|
-
<Upload
|
|
81
|
-
usAccept="*"
|
|
82
|
-
usLabel="Upload a file"
|
|
83
|
-
usPlaceholder="Maximum filesize is 1B"
|
|
84
|
-
usDisabled={false}
|
|
85
|
-
maxSize={1}
|
|
86
|
-
errorIconLabel="File too large error"
|
|
87
|
-
httpOptions={{
|
|
88
|
-
url: 'https://httpbin.org/post',
|
|
89
|
-
method: 'POST',
|
|
90
|
-
}}
|
|
91
|
-
/>
|
|
92
|
-
</Field>
|
|
93
|
-
),
|
|
94
|
-
play: async ({ canvasElement }) => {
|
|
95
|
-
const canvas = within(canvasElement);
|
|
96
|
-
const fileInput = canvasElement.querySelector<HTMLInputElement>('input[type="file"]');
|
|
97
|
-
|
|
98
|
-
if (!fileInput) {
|
|
99
|
-
throw new Error('File input not found');
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
const file = new File(['This file content is definitely more than 1 byte'], 'test-file.txt', {
|
|
103
|
-
type: 'text/plain',
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
await userEvent.upload(fileInput, file);
|
|
107
|
-
await waitFor(async () => canvas.findByText(/Maximum filesize is/i), { timeout: 3000 });
|
|
108
|
-
},
|
|
109
|
-
};
|
|
110
|
-
|
|
111
76
|
export const AllVariants = () => {
|
|
112
77
|
return (
|
|
113
78
|
<div style={{ display: 'flex', gap: '1rem' }}>
|
package/src/upload/Upload.tsx
CHANGED
|
@@ -55,7 +55,7 @@ export interface UploadProps extends WrappedComponentProps {
|
|
|
55
55
|
usLabel?: string;
|
|
56
56
|
usPlaceholder?: string;
|
|
57
57
|
/**
|
|
58
|
-
* Override for the [
|
|
58
|
+
* Override for the [InlineAlert icon's default, accessible name](/?path=/docs/other-statusicon-accessibility--docs)
|
|
59
59
|
* announced by the screen readers
|
|
60
60
|
* */
|
|
61
61
|
errorIconLabel?: string;
|
|
@@ -2,7 +2,7 @@ import { Upload as UploadIcon } from '@transferwise/icons';
|
|
|
2
2
|
import { createRef, PureComponent } from 'react';
|
|
3
3
|
import StatusIcon from '../../../statusIcon';
|
|
4
4
|
import { Sentiment, Size } from '../../../common';
|
|
5
|
-
import
|
|
5
|
+
import InlineAlert from '../../../inlineAlert';
|
|
6
6
|
|
|
7
7
|
export interface UploadImageStepProps {
|
|
8
8
|
fileDropped: (file: File) => void;
|
|
@@ -105,13 +105,9 @@ export default class UploadImageStep extends PureComponent<UploadImageStepProps>
|
|
|
105
105
|
{errorMessage && (
|
|
106
106
|
<div className="upload-error-message">
|
|
107
107
|
<div className="m-t-3 has-error">
|
|
108
|
-
<
|
|
109
|
-
sentiment={Sentiment.NEGATIVE}
|
|
110
|
-
mediaLabel={errorIconLabel}
|
|
111
|
-
width="full"
|
|
112
|
-
>
|
|
108
|
+
<InlineAlert type={Sentiment.NEGATIVE} iconLabel={errorIconLabel}>
|
|
113
109
|
{errorMessage}
|
|
114
|
-
</
|
|
110
|
+
</InlineAlert>
|
|
115
111
|
</div>
|
|
116
112
|
</div>
|
|
117
113
|
)}
|