@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.mjs CHANGED
@@ -2,7 +2,7 @@ import * as React from 'react';
2
2
  import React__default, { forwardRef, useId, cloneElement, useState, useEffect, useRef, useMemo, Component, createContext, useContext, useSyncExternalStore, useCallback, useImperativeHandle, createElement, PureComponent, createRef, isValidElement, Children, Fragment as Fragment$1 } from 'react';
3
3
  import classNames from 'classnames';
4
4
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
5
- import { ChevronUp, CrossCircleFill, Cross, Check, Info as Info$1, Alert as Alert$1, ClockBorderless, NavigateAway, Briefcase, Person, ArrowRight, Download, ChevronLeft, ChevronRight, AlertCircleFill, AlertCircle, ArrowLeft, QuestionMarkCircle, Search, CrossCircle, ChevronDown, CheckCircleFill, ClockFill, Upload as Upload$2, Document, Plus, PlusCircle, Bin } from '@transferwise/icons';
5
+ import { ChevronUp, CrossCircleFill, Cross, Check, Info as Info$1, Alert as Alert$1, ClockBorderless, NavigateAway, Briefcase, Person, ArrowRight, Download, ChevronLeft, ChevronRight, AlertCircleFill, ArrowLeft, QuestionMarkCircle, Search, CrossCircle, ChevronDown, CheckCircleFill, ClockFill, Upload as Upload$2, Document, Plus, PlusCircle, Bin } from '@transferwise/icons';
6
6
  import { defineMessages, useIntl, injectIntl, IntlProvider } from 'react-intl';
7
7
  import commonmark from 'commonmark';
8
8
  import { useTheme, ThemeProvider } from '@wise/components-theming';
@@ -717,7 +717,7 @@ const StatusIcon = ({
717
717
  const iconColor = sentiment === 'warning' || sentiment === 'pending' ? 'dark' : 'light';
718
718
  return /*#__PURE__*/jsx("span", {
719
719
  "data-testid": "status-icon",
720
- className: classNames('status-circle', 'status-circle-' + size, sentiment),
720
+ className: classNames('status-circle', `status-circle-${size}`, sentiment),
721
721
  children: /*#__PURE__*/jsx(Icon, {
722
722
  className: classNames('status-icon', iconColor)
723
723
  })
@@ -3159,8 +3159,10 @@ const DateInput = ({
3159
3159
  return null;
3160
3160
  };
3161
3161
  const [day, setDay] = useState(() => getInitialDate('day'));
3162
+ const [displayDay, setDisplayDay] = useState(day?.toString());
3162
3163
  const [month, setMonth] = useState(() => getInitialDate('month'));
3163
3164
  const [year, setYear] = useState(() => getInitialDate('year'));
3165
+ const [displayYear, setDisplayYear] = useState(year?.toString());
3164
3166
  const [lastBroadcastedValue, setLastBroadcastedValue] = useState(getDateObject);
3165
3167
  const monthNames = getMonthNames(locale, monthFormat);
3166
3168
  dayLabel ||= formatMessage(messages$9.dayLabel);
@@ -3186,8 +3188,8 @@ const DateInput = ({
3186
3188
  const getSelectElement = () => {
3187
3189
  return /*#__PURE__*/jsxs("label", {
3188
3190
  className: "d-flex flex-column",
3189
- children: [/*#__PURE__*/jsx("span", {
3190
- className: "sr-only",
3191
+ children: [/*#__PURE__*/jsx(Body, {
3192
+ type: Typography.BODY_DEFAULT,
3191
3193
  children: monthLabel
3192
3194
  }), /*#__PURE__*/jsx(SelectInput, {
3193
3195
  name: "month",
@@ -3209,12 +3211,23 @@ const DateInput = ({
3209
3211
  })]
3210
3212
  });
3211
3213
  };
3214
+ const isDayValid = (newDay, newMonth, newYear) => {
3215
+ const maxDay = new Date(newYear, newMonth + 1, 0).getDate();
3216
+ return newDay <= maxDay;
3217
+ };
3212
3218
  const handleInternalValue = (newDay = day, newMonth = month, newYear = year) => {
3213
- if (newDay == null || newMonth == null || newYear == null) {
3219
+ if (newDay == null || newDay === 0 || newMonth == null || newYear == null || newYear === 0) {
3220
+ broadcastNewValue(null);
3221
+ return;
3222
+ }
3223
+ if (!isDayValid(newDay, newMonth, newYear)) {
3214
3224
  broadcastNewValue(null);
3215
3225
  return;
3216
3226
  }
3217
3227
  const dateValue = new Date(newYear, newMonth, newDay);
3228
+ if (newYear < 100) {
3229
+ dateValue.setFullYear(newYear);
3230
+ }
3218
3231
  if (!isDateValid(dateValue)) {
3219
3232
  broadcastNewValue(null);
3220
3233
  return;
@@ -3228,11 +3241,11 @@ const DateInput = ({
3228
3241
  }
3229
3242
  };
3230
3243
  const handleDayChange = event => {
3231
- const {
3232
- checkedDay
3233
- } = checkDate(Number.parseInt(event.target.value, 10), month, year);
3234
- setDay(checkedDay);
3235
- handleInternalValue(checkedDay, month, year);
3244
+ const newDayString = event.target.value.replace(/\D/g, '');
3245
+ const newDayNumber = Number.parseInt(newDayString, 10);
3246
+ setDay(newDayNumber);
3247
+ setDisplayDay(newDayString);
3248
+ handleInternalValue(newDayNumber, month, year);
3236
3249
  };
3237
3250
  const handleMonthChange = selectedMonth => {
3238
3251
  if (selectedMonth === null) {
@@ -3240,30 +3253,19 @@ const DateInput = ({
3240
3253
  handleInternalValue(day, null, year);
3241
3254
  return;
3242
3255
  }
3243
- const {
3244
- checkedDay
3245
- } = checkDate(day, selectedMonth, year);
3246
3256
  setMonth(selectedMonth);
3247
- if (day && checkedDay !== day) {
3248
- setDay(checkedDay);
3249
- }
3250
- handleInternalValue(checkedDay, selectedMonth, year);
3257
+ handleInternalValue(day, selectedMonth, year);
3251
3258
  };
3252
3259
  const handleYearChange = event => {
3253
- const newValue = event.target.value;
3254
- const slicedYear = newValue.length > 4 ? newValue.slice(0, 4) : newValue;
3255
- if (slicedYear.toString().length === 4) {
3256
- // Correct day based on year and month.
3257
- const {
3258
- checkedDay
3259
- } = checkDate(day, month, Number.parseInt(newValue, 10));
3260
- if (day && checkedDay !== day) {
3261
- setDay(checkedDay);
3262
- }
3263
- setYear(Number.parseInt(slicedYear, 10));
3264
- handleInternalValue(checkedDay, month, Number.parseInt(slicedYear, 10));
3260
+ const newYearString = event.target.value.replace(/\D/g, '');
3261
+ const newYearNumber = Number.parseInt(newYearString, 10);
3262
+ if (newYearString.length >= 4 && newYearString.length <= 6) {
3263
+ setYear(newYearNumber);
3264
+ setDisplayYear(newYearString);
3265
+ handleInternalValue(day, month, newYearNumber);
3265
3266
  } else {
3266
- setYear(Number.parseInt(slicedYear, 10));
3267
+ setYear(null);
3268
+ setDisplayYear(newYearString);
3267
3269
  handleInternalValue(day, month, null);
3268
3270
  }
3269
3271
  };
@@ -3273,24 +3275,6 @@ const DateInput = ({
3273
3275
  onChange(newValue != null ? getDateAsString(newValue) : null);
3274
3276
  }
3275
3277
  };
3276
- const checkDate = (newDay = null, newMonth = 0, newYear = null) => {
3277
- let checkedDay = newDay;
3278
- const maxDay = new Date(newYear || 2000, newMonth != null ? newMonth + 1 : 1, 0).getDate();
3279
- if (!newDay) {
3280
- checkedDay = null;
3281
- }
3282
- if (newDay && newDay < 0) {
3283
- checkedDay = 1;
3284
- }
3285
- if (newDay && newMonth || newDay && newDay > 31) {
3286
- checkedDay = newDay > maxDay ? maxDay : newDay;
3287
- }
3288
- return {
3289
- checkedDay,
3290
- checkedMonth: newMonth,
3291
- checkedYear: newYear
3292
- };
3293
- };
3294
3278
  const monthYearOnly = mode === DateMode.MONTH_YEAR;
3295
3279
  const monthWidth = classNames({
3296
3280
  'col-sm-8': monthYearOnly,
@@ -3306,8 +3290,8 @@ const DateInput = ({
3306
3290
  return /*#__PURE__*/jsx("div", {
3307
3291
  className: "col-sm-3",
3308
3292
  children: /*#__PURE__*/jsxs("label", {
3309
- children: [/*#__PURE__*/jsx("span", {
3310
- className: "sr-only",
3293
+ children: [/*#__PURE__*/jsx(Body, {
3294
+ type: Typography.BODY_DEFAULT,
3311
3295
  children: dayLabel
3312
3296
  }), /*#__PURE__*/jsx("div", {
3313
3297
  className: `input-group input-group-${size}`,
@@ -3317,10 +3301,12 @@ const DateInput = ({
3317
3301
  pattern: "[0-9]*",
3318
3302
  name: "day",
3319
3303
  autoComplete: dayAutoComplete,
3320
- value: day || '',
3304
+ value: displayDay || '',
3321
3305
  placeholder: placeholders?.day,
3322
3306
  disabled: disabled,
3323
3307
  min: 1,
3308
+ max: 31,
3309
+ maxLength: 2,
3324
3310
  onChange: event => handleDayChange(event)
3325
3311
  })
3326
3312
  })]
@@ -3331,8 +3317,8 @@ const DateInput = ({
3331
3317
  return /*#__PURE__*/jsx("div", {
3332
3318
  className: "col-sm-4",
3333
3319
  children: /*#__PURE__*/jsxs("label", {
3334
- children: [/*#__PURE__*/jsx("span", {
3335
- className: "sr-only",
3320
+ children: [/*#__PURE__*/jsx(Body, {
3321
+ type: Typography.BODY_DEFAULT,
3336
3322
  children: yearLabel
3337
3323
  }), /*#__PURE__*/jsx("div", {
3338
3324
  className: `input-group input-group-${size}`,
@@ -3343,9 +3329,11 @@ const DateInput = ({
3343
3329
  name: "year",
3344
3330
  autoComplete: yearAutoComplete,
3345
3331
  placeholder: placeholders?.year,
3346
- value: year || '',
3332
+ value: displayYear || '',
3347
3333
  disabled: disabled,
3348
- min: 1,
3334
+ min: 0,
3335
+ max: 9999,
3336
+ maxLength: 6,
3349
3337
  onChange: event => handleYearChange(event)
3350
3338
  })
3351
3339
  })]
@@ -4849,14 +4837,20 @@ function InlineAlert({
4849
4837
  className,
4850
4838
  children
4851
4839
  }) {
4852
- const danger = type === 'negative' || type === 'error';
4853
- return /*#__PURE__*/jsxs("div", {
4840
+ return /*#__PURE__*/jsx("div", {
4854
4841
  role: "alert",
4855
4842
  id: id,
4856
- className: classNames('alert alert-detach', `alert-${danger ? 'danger' : type}`, className),
4857
- children: [danger && /*#__PURE__*/jsx(AlertCircle, {}), /*#__PURE__*/jsx("div", {
4858
- children: children
4859
- })]
4843
+ className: classNames('alert alert-detach', `alert-${type === Sentiment.NEGATIVE || type === Sentiment.ERROR ? 'danger' : type}`, className),
4844
+ children: /*#__PURE__*/jsxs("div", {
4845
+ className: "d-inline-flex",
4846
+ children: [type !== Sentiment.NEUTRAL && type !== Sentiment.PENDING && /*#__PURE__*/jsx(StatusIcon, {
4847
+ sentiment: type,
4848
+ size: Size.SMALL
4849
+ }), /*#__PURE__*/jsx("div", {
4850
+ className: "np-text-body-default",
4851
+ children: children
4852
+ })]
4853
+ })
4860
4854
  });
4861
4855
  }
4862
4856
 
@@ -4877,13 +4871,15 @@ const Label = ({
4877
4871
  const Field = ({
4878
4872
  id,
4879
4873
  label,
4880
- hint,
4881
- error,
4874
+ message: propMessage,
4875
+ sentiment: propType = Sentiment.NEUTRAL,
4882
4876
  className,
4883
- children
4877
+ children,
4878
+ ...props
4884
4879
  }) => {
4885
- const hasError = Boolean(error);
4886
- const hasHint = Boolean(hint) && !hasError;
4880
+ const sentiment = props.error ? Sentiment.NEGATIVE : propType;
4881
+ const message = props.error || props.hint || propMessage;
4882
+ const hasError = sentiment === Sentiment.NEGATIVE;
4887
4883
  const labelId = useId();
4888
4884
  const fallbackInputId = useId();
4889
4885
  const inputId = id !== null ? id ?? fallbackInputId : undefined;
@@ -4893,26 +4889,24 @@ const Field = ({
4893
4889
  children: /*#__PURE__*/jsx(InputIdContextProvider, {
4894
4890
  value: inputId,
4895
4891
  children: /*#__PURE__*/jsx(InputDescribedByProvider, {
4896
- value: hasError || hasHint ? descriptionId : undefined,
4892
+ value: message ? descriptionId : undefined,
4897
4893
  children: /*#__PURE__*/jsx(InputInvalidProvider, {
4898
4894
  value: hasError,
4899
4895
  children: /*#__PURE__*/jsxs("div", {
4900
4896
  className: classNames('form-group d-block', {
4897
+ 'has-success': sentiment === Sentiment.POSITIVE,
4898
+ 'has-warning': sentiment === Sentiment.WARNING,
4901
4899
  'has-error': hasError,
4902
- 'has-info': hasHint
4900
+ 'has-info': sentiment === Sentiment.NEUTRAL
4903
4901
  }, className),
4904
4902
  children: [/*#__PURE__*/jsxs(Label, {
4905
4903
  id: labelId,
4906
4904
  htmlFor: inputId,
4907
4905
  children: [label, children]
4908
- }), hasHint && /*#__PURE__*/jsx(InlineAlert, {
4909
- type: Sentiment.NEUTRAL,
4906
+ }), message && /*#__PURE__*/jsx(InlineAlert, {
4907
+ type: sentiment,
4910
4908
  id: descriptionId,
4911
- children: hint
4912
- }), hasError && /*#__PURE__*/jsx(InlineAlert, {
4913
- type: Sentiment.NEGATIVE,
4914
- id: descriptionId,
4915
- children: error
4909
+ children: message
4916
4910
  })]
4917
4911
  })
4918
4912
  })