@transferwise/components 46.140.0 → 46.141.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (151) hide show
  1. package/build/avatarWrapper/AvatarWrapper.js +3 -4
  2. package/build/avatarWrapper/AvatarWrapper.js.map +1 -1
  3. package/build/avatarWrapper/AvatarWrapper.mjs +4 -5
  4. package/build/avatarWrapper/AvatarWrapper.mjs.map +1 -1
  5. package/build/button/LegacyButton.js.map +1 -1
  6. package/build/button/LegacyButton.mjs.map +1 -1
  7. package/build/common/hooks/useHasIntersected/useHasIntersected.js +6 -4
  8. package/build/common/hooks/useHasIntersected/useHasIntersected.js.map +1 -1
  9. package/build/common/hooks/useHasIntersected/useHasIntersected.mjs +6 -4
  10. package/build/common/hooks/useHasIntersected/useHasIntersected.mjs.map +1 -1
  11. package/build/common/liveRegion/LiveRegion.js +4 -1
  12. package/build/common/liveRegion/LiveRegion.js.map +1 -1
  13. package/build/common/liveRegion/LiveRegion.mjs +4 -1
  14. package/build/common/liveRegion/LiveRegion.mjs.map +1 -1
  15. package/build/dateInput/DateInput.js +10 -10
  16. package/build/dateInput/DateInput.js.map +1 -1
  17. package/build/dateInput/DateInput.mjs +10 -10
  18. package/build/dateInput/DateInput.mjs.map +1 -1
  19. package/build/dateLookup/DateLookup.js +1 -1
  20. package/build/dateLookup/DateLookup.js.map +1 -1
  21. package/build/dateLookup/DateLookup.mjs +1 -1
  22. package/build/dateLookup/DateLookup.mjs.map +1 -1
  23. package/build/dateLookup/monthCalendar/table/MonthCalendarTable.js +1 -1
  24. package/build/dateLookup/monthCalendar/table/MonthCalendarTable.js.map +1 -1
  25. package/build/dateLookup/monthCalendar/table/MonthCalendarTable.mjs +1 -1
  26. package/build/dateLookup/monthCalendar/table/MonthCalendarTable.mjs.map +1 -1
  27. package/build/dateLookup/yearCalendar/table/YearCalendarTable.js +1 -1
  28. package/build/dateLookup/yearCalendar/table/YearCalendarTable.js.map +1 -1
  29. package/build/dateLookup/yearCalendar/table/YearCalendarTable.mjs +1 -1
  30. package/build/dateLookup/yearCalendar/table/YearCalendarTable.mjs.map +1 -1
  31. package/build/expressiveMoneyInput/ExpressiveMoneyInput.js.map +1 -1
  32. package/build/expressiveMoneyInput/ExpressiveMoneyInput.mjs.map +1 -1
  33. package/build/expressiveMoneyInput/amountInput/AmountInput.js +17 -11
  34. package/build/expressiveMoneyInput/amountInput/AmountInput.js.map +1 -1
  35. package/build/expressiveMoneyInput/amountInput/AmountInput.mjs +18 -12
  36. package/build/expressiveMoneyInput/amountInput/AmountInput.mjs.map +1 -1
  37. package/build/expressiveMoneyInput/hooks/useInputStyle.js +8 -6
  38. package/build/expressiveMoneyInput/hooks/useInputStyle.js.map +1 -1
  39. package/build/expressiveMoneyInput/hooks/useInputStyle.mjs +9 -7
  40. package/build/expressiveMoneyInput/hooks/useInputStyle.mjs.map +1 -1
  41. package/build/header/Header.js +1 -1
  42. package/build/header/Header.js.map +1 -1
  43. package/build/header/Header.mjs +1 -1
  44. package/build/header/Header.mjs.map +1 -1
  45. package/build/inputs/SelectInput/BottomSheet/SelectInputBottomSheet.js.map +1 -1
  46. package/build/inputs/SelectInput/BottomSheet/SelectInputBottomSheet.mjs.map +1 -1
  47. package/build/inputs/SelectInput/Options/SelectInputOptions.js +34 -22
  48. package/build/inputs/SelectInput/Options/SelectInputOptions.js.map +1 -1
  49. package/build/inputs/SelectInput/Options/SelectInputOptions.mjs +35 -23
  50. package/build/inputs/SelectInput/Options/SelectInputOptions.mjs.map +1 -1
  51. package/build/inputs/SelectInput/Popover/SelectInputPopover.js.map +1 -1
  52. package/build/inputs/SelectInput/Popover/SelectInputPopover.mjs.map +1 -1
  53. package/build/inputs/SelectInput/SelectInput.js +8 -6
  54. package/build/inputs/SelectInput/SelectInput.js.map +1 -1
  55. package/build/inputs/SelectInput/SelectInput.mjs +9 -7
  56. package/build/inputs/SelectInput/SelectInput.mjs.map +1 -1
  57. package/build/inputs/SelectInput/TriggerButton/SelectInputTriggerButton.js.map +1 -1
  58. package/build/inputs/SelectInput/TriggerButton/SelectInputTriggerButton.mjs.map +1 -1
  59. package/build/main.css +58 -53
  60. package/build/nudge/Nudge.js +31 -15
  61. package/build/nudge/Nudge.js.map +1 -1
  62. package/build/nudge/Nudge.mjs +32 -16
  63. package/build/nudge/Nudge.mjs.map +1 -1
  64. package/build/phoneNumberInput/PhoneNumberInput.js +9 -12
  65. package/build/phoneNumberInput/PhoneNumberInput.js.map +1 -1
  66. package/build/phoneNumberInput/PhoneNumberInput.mjs +9 -12
  67. package/build/phoneNumberInput/PhoneNumberInput.mjs.map +1 -1
  68. package/build/promoCard/PromoCardGroup.js +34 -16
  69. package/build/promoCard/PromoCardGroup.js.map +1 -1
  70. package/build/promoCard/PromoCardGroup.mjs +35 -17
  71. package/build/promoCard/PromoCardGroup.mjs.map +1 -1
  72. package/build/segmentedControl/SegmentedControl.js +6 -1
  73. package/build/segmentedControl/SegmentedControl.js.map +1 -1
  74. package/build/segmentedControl/SegmentedControl.mjs +7 -2
  75. package/build/segmentedControl/SegmentedControl.mjs.map +1 -1
  76. package/build/styles/css/neptune.css +58 -53
  77. package/build/styles/less/neptune-tokens.less +2 -2
  78. package/build/styles/main.css +58 -53
  79. package/build/styles/props/neptune-tokens.css +1 -1
  80. package/build/styles/styles/less/core/viewport-themes.css +46 -42
  81. package/build/styles/styles/less/neptune.css +58 -53
  82. package/build/tabs/Tabs.js +1 -1
  83. package/build/tabs/Tabs.js.map +1 -1
  84. package/build/tabs/Tabs.mjs +1 -1
  85. package/build/tabs/Tabs.mjs.map +1 -1
  86. package/build/tooltip/Tooltip.js +6 -3
  87. package/build/tooltip/Tooltip.js.map +1 -1
  88. package/build/tooltip/Tooltip.mjs +6 -3
  89. package/build/tooltip/Tooltip.mjs.map +1 -1
  90. package/build/types/avatarWrapper/AvatarWrapper.d.ts.map +1 -1
  91. package/build/types/common/hooks/useHasIntersected/useHasIntersected.d.ts.map +1 -1
  92. package/build/types/common/liveRegion/LiveRegion.d.ts.map +1 -1
  93. package/build/types/dateLookup/monthCalendar/table/MonthCalendarTable.d.ts.map +1 -1
  94. package/build/types/expressiveMoneyInput/ExpressiveMoneyInput.d.ts.map +1 -1
  95. package/build/types/expressiveMoneyInput/amountInput/AmountInput.d.ts.map +1 -1
  96. package/build/types/expressiveMoneyInput/hooks/useInputStyle.d.ts +2 -2
  97. package/build/types/expressiveMoneyInput/hooks/useInputStyle.d.ts.map +1 -1
  98. package/build/types/expressiveMoneyInput/hooks/useSelectionRange.d.ts.map +1 -1
  99. package/build/types/inputs/SelectInput/BottomSheet/SelectInputBottomSheet.d.ts.map +1 -1
  100. package/build/types/inputs/SelectInput/Options/SelectInputOptions.d.ts.map +1 -1
  101. package/build/types/inputs/SelectInput/Popover/SelectInputPopover.d.ts.map +1 -1
  102. package/build/types/inputs/SelectInput/SelectInput.d.ts.map +1 -1
  103. package/build/types/nudge/Nudge.d.ts.map +1 -1
  104. package/build/types/phoneNumberInput/PhoneNumberInput.d.ts.map +1 -1
  105. package/build/types/promoCard/PromoCardGroup.d.ts.map +1 -1
  106. package/build/types/segmentedControl/SegmentedControl.d.ts.map +1 -1
  107. package/build/types/tooltip/Tooltip.d.ts.map +1 -1
  108. package/build/types/uploadInput/UploadInput.d.ts.map +1 -1
  109. package/build/uploadInput/UploadInput.js +29 -25
  110. package/build/uploadInput/UploadInput.js.map +1 -1
  111. package/build/uploadInput/UploadInput.mjs +29 -25
  112. package/build/uploadInput/UploadInput.mjs.map +1 -1
  113. package/package.json +3 -3
  114. package/src/avatarWrapper/AvatarWrapper.test.tsx +33 -3
  115. package/src/avatarWrapper/AvatarWrapper.tsx +5 -6
  116. package/src/button/LegacyButton.tsx +1 -1
  117. package/src/button/_stories/Button.test.story.tsx +3 -3
  118. package/src/common/hooks/useContainerSize.test.tsx +1 -1
  119. package/src/common/hooks/useHasIntersected/useHasIntersected.ts +12 -4
  120. package/src/common/liveRegion/LiveRegion.tsx +5 -2
  121. package/src/dateInput/DateInput.tsx +10 -10
  122. package/src/dateLookup/DateLookup.test.story.tsx +16 -0
  123. package/src/dateLookup/DateLookup.tsx +1 -1
  124. package/src/dateLookup/monthCalendar/table/MonthCalendarTable.tsx +1 -5
  125. package/src/dateLookup/yearCalendar/table/YearCalendarTable.tsx +1 -1
  126. package/src/expressiveMoneyInput/ExpressiveMoneyInput.tsx +1 -1
  127. package/src/expressiveMoneyInput/amountInput/AmountInput.tsx +22 -15
  128. package/src/expressiveMoneyInput/hooks/useInputStyle.ts +20 -8
  129. package/src/expressiveMoneyInput/hooks/useSelectionRange.ts +2 -0
  130. package/src/header/Header.tsx +2 -2
  131. package/src/inputs/SelectInput/BottomSheet/SelectInputBottomSheet.tsx +4 -0
  132. package/src/inputs/SelectInput/Options/SelectInputOptions.tsx +43 -27
  133. package/src/inputs/SelectInput/Popover/SelectInputPopover.tsx +4 -0
  134. package/src/inputs/SelectInput/SelectInput.tsx +21 -15
  135. package/src/inputs/SelectInput/TriggerButton/SelectInputTriggerButton.tsx +1 -1
  136. package/src/main.css +58 -53
  137. package/src/nudge/Nudge.tsx +29 -20
  138. package/src/phoneNumberInput/PhoneNumberInput.test.tsx +16 -0
  139. package/src/phoneNumberInput/PhoneNumberInput.tsx +11 -13
  140. package/src/promoCard/PromoCard.story.tsx +3 -3
  141. package/src/promoCard/PromoCardGroup.tsx +39 -21
  142. package/src/segmentedControl/SegmentedControl.test.tsx +25 -0
  143. package/src/segmentedControl/SegmentedControl.tsx +7 -1
  144. package/src/select/Select.story.tsx +1 -1
  145. package/src/styles/less/core/viewport-themes.css +46 -42
  146. package/src/styles/less/core/viewport-themes.less +2 -45
  147. package/src/styles/less/neptune.css +58 -53
  148. package/src/tabs/Tabs.tsx +1 -1
  149. package/src/tooltip/Tooltip.tsx +3 -0
  150. package/src/uploadInput/UploadInput.test.tsx +19 -0
  151. package/src/uploadInput/UploadInput.tsx +28 -24
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Do not edit directly, this file was auto-generated.
3
- * Generated on Wed, 13 May 2026 12:45:11 GMT
3
+ * Generated on Thu, 14 May 2026 16:11:43 GMT
4
4
  */
5
5
 
6
6
  :root {
@@ -144,7 +144,7 @@
144
144
 
145
145
  /**
146
146
  * Do not edit directly, this file was auto-generated.
147
- * Generated on Wed, 13 May 2026 12:45:12 GMT
147
+ * Generated on Thu, 14 May 2026 16:11:44 GMT
148
148
  */
149
149
 
150
150
  .np-theme-personal {
@@ -328,7 +328,7 @@
328
328
 
329
329
  /**
330
330
  * Do not edit directly, this file was auto-generated.
331
- * Generated on Wed, 13 May 2026 12:45:12 GMT
331
+ * Generated on Thu, 14 May 2026 16:11:44 GMT
332
332
  */
333
333
 
334
334
  .np-theme-personal--forest-green {
@@ -512,7 +512,7 @@
512
512
 
513
513
  /**
514
514
  * Do not edit directly, this file was auto-generated.
515
- * Generated on Wed, 13 May 2026 12:45:12 GMT
515
+ * Generated on Thu, 14 May 2026 16:11:44 GMT
516
516
  */
517
517
 
518
518
  .np-theme-personal--bright-green {
@@ -696,7 +696,7 @@
696
696
 
697
697
  /**
698
698
  * Do not edit directly, this file was auto-generated.
699
- * Generated on Wed, 13 May 2026 12:45:12 GMT
699
+ * Generated on Thu, 14 May 2026 16:11:44 GMT
700
700
  */
701
701
 
702
702
  .np-theme-personal--dark {
@@ -880,7 +880,7 @@
880
880
 
881
881
  /**
882
882
  * Do not edit directly, this file was auto-generated.
883
- * Generated on Wed, 13 May 2026 12:45:12 GMT
883
+ * Generated on Thu, 14 May 2026 16:11:44 GMT
884
884
  */
885
885
 
886
886
  .np-theme-platform {
@@ -1064,7 +1064,7 @@
1064
1064
 
1065
1065
  /**
1066
1066
  * Do not edit directly, this file was auto-generated.
1067
- * Generated on Wed, 13 May 2026 12:45:12 GMT
1067
+ * Generated on Thu, 14 May 2026 16:11:44 GMT
1068
1068
  */
1069
1069
 
1070
1070
  .np-theme-platform--forest-green {
@@ -1248,7 +1248,7 @@
1248
1248
 
1249
1249
  /**
1250
1250
  * Do not edit directly, this file was auto-generated.
1251
- * Generated on Wed, 13 May 2026 12:45:12 GMT
1251
+ * Generated on Thu, 14 May 2026 16:11:44 GMT
1252
1252
  */
1253
1253
 
1254
1254
  .np-theme-business {
@@ -1433,7 +1433,7 @@
1433
1433
 
1434
1434
  /**
1435
1435
  * Do not edit directly, this file was auto-generated.
1436
- * Generated on Wed, 13 May 2026 12:45:12 GMT
1436
+ * Generated on Thu, 14 May 2026 16:11:44 GMT
1437
1437
  */
1438
1438
 
1439
1439
  .np-theme-business--dark {
@@ -1618,7 +1618,7 @@
1618
1618
 
1619
1619
  /**
1620
1620
  * Do not edit directly, this file was auto-generated.
1621
- * Generated on Wed, 13 May 2026 12:45:12 GMT
1621
+ * Generated on Thu, 14 May 2026 16:11:44 GMT
1622
1622
  */
1623
1623
 
1624
1624
  .np-theme-business--forest-green {
@@ -1803,7 +1803,7 @@
1803
1803
 
1804
1804
  /**
1805
1805
  * Do not edit directly, this file was auto-generated.
1806
- * Generated on Wed, 13 May 2026 12:45:12 GMT
1806
+ * Generated on Thu, 14 May 2026 16:11:44 GMT
1807
1807
  */
1808
1808
 
1809
1809
  .np-theme-business--bright-green {
@@ -4351,48 +4351,53 @@ a.text-inverse:focus {
4351
4351
 
4352
4352
  @media (max-width: 320px) {
4353
4353
  .np-theme-personal {
4354
- --delta: 2;
4355
- --size-4: calc(4px / var(--delta));
4356
- --size-5: calc(5px / var(--delta));
4357
- --size-8: calc(8px / var(--delta));
4358
- --size-10: calc(10px / var(--delta));
4359
- --size-12: calc(12px / var(--delta));
4360
- --size-14: calc(14px / var(--delta));
4361
- --size-16: calc(16px / var(--delta));
4362
- --size-24: calc(24px / var(--delta));
4363
- --size-32: calc(32px / var(--delta));
4364
- --size-40: calc(40px / var(--delta));
4365
- --size-48: calc(48px / var(--delta));
4366
- --size-52: calc(52px / var(--delta));
4367
- --size-56: calc(56px / var(--delta));
4368
- --size-60: calc(60px / var(--delta));
4369
- --size-64: calc(64px / var(--delta));
4370
- --size-72: calc(72px / var(--delta));
4371
- --size-80: calc(80px / var(--delta));
4372
- --size-88: calc(88px / var(--delta));
4373
- --size-96: calc(96px / var(--delta));
4374
- --size-104: calc(104px / var(--delta));
4375
- --size-112: calc(112px / var(--delta));
4376
- --size-120: calc(120px / var(--delta));
4377
- --size-126: calc(126px / var(--delta));
4378
- --size-128: calc(128px / var(--delta));
4379
- --size-146: calc(146px / var(--delta));
4380
- --size-154: calc(154px / var(--delta));
4381
- --size-x-small: calc(24px / var(--delta));
4382
- --size-small: calc(32px / var(--delta));
4383
- --size-medium: calc(40px / var(--delta));
4384
- --size-large: calc(48px / var(--delta));
4385
- --size-x-large: calc(56px / var(--delta));
4386
- --size-2x-large: calc(72px / var(--delta));
4387
- --space-content-horizontal: calc(16px / var(--delta));
4388
- --space-small: calc(16px / var(--delta));
4389
- --space-medium: calc(32px / var(--delta));
4390
- --space-large: calc(40px / var(--delta));
4391
- --space-x-large: calc(56px / var(--delta));
4392
- --padding-x-small: var(--size-8);
4393
- --padding-small: var(--size-16);
4394
- --padding-medium: var(--size-24);
4395
- --padding-large: var(--size-32);
4354
+ --padding-x-small: 4px;
4355
+ --padding-small: 8px;
4356
+ --padding-medium: 12px;
4357
+ --padding-large: 16px;
4358
+ --size-4: 2px;
4359
+ --size-5: 2.5px;
4360
+ --size-8: 4px;
4361
+ --size-10: 5px;
4362
+ --size-12: 6px;
4363
+ --size-14: 7px;
4364
+ --size-16: 8px;
4365
+ --size-24: 12px;
4366
+ --size-32: 16px;
4367
+ --size-40: 20px;
4368
+ --size-48: 24px;
4369
+ --size-52: 26px;
4370
+ --size-56: 28px;
4371
+ --size-60: 30px;
4372
+ --size-64: 32px;
4373
+ --size-72: 36px;
4374
+ --size-80: 40px;
4375
+ --size-88: 44px;
4376
+ --size-96: 48px;
4377
+ --size-104: 52px;
4378
+ --size-112: 56px;
4379
+ --size-120: 60px;
4380
+ --size-126: 63px;
4381
+ --size-128: 64px;
4382
+ --size-146: 73px;
4383
+ --size-154: 77px;
4384
+ --size-160: 80px;
4385
+ --size-x-small: 12px;
4386
+ --size-small: 16px;
4387
+ --size-medium: 20px;
4388
+ --size-large: 24px;
4389
+ --size-x-large: 28px;
4390
+ --size-2x-large: 36px;
4391
+ --space-content-horizontal: 8px;
4392
+ --space-small: 8px;
4393
+ --space-medium: 16px;
4394
+ --space-large: 20px;
4395
+ --space-x-large: 28px;
4396
+ }
4397
+ }
4398
+
4399
+ @media (max-width: 320px) {
4400
+ .np-theme-personal {
4396
4401
  --input-height-base: var(--size-32);
4397
4402
  --input-height-large: var(--input-height-small);
4398
4403
  --input-padding: var(--input-padding-small);
package/src/tabs/Tabs.tsx CHANGED
@@ -254,7 +254,7 @@ export default class Tabs extends Component<TabsProps, TabsState> {
254
254
  };
255
255
 
256
256
  onKeyDown = (index: number) => (event: React.KeyboardEvent<HTMLLIElement>) => {
257
- if (event && event.key === 'Enter') {
257
+ if (event?.key === 'Enter') {
258
258
  this.switchTab(index);
259
259
  }
260
260
  };
@@ -51,6 +51,7 @@ const Tooltip = ({
51
51
  middleware: [
52
52
  offset(16),
53
53
  flip({ fallbackPlacements: [Position.TOP] }),
54
+ // eslint-disable-next-line react-hooks/refs -- arrowRef is passed to floating-ui middleware, legitimate API usage
54
55
  arrowMiddleware({ element: arrowRef, padding: 8 }),
55
56
  ],
56
57
  whileElementsMounted: open ? autoUpdate : undefined,
@@ -63,6 +64,7 @@ const Tooltip = ({
63
64
  };
64
65
 
65
66
  return (
67
+ /* eslint-disable react-hooks/refs -- setReference and setFloating are callback refs from floating-ui, safe to pass during render */
66
68
  <span
67
69
  ref={refs.setReference}
68
70
  className="tw-tooltip-container"
@@ -96,6 +98,7 @@ const Tooltip = ({
96
98
  </div>
97
99
  </div>
98
100
  </span>
101
+ /* eslint-enable react-hooks/refs */
99
102
  );
100
103
  };
101
104
 
@@ -66,6 +66,25 @@ describe('UploadInput', () => {
66
66
  jest.useRealTimers();
67
67
  });
68
68
 
69
+ describe('onFilesChange mount behavior', () => {
70
+ it('should not call onFilesChange on initial mount', () => {
71
+ const onFilesChange = jest.fn();
72
+ renderComponent({
73
+ ...props,
74
+ files: [
75
+ {
76
+ id: 1,
77
+ filename: 'existing-file.pdf',
78
+ status: Status.SUCCEEDED,
79
+ },
80
+ ],
81
+ onFilesChange,
82
+ });
83
+
84
+ expect(onFilesChange).not.toHaveBeenCalled();
85
+ });
86
+ });
87
+
69
88
  describe('single file upload', () => {
70
89
  it('should trigger onUploadFiles & onFilesChange with a single FormData entry containing `file` field', async () => {
71
90
  const date = Date.now();
@@ -170,10 +170,10 @@ const UploadInput = ({
170
170
  const inputAttributes = useInputAttributes({ nonLabelable: true });
171
171
  const [markedFileForDelete, setMarkedFileForDelete] = useState<UploadedFile | null>(null);
172
172
  const [lastAttemptedDeleteId, setLastAttemptedDeleteId] = useState<string | number | null>(null);
173
- const [mounted, setMounted] = useState(false);
173
+ const mountedRef = useRef(false);
174
174
  const { formatMessage } = useIntl();
175
175
  const uploadInputRef = useRef<HTMLInputElement | null>(null);
176
- let fileRefs: (HTMLDivElement | UploadItemRef | null)[] = [];
176
+ const fileRefs = useRef<(HTMLDivElement | UploadItemRef | null)[]>([]);
177
177
 
178
178
  const PROGRESS_STATUSES = new Set([Status.PENDING, Status.PROCESSING]);
179
179
 
@@ -196,7 +196,7 @@ const UploadInput = ({
196
196
  updateFileList((list) =>
197
197
  list.filter((fileInList) => file !== fileInList && file.id !== fileInList.id),
198
198
  );
199
- fileRefs = fileRefs.filter((ref) => ref && ref.id !== file.id);
199
+ fileRefs.current = fileRefs.current.filter((ref) => ref && ref.id !== file.id);
200
200
  }
201
201
 
202
202
  function modifyFileInList(file: UploadedFile, updates: Partial<UploadedFile>) {
@@ -208,18 +208,18 @@ const UploadInput = ({
208
208
  }
209
209
 
210
210
  const removeFile = async (file: UploadedFile) => {
211
- const { id, status } = file;
212
- fileRefs = fileRefs.filter((item) => item && item.id !== file.id);
211
+ const { id: fileId, status } = file;
212
+ fileRefs.current = fileRefs.current.filter((item) => item && item.id !== file.id);
213
213
 
214
214
  if (status === Status.FAILED) {
215
215
  removeFileFromList(file);
216
216
  return Promise.resolve();
217
217
  }
218
218
 
219
- if (onDeleteFile && id) {
219
+ if (onDeleteFile && fileId) {
220
220
  modifyFileInList(file, { status: Status.PROCESSING, error: undefined });
221
221
 
222
- return onDeleteFile(id)
222
+ return onDeleteFile(fileId)
223
223
  .then(() => {
224
224
  removeFileFromList(file);
225
225
  })
@@ -248,6 +248,7 @@ const UploadInput = ({
248
248
 
249
249
  function getNumberOfFilesUploaded() {
250
250
  const uploadInitiatedStatus = new Set([Status.SUCCEEDED, Status.PENDING]);
251
+
251
252
  const validFiles = uploadedFilesListReference.current.filter(
252
253
  (file) => file.status && uploadInitiatedStatus.has(file.status),
253
254
  );
@@ -321,14 +322,16 @@ const UploadInput = ({
321
322
  };
322
323
 
323
324
  useEffect(() => {
324
- setMounted(true);
325
- }, []);
325
+ // Skip onFilesChange call on initial mount, only call on updates
326
+ if (!mountedRef.current) {
327
+ mountedRef.current = true;
328
+ return;
329
+ }
326
330
 
327
- useEffect(() => {
328
- if (onFilesChange && mounted) {
331
+ if (onFilesChange) {
329
332
  onFilesChange([...uploadedFiles]);
330
333
  }
331
- }, [onFilesChange, uploadedFiles]); // eslint-disable-line react-hooks/exhaustive-deps
334
+ }, [onFilesChange, uploadedFiles]);
332
335
 
333
336
  type NextFocusable =
334
337
  | HTMLDivElement
@@ -336,14 +339,14 @@ const UploadInput = ({
336
339
  | { ref: HTMLDivElement | UploadItemRef; target: 'button' | 'link' }
337
340
  | null;
338
341
 
339
- const [nextFocusable, setNextFocusable] = useState<NextFocusable>(uploadInputRef.current);
342
+ const [nextFocusable, setNextFocusable] = useState<NextFocusable>(null);
340
343
 
341
344
  const handleFocus = (fileId: string | number) => {
342
- fileRefs = fileRefs.filter((ref) => {
345
+ fileRefs.current = fileRefs.current.filter((ref) => {
343
346
  return ref && ref.id !== markedFileForDelete?.id;
344
347
  });
345
348
 
346
- const filesCount = fileRefs.length;
349
+ const filesCount = fileRefs.current.length;
347
350
  let next: UploadItemRef | HTMLDivElement | null = uploadInputRef.current;
348
351
  let focusTarget: 'button' | 'link' = 'button';
349
352
 
@@ -355,15 +358,15 @@ const UploadInput = ({
355
358
  }
356
359
 
357
360
  if (filesCount > 1) {
358
- const currentFileIndex = fileRefs.findIndex((file) => file?.id === fileId);
359
- const currentFileId = fileRefs?.[currentFileIndex]?.id;
360
- const lastFileId = fileRefs?.[filesCount - 1]?.id;
361
+ const currentFileIndex = fileRefs.current.findIndex((file) => file?.id === fileId);
362
+ const currentFileId = fileRefs.current?.[currentFileIndex]?.id;
363
+ const lastFileId = fileRefs.current?.[filesCount - 1]?.id;
361
364
 
362
365
  // if last file, select a previous one
363
366
  if (currentFileId === lastFileId) {
364
- next = fileRefs[filesCount - 2];
367
+ next = fileRefs.current[filesCount - 2];
365
368
  } else {
366
- next = fileRefs[currentFileIndex + 1];
369
+ next = fileRefs.current[currentFileIndex + 1];
367
370
  }
368
371
 
369
372
  // If next is an UploadItemRef, check if it has a URL (succeeded)
@@ -401,7 +404,7 @@ const UploadInput = ({
401
404
  typeof uploadInputRef.current.focus === 'function'
402
405
  ) {
403
406
  setTimeout(() => {
404
- uploadInputRef.current!.focus();
407
+ uploadInputRef.current?.focus();
405
408
  }, 0);
406
409
  } else if (
407
410
  typeof focusTarget === 'object' &&
@@ -436,17 +439,17 @@ const UploadInput = ({
436
439
  aria-relevant="all"
437
440
  role="region"
438
441
  >
439
- {uploadedFiles.map((file, index) => (
442
+ {uploadedFiles.map((file) => (
440
443
  <UploadItem
441
444
  key={file.id}
442
445
  ref={(el: UploadItemRef | null) => {
443
446
  if (
444
447
  el &&
445
448
  el.id !== markedFileForDelete?.id &&
446
- !fileRefs.some((ref) => ref && ref.id === el.id) &&
449
+ !fileRefs.current.some((ref) => ref?.id === el.id) &&
447
450
  el.status !== 'processing'
448
451
  ) {
449
- fileRefs.push(el);
452
+ fileRefs.current.push(el);
450
453
  }
451
454
  }}
452
455
  file={file}
@@ -478,6 +481,7 @@ const UploadInput = ({
478
481
  ref={uploadInputRef}
479
482
  id={id}
480
483
  uploadButtonTitle={uploadButtonTitle}
484
+ // eslint-disable-next-line react-hooks/refs -- Function reads ref for file count check
481
485
  disabled={areMaximumFilesUploadedAlready() || disabled}
482
486
  multiple={multiple}
483
487
  fileTypes={fileTypes}