@transferwise/components 0.0.0-experimental-be73f56 → 0.0.0-experimental-f304e2c

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 (106) hide show
  1. package/build/dateLookup/dateTrigger/DateTrigger.js +8 -4
  2. package/build/dateLookup/dateTrigger/DateTrigger.js.map +1 -1
  3. package/build/dateLookup/dateTrigger/DateTrigger.mjs +8 -4
  4. package/build/dateLookup/dateTrigger/DateTrigger.mjs.map +1 -1
  5. package/build/field/Field.js +13 -3
  6. package/build/field/Field.js.map +1 -1
  7. package/build/field/Field.mjs +13 -3
  8. package/build/field/Field.mjs.map +1 -1
  9. package/build/i18n/en.json +3 -2
  10. package/build/i18n/en.json.js +3 -2
  11. package/build/i18n/en.json.js.map +1 -1
  12. package/build/i18n/en.json.mjs +3 -2
  13. package/build/i18n/en.json.mjs.map +1 -1
  14. package/build/inlineAlert/InlineAlert.js +4 -6
  15. package/build/inlineAlert/InlineAlert.js.map +1 -1
  16. package/build/inlineAlert/InlineAlert.mjs +4 -6
  17. package/build/inlineAlert/InlineAlert.mjs.map +1 -1
  18. package/build/label/Label.js +29 -1
  19. package/build/label/Label.js.map +1 -1
  20. package/build/label/Label.messages.js +15 -0
  21. package/build/label/Label.messages.js.map +1 -0
  22. package/build/label/Label.messages.mjs +13 -0
  23. package/build/label/Label.messages.mjs.map +1 -0
  24. package/build/label/Label.mjs +30 -2
  25. package/build/label/Label.mjs.map +1 -1
  26. package/build/main.css +4 -14
  27. package/build/styles/dateLookup/dateTrigger/DateTrigger.css +0 -8
  28. package/build/styles/field/Field.css +4 -0
  29. package/build/styles/main.css +4 -14
  30. package/build/styles/upload/Upload.css +0 -6
  31. package/build/types/dateLookup/dateTrigger/DateTrigger.d.ts.map +1 -1
  32. package/build/types/field/Field.d.ts +4 -2
  33. package/build/types/field/Field.d.ts.map +1 -1
  34. package/build/types/index.d.ts +1 -1
  35. package/build/types/index.d.ts.map +1 -1
  36. package/build/types/inlineAlert/InlineAlert.d.ts.map +1 -1
  37. package/build/types/label/Label.d.ts +10 -1
  38. package/build/types/label/Label.d.ts.map +1 -1
  39. package/build/types/label/Label.messages.d.ts +12 -0
  40. package/build/types/label/Label.messages.d.ts.map +1 -0
  41. package/build/types/label/index.d.ts +3 -0
  42. package/build/types/label/index.d.ts.map +1 -0
  43. package/build/types/upload/Upload.d.ts +0 -1
  44. package/build/types/upload/Upload.d.ts.map +1 -1
  45. package/build/types/upload/Upload.messages.d.ts +0 -4
  46. package/build/types/upload/Upload.messages.d.ts.map +1 -1
  47. package/build/types/upload/steps/completeStep/completeStep.d.ts +3 -1
  48. package/build/types/upload/steps/completeStep/completeStep.d.ts.map +1 -1
  49. package/build/types/upload/steps/uploadImageStep/uploadImageStep.d.ts +0 -1
  50. package/build/types/upload/steps/uploadImageStep/uploadImageStep.d.ts.map +1 -1
  51. package/build/upload/Upload.js +12 -26
  52. package/build/upload/Upload.js.map +1 -1
  53. package/build/upload/Upload.messages.js +0 -3
  54. package/build/upload/Upload.messages.js.map +1 -1
  55. package/build/upload/Upload.messages.mjs +0 -3
  56. package/build/upload/Upload.messages.mjs.map +1 -1
  57. package/build/upload/Upload.mjs +12 -26
  58. package/build/upload/Upload.mjs.map +1 -1
  59. package/build/upload/steps/completeStep/completeStep.js +30 -15
  60. package/build/upload/steps/completeStep/completeStep.js.map +1 -1
  61. package/build/upload/steps/completeStep/completeStep.mjs +31 -16
  62. package/build/upload/steps/completeStep/completeStep.mjs.map +1 -1
  63. package/build/upload/steps/uploadImageStep/uploadImageStep.js +32 -56
  64. package/build/upload/steps/uploadImageStep/uploadImageStep.js.map +1 -1
  65. package/build/upload/steps/uploadImageStep/uploadImageStep.mjs +32 -56
  66. package/build/upload/steps/uploadImageStep/uploadImageStep.mjs.map +1 -1
  67. package/package.json +3 -3
  68. package/src/dateInput/DateInput.tests.story.tsx +7 -31
  69. package/src/dateLookup/DateLookup.rtl.spec.tsx +1 -1
  70. package/src/dateLookup/dateTrigger/DateTrigger.css +0 -8
  71. package/src/dateLookup/dateTrigger/DateTrigger.less +0 -8
  72. package/src/dateLookup/dateTrigger/DateTrigger.spec.js +1 -1
  73. package/src/dateLookup/dateTrigger/DateTrigger.tsx +9 -4
  74. package/src/field/Field.css +4 -0
  75. package/src/field/Field.less +5 -0
  76. package/src/field/Field.spec.tsx +3 -3
  77. package/src/field/Field.story.tsx +106 -7
  78. package/src/field/Field.tsx +12 -6
  79. package/src/i18n/en.json +3 -2
  80. package/src/index.ts +1 -1
  81. package/src/inlineAlert/InlineAlert.story.tsx +8 -72
  82. package/src/inlineAlert/InlineAlert.tsx +5 -3
  83. package/src/inputs/InputGroup.spec.tsx +1 -1
  84. package/src/inputs/SearchInput.spec.tsx +1 -1
  85. package/src/inputs/SelectInput.spec.tsx +1 -1
  86. package/src/label/Label.messages.tsx +12 -0
  87. package/src/label/Label.story.tsx +19 -25
  88. package/src/label/Label.tsx +38 -2
  89. package/src/label/index.ts +2 -0
  90. package/src/main.css +4 -14
  91. package/src/main.less +1 -0
  92. package/src/moneyInput/MoneyInput.story.tsx +0 -2
  93. package/src/radioGroup/RadioGroup.rtl.spec.tsx +1 -1
  94. package/src/select/Select.rtl.spec.tsx +1 -1
  95. package/src/switch/Switch.spec.tsx +1 -1
  96. package/src/upload/Upload.css +0 -6
  97. package/src/upload/Upload.less +0 -5
  98. package/src/upload/Upload.messages.ts +0 -4
  99. package/src/upload/Upload.spec.js +7 -8
  100. package/src/upload/Upload.story.tsx +0 -18
  101. package/src/upload/Upload.tsx +20 -39
  102. package/src/upload/steps/completeStep/completeStep.spec.js +9 -0
  103. package/src/upload/steps/completeStep/completeStep.tsx +29 -14
  104. package/src/upload/steps/uploadImageStep/uploadImageStep.spec.js +0 -12
  105. package/src/upload/steps/uploadImageStep/uploadImageStep.tsx +24 -43
  106. package/src/field/Field.tests.story.tsx +0 -33
@@ -2,9 +2,9 @@ import { select, text } from '@storybook/addon-knobs';
2
2
  import { Meta } from '@storybook/react';
3
3
 
4
4
  import { Sentiment } from '../common';
5
- import { Input } from '../inputs/Input';
6
5
 
7
6
  import InlineAlert, { InlineAlertProps } from './InlineAlert';
7
+ import { lorem40 } from '../test-utils';
8
8
 
9
9
  export default {
10
10
  component: InlineAlert,
@@ -29,81 +29,17 @@ export const Basic = () => {
29
29
 
30
30
  const message = text('message', 'Please enter a password over 5 characters');
31
31
 
32
- let typeClass = '';
33
- switch (type) {
34
- case Sentiment.ERROR:
35
- case Sentiment.NEGATIVE:
36
- typeClass = 'has-error';
37
- break;
38
- case Sentiment.SUCCESS:
39
- case Sentiment.POSITIVE:
40
- typeClass = 'has-success';
41
- break;
42
- case Sentiment.INFO:
43
- case Sentiment.NEUTRAL:
44
- typeClass = 'has-info';
45
- break;
46
- case Sentiment.WARNING:
47
- typeClass = 'has-warning';
48
- break;
49
- case Sentiment.PENDING:
50
- }
51
-
52
32
  return (
53
33
  <>
54
- {/* eslint-disable-next-line react/no-adjacent-inline-elements */}
55
- <p>
56
- The styling for the input (the coloured border) and the visibility of the inline alert is
57
- controlled through the use of <code>has-***</code> classes which are applied to the{' '}
58
- <code>form-group</code> element. For example, to display an inline alert of type error, you
59
- must also apply the class <code>has-error</code> to the parent <code>form-group</code>{' '}
60
- element. The available classes are <code>has-error</code>, <code>has-info</code>,{' '}
61
- <code>has-warning</code> and <code>has-success</code>.
62
- </p>
63
34
  <p>
64
- Where possible consumers should use{' '}
65
- <a href="https://storybook.wise.design/?path=/story/field--basic">Field</a> instead of doing
66
- this manually.
35
+ Avoid using <code>InlineAlert</code> directly (unless for some custom use cases), for form
36
+ control validation, info messaging please use <code>Field</code> component
37
+ <pre>{'<Field sentiment={..} message={..}>'}</pre>
67
38
  </p>
68
- <div className={`form-group ${typeClass}`}>
69
- <label className="control-label" htmlFor="id0">
70
- Toggleable
71
- </label>
72
- <Input id="id0" value="Neptune is cool" />
73
- <InlineAlert type={type}>{message}</InlineAlert>
74
- </div>
75
- <div className="form-group has-error">
76
- <label className="control-label" htmlFor="id1">
77
- Negative
78
- </label>
79
- <Input id="id1" value="Neptune is cool" />
80
- <InlineAlert type="negative">{message}</InlineAlert>
81
- </div>
82
- <div className="form-group has-success">
83
- <label className="control-label" htmlFor="id2">
84
- Positive
85
- </label>
86
- <Input id="id2" value="Neptune is cool" />
87
- <InlineAlert type="positive">
88
- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt
89
- ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation
90
- ullamco laboris nisi ut aliquip ex ea commodo consequat.
91
- </InlineAlert>
92
- </div>
93
- <div className="form-group has-neutral">
94
- <label className="control-label" htmlFor="id3">
95
- Neutral
96
- </label>
97
- <Input id="id3" value="Neptune is cool" />
98
- <InlineAlert type="neutral">{message}</InlineAlert>
99
- </div>
100
- <div className="form-group">
101
- <label className="control-label" htmlFor="id4">
102
- No has-* class
103
- </label>
104
- <Input id="id4" value="Neptune is cool" />
105
- <InlineAlert type="negative">{message}</InlineAlert>
106
- </div>
39
+ <InlineAlert type={type}>{message}</InlineAlert>
40
+ <InlineAlert type="negative">{message}</InlineAlert>
41
+ <InlineAlert type="positive">{lorem40}</InlineAlert>
42
+ <InlineAlert type="negative">{message}</InlineAlert>
107
43
  </>
108
44
  );
109
45
  };
@@ -3,6 +3,7 @@ import { ReactNode } from 'react';
3
3
 
4
4
  import { Sentiment, Size } from '../common';
5
5
  import StatusIcon from '../statusIcon';
6
+ import Body from '../body';
6
7
 
7
8
  export interface InlineAlertProps {
8
9
  id?: string;
@@ -26,17 +27,18 @@ export default function InlineAlert({
26
27
  children,
27
28
  }: InlineAlertProps) {
28
29
  return (
29
- <div
30
+ <Body
30
31
  role="alert"
31
32
  id={id}
32
33
  className={clsx(
33
34
  'alert alert-detach',
34
35
  `alert-${type === Sentiment.NEGATIVE || type === Sentiment.ERROR ? 'danger' : type}`,
36
+ 'd-flex',
35
37
  className,
36
38
  )}
37
39
  >
38
40
  {iconTypes.has(type) && <StatusIcon sentiment={type} size={Size.SMALL} />}
39
- <div className="np-text-body-default">{children}</div>
40
- </div>
41
+ {children}
42
+ </Body>
41
43
  );
42
44
  }
@@ -26,6 +26,6 @@ describe('InputGroup', () => {
26
26
  </InputGroup>
27
27
  </Field>,
28
28
  );
29
- expect(screen.getByLabelText('Search…')).toHaveRole('textbox');
29
+ expect(screen.getByLabelText(/Search…/)).toHaveRole('textbox');
30
30
  });
31
31
  });
@@ -11,6 +11,6 @@ describe('SearchInput', () => {
11
11
  <SearchInput />
12
12
  </Field>,
13
13
  );
14
- expect(screen.getByLabelText('Search…')).toHaveRole('searchbox');
14
+ expect(screen.getByLabelText(/Search…/)).toHaveRole('searchbox');
15
15
  });
16
16
  });
@@ -214,6 +214,6 @@ describe('SelectInput', () => {
214
214
  <SelectInput items={[{ type: 'option', value: 'USD' }]} value="USD" />
215
215
  </Field>,
216
216
  );
217
- expect(screen.getByLabelText('Currency')).toHaveAttribute('aria-haspopup');
217
+ expect(screen.getByLabelText(/Currency/)).toHaveAttribute('aria-haspopup');
218
218
  });
219
219
  });
@@ -0,0 +1,12 @@
1
+ import { defineMessages } from 'react-intl';
2
+
3
+ export default defineMessages({
4
+ optionalLabel: {
5
+ id: 'neptune.Label.optional',
6
+ defaultMessage: '(Optional)',
7
+ },
8
+ optionalAriaLabel: {
9
+ id: 'neptune.aria.Label.optional',
10
+ defaultMessage: 'This field is optional',
11
+ },
12
+ });
@@ -1,37 +1,31 @@
1
- import { useState } from 'react';
2
-
3
- import Info from '../info/Info';
4
- import { Input } from '../inputs/Input';
5
1
  import { Label } from './Label';
6
2
 
7
3
  export default {
8
4
  component: Label,
9
5
  title: 'Label',
6
+ tags: ['autodocs'],
10
7
  };
11
8
 
12
9
  export const Basic = () => {
13
- const [value, setValue] = useState<string | undefined>('This is some text');
14
10
  return (
15
- <Label>
16
- Phone number
17
- <Input value={value} id="input" onChange={({ target }) => setValue(target.value)} />
18
- </Label>
19
- );
20
- };
11
+ <>
12
+ <p>
13
+ Avoid using <code>Label</code> component directly (unless for some custom use cases), for
14
+ form control labels and descriptions / info messages, please use <code>Field</code>{' '}
15
+ component
16
+ <pre>{'<Field label={..} description={..} required={..}>'}</pre>
17
+ </p>
21
18
 
22
- export const WithInfo = () => {
23
- const [value, setValue] = useState<string | undefined>('This is some text');
24
- return (
25
- <Label>
26
- <span className="d-flex">
27
- Phone number{' '}
28
- <Info
29
- content="This is some help in popover"
30
- aria-label="The aria label"
31
- className="m-l-1"
32
- />
33
- </span>
34
- <Input value={value} id="input" onChange={({ target }) => setValue(target.value)} />
35
- </Label>
19
+ <Label className="m-b-2">Text Input</Label>
20
+
21
+ <Label className="m-b-2">
22
+ <Label.Optional>Text Input</Label.Optional>
23
+ </Label>
24
+
25
+ <Label className="m-b-2">
26
+ <Label.Optional>Text Input with Description</Label.Optional>
27
+ <Label.Description>This a field Description</Label.Description>
28
+ </Label>
29
+ </>
36
30
  );
37
31
  };
@@ -1,4 +1,9 @@
1
1
  import { clsx } from 'clsx';
2
+ import messages from './Label.messages';
3
+ import { useIntl } from 'react-intl';
4
+ import Body from '../body';
5
+ import { CommonProps } from '../common';
6
+ import { PropsWithChildren } from 'react';
2
7
 
3
8
  export type LabelProps = {
4
9
  id?: string;
@@ -7,14 +12,45 @@ export type LabelProps = {
7
12
  children?: React.ReactNode;
8
13
  };
9
14
 
10
- export const Label = ({ id, htmlFor, className, children }: LabelProps) => {
15
+ const Label = ({ id, htmlFor, className, children }: LabelProps) => {
11
16
  return (
12
17
  <label
13
18
  id={id}
14
19
  htmlFor={htmlFor}
15
- className={clsx('control-label d-flex flex-column gap-y-1 m-b-0', className)}
20
+ className={clsx(
21
+ 'np-label d-flex flex-column m-b-0 np-text-body-default-bold text-primary',
22
+ className,
23
+ )}
16
24
  >
17
25
  {children}
18
26
  </label>
19
27
  );
20
28
  };
29
+
30
+ export type LabelOptionalProps = PropsWithChildren<CommonProps>;
31
+
32
+ const Optional = ({ children, className }: LabelOptionalProps) => {
33
+ const { formatMessage } = useIntl();
34
+ return (
35
+ <div>
36
+ {children}
37
+ <Body
38
+ as="span"
39
+ aria-label={formatMessage(messages.optionalAriaLabel)}
40
+ className={clsx('text-secondary', 'm-l-1', className)}
41
+ >
42
+ {formatMessage(messages.optionalLabel)}
43
+ </Body>
44
+ </div>
45
+ );
46
+ };
47
+
48
+ export type LabelDescriptionProps = PropsWithChildren<CommonProps>;
49
+
50
+ const Description = ({ children, className }: LabelDescriptionProps) =>
51
+ children ? <Body className={clsx('text-secondary', className)}>{children}</Body> : null;
52
+
53
+ Label.Optional = Optional;
54
+ Label.Description = Description;
55
+
56
+ export { Label };
@@ -0,0 +1,2 @@
1
+ export { Label } from './Label';
2
+ export type { LabelProps, LabelOptionalProps, LabelDescriptionProps } from './Label';
package/src/main.css CHANGED
@@ -1719,18 +1719,10 @@ button.np-option {
1719
1719
  white-space: nowrap;
1720
1720
  width: 100%;
1721
1721
  }
1722
- .np-date-trigger .control-label {
1723
- font-weight: 400;
1724
- font-weight: var(--font-weight-regular);
1725
- }
1726
1722
  .np-theme-personal .np-date-trigger {
1727
1723
  padding-left: 16px;
1728
1724
  padding-left: var(--size-16);
1729
1725
  }
1730
- .np-theme-personal .np-date-trigger .control-label + span {
1731
- font-weight: 400;
1732
- font-weight: var(--font-weight-regular);
1733
- }
1734
1726
  .clear-btn {
1735
1727
  transition: color 0.15s ease-in-out;
1736
1728
  color: #c9cbce;
@@ -2385,6 +2377,10 @@ html:not([dir="rtl"]) .np-flow-navigation--sm .np-flow-navigation__stepper {
2385
2377
  border-radius: 9999px !important;
2386
2378
  border-radius: var(--radius-full) !important;
2387
2379
  }
2380
+ .np-field-control {
2381
+ margin-top: 4px;
2382
+ margin-top: var(--size-4);
2383
+ }
2388
2384
  .np-input-group {
2389
2385
  display: inline-grid;
2390
2386
  width: 100%;
@@ -5444,12 +5440,6 @@ html:not([dir="rtl"]) .np-navigation-option {
5444
5440
  .tw-droppable-sm {
5445
5441
  min-height: 245px;
5446
5442
  }
5447
- .upload-error-message {
5448
- margin-top: 24px;
5449
- margin-top: var(--padding-medium);
5450
- border-top: 1px solid rgba(0,0,0,0.10196);
5451
- border-top: 1px solid var(--color-border-neutral);
5452
- }
5453
5443
  .np-upload-button-container {
5454
5444
  border-style: solid;
5455
5445
  }
package/src/main.less CHANGED
@@ -32,6 +32,7 @@
32
32
  @import "./image/Image.less";
33
33
  @import "./info/Info.less";
34
34
  @import "./inputs/Input.less";
35
+ @import "./field/Field.less";
35
36
  @import "./inputs/InputGroup.less";
36
37
  @import "./inputs/SelectInput.less";
37
38
  @import "./inputs/TextArea.less";
@@ -4,8 +4,6 @@ import { Lock } from '@transferwise/icons';
4
4
  import { useState } from 'react';
5
5
 
6
6
  import MoneyInput, { CurrencyOptionItem } from '.';
7
- import Provider from '../provider/Provider';
8
- import translations from '../i18n';
9
7
 
10
8
  export default {
11
9
  component: MoneyInput,
@@ -1,4 +1,4 @@
1
- import { render, screen } from '@testing-library/react';
1
+ import { render, screen } from '../test-utils';
2
2
 
3
3
  import RadioGroup from '.';
4
4
  import { Field } from '../field/Field';
@@ -12,6 +12,6 @@ describe('Select', () => {
12
12
  <Select options={options} selected={options[0]} onChange={() => {}} />
13
13
  </Field>,
14
14
  );
15
- expect(screen.getByLabelText('Currency')).toHaveTextContent('USD');
15
+ expect(screen.getByLabelText(/Currency/)).toHaveTextContent('USD');
16
16
  });
17
17
  });
@@ -89,6 +89,6 @@ describe('Switch', () => {
89
89
  <Switch checked onClick={props.onClick} />
90
90
  </Field>,
91
91
  );
92
- expect(screen.getByLabelText('Dark mode')).toHaveAttribute('role', 'switch');
92
+ expect(screen.getByLabelText(/Dark mode/)).toHaveAttribute('role', 'switch');
93
93
  });
94
94
  });
@@ -13,9 +13,3 @@
13
13
  .tw-droppable-sm {
14
14
  min-height: 245px;
15
15
  }
16
- .upload-error-message {
17
- margin-top: 24px;
18
- margin-top: var(--padding-medium);
19
- border-top: 1px solid rgba(0,0,0,0.10196);
20
- border-top: 1px solid var(--color-border-neutral);
21
- }
@@ -19,8 +19,3 @@
19
19
  .tw-droppable-sm {
20
20
  min-height: 245px;
21
21
  }
22
-
23
- .upload-error-message {
24
- margin-top: var(--padding-medium);
25
- border-top: 1px solid var(--color-border-neutral);
26
- }
@@ -41,8 +41,4 @@ export default defineMessages({
41
41
  id: 'neptune.Upload.usPlaceholder',
42
42
  defaultMessage: 'Drag and drop a file less than {maxSize}MB',
43
43
  },
44
- retry: {
45
- id: 'neptune.Upload.retry',
46
- defaultMessage: 'Retry',
47
- },
48
44
  });
@@ -46,7 +46,6 @@ const props = {
46
46
  psProcessingText: 'psProcessingText',
47
47
  usAccept: 'image/*',
48
48
  usButtonText: 'Or Select File',
49
- usButtonRetryText: 'Try again',
50
49
  usDropMessage: 'Drop file to start upload',
51
50
  usPlaceholder: 'Drag and drop a file less than 5MB',
52
51
  };
@@ -232,7 +231,7 @@ describe('Upload', () => {
232
231
  expect(component.find(CompleteStep)).toHaveLength(1);
233
232
  });
234
233
 
235
- it('step UploadImageStep is called with error props', async () => {
234
+ it('step CompleteStep is called with error props', async () => {
236
235
  component = mount(<Upload {...props} />);
237
236
  const upload = component.children();
238
237
  asyncFileRead.mockImplementation(async () => {
@@ -245,12 +244,12 @@ describe('Upload', () => {
245
244
  await waitForUpload();
246
245
  component.update();
247
246
 
248
- expect(component.find(UploadImageStep).props()).toStrictEqual({
249
- ...UPLOADIMAGE_STEP_PROPS,
250
- isComplete: false,
251
- errorMessage: 'csFailureText',
252
- usButtonText: 'Try again',
253
- usHelpImage: null,
247
+ expect(component.find(CompleteStep).props()).toStrictEqual({
248
+ ...COMPLETED_STEP_PROPS,
249
+ isImage: false,
250
+ isComplete: true,
251
+ isError: true,
252
+ uploadedImage: undefined,
254
253
  });
255
254
  });
256
255
 
@@ -6,7 +6,6 @@ import { MAX_SIZE_DEFAULT } from './Upload';
6
6
 
7
7
  const meta = {
8
8
  component: Upload,
9
- title: 'Forms/Upload',
10
9
  tags: ['autodocs'],
11
10
  argTypes: {
12
11
  maxSize: {
@@ -36,20 +35,3 @@ export const Basic = {
36
35
  onCancel: fn(),
37
36
  },
38
37
  } satisfies Story;
39
-
40
- export const Loading = {
41
- args: {
42
- animationDelay: 10000000000,
43
- maxSize: MAX_SIZE_DEFAULT,
44
- usAccept: 'image/*',
45
- usLabel: 'Front of your ID document',
46
- httpOptions: {
47
- url: 'https://httpbin.org/post',
48
- method: 'POST',
49
- },
50
- onStart: fn(),
51
- onSuccess: fn(),
52
- onFailure: fn(),
53
- onCancel: fn(),
54
- },
55
- } satisfies Story;
@@ -50,7 +50,6 @@ export interface UploadProps extends WrappedComponentProps {
50
50
  */
51
51
  usAccept?: string;
52
52
  usButtonText?: string;
53
- usButtonRetryText?: string;
54
53
  usDisabled?: boolean;
55
54
  usDropMessage?: string;
56
55
  usHelpImage?: React.ReactNode;
@@ -326,7 +325,6 @@ export class Upload extends Component<UploadProps, UploadState> {
326
325
  usDropMessage,
327
326
  usAccept,
328
327
  usButtonText,
329
- usButtonRetryText,
330
328
  usDisabled,
331
329
  usHelpImage,
332
330
  usLabel,
@@ -361,8 +359,8 @@ export class Upload extends Component<UploadProps, UploadState> {
361
359
  'tw-droppable-lg droppable-lg': size === 'lg',
362
360
  'droppable-dropping': isDroppable,
363
361
  'droppable-processing': isProcessing,
364
- 'droppable-complete': isComplete && !isError,
365
- 'droppable-negative': isError && !isProcessing,
362
+ 'droppable-complete': isComplete,
363
+ 'droppable-negative': isError,
366
364
  })}
367
365
  onDragEnter={(event) => this.onDragEnter(event)}
368
366
  onDragLeave={(event) => this.onDragLeave(event)}
@@ -385,36 +383,28 @@ export class Upload extends Component<UploadProps, UploadState> {
385
383
  />
386
384
  )}
387
385
 
388
- {/* Starts render the step when isSuccess is true so markup is there when css transition kicks in
386
+ {isProcessing && (
387
+ <ProcessingStep
388
+ isComplete={isComplete}
389
+ isError={isError}
390
+ isSuccess={isSuccess}
391
+ psButtonText={psButtonText || intl.formatMessage(messages.psButtonText)}
392
+ psProcessingText={psProcessingText || intl.formatMessage(messages.psProcessingText)}
393
+ psButtonDisabled={psButtonDisabled}
394
+ onAnimationCompleted={async (status) => this.onAnimationCompleted(status)}
395
+ onClear={(event) => this.handleOnClear(event)}
396
+ />
397
+ )}
398
+ {/* Starts render the step when isSuccess or isError are true so markup is there when css transition kicks in
389
399
  css transition to work properly */}
390
- {(isSuccess || isComplete) && !isError && (
400
+ {(isSuccess || isError || isComplete) && (
391
401
  <CompleteStep
392
402
  fileName={fileName}
393
403
  isComplete={isComplete}
404
+ isError={isError}
394
405
  isImage={isImage}
395
406
  csButtonText={csButtonText || intl.formatMessage(messages.csButtonText)}
396
- csSuccessText={csSuccessText || intl.formatMessage(messages.csSuccessText)}
397
- uploadedImage={uploadedImage}
398
- onClear={(event) => this.handleOnClear(event)}
399
- />
400
- )}
401
- {isError && !isProcessing && (
402
- <UploadImageStep
403
- fileDropped={async (file) => {
404
- this.reset();
405
- await this.fileDropped(file);
406
- }}
407
- isComplete={!isError}
408
- usAccept={usAccept}
409
- usButtonText={usButtonRetryText || intl.formatMessage(messages.retry)}
410
- usDisabled={usDisabled}
411
- usHelpImage={null}
412
- usLabel={usLabel}
413
- usPlaceholder={
414
- usPlaceholder ||
415
- intl.formatMessage(messages.usPlaceholder, { maxSize: maxSize / 1000000 })
416
- }
417
- errorMessage={this.getErrorMessage(
407
+ csFailureText={this.getErrorMessage(
418
408
  response != null &&
419
409
  typeof response === 'object' &&
420
410
  'status' in response &&
@@ -422,17 +412,8 @@ export class Upload extends Component<UploadProps, UploadState> {
422
412
  ? response.status
423
413
  : undefined,
424
414
  )}
425
- />
426
- )}
427
- {isProcessing && (
428
- <ProcessingStep
429
- isComplete={isComplete}
430
- isError={isError}
431
- isSuccess={isSuccess}
432
- psButtonText={psButtonText || intl.formatMessage(messages.psButtonText)}
433
- psProcessingText={psProcessingText || intl.formatMessage(messages.psProcessingText)}
434
- psButtonDisabled={psButtonDisabled}
435
- onAnimationCompleted={async (status) => this.onAnimationCompleted(status)}
415
+ csSuccessText={csSuccessText || intl.formatMessage(messages.csSuccessText)}
416
+ uploadedImage={uploadedImage}
436
417
  onClear={(event) => this.handleOnClear(event)}
437
418
  />
438
419
  )}
@@ -3,6 +3,7 @@ import { shallow } from 'enzyme';
3
3
 
4
4
  import Body from '../../../body';
5
5
  import Button from '../../../button';
6
+ import StatusIcon from '../../../statusIcon/StatusIcon';
6
7
 
7
8
  import CompleteStep from '.';
8
9
 
@@ -40,6 +41,14 @@ describe('CompleteStep', () => {
40
41
  });
41
42
  });
42
43
 
44
+ describe('when error is true', () => {
45
+ it('renders errorMessage and icon when error is true', () => {
46
+ component = shallow(<CompleteStep {...COMPLETED_STEP_PROPS} isError />);
47
+ expect(component.find('p').text()).toBe(COMPLETED_STEP_PROPS.csFailureText);
48
+ expect(component.find(StatusIcon)).toHaveLength(1);
49
+ });
50
+ });
51
+
43
52
  it('renders button when csButtonText is set up', () => {
44
53
  expect(component.find(Button)).toHaveLength(1);
45
54
  });