@transferwise/components 0.0.0-experimental-b9f8dc1 → 0.0.0-experimental-e1f66d5

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 (44) hide show
  1. package/build/main.css +210 -209
  2. package/build/moneyInput/MoneyInput.js +1 -0
  3. package/build/moneyInput/MoneyInput.js.map +1 -1
  4. package/build/moneyInput/MoneyInput.mjs +1 -0
  5. package/build/moneyInput/MoneyInput.mjs.map +1 -1
  6. package/build/styles/main.css +210 -209
  7. package/build/styles/uploadInput/UploadInput.css +81 -13
  8. package/build/styles/uploadInput/uploadButton/UploadButton.css +31 -77
  9. package/build/styles/uploadInput/uploadItem/UploadItem.css +109 -130
  10. package/build/types/moneyInput/MoneyInput.d.ts.map +1 -1
  11. package/build/types/uploadInput/UploadInput.d.ts.map +1 -1
  12. package/build/types/uploadInput/uploadButton/UploadButton.d.ts +0 -5
  13. package/build/types/uploadInput/uploadButton/UploadButton.d.ts.map +1 -1
  14. package/build/types/uploadInput/uploadItem/UploadItem.d.ts.map +1 -1
  15. package/build/uploadInput/UploadInput.js +20 -30
  16. package/build/uploadInput/UploadInput.js.map +1 -1
  17. package/build/uploadInput/UploadInput.mjs +20 -30
  18. package/build/uploadInput/UploadInput.mjs.map +1 -1
  19. package/build/uploadInput/uploadButton/UploadButton.js +32 -25
  20. package/build/uploadInput/uploadButton/UploadButton.js.map +1 -1
  21. package/build/uploadInput/uploadButton/UploadButton.mjs +32 -25
  22. package/build/uploadInput/uploadButton/UploadButton.mjs.map +1 -1
  23. package/build/uploadInput/uploadItem/UploadItem.js +38 -32
  24. package/build/uploadInput/uploadItem/UploadItem.js.map +1 -1
  25. package/build/uploadInput/uploadItem/UploadItem.mjs +39 -33
  26. package/build/uploadInput/uploadItem/UploadItem.mjs.map +1 -1
  27. package/build/uploadInput/uploadItem/UploadItemLink.js +1 -2
  28. package/build/uploadInput/uploadItem/UploadItemLink.js.map +1 -1
  29. package/build/uploadInput/uploadItem/UploadItemLink.mjs +1 -2
  30. package/build/uploadInput/uploadItem/UploadItemLink.mjs.map +1 -1
  31. package/package.json +3 -3
  32. package/src/main.css +210 -209
  33. package/src/moneyInput/MoneyInput.tsx +1 -0
  34. package/src/uploadInput/UploadInput.css +81 -13
  35. package/src/uploadInput/UploadInput.less +80 -18
  36. package/src/uploadInput/UploadInput.tests.story.tsx +5 -5
  37. package/src/uploadInput/UploadInput.tsx +32 -43
  38. package/src/uploadInput/uploadButton/UploadButton.css +31 -77
  39. package/src/uploadInput/uploadButton/UploadButton.less +35 -77
  40. package/src/uploadInput/uploadButton/UploadButton.tsx +26 -37
  41. package/src/uploadInput/uploadItem/UploadItem.css +109 -130
  42. package/src/uploadInput/uploadItem/UploadItem.less +118 -130
  43. package/src/uploadInput/uploadItem/UploadItem.tsx +28 -26
  44. package/src/uploadInput/uploadItem/UploadItemLink.tsx +3 -3
@@ -3,28 +3,90 @@
3
3
  @import (reference) './uploadItem/UploadItem.less';
4
4
 
5
5
  .np-upload-input {
6
- --outerBorder: 1px solid var(--color-interactive-secondary);
7
- border-radius: var(--radius-small);
6
+ &.form-control {
7
+ height: auto;
8
+ padding: initial;
9
+ }
10
+
11
+ & > div {
12
+ &:first-child,
13
+ &:first-child .np-upload-item--single-file,
14
+ &:first-child .np-upload-item--link {
15
+ border-top-left-radius: var(--radius-small);
16
+ border-top-right-radius: var(--radius-small);
17
+ }
18
+
19
+ &:last-child {
20
+ border-bottom-left-radius: var(--radius-small);
21
+ border-bottom-right-radius: var(--radius-small);
22
+ }
23
+ }
24
+ }
25
+
26
+ .np-theme-personal {
27
+ .np-upload-input {
28
+ &.disabled .btn {
29
+ cursor: inherit;
30
+ }
31
+
32
+ .np-upload-icon {
33
+ color: var(--color-interactive-primary);
34
+ }
35
+
36
+ .media-body {
37
+ padding-right: var(--size-32);
38
+ color: var(--color-content-link);
39
+ white-space: break-spaces;
40
+
41
+ @media (--screen-400-zoom) {
42
+ padding-right: var(--size-64);
43
+ }
44
+
45
+ .np-text-body-large-bold {
46
+ text-decoration: underline;
47
+ .link-underline();
48
+ }
49
+
50
+ .np-text-body-default,
51
+ .np-upload-description,
52
+ .text-positive {
53
+ color: var(--color-content-secondary) !important;
54
+ }
55
+
56
+ .text-negative {
57
+ color: var(--color-sentiment-negative) !important;
58
+ }
59
+ }
60
+
61
+ &-errors {
62
+ list-style: none;
63
+ padding-left: 0;
8
64
 
9
- .np-upload-input__section {
10
- margin: 0;
65
+ li {
66
+ position: relative;
67
+ padding-left: var(--size-16);
11
68
 
12
- // only 1 file allowed and already uploaded (no UploadButton shown)
13
- &:only-child {
14
- .np-upload-input__item {
15
- border-radius: var(--radius-small);
16
- border-bottom: var(--outerBorder);
69
+ @media (--screen-400-zoom) {
70
+ padding-left: var(--size-32);
71
+ }
72
+
73
+ &:before {
74
+ content: '•';
75
+ position: absolute;
76
+ display: block;
77
+ left: 0;
78
+ }
17
79
  }
18
80
  }
19
81
 
20
- // if the last item in the file list is interactive (not an error)
21
- // and the user is hovering over it, then we need to adjust the
22
- // bottom separator, which happens to be in .np-upload-input__section--uploader
23
- &:has(.np-upload-input__item:last-child.is-interactive:hover):not(:has(.np-upload-input__item-button:hover))
24
- + .np-upload-input__section--uploader .np-upload-input__upload-button::before {
25
- left: 0;
26
- width: 100%;
27
- top: 0;
82
+ .status-circle {
83
+ width: var(--size-x-small);
84
+ height: var(--size-x-small);
85
+
86
+ @media (--screen-400-zoom) {
87
+ width: var(--size-large);
88
+ height: var(--size-large);
89
+ }
28
90
  }
29
91
  }
30
- }
92
+ }
@@ -25,23 +25,23 @@ const files = [
25
25
  filename: 'purchase-receipt-1.pdf',
26
26
  },
27
27
  {
28
- id: 3,
29
- filename: 'purchase-receipt-2.pdf',
28
+ id: 6,
29
+ filename: 'purchase-receipt-1.pdf',
30
30
  url: 'https://wise.com/public-resources/assets/logos/wise/brand_logo_inverse.svg',
31
31
  },
32
32
  {
33
- id: 4,
33
+ id: 3,
34
34
  filename: 'receipt failed.png',
35
35
  status: Status.FAILED,
36
36
  },
37
37
  {
38
- id: 5,
38
+ id: 4,
39
39
  filename: 'receipt failed With error string.png',
40
40
  status: Status.FAILED,
41
41
  error: 'Something went wrong',
42
42
  },
43
43
  {
44
- id: 6,
44
+ id: 5,
45
45
  filename: 'receipt failed With error object.png',
46
46
  status: Status.FAILED,
47
47
  error: { message: 'Something went wrong' },
@@ -345,50 +345,39 @@ const UploadInput = ({
345
345
  className={clsx('np-upload-input', className, { disabled })}
346
346
  {...inputAttributes}
347
347
  >
348
- <div
349
- className="np-upload-input__section"
350
- aria-live="polite"
351
- aria-relevant="all"
352
- role="region"
353
- >
354
- {uploadedFiles.map((file, index) => (
355
- <UploadItem
356
- key={file.id}
357
- ref={(el: UploadItemRef | null) => {
358
- itemRefs.current[index] = el;
359
- }}
360
- file={file}
361
- singleFileUpload={!multiple}
362
- canDelete={
363
- (!!onDeleteFile || file.status === Status.FAILED) &&
364
- (!file.status || !PROGRESS_STATUSES.has(file.status))
365
- }
366
- onDelete={
367
- file.status === Status.FAILED
368
- ? () => removeFile(file)
369
- : () => setMarkedFileForDelete(file)
370
- }
371
- onDownload={onDownload}
372
- />
373
- ))}
374
- </div>
348
+ {uploadedFiles.map((file, index) => (
349
+ <UploadItem
350
+ key={file.id}
351
+ ref={(el: UploadItemRef | null) => {
352
+ itemRefs.current[index] = el;
353
+ }}
354
+ file={file}
355
+ singleFileUpload={!multiple}
356
+ canDelete={
357
+ (!!onDeleteFile || file.status === Status.FAILED) &&
358
+ (!file.status || !PROGRESS_STATUSES.has(file.status))
359
+ }
360
+ onDelete={
361
+ file.status === Status.FAILED
362
+ ? () => removeFile(file)
363
+ : () => setMarkedFileForDelete(file)
364
+ }
365
+ onDownload={onDownload}
366
+ />
367
+ ))}
375
368
  {(multiple || (!multiple && !uploadedFiles.length)) && (
376
- <div className="np-upload-input__section np-upload-input__section--uploader">
377
- <UploadButton
378
- ref={uploadInputRef}
379
- id={id}
380
- uploadButtonTitle={uploadButtonTitle}
381
- disabled={areMaximumFilesUploadedAlready() || disabled}
382
- multiple={multiple}
383
- fileTypes={fileTypes}
384
- sizeLimit={sizeLimit}
385
- description={description}
386
- maxFiles={maxFiles}
387
- withEntries={Boolean(uploadedFiles.length)}
388
- onChange={addFiles}
389
-
390
- />
391
- </div>
369
+ <UploadButton
370
+ ref={uploadInputRef}
371
+ id={id}
372
+ uploadButtonTitle={uploadButtonTitle}
373
+ disabled={areMaximumFilesUploadedAlready() || disabled}
374
+ multiple={multiple}
375
+ fileTypes={fileTypes}
376
+ sizeLimit={sizeLimit}
377
+ description={description}
378
+ maxFiles={maxFiles}
379
+ onChange={addFiles}
380
+ />
392
381
  )}
393
382
  </div>
394
383
  <Modal
@@ -1,90 +1,44 @@
1
- .np-upload-input__upload-button {
2
- position: relative;
3
- padding: 16px;
4
- padding: var(--size-16);
5
- display: flex;
6
- align-items: center;
7
- margin: 0;
8
- border-bottom-left-radius: 10px;
9
- border-bottom-left-radius: var(--radius-small);
10
- border-bottom-right-radius: 10px;
11
- border-bottom-right-radius: var(--radius-small);
12
- border: var(--outerBorder);
13
- cursor: pointer;
14
- }
15
- .np-upload-input__upload-button .np-upload-input__title {
16
- color: var(--color-content-link);
17
- -webkit-text-decoration: underline;
18
- text-decoration: underline;
19
- text-underline-offset: 0.3em;
20
- }
21
- .np-upload-input__upload-button .np-upload-input__title + .np-upload-input__text {
22
- margin-top: 4px;
23
- margin-top: var(--size-4);
1
+ .np-upload-button-container {
2
+ border-style: solid;
24
3
  }
25
- .np-upload-input__upload-button .np-upload-input__icon {
26
- padding-right: 16px;
27
- padding-right: var(--size-16);
28
- color: var(--color-interactive-primary);
4
+ .np-upload-button-container .droppable-card-content {
5
+ display: flex;
29
6
  }
30
- .np-upload-input__upload-button.is-dropping .np-upload-input__icon,
31
- .np-upload-input__upload-button.is-dropping .np-upload-input__item-content {
32
- display: none;
7
+ .np-upload-button-container.droppable-dropping {
8
+ border-color: #c9cbce !important;
9
+ border-color: var(--color-interactive-secondary) !important;
33
10
  }
34
- .np-upload-input__upload-button:focus-within,
35
- .np-upload-input__upload-button:focus-visible {
36
- outline: var(--ring-outline-color) solid 3px;
37
- outline-offset: -3px;
11
+ .np-upload-button-container.droppable-dropping:before {
12
+ z-index: 2;
38
13
  }
39
- .np-upload-input__upload-button-input {
40
- position: absolute;
14
+ .np-upload-button-container input[type="file"] {
41
15
  opacity: 0;
42
16
  z-index: -1;
17
+ position: absolute;
43
18
  }
44
- .np-upload-input__upload-button-input:focus {
45
- outline: none;
46
- }
47
- .np-upload-input__upload-button .np-upload-input__drop-file-overlay {
48
- display: flex;
49
- flex: 1;
50
- padding: 13px 0 !important;
51
- background-color: transparent;
52
- transition: transform 0.3s ease;
53
- position: relative;
54
- }
55
- .np-upload-input__upload-button--with-entries {
56
- border-top-width: 0;
19
+ .np-upload-button-container .np-upload-button {
20
+ border: none;
57
21
  }
58
- .np-upload-input__upload-button--with-entries:before {
59
- display: block;
60
- position: absolute;
61
- height: 1px;
62
- background-color: rgba(0,0,0,0.10196);
63
- background-color: var(--color-border-neutral);
64
- content: " ";
65
- left: 16px;
66
- left: var(--size-16);
67
- width: calc(100% - 2 * 16px);
68
- width: calc(100% - 2 * var(--size-16));
69
- top: 0;
22
+ .np-upload-button {
23
+ width: 100%;
24
+ border-top: 1px solid transparent;
25
+ padding: 16px;
26
+ padding: var(--padding-small);
27
+ border-radius: 0;
70
28
  }
71
- .np-upload-input__upload-button--without-entries {
72
- border-top: var(--outerBorder);
73
- border-radius: 10px;
74
- border-radius: var(--radius-small);
29
+ label.np-upload-button:not(.disabled):hover,
30
+ label.np-upload-button:not(.disabled):active {
31
+ background-color: var(--color-background-screen-hover);
75
32
  }
76
- .np-upload-input__upload-button--enabled.is-dropping,
77
- .np-upload-input__upload-button--enabled:hover,
78
- .np-upload-input__upload-button--enabled:active {
79
- background: rgba(134,167,189,0.10196);
80
- background: var(--color-background-neutral);
33
+ .disabled label.np-upload-button:not(.disabled):hover,
34
+ .disabled label.np-upload-button:not(.disabled):active {
35
+ background-color: transparent;
81
36
  }
82
- .np-upload-input__upload-button--enabled.is-dropping:before,
83
- .np-upload-input__upload-button--enabled:hover:before,
84
- .np-upload-input__upload-button--enabled:active:before {
85
- width: 100%;
86
- left: 0;
37
+ .np-upload-button .media {
38
+ align-items: flex-start;
87
39
  }
88
- .np-upload-input__upload-button--disabled {
89
- cursor: inherit;
40
+ @media (max-width: 320px) {
41
+ .np-upload-icon {
42
+ padding-left: 0;
43
+ }
90
44
  }
@@ -1,97 +1,55 @@
1
- .np-upload-input__upload-button {
2
- position: relative;
3
- padding: var(--size-16);
4
- display: flex;
5
- align-items: center;
6
- margin: 0;
7
- border-bottom-left-radius: var(--radius-small);
8
- border-bottom-right-radius: var(--radius-small);
9
- border: var(--outerBorder);
10
- cursor: pointer;
1
+ .np-upload-button-container {
2
+ border-style: solid;
11
3
 
12
- .np-upload-input__title {
13
- color: var(--color-content-link);
14
- text-decoration: underline;
15
- text-underline-offset: 0.3em;
16
-
17
- & + .np-upload-input__text {
18
- margin-top: var(--size-4);
19
- }
4
+ .droppable-card-content {
5
+ display: flex;
20
6
  }
21
7
 
22
- .np-upload-input__icon {
23
- padding-right: var(--size-16);
24
- color: var(--color-interactive-primary);
25
- }
8
+ &.droppable-dropping {
9
+ border-color: var(--color-interactive-secondary) !important;
26
10
 
27
- &.is-dropping {
28
- .np-upload-input__icon,
29
- .np-upload-input__item-content {
30
- display: none;
11
+ &:before {
12
+ z-index: 2;
31
13
  }
32
14
  }
33
15
 
34
- &:focus-within,
35
- &:focus-visible {
36
- outline: var(--ring-outline-color) solid 3px;
37
- outline-offset: -3px;
38
- }
39
-
40
- &-input {
41
- position: absolute;
16
+ input[type="file"] {
42
17
  opacity: 0;
43
18
  z-index: -1;
44
-
45
- &:focus {
46
- outline: none;
47
- }
19
+ position: absolute;
48
20
  }
49
21
 
50
- .np-upload-input__drop-file-overlay {
51
- display: flex;
52
- flex: 1;
53
- padding: 13px 0 !important;
54
- background-color: transparent;
55
- transition: transform 0.3s ease;
56
- position: relative;
22
+ .np-upload-button {
23
+ border: none;
57
24
  }
58
25
  }
59
26
 
60
- // at least 1 file uploaded or 1 error visible
61
- .np-upload-input__upload-button--with-entries {
62
- border-top-width: 0;
63
-
64
- &:before {
65
- display: block;
66
- position: absolute;
67
- height: 1px;
68
- background-color: var(--color-border-neutral);
69
- content: " ";
70
- left: var(--size-16);
71
- width: calc(100% - 2 * var(--size-16));
72
- top: 0;
27
+ .np-upload-button {
28
+ width: 100%;
29
+ border-top: 1px solid transparent;
30
+ padding: var(--padding-small);
31
+ border-radius: 0;
32
+
33
+ label& {
34
+ &:not(.disabled) {
35
+ &:hover,
36
+ &:active {
37
+ background-color: var(--color-background-screen-hover);
38
+
39
+ .disabled & {
40
+ background-color: transparent;
41
+ }
42
+ }
43
+ }
73
44
  }
74
- }
75
45
 
76
- // no files uploaded (only button shown)
77
- .np-upload-input__upload-button--without-entries {
78
- border-top: var(--outerBorder);
79
- border-radius: var(--radius-small);
80
- }
81
-
82
- .np-upload-input__upload-button--enabled {
83
- &.is-dropping,
84
- &:hover,
85
- &:active {
86
- background: var(--color-background-neutral);
87
-
88
- &:before {
89
- width: 100%;
90
- left: 0;
91
- }
46
+ .media {
47
+ align-items: flex-start;
92
48
  }
93
49
  }
94
50
 
95
- .np-upload-input__upload-button--disabled {
96
- cursor: inherit;
51
+ .np-upload-icon{
52
+ @media (max-width: 320px) {
53
+ padding-left: 0;
54
+ }
97
55
  }
@@ -25,12 +25,6 @@ export type UploadButtonProps = {
25
25
  */
26
26
  disabled?: boolean;
27
27
 
28
- /**
29
- * Should be true, if the UploadInput has at least 1
30
- * file (valid or invalid) listed.
31
- */
32
- withEntries?: boolean;
33
-
34
28
  /**
35
29
  * Allow multiple file uploads
36
30
  */
@@ -88,7 +82,6 @@ const UploadButton = forwardRef<HTMLInputElement | null, UploadButtonProps>(
88
82
  (
89
83
  {
90
84
  disabled,
91
- withEntries,
92
85
  multiple,
93
86
  description,
94
87
  fileTypes = imageFileTypes,
@@ -195,7 +188,7 @@ const UploadButton = forwardRef<HTMLInputElement | null, UploadButtonProps>(
195
188
 
196
189
  function renderDescription() {
197
190
  return (
198
- <Body className="np-upload-input__text">
191
+ <Body className={clsx({ 'text-primary': !disabled })}>
199
192
  {getDescription()}
200
193
  {maxFiles && (
201
194
  <>
@@ -215,53 +208,49 @@ const UploadButton = forwardRef<HTMLInputElement | null, UploadButtonProps>(
215
208
  }
216
209
 
217
210
  return (
218
- <label
219
- className={clsx(
220
- 'np-upload-input__upload-button',
221
- `np-upload-input__upload-button--${disabled ? 'disabled' : 'enabled'}`,
222
- `np-upload-input__upload-button--${withEntries ? 'with-entries' : 'without-entries'}`,
223
- {
224
- 'is-dropping': isDropping,
225
- },
226
- )}
227
- htmlFor={id}
211
+ <div
212
+ className={clsx('np-upload-button-container', 'droppable', {
213
+ 'droppable-dropping': isDropping,
214
+ })}
228
215
  {...(!disabled && { onDragEnter, onDragLeave, onDrop, onDragOver })}
229
216
  >
230
- <span className="np-upload-input__icon">
231
- <UploadIcon size={24} className="text-link" />
232
- </span>
233
- <div className="np-upload-input__item-content" data-testid={TEST_IDS.mediaBody}>
234
- <Body type={Typography.BODY_LARGE_BOLD} className="np-upload-input__title">
235
- {renderButtonTitle()}
236
- </Body>
237
- {renderDescription()}
238
- </div>
239
217
  <input
240
- className="np-upload-input__upload-button-input sr-only"
241
- type="file"
218
+ ref={inputRef}
242
219
  id={id}
220
+ type="file"
243
221
  {...getAcceptedTypes()}
244
222
  {...(multiple && { multiple: true })}
245
- ref={inputRef}
223
+ className="tw-droppable-input"
246
224
  disabled={disabled}
247
225
  name="file-upload"
248
226
  data-testid={TEST_IDS.uploadInput}
249
227
  onChange={filesSelected}
250
228
  />
229
+ {/* eslint-disable-next-line jsx-a11y/label-has-associated-control */}
230
+ <label htmlFor={id} className={clsx('btn', 'np-upload-button')}>
231
+ <div className="media">
232
+ <div className="np-upload-icon media-middle media-left">
233
+ <UploadIcon size={24} className="text-link" />
234
+ </div>
235
+ <div className="media-body text-xs-left" data-testid={TEST_IDS.mediaBody}>
236
+ <Body type={Typography.BODY_LARGE_BOLD} className="d-block">
237
+ {renderButtonTitle()}
238
+ </Body>
239
+ {renderDescription()}
240
+ </div>
241
+ </div>
242
+ </label>
243
+
244
+ {/* Drop area overlay */}
251
245
  {isDropping && (
252
246
  <div
253
- className={clsx(
254
- 'np-upload-input__drop-file-overlay',
255
- 'droppable-card',
256
- 'droppable-dropping-card',
257
- 'droppable-card-content',
258
- )}
247
+ className={clsx('droppable-card', 'droppable-dropping-card', 'droppable-card-content')}
259
248
  >
260
249
  <PlusIcon className="m-x-1" size={24} />
261
250
  <div>{formatMessage(MESSAGES.dropFile)}</div>
262
251
  </div>
263
252
  )}
264
- </label>
253
+ </div>
265
254
  );
266
255
  },
267
256
  );