@moda/om 21.8.0 → 21.9.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.
package/dist/index.cjs.js CHANGED
@@ -12338,6 +12338,273 @@ var Paginator = function Paginator(_ref) {
12338
12338
  })));
12339
12339
  };
12340
12340
 
12341
+ var isStyleObject = function isStyleObject(obj) {
12342
+ return _typeof$1(obj) === 'object' && obj !== null;
12343
+ };
12344
+ var OTPInput = function OTPInput(_a) {
12345
+ var _b = _a.value,
12346
+ value = _b === void 0 ? '' : _b,
12347
+ _c = _a.numInputs,
12348
+ numInputs = _c === void 0 ? 4 : _c,
12349
+ onChange = _a.onChange,
12350
+ onPaste = _a.onPaste,
12351
+ renderInput = _a.renderInput,
12352
+ _d = _a.shouldAutoFocus,
12353
+ shouldAutoFocus = _d === void 0 ? false : _d,
12354
+ _e = _a.inputType,
12355
+ inputType = _e === void 0 ? 'text' : _e,
12356
+ renderSeparator = _a.renderSeparator,
12357
+ placeholder = _a.placeholder,
12358
+ containerStyle = _a.containerStyle,
12359
+ inputStyle = _a.inputStyle,
12360
+ _f = _a.skipDefaultStyles,
12361
+ skipDefaultStyles = _f === void 0 ? false : _f;
12362
+ var _g = React.useState(0),
12363
+ activeInput = _g[0],
12364
+ setActiveInput = _g[1];
12365
+ var inputRefs = React.useRef([]);
12366
+ var getOTPValue = function getOTPValue() {
12367
+ return value ? value.toString().split('') : [];
12368
+ };
12369
+ var isInputNum = inputType === 'number' || inputType === 'tel';
12370
+ React.useEffect(function () {
12371
+ inputRefs.current = inputRefs.current.slice(0, numInputs);
12372
+ }, [numInputs]);
12373
+ React.useEffect(function () {
12374
+ var _a;
12375
+ if (shouldAutoFocus) {
12376
+ (_a = inputRefs.current[0]) === null || _a === void 0 ? void 0 : _a.focus();
12377
+ }
12378
+ }, [shouldAutoFocus]);
12379
+ var getPlaceholderValue = function getPlaceholderValue() {
12380
+ if (typeof placeholder === 'string') {
12381
+ if (placeholder.length === numInputs) {
12382
+ return placeholder;
12383
+ }
12384
+ if (placeholder.length > 0) {
12385
+ console.error('Length of the placeholder should be equal to the number of inputs.');
12386
+ }
12387
+ }
12388
+ return undefined;
12389
+ };
12390
+ var isInputValueValid = function isInputValueValid(value) {
12391
+ var isTypeValid = isInputNum ? !isNaN(Number(value)) : typeof value === 'string';
12392
+ return isTypeValid && value.trim().length === 1;
12393
+ };
12394
+ var handleChange = function handleChange(event) {
12395
+ var value = event.target.value;
12396
+ if (isInputValueValid(value)) {
12397
+ changeCodeAtFocus(value);
12398
+ focusInput(activeInput + 1);
12399
+ }
12400
+ };
12401
+ var handleInputChange = function handleInputChange(event) {
12402
+ var nativeEvent = event.nativeEvent;
12403
+ var value = event.target.value;
12404
+ if (!isInputValueValid(value)) {
12405
+ // Pasting from the native autofill suggestion on a mobile device can pass
12406
+ // the pasted string as one long input to one of the cells. This ensures
12407
+ // that we handle the full input and not just the first character.
12408
+ if (value.length === numInputs) {
12409
+ var hasInvalidInput = value.split('').some(function (cellInput) {
12410
+ return !isInputValueValid(cellInput);
12411
+ });
12412
+ if (!hasInvalidInput) {
12413
+ handleOTPChange(value.split(''));
12414
+ focusInput(numInputs - 1);
12415
+ }
12416
+ }
12417
+ // @ts-expect-error - This was added previously to handle and edge case
12418
+ // for dealing with keyCode "229 Unidentified" on Android. Check if this is
12419
+ // still needed.
12420
+ if (nativeEvent.data === null && nativeEvent.inputType === 'deleteContentBackward') {
12421
+ event.preventDefault();
12422
+ changeCodeAtFocus('');
12423
+ focusInput(activeInput - 1);
12424
+ }
12425
+ // Clear the input if it's not valid value because firefox allows
12426
+ // pasting non-numeric characters in a number type input
12427
+ event.target.value = '';
12428
+ }
12429
+ };
12430
+ var handleFocus = function handleFocus(event) {
12431
+ return function (index) {
12432
+ setActiveInput(index);
12433
+ event.target.select();
12434
+ };
12435
+ };
12436
+ var handleBlur = function handleBlur() {
12437
+ setActiveInput(activeInput - 1);
12438
+ };
12439
+ var handleKeyDown = function handleKeyDown(event) {
12440
+ var otp = getOTPValue();
12441
+ if ([event.code, event.key].includes('Backspace')) {
12442
+ event.preventDefault();
12443
+ changeCodeAtFocus('');
12444
+ focusInput(activeInput - 1);
12445
+ } else if (event.code === 'Delete') {
12446
+ event.preventDefault();
12447
+ changeCodeAtFocus('');
12448
+ } else if (event.code === 'ArrowLeft') {
12449
+ event.preventDefault();
12450
+ focusInput(activeInput - 1);
12451
+ } else if (event.code === 'ArrowRight') {
12452
+ event.preventDefault();
12453
+ focusInput(activeInput + 1);
12454
+ }
12455
+ // React does not trigger onChange when the same value is entered
12456
+ // again. So we need to focus the next input manually in this case.
12457
+ else if (event.key === otp[activeInput]) {
12458
+ event.preventDefault();
12459
+ focusInput(activeInput + 1);
12460
+ } else if (event.code === 'Spacebar' || event.code === 'Space' || event.code === 'ArrowUp' || event.code === 'ArrowDown') {
12461
+ event.preventDefault();
12462
+ }
12463
+ };
12464
+ var focusInput = function focusInput(index) {
12465
+ var _a, _b;
12466
+ var activeInput = Math.max(Math.min(numInputs - 1, index), 0);
12467
+ if (inputRefs.current[activeInput]) {
12468
+ (_a = inputRefs.current[activeInput]) === null || _a === void 0 ? void 0 : _a.focus();
12469
+ (_b = inputRefs.current[activeInput]) === null || _b === void 0 ? void 0 : _b.select();
12470
+ setActiveInput(activeInput);
12471
+ }
12472
+ };
12473
+ var changeCodeAtFocus = function changeCodeAtFocus(value) {
12474
+ var otp = getOTPValue();
12475
+ otp[activeInput] = value[0];
12476
+ handleOTPChange(otp);
12477
+ };
12478
+ var handleOTPChange = function handleOTPChange(otp) {
12479
+ var otpValue = otp.join('');
12480
+ onChange(otpValue);
12481
+ };
12482
+ var handlePaste = function handlePaste(event) {
12483
+ var _a;
12484
+ event.preventDefault();
12485
+ var otp = getOTPValue();
12486
+ var nextActiveInput = activeInput;
12487
+ // Get pastedData in an array of max size (num of inputs - current position)
12488
+ var pastedData = event.clipboardData.getData('text/plain').slice(0, numInputs - activeInput).split('');
12489
+ // Prevent pasting if the clipboard data contains non-numeric values for number inputs
12490
+ if (isInputNum && pastedData.some(function (value) {
12491
+ return isNaN(Number(value));
12492
+ })) {
12493
+ return;
12494
+ }
12495
+ // Paste data from focused input onwards
12496
+ for (var pos = 0; pos < numInputs; ++pos) {
12497
+ if (pos >= activeInput && pastedData.length > 0) {
12498
+ otp[pos] = (_a = pastedData.shift()) !== null && _a !== void 0 ? _a : '';
12499
+ nextActiveInput++;
12500
+ }
12501
+ }
12502
+ focusInput(nextActiveInput);
12503
+ handleOTPChange(otp);
12504
+ };
12505
+ return /*#__PURE__*/React.createElement("div", {
12506
+ style: Object.assign({
12507
+ display: 'flex',
12508
+ alignItems: 'center'
12509
+ }, isStyleObject(containerStyle) && containerStyle),
12510
+ className: typeof containerStyle === 'string' ? containerStyle : undefined,
12511
+ onPaste: onPaste
12512
+ }, Array.from({
12513
+ length: numInputs
12514
+ }, function (_, index) {
12515
+ return index;
12516
+ }).map(function (index) {
12517
+ var _a, _b, _c;
12518
+ return /*#__PURE__*/React.createElement(React.Fragment, {
12519
+ key: index
12520
+ }, renderInput({
12521
+ value: (_a = getOTPValue()[index]) !== null && _a !== void 0 ? _a : '',
12522
+ placeholder: (_c = (_b = getPlaceholderValue()) === null || _b === void 0 ? void 0 : _b[index]) !== null && _c !== void 0 ? _c : undefined,
12523
+ ref: function ref(element) {
12524
+ return inputRefs.current[index] = element;
12525
+ },
12526
+ onChange: handleChange,
12527
+ onFocus: function onFocus(event) {
12528
+ return handleFocus(event)(index);
12529
+ },
12530
+ onBlur: handleBlur,
12531
+ onKeyDown: handleKeyDown,
12532
+ onPaste: handlePaste,
12533
+ autoComplete: 'off',
12534
+ 'aria-label': "Please enter OTP character ".concat(index + 1),
12535
+ style: Object.assign(!skipDefaultStyles ? {
12536
+ width: '1em',
12537
+ textAlign: 'center'
12538
+ } : {}, isStyleObject(inputStyle) ? inputStyle : {}),
12539
+ className: typeof inputStyle === 'string' ? inputStyle : undefined,
12540
+ type: inputType,
12541
+ inputMode: isInputNum ? 'numeric' : 'text',
12542
+ onInput: handleInputChange
12543
+ }, index), index < numInputs - 1 && (typeof renderSeparator === 'function' ? renderSeparator(index) : renderSeparator));
12544
+ }));
12545
+ };
12546
+
12547
+ var getInputAriaLabel = function getInputAriaLabel(index, inputCount, ariaLabel, label) {
12548
+ var baseLabel = ariaLabel || label || 'One-time password digit';
12549
+ return "".concat(baseLabel, " ").concat(index + 1, " of ").concat(inputCount);
12550
+ };
12551
+ var OtpInput = function OtpInput(_ref) {
12552
+ var ariaDescribedBy = _ref['aria-describedby'],
12553
+ ariaLabel = _ref['aria-label'],
12554
+ _ref$autoComplete = _ref.autoComplete,
12555
+ autoComplete = _ref$autoComplete === void 0 ? 'one-time-code' : _ref$autoComplete,
12556
+ className = _ref.className,
12557
+ disabled = _ref.disabled,
12558
+ error = _ref.error,
12559
+ focus = _ref.focus,
12560
+ id = _ref.id,
12561
+ inputClassName = _ref.inputClassName,
12562
+ _ref$inputType = _ref.inputType,
12563
+ inputType = _ref$inputType === void 0 ? 'tel' : _ref$inputType,
12564
+ label = _ref.label,
12565
+ name = _ref.name,
12566
+ _ref$numInputs = _ref.numInputs,
12567
+ numInputs = _ref$numInputs === void 0 ? 4 : _ref$numInputs,
12568
+ onChange = _ref.onChange,
12569
+ onPaste = _ref.onPaste,
12570
+ placeholder = _ref.placeholder,
12571
+ renderSeparator = _ref.renderSeparator,
12572
+ required = _ref.required,
12573
+ shouldAutoFocus = _ref.shouldAutoFocus,
12574
+ _ref$value = _ref.value,
12575
+ value = _ref$value === void 0 ? '' : _ref$value;
12576
+ return /*#__PURE__*/React.createElement(OTPInput, {
12577
+ containerStyle: classNames('OtpInput', className),
12578
+ inputType: inputType,
12579
+ numInputs: numInputs,
12580
+ onChange: onChange,
12581
+ onPaste: onPaste,
12582
+ placeholder: placeholder,
12583
+ renderSeparator: renderSeparator,
12584
+ shouldAutoFocus: shouldAutoFocus,
12585
+ skipDefaultStyles: true,
12586
+ value: value,
12587
+ renderInput: function renderInput(inputProps, index) {
12588
+ return /*#__PURE__*/React.createElement("input", _extends$1({}, inputProps, {
12589
+ id: id ? "".concat(id, "-").concat(index + 1) : undefined,
12590
+ autoComplete: autoComplete,
12591
+ "aria-describedby": ariaDescribedBy,
12592
+ "aria-invalid": error ? true : undefined,
12593
+ "aria-label": getInputAriaLabel(index, numInputs, ariaLabel, label),
12594
+ className: classNames(inputProps.className, 'OtpInput__input', inputClassName, {
12595
+ 'OtpInput__input--disabled': disabled,
12596
+ 'OtpInput__input--error': error,
12597
+ 'OtpInput__input--focus': focus
12598
+ }),
12599
+ disabled: disabled,
12600
+ name: name,
12601
+ required: required
12602
+ }));
12603
+ }
12604
+ });
12605
+ };
12606
+ OtpInput.displayName = 'OtpInput';
12607
+
12341
12608
  var PasswordInput = /*#__PURE__*/React.forwardRef(function (_ref, ref) {
12342
12609
  var rest = _extends$1({}, (_objectDestructuringEmpty(_ref), _ref));
12343
12610
  var _useState = React.useState(false),
@@ -12891,6 +13158,7 @@ exports.Modal = Modal;
12891
13158
  exports.ModalOverlay = ModalOverlay;
12892
13159
  exports.MultiSelect = MultiSelect;
12893
13160
  exports.NoLineDivider = NoLineDivider;
13161
+ exports.OtpInput = OtpInput;
12894
13162
  exports.Oval = Oval;
12895
13163
  exports.Overlay = Overlay;
12896
13164
  exports.POPOVER_MOUSEOUT_DELAY_MS = POPOVER_MOUSEOUT_DELAY_MS;