@wise/dynamic-flow-client-internal 5.30.0 → 5.30.1-experimental-1e1196b

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/main.mjs CHANGED
@@ -6777,7 +6777,98 @@ import {
6777
6777
  TextArea,
6778
6778
  TextareaWithDisplayFormat
6779
6779
  } from "@transferwise/components";
6780
- import { jsx as jsx100 } from "react/jsx-runtime";
6780
+ import { Eye, EyeShut } from "@transferwise/icons";
6781
+ import { useIntl as useIntl21 } from "react-intl";
6782
+ import { useLayoutEffect as useLayoutEffect3, useRef as useRef5, useState as useState20 } from "react";
6783
+
6784
+ // ../renderers/src/messages/ssn-input.messages.ts
6785
+ import { defineMessages as defineMessages15 } from "react-intl";
6786
+ var ssn_input_messages_default = defineMessages15({
6787
+ showValue: {
6788
+ id: "df.wise.ssnInput.showValue",
6789
+ defaultMessage: "Show value",
6790
+ description: "Accessible label for showing a masked SSN or SIN value"
6791
+ },
6792
+ hideValue: {
6793
+ id: "df.wise.ssnInput.hideValue",
6794
+ defaultMessage: "Hide value",
6795
+ description: "Accessible label for hiding an SSN or SIN value"
6796
+ }
6797
+ });
6798
+
6799
+ // ../renderers/src/components/ssnInputUtils.ts
6800
+ function formatSsnValue(rawValue, displayFormat, isVisible) {
6801
+ if (!displayFormat) {
6802
+ return isVisible ? rawValue : "\u2022".repeat(rawValue.length);
6803
+ }
6804
+ return displayFormat.split("").reduce(
6805
+ ({ display, digitsUsed }, character) => {
6806
+ if (character === "*") {
6807
+ return digitsUsed < rawValue.length ? {
6808
+ display: `${display}${isVisible ? rawValue[digitsUsed] : "\u2022"}`,
6809
+ digitsUsed: digitsUsed + 1
6810
+ } : { display, digitsUsed };
6811
+ }
6812
+ return digitsUsed > 0 && digitsUsed < rawValue.length ? { display: `${display}${character}`, digitsUsed } : { display, digitsUsed };
6813
+ },
6814
+ { display: "", digitsUsed: 0 }
6815
+ ).display;
6816
+ }
6817
+ function getRawOffset(displayValue, displayOffset, rawValueLength) {
6818
+ return Math.min(
6819
+ displayValue.slice(0, displayOffset).split("").filter((character) => character === "\u2022" || /\d/.test(character)).length,
6820
+ rawValueLength
6821
+ );
6822
+ }
6823
+ function replaceSsnSelection(rawValue, displayValue, insertedValue, start, end, maxDigits) {
6824
+ const startOffset = getRawOffset(displayValue, start, rawValue.length);
6825
+ const endOffset = getRawOffset(displayValue, end, rawValue.length);
6826
+ const selectedLength = endOffset - startOffset;
6827
+ const availableCapacity = Math.max(0, maxDigits - (rawValue.length - selectedLength));
6828
+ const acceptedInsertedValue = insertedValue.slice(0, availableCapacity);
6829
+ if (!acceptedInsertedValue) {
6830
+ return void 0;
6831
+ }
6832
+ return {
6833
+ value: `${rawValue.slice(0, startOffset)}${acceptedInsertedValue}${rawValue.slice(endOffset)}`,
6834
+ caret: startOffset + acceptedInsertedValue.length
6835
+ };
6836
+ }
6837
+ function deleteSsnSelection(rawValue, displayValue, start, end, backward) {
6838
+ let startOffset = getRawOffset(displayValue, start, rawValue.length);
6839
+ let endOffset = getRawOffset(displayValue, end, rawValue.length);
6840
+ if (startOffset === endOffset) {
6841
+ if (backward) {
6842
+ startOffset = Math.max(0, startOffset - 1);
6843
+ } else {
6844
+ endOffset = Math.min(rawValue.length, endOffset + 1);
6845
+ }
6846
+ }
6847
+ return {
6848
+ value: `${rawValue.slice(0, startOffset)}${rawValue.slice(endOffset)}`,
6849
+ caret: startOffset
6850
+ };
6851
+ }
6852
+ function getDisplayOffset(displayValue, rawOffset) {
6853
+ if (rawOffset === 0) {
6854
+ return 0;
6855
+ }
6856
+ let displayOffset = 0;
6857
+ let digitsSeen = 0;
6858
+ for (const character of displayValue) {
6859
+ if (character === "\u2022" || /\d/.test(character)) {
6860
+ digitsSeen += 1;
6861
+ if (digitsSeen === rawOffset) {
6862
+ return displayOffset + 1;
6863
+ }
6864
+ }
6865
+ displayOffset += 1;
6866
+ }
6867
+ return displayOffset;
6868
+ }
6869
+
6870
+ // ../renderers/src/components/VariableTextInput.tsx
6871
+ import { jsx as jsx100, jsxs as jsxs40 } from "react/jsx-runtime";
6781
6872
  var commonKeys = [
6782
6873
  "autoComplete",
6783
6874
  "autoCapitalize",
@@ -6794,6 +6885,9 @@ var commonKeys = [
6794
6885
  function VariableTextInput(inputProps) {
6795
6886
  const { id, value, control, onChange } = inputProps;
6796
6887
  const commonProps = __spreadProps(__spreadValues({}, pick(inputProps, ...commonKeys)), { name: id });
6888
+ if (control === "ssn-input") {
6889
+ return /* @__PURE__ */ jsx100(SsnInput, __spreadProps(__spreadValues({}, commonProps), { maxLength: inputProps.maxLength, onChange }));
6890
+ }
6797
6891
  switch (control) {
6798
6892
  case "email":
6799
6893
  return /* @__PURE__ */ jsx100(TextInput, __spreadProps(__spreadValues({}, commonProps), { type: "email", onChange }));
@@ -6819,10 +6913,142 @@ function VariableTextInput(inputProps) {
6819
6913
  }
6820
6914
  }
6821
6915
  function TextInput(props) {
6822
- const _a = props, { control, displayFormat, onChange } = _a, commonProps = __objRest(_a, ["control", "displayFormat", "onChange"]);
6916
+ const _a = props, { control, displayFormat, onChange, type } = _a, commonProps = __objRest(_a, ["control", "displayFormat", "onChange", "type"]);
6823
6917
  const InputWithPattern = control === "textarea" ? TextareaWithDisplayFormat : InputWithDisplayFormat;
6824
6918
  const InputWithoutPattern = control === "textarea" ? TextArea : Input6;
6825
- return displayFormat ? /* @__PURE__ */ jsx100(InputWithPattern, __spreadProps(__spreadValues({ displayPattern: displayFormat }, commonProps), { onChange })) : /* @__PURE__ */ jsx100(InputWithoutPattern, __spreadProps(__spreadValues({}, commonProps), { onChange: (e) => onChange(e.target.value) }));
6919
+ return displayFormat ? /* @__PURE__ */ jsx100(InputWithPattern, __spreadProps(__spreadValues({ displayPattern: displayFormat }, commonProps), { onChange })) : /* @__PURE__ */ jsx100(InputWithoutPattern, __spreadProps(__spreadValues({}, commonProps), { type, onChange: (e) => onChange(e.target.value) }));
6920
+ }
6921
+ function SsnInput(props) {
6922
+ const _a = props, {
6923
+ displayFormat = "",
6924
+ maxLength,
6925
+ onChange,
6926
+ type: _type,
6927
+ value = ""
6928
+ } = _a, commonProps = __objRest(_a, [
6929
+ "displayFormat",
6930
+ "maxLength",
6931
+ "onChange",
6932
+ "type",
6933
+ "value"
6934
+ ]);
6935
+ const { formatMessage } = useIntl21();
6936
+ const [isVisible, setIsVisible] = useState20(false);
6937
+ const [editVersion, setEditVersion] = useState20(0);
6938
+ const inputRef = useRef5(null);
6939
+ const selection = useRef5({ start: 0, end: 0 });
6940
+ const pendingCaret = useRef5(null);
6941
+ const maxDigits = displayFormat.split("").filter((character) => character === "*").length || maxLength || Infinity;
6942
+ const rawValue = value.replace(/\D/g, "");
6943
+ const formattedValue = formatSsnValue(rawValue, displayFormat, isVisible);
6944
+ const scheduleCaret = (rawOffset) => {
6945
+ pendingCaret.current = rawOffset;
6946
+ setEditVersion((version) => version + 1);
6947
+ };
6948
+ const replaceSelection = (insertedValue, start, end) => {
6949
+ const result = replaceSsnSelection(
6950
+ rawValue,
6951
+ formattedValue,
6952
+ insertedValue,
6953
+ start,
6954
+ end,
6955
+ maxDigits
6956
+ );
6957
+ if (!result) {
6958
+ return;
6959
+ }
6960
+ scheduleCaret(result.caret);
6961
+ onChange(result.value);
6962
+ };
6963
+ const deleteSelection = (start, end, backward) => {
6964
+ const result = deleteSsnSelection(rawValue, formattedValue, start, end, backward);
6965
+ scheduleCaret(result.caret);
6966
+ onChange(result.value);
6967
+ };
6968
+ useLayoutEffect3(() => {
6969
+ if (pendingCaret.current === null || !inputRef.current) {
6970
+ return;
6971
+ }
6972
+ inputRef.current.setSelectionRange(
6973
+ getDisplayOffset(formattedValue, pendingCaret.current),
6974
+ getDisplayOffset(formattedValue, pendingCaret.current)
6975
+ );
6976
+ pendingCaret.current = null;
6977
+ }, [editVersion, formattedValue, rawValue]);
6978
+ return /* @__PURE__ */ jsxs40("div", { className: "df-ssn-input-wrapper", children: [
6979
+ /* @__PURE__ */ jsx100(
6980
+ "input",
6981
+ __spreadProps(__spreadValues({
6982
+ ref: inputRef
6983
+ }, commonProps), {
6984
+ className: "form-control np-form-control np-input np-input--shape-rectangle df-ssn-input",
6985
+ type: "text",
6986
+ inputMode: "numeric",
6987
+ maxLength: displayFormat.length || maxLength,
6988
+ value: formattedValue,
6989
+ onChange: (event) => {
6990
+ const nextValue = event.currentTarget.value;
6991
+ const inputType = event.nativeEvent.inputType;
6992
+ const start = selection.current.start;
6993
+ const end = selection.current.end;
6994
+ if (isVisible || /^\d+$/.test(nextValue)) {
6995
+ const nextRawValue = nextValue.replace(/\D/g, "").slice(0, maxDigits);
6996
+ scheduleCaret(nextRawValue.length);
6997
+ onChange(nextRawValue);
6998
+ } else if ((inputType == null ? void 0 : inputType.startsWith("delete")) || nextValue.length < formattedValue.length) {
6999
+ deleteSelection(start, end, inputType === "deleteContentBackward");
7000
+ } else {
7001
+ replaceSelection(nextValue.replace(/\D/g, ""), start, end);
7002
+ }
7003
+ },
7004
+ onSelect: (event) => {
7005
+ var _a2, _b;
7006
+ selection.current = {
7007
+ start: (_a2 = event.currentTarget.selectionStart) != null ? _a2 : 0,
7008
+ end: (_b = event.currentTarget.selectionEnd) != null ? _b : 0
7009
+ };
7010
+ },
7011
+ onKeyDown: (event) => {
7012
+ var _a2, _b;
7013
+ selection.current = {
7014
+ start: (_a2 = event.currentTarget.selectionStart) != null ? _a2 : 0,
7015
+ end: (_b = event.currentTarget.selectionEnd) != null ? _b : 0
7016
+ };
7017
+ if (/^\d$/.test(event.key)) {
7018
+ event.preventDefault();
7019
+ replaceSelection(event.key, selection.current.start, selection.current.end);
7020
+ } else if (event.key === "Backspace") {
7021
+ event.preventDefault();
7022
+ deleteSelection(selection.current.start, selection.current.end, true);
7023
+ } else if (event.key === "Delete") {
7024
+ event.preventDefault();
7025
+ deleteSelection(selection.current.start, selection.current.end, false);
7026
+ }
7027
+ },
7028
+ onPaste: (event) => {
7029
+ var _a2, _b;
7030
+ event.preventDefault();
7031
+ selection.current = {
7032
+ start: (_a2 = event.currentTarget.selectionStart) != null ? _a2 : 0,
7033
+ end: (_b = event.currentTarget.selectionEnd) != null ? _b : 0
7034
+ };
7035
+ const pastedValue = event.clipboardData.getData("text").replace(/\D/g, "");
7036
+ replaceSelection(pastedValue, selection.current.start, selection.current.end);
7037
+ }
7038
+ })
7039
+ ),
7040
+ /* @__PURE__ */ jsx100(
7041
+ "button",
7042
+ {
7043
+ type: "button",
7044
+ className: "df-ssn-input-toggle",
7045
+ "aria-label": formatMessage(isVisible ? ssn_input_messages_default.hideValue : ssn_input_messages_default.showValue),
7046
+ "aria-pressed": isVisible,
7047
+ onClick: () => setIsVisible((visible) => !visible),
7048
+ children: isVisible ? /* @__PURE__ */ jsx100(EyeShut, { size: 24 }) : /* @__PURE__ */ jsx100(Eye, { size: 24 })
7049
+ }
7050
+ )
7051
+ ] });
6826
7052
  }
6827
7053
 
6828
7054
  // ../renderers/src/TextInputRenderer.tsx
@@ -7034,7 +7260,7 @@ var LargeUploadRenderer = {
7034
7260
  // ../renderers/src/UpsellRenderer.tsx
7035
7261
  var import_classnames35 = __toESM(require_classnames());
7036
7262
  import { Nudge } from "@transferwise/components";
7037
- import { useState as useState20 } from "react";
7263
+ import { useState as useState21 } from "react";
7038
7264
  import { jsx as jsx104 } from "react/jsx-runtime";
7039
7265
  var UpsellRenderer = {
7040
7266
  canRenderType: "upsell",
@@ -7042,7 +7268,7 @@ var UpsellRenderer = {
7042
7268
  };
7043
7269
  function UpsellRendererComponent(props) {
7044
7270
  const { text, callToAction, media, margin, onDismiss, control, tags } = props;
7045
- const [isVisible, setIsVisible] = useState20(true);
7271
+ const [isVisible, setIsVisible] = useState21(true);
7046
7272
  return isVisible ? /* @__PURE__ */ jsx104(
7047
7273
  Nudge,
7048
7274
  {
@@ -7272,11 +7498,11 @@ var customEventsToAnalytics = {
7272
7498
 
7273
7499
  // src/dynamicFlow/useOnCopy.tsx
7274
7500
  import { useCallback as useCallback2 } from "react";
7275
- import { useIntl as useIntl21 } from "react-intl";
7501
+ import { useIntl as useIntl22 } from "react-intl";
7276
7502
 
7277
7503
  // src/dynamicFlow/messages.ts
7278
- import { defineMessages as defineMessages15 } from "react-intl";
7279
- var messages_default = defineMessages15({
7504
+ import { defineMessages as defineMessages16 } from "react-intl";
7505
+ var messages_default = defineMessages16({
7280
7506
  copied: {
7281
7507
  id: "df.wise.CopyFeedback.copy",
7282
7508
  defaultMessage: "Copied to clipboard",
@@ -7291,7 +7517,7 @@ var messages_default = defineMessages15({
7291
7517
 
7292
7518
  // src/dynamicFlow/useOnCopy.tsx
7293
7519
  var useOnCopy = () => {
7294
- const { formatMessage } = useIntl21();
7520
+ const { formatMessage } = useIntl22();
7295
7521
  const createSnackBar = useSnackBarIfAvailable();
7296
7522
  return useCallback2(
7297
7523
  (copiedContent) => {
@@ -7307,9 +7533,9 @@ var useOnCopy = () => {
7307
7533
 
7308
7534
  // src/dynamicFlow/useWiseHttpClient.tsx
7309
7535
  import { useCallback as useCallback3 } from "react";
7310
- import { useIntl as useIntl22 } from "react-intl";
7536
+ import { useIntl as useIntl23 } from "react-intl";
7311
7537
  var useWiseHttpClient = (httpClient) => {
7312
- const { locale } = useIntl22();
7538
+ const { locale } = useIntl23();
7313
7539
  return useCallback3(
7314
7540
  async (input, init = {}) => {
7315
7541
  const headers = new Headers(init.headers);
@@ -7389,13 +7615,13 @@ var openLinkInNewTab = (url) => {
7389
7615
  };
7390
7616
 
7391
7617
  // src/dynamicFlow/DynamicFlow.tsx
7392
- import { jsxs as jsxs40 } from "react/jsx-runtime";
7618
+ import { jsxs as jsxs41 } from "react/jsx-runtime";
7393
7619
  function DynamicFlow(props) {
7394
7620
  const { className = "" } = props;
7395
7621
  const dfProps = useWiseToCoreProps(props);
7396
7622
  const df = useDynamicFlow(dfProps);
7397
7623
  const { onContextMenu, contextMenu } = useDFContextMenu(df.controller);
7398
- return /* @__PURE__ */ jsxs40("div", { className, onContextMenu, children: [
7624
+ return /* @__PURE__ */ jsxs41("div", { className, onContextMenu, children: [
7399
7625
  df.view,
7400
7626
  contextMenu
7401
7627
  ] });