@transferwise/components 46.40.0 → 46.41.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/build/index.js +68 -74
  2. package/build/index.js.map +1 -1
  3. package/build/index.mjs +69 -75
  4. package/build/index.mjs.map +1 -1
  5. package/build/main.css +69 -14
  6. package/build/styles/main.css +69 -14
  7. package/build/styles/statusIcon/StatusIcon.css +4 -2
  8. package/build/styles/uploadInput/UploadInput.css +18 -1
  9. package/build/styles/uploadInput/uploadButton/UploadButton.css +4 -0
  10. package/build/styles/uploadInput/uploadItem/UploadItem.css +43 -11
  11. package/build/types/dateInput/DateInput.d.ts.map +1 -1
  12. package/build/types/field/Field.d.ts +6 -1
  13. package/build/types/field/Field.d.ts.map +1 -1
  14. package/build/types/inlineAlert/InlineAlert.d.ts.map +1 -1
  15. package/package.json +4 -4
  16. package/src/dateInput/DateInput.spec.tsx +220 -0
  17. package/src/dateInput/DateInput.story.tsx +3 -76
  18. package/src/dateInput/DateInput.tests.story.tsx +238 -0
  19. package/src/dateInput/DateInput.tsx +50 -53
  20. package/src/field/Field.story.tsx +17 -36
  21. package/src/field/Field.tests.story.tsx +33 -0
  22. package/src/field/Field.tsx +23 -13
  23. package/src/inlineAlert/InlineAlert.story.tsx +13 -5
  24. package/src/inlineAlert/InlineAlert.tsx +13 -6
  25. package/src/main.css +69 -14
  26. package/src/statusIcon/StatusIcon.css +4 -2
  27. package/src/statusIcon/StatusIcon.less +4 -2
  28. package/src/statusIcon/StatusIcon.tsx +1 -1
  29. package/src/uploadInput/UploadInput.css +18 -1
  30. package/src/uploadInput/UploadInput.less +17 -1
  31. package/src/uploadInput/UploadInput.tests.story.tsx +13 -2
  32. package/src/uploadInput/uploadButton/UploadButton.css +4 -0
  33. package/src/uploadInput/uploadButton/UploadButton.less +5 -0
  34. package/src/uploadInput/uploadItem/UploadItem.css +43 -11
  35. package/src/uploadInput/uploadItem/UploadItem.less +61 -17
  36. package/src/dateInput/DateInput.rtl.spec.tsx +0 -17
  37. package/src/dateInput/DateInput.spec.js +0 -477
package/build/index.js CHANGED
@@ -746,7 +746,7 @@ const StatusIcon = ({
746
746
  const iconColor = sentiment === 'warning' || sentiment === 'pending' ? 'dark' : 'light';
747
747
  return /*#__PURE__*/jsxRuntime.jsx("span", {
748
748
  "data-testid": "status-icon",
749
- className: classNames__default.default('status-circle', 'status-circle-' + size, sentiment),
749
+ className: classNames__default.default('status-circle', `status-circle-${size}`, sentiment),
750
750
  children: /*#__PURE__*/jsxRuntime.jsx(Icon, {
751
751
  className: classNames__default.default('status-icon', iconColor)
752
752
  })
@@ -3188,8 +3188,10 @@ const DateInput = ({
3188
3188
  return null;
3189
3189
  };
3190
3190
  const [day, setDay] = React.useState(() => getInitialDate('day'));
3191
+ const [displayDay, setDisplayDay] = React.useState(day?.toString());
3191
3192
  const [month, setMonth] = React.useState(() => getInitialDate('month'));
3192
3193
  const [year, setYear] = React.useState(() => getInitialDate('year'));
3194
+ const [displayYear, setDisplayYear] = React.useState(year?.toString());
3193
3195
  const [lastBroadcastedValue, setLastBroadcastedValue] = React.useState(getDateObject);
3194
3196
  const monthNames = getMonthNames(locale, monthFormat);
3195
3197
  dayLabel ||= formatMessage(messages$9.dayLabel);
@@ -3215,8 +3217,8 @@ const DateInput = ({
3215
3217
  const getSelectElement = () => {
3216
3218
  return /*#__PURE__*/jsxRuntime.jsxs("label", {
3217
3219
  className: "d-flex flex-column",
3218
- children: [/*#__PURE__*/jsxRuntime.jsx("span", {
3219
- className: "sr-only",
3220
+ children: [/*#__PURE__*/jsxRuntime.jsx(Body, {
3221
+ type: exports.Typography.BODY_DEFAULT,
3220
3222
  children: monthLabel
3221
3223
  }), /*#__PURE__*/jsxRuntime.jsx(SelectInput, {
3222
3224
  name: "month",
@@ -3238,12 +3240,23 @@ const DateInput = ({
3238
3240
  })]
3239
3241
  });
3240
3242
  };
3243
+ const isDayValid = (newDay, newMonth, newYear) => {
3244
+ const maxDay = new Date(newYear, newMonth + 1, 0).getDate();
3245
+ return newDay <= maxDay;
3246
+ };
3241
3247
  const handleInternalValue = (newDay = day, newMonth = month, newYear = year) => {
3242
- if (newDay == null || newMonth == null || newYear == null) {
3248
+ if (newDay == null || newDay === 0 || newMonth == null || newYear == null || newYear === 0) {
3249
+ broadcastNewValue(null);
3250
+ return;
3251
+ }
3252
+ if (!isDayValid(newDay, newMonth, newYear)) {
3243
3253
  broadcastNewValue(null);
3244
3254
  return;
3245
3255
  }
3246
3256
  const dateValue = new Date(newYear, newMonth, newDay);
3257
+ if (newYear < 100) {
3258
+ dateValue.setFullYear(newYear);
3259
+ }
3247
3260
  if (!isDateValid(dateValue)) {
3248
3261
  broadcastNewValue(null);
3249
3262
  return;
@@ -3257,11 +3270,11 @@ const DateInput = ({
3257
3270
  }
3258
3271
  };
3259
3272
  const handleDayChange = event => {
3260
- const {
3261
- checkedDay
3262
- } = checkDate(Number.parseInt(event.target.value, 10), month, year);
3263
- setDay(checkedDay);
3264
- handleInternalValue(checkedDay, month, year);
3273
+ const newDayString = event.target.value.replace(/\D/g, '');
3274
+ const newDayNumber = Number.parseInt(newDayString, 10);
3275
+ setDay(newDayNumber);
3276
+ setDisplayDay(newDayString);
3277
+ handleInternalValue(newDayNumber, month, year);
3265
3278
  };
3266
3279
  const handleMonthChange = selectedMonth => {
3267
3280
  if (selectedMonth === null) {
@@ -3269,30 +3282,19 @@ const DateInput = ({
3269
3282
  handleInternalValue(day, null, year);
3270
3283
  return;
3271
3284
  }
3272
- const {
3273
- checkedDay
3274
- } = checkDate(day, selectedMonth, year);
3275
3285
  setMonth(selectedMonth);
3276
- if (day && checkedDay !== day) {
3277
- setDay(checkedDay);
3278
- }
3279
- handleInternalValue(checkedDay, selectedMonth, year);
3286
+ handleInternalValue(day, selectedMonth, year);
3280
3287
  };
3281
3288
  const handleYearChange = event => {
3282
- const newValue = event.target.value;
3283
- const slicedYear = newValue.length > 4 ? newValue.slice(0, 4) : newValue;
3284
- if (slicedYear.toString().length === 4) {
3285
- // Correct day based on year and month.
3286
- const {
3287
- checkedDay
3288
- } = checkDate(day, month, Number.parseInt(newValue, 10));
3289
- if (day && checkedDay !== day) {
3290
- setDay(checkedDay);
3291
- }
3292
- setYear(Number.parseInt(slicedYear, 10));
3293
- handleInternalValue(checkedDay, month, Number.parseInt(slicedYear, 10));
3289
+ const newYearString = event.target.value.replace(/\D/g, '');
3290
+ const newYearNumber = Number.parseInt(newYearString, 10);
3291
+ if (newYearString.length >= 4 && newYearString.length <= 6) {
3292
+ setYear(newYearNumber);
3293
+ setDisplayYear(newYearString);
3294
+ handleInternalValue(day, month, newYearNumber);
3294
3295
  } else {
3295
- setYear(Number.parseInt(slicedYear, 10));
3296
+ setYear(null);
3297
+ setDisplayYear(newYearString);
3296
3298
  handleInternalValue(day, month, null);
3297
3299
  }
3298
3300
  };
@@ -3302,24 +3304,6 @@ const DateInput = ({
3302
3304
  onChange(newValue != null ? getDateAsString(newValue) : null);
3303
3305
  }
3304
3306
  };
3305
- const checkDate = (newDay = null, newMonth = 0, newYear = null) => {
3306
- let checkedDay = newDay;
3307
- const maxDay = new Date(newYear || 2000, newMonth != null ? newMonth + 1 : 1, 0).getDate();
3308
- if (!newDay) {
3309
- checkedDay = null;
3310
- }
3311
- if (newDay && newDay < 0) {
3312
- checkedDay = 1;
3313
- }
3314
- if (newDay && newMonth || newDay && newDay > 31) {
3315
- checkedDay = newDay > maxDay ? maxDay : newDay;
3316
- }
3317
- return {
3318
- checkedDay,
3319
- checkedMonth: newMonth,
3320
- checkedYear: newYear
3321
- };
3322
- };
3323
3307
  const monthYearOnly = mode === exports.DateMode.MONTH_YEAR;
3324
3308
  const monthWidth = classNames__default.default({
3325
3309
  'col-sm-8': monthYearOnly,
@@ -3335,8 +3319,8 @@ const DateInput = ({
3335
3319
  return /*#__PURE__*/jsxRuntime.jsx("div", {
3336
3320
  className: "col-sm-3",
3337
3321
  children: /*#__PURE__*/jsxRuntime.jsxs("label", {
3338
- children: [/*#__PURE__*/jsxRuntime.jsx("span", {
3339
- className: "sr-only",
3322
+ children: [/*#__PURE__*/jsxRuntime.jsx(Body, {
3323
+ type: exports.Typography.BODY_DEFAULT,
3340
3324
  children: dayLabel
3341
3325
  }), /*#__PURE__*/jsxRuntime.jsx("div", {
3342
3326
  className: `input-group input-group-${size}`,
@@ -3346,10 +3330,12 @@ const DateInput = ({
3346
3330
  pattern: "[0-9]*",
3347
3331
  name: "day",
3348
3332
  autoComplete: dayAutoComplete,
3349
- value: day || '',
3333
+ value: displayDay || '',
3350
3334
  placeholder: placeholders?.day,
3351
3335
  disabled: disabled,
3352
3336
  min: 1,
3337
+ max: 31,
3338
+ maxLength: 2,
3353
3339
  onChange: event => handleDayChange(event)
3354
3340
  })
3355
3341
  })]
@@ -3360,8 +3346,8 @@ const DateInput = ({
3360
3346
  return /*#__PURE__*/jsxRuntime.jsx("div", {
3361
3347
  className: "col-sm-4",
3362
3348
  children: /*#__PURE__*/jsxRuntime.jsxs("label", {
3363
- children: [/*#__PURE__*/jsxRuntime.jsx("span", {
3364
- className: "sr-only",
3349
+ children: [/*#__PURE__*/jsxRuntime.jsx(Body, {
3350
+ type: exports.Typography.BODY_DEFAULT,
3365
3351
  children: yearLabel
3366
3352
  }), /*#__PURE__*/jsxRuntime.jsx("div", {
3367
3353
  className: `input-group input-group-${size}`,
@@ -3372,9 +3358,11 @@ const DateInput = ({
3372
3358
  name: "year",
3373
3359
  autoComplete: yearAutoComplete,
3374
3360
  placeholder: placeholders?.year,
3375
- value: year || '',
3361
+ value: displayYear || '',
3376
3362
  disabled: disabled,
3377
- min: 1,
3363
+ min: 0,
3364
+ max: 9999,
3365
+ maxLength: 6,
3378
3366
  onChange: event => handleYearChange(event)
3379
3367
  })
3380
3368
  })]
@@ -4878,14 +4866,20 @@ function InlineAlert({
4878
4866
  className,
4879
4867
  children
4880
4868
  }) {
4881
- const danger = type === 'negative' || type === 'error';
4882
- return /*#__PURE__*/jsxRuntime.jsxs("div", {
4869
+ return /*#__PURE__*/jsxRuntime.jsx("div", {
4883
4870
  role: "alert",
4884
4871
  id: id,
4885
- className: classNames__default.default('alert alert-detach', `alert-${danger ? 'danger' : type}`, className),
4886
- children: [danger && /*#__PURE__*/jsxRuntime.jsx(icons.AlertCircle, {}), /*#__PURE__*/jsxRuntime.jsx("div", {
4887
- children: children
4888
- })]
4872
+ className: classNames__default.default('alert alert-detach', `alert-${type === exports.Sentiment.NEGATIVE || type === exports.Sentiment.ERROR ? 'danger' : type}`, className),
4873
+ children: /*#__PURE__*/jsxRuntime.jsxs("div", {
4874
+ className: "d-inline-flex",
4875
+ children: [type !== exports.Sentiment.NEUTRAL && type !== exports.Sentiment.PENDING && /*#__PURE__*/jsxRuntime.jsx(StatusIcon, {
4876
+ sentiment: type,
4877
+ size: exports.Size.SMALL
4878
+ }), /*#__PURE__*/jsxRuntime.jsx("div", {
4879
+ className: "np-text-body-default",
4880
+ children: children
4881
+ })]
4882
+ })
4889
4883
  });
4890
4884
  }
4891
4885
 
@@ -4906,13 +4900,15 @@ const Label = ({
4906
4900
  const Field = ({
4907
4901
  id,
4908
4902
  label,
4909
- hint,
4910
- error,
4903
+ message: propMessage,
4904
+ sentiment: propType = exports.Sentiment.NEUTRAL,
4911
4905
  className,
4912
- children
4906
+ children,
4907
+ ...props
4913
4908
  }) => {
4914
- const hasError = Boolean(error);
4915
- const hasHint = Boolean(hint) && !hasError;
4909
+ const sentiment = props.error ? exports.Sentiment.NEGATIVE : propType;
4910
+ const message = props.error || props.hint || propMessage;
4911
+ const hasError = sentiment === exports.Sentiment.NEGATIVE;
4916
4912
  const labelId = React.useId();
4917
4913
  const fallbackInputId = React.useId();
4918
4914
  const inputId = id !== null ? id ?? fallbackInputId : undefined;
@@ -4922,26 +4918,24 @@ const Field = ({
4922
4918
  children: /*#__PURE__*/jsxRuntime.jsx(InputIdContextProvider, {
4923
4919
  value: inputId,
4924
4920
  children: /*#__PURE__*/jsxRuntime.jsx(InputDescribedByProvider, {
4925
- value: hasError || hasHint ? descriptionId : undefined,
4921
+ value: message ? descriptionId : undefined,
4926
4922
  children: /*#__PURE__*/jsxRuntime.jsx(InputInvalidProvider, {
4927
4923
  value: hasError,
4928
4924
  children: /*#__PURE__*/jsxRuntime.jsxs("div", {
4929
4925
  className: classNames__default.default('form-group d-block', {
4926
+ 'has-success': sentiment === exports.Sentiment.POSITIVE,
4927
+ 'has-warning': sentiment === exports.Sentiment.WARNING,
4930
4928
  'has-error': hasError,
4931
- 'has-info': hasHint
4929
+ 'has-info': sentiment === exports.Sentiment.NEUTRAL
4932
4930
  }, className),
4933
4931
  children: [/*#__PURE__*/jsxRuntime.jsxs(Label, {
4934
4932
  id: labelId,
4935
4933
  htmlFor: inputId,
4936
4934
  children: [label, children]
4937
- }), hasHint && /*#__PURE__*/jsxRuntime.jsx(InlineAlert, {
4938
- type: exports.Sentiment.NEUTRAL,
4935
+ }), message && /*#__PURE__*/jsxRuntime.jsx(InlineAlert, {
4936
+ type: sentiment,
4939
4937
  id: descriptionId,
4940
- children: hint
4941
- }), hasError && /*#__PURE__*/jsxRuntime.jsx(InlineAlert, {
4942
- type: exports.Sentiment.NEGATIVE,
4943
- id: descriptionId,
4944
- children: error
4938
+ children: message
4945
4939
  })]
4946
4940
  })
4947
4941
  })