@transferwise/components 0.0.0-experimental-3ede9cc → 0.0.0-experimental-a8c8413

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.
package/build/index.js CHANGED
@@ -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,42 +4866,12 @@ function InlineAlert({
4878
4866
  className,
4879
4867
  children
4880
4868
  }) {
4881
- const getStatusIcon = sentiment => {
4882
- switch (sentiment) {
4883
- case exports.Sentiment.POSITIVE:
4884
- case exports.Sentiment.SUCCESS:
4885
- return /*#__PURE__*/jsxRuntime.jsx(icons.CheckCircleFill, {});
4886
- case exports.Sentiment.WARNING:
4887
- return /*#__PURE__*/jsxRuntime.jsx(icons.AlertCircleFill, {});
4888
- case exports.Sentiment.NEGATIVE:
4889
- case exports.Sentiment.ERROR:
4890
- return /*#__PURE__*/jsxRuntime.jsx(icons.CrossCircleFill, {});
4891
- default:
4892
- return null;
4893
- }
4894
- };
4895
- const hasTextChildren = content => {
4896
- let label = '';
4897
- const fillLabel = childrenNodes => {
4898
- React__namespace.default.Children.map(childrenNodes, child => {
4899
- if (typeof child === 'string') {
4900
- label += child;
4901
- }
4902
- if (typeof child === 'object' && /*#__PURE__*/React__namespace.default.isValidElement(child)) {
4903
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
4904
- fillLabel(child?.props?.children);
4905
- }
4906
- });
4907
- };
4908
- fillLabel(content);
4909
- return !!label.length;
4910
- };
4869
+ const danger = type === 'negative' || type === 'error';
4911
4870
  return /*#__PURE__*/jsxRuntime.jsxs("div", {
4912
4871
  role: "alert",
4913
4872
  id: id,
4914
- className: classNames__default.default('alert alert-detach', `alert-${[exports.Sentiment.NEGATIVE, exports.Sentiment.ERROR].includes(type) ? 'danger' : type}`, className),
4915
- children: [hasTextChildren(children) && getStatusIcon(type), /*#__PURE__*/jsxRuntime.jsx("div", {
4916
- className: "np-text-body-default",
4873
+ className: classNames__default.default('alert alert-detach', `alert-${danger ? 'danger' : type}`, className),
4874
+ children: [danger && /*#__PURE__*/jsxRuntime.jsx(icons.AlertCircle, {}), /*#__PURE__*/jsxRuntime.jsx("div", {
4917
4875
  children: children
4918
4876
  })]
4919
4877
  });
@@ -4928,7 +4886,7 @@ const Label = ({
4928
4886
  return /*#__PURE__*/jsxRuntime.jsx("label", {
4929
4887
  id: id,
4930
4888
  htmlFor: htmlFor,
4931
- className: classNames__default.default('control-label d-flex flex-column gap-y-xs m-b-0', className),
4889
+ className: classNames__default.default('control-label d-flex flex-column gap-y-1 m-b-0', className),
4932
4890
  children: children
4933
4891
  });
4934
4892
  };
@@ -4936,15 +4894,13 @@ const Label = ({
4936
4894
  const Field = ({
4937
4895
  id,
4938
4896
  label,
4939
- message: propMessage,
4940
- type: propType,
4897
+ hint,
4898
+ error,
4941
4899
  className,
4942
- children,
4943
- ...props
4900
+ children
4944
4901
  }) => {
4945
- const type = props.error ? exports.Sentiment.NEGATIVE : propType;
4946
- const message = props.error || props.hint || propMessage;
4947
- const hasError = type === exports.Sentiment.NEGATIVE;
4902
+ const hasError = Boolean(error);
4903
+ const hasHint = Boolean(hint) && !hasError;
4948
4904
  const labelId = React.useId();
4949
4905
  const fallbackInputId = React.useId();
4950
4906
  const inputId = id !== null ? id ?? fallbackInputId : undefined;
@@ -4954,24 +4910,26 @@ const Field = ({
4954
4910
  children: /*#__PURE__*/jsxRuntime.jsx(InputIdContextProvider, {
4955
4911
  value: inputId,
4956
4912
  children: /*#__PURE__*/jsxRuntime.jsx(InputDescribedByProvider, {
4957
- value: message ? descriptionId : undefined,
4913
+ value: hasError || hasHint ? descriptionId : undefined,
4958
4914
  children: /*#__PURE__*/jsxRuntime.jsx(InputInvalidProvider, {
4959
4915
  value: hasError,
4960
4916
  children: /*#__PURE__*/jsxRuntime.jsxs("div", {
4961
4917
  className: classNames__default.default('form-group d-block', {
4962
- 'has-success': type === exports.Sentiment.POSITIVE,
4963
- 'has-warning': type === exports.Sentiment.WARNING,
4964
4918
  'has-error': hasError,
4965
- 'has-info': type === exports.Sentiment.NEUTRAL
4919
+ 'has-info': hasHint
4966
4920
  }, className),
4967
4921
  children: [/*#__PURE__*/jsxRuntime.jsxs(Label, {
4968
4922
  id: labelId,
4969
4923
  htmlFor: inputId,
4970
4924
  children: [label, children]
4971
- }), message && /*#__PURE__*/jsxRuntime.jsx(InlineAlert, {
4972
- type: type,
4925
+ }), hasHint && /*#__PURE__*/jsxRuntime.jsx(InlineAlert, {
4926
+ type: exports.Sentiment.NEUTRAL,
4973
4927
  id: descriptionId,
4974
- children: message
4928
+ children: hint
4929
+ }), hasError && /*#__PURE__*/jsxRuntime.jsx(InlineAlert, {
4930
+ type: exports.Sentiment.NEGATIVE,
4931
+ id: descriptionId,
4932
+ children: error
4975
4933
  })]
4976
4934
  })
4977
4935
  })