@wise/dynamic-flow-client-internal 5.29.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
@@ -127,7 +127,7 @@ import { useDynamicFlow } from "@wise/dynamic-flow-client";
127
127
  // src/dynamicFlow/telemetry/app-version.ts
128
128
  var appVersion = (
129
129
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
130
- typeof process !== "undefined" ? "5.29.0" : "0.0.0"
130
+ typeof process !== "undefined" ? "5.30.0" : "0.0.0"
131
131
  );
132
132
 
133
133
  // src/dynamicFlow/context-menu/useContextMenu.tsx
@@ -607,11 +607,16 @@ var LegacyMedia = ({ image, icon, preferAvatar, size }) => {
607
607
  // ../renderers/src/components/Media/Media.tsx
608
608
  import { jsx as jsx10 } from "react/jsx-runtime";
609
609
  var Media = ({ media, preferAvatar = false, size }) => {
610
+ var _a, _b;
610
611
  switch (media == null ? void 0 : media.type) {
611
612
  case "avatar":
612
- return /* @__PURE__ */ jsx10(AvatarMedia, __spreadProps(__spreadValues({}, media), { size }));
613
+ return /* @__PURE__ */ jsx10(AvatarMedia, __spreadProps(__spreadValues({}, media), { size: (_a = media.size && mediaSizeTokenMappings[media.size]) != null ? _a : size }));
613
614
  case "image": {
614
- const { asset, icon } = resolveMediaFromUri(media.uri, size, media.accessibilityDescription);
615
+ const { asset, icon } = resolveMediaFromUri(
616
+ media.uri,
617
+ (_b = media.size && mediaSizeTokenMappings[media.size]) != null ? _b : size,
618
+ media.accessibilityDescription
619
+ );
615
620
  return icon != null ? icon : asset;
616
621
  }
617
622
  case "legacy": {
@@ -650,6 +655,13 @@ function extractFirstImageFromAvatar(avatar) {
650
655
  accessibilityDescription: avatar.accessibilityDescription
651
656
  };
652
657
  }
658
+ var mediaSizeTokenMappings = {
659
+ xs: 24,
660
+ sm: 32,
661
+ md: 48,
662
+ lg: 56,
663
+ xl: 72
664
+ };
653
665
 
654
666
  // ../renderers/src/components/Media/OptionMedia.tsx
655
667
  import { jsx as jsx11 } from "react/jsx-runtime";
@@ -4763,11 +4775,28 @@ var AvatarMediaRendererComponent = ({
4763
4775
  };
4764
4776
  var ImageMediaRendererComponent = (_a) => {
4765
4777
  var _b = _a, {
4766
- media
4778
+ media,
4779
+ size
4767
4780
  } = _b, rest = __objRest(_b, [
4768
- "media"
4781
+ "media",
4782
+ "size"
4769
4783
  ]);
4770
- return isUrnImage(media.uri) ? /* @__PURE__ */ jsx64(UrnImage, __spreadValues({ uri: media.uri, accessibilityDescription: media.accessibilityDescription }, rest)) : /* @__PURE__ */ jsx64(UrlImage, __spreadValues({ uri: media.uri, accessibilityDescription: media.accessibilityDescription }, rest));
4784
+ var _a2, _b2;
4785
+ return isUrnImage(media.uri) ? /* @__PURE__ */ jsx64(
4786
+ UrnImage,
4787
+ __spreadValues({
4788
+ uri: media.uri,
4789
+ size: (_a2 = media.size) != null ? _a2 : size,
4790
+ accessibilityDescription: media.accessibilityDescription
4791
+ }, rest)
4792
+ ) : /* @__PURE__ */ jsx64(
4793
+ UrlImage,
4794
+ __spreadValues({
4795
+ uri: media.uri,
4796
+ size: (_b2 = media.size) != null ? _b2 : size,
4797
+ accessibilityDescription: media.accessibilityDescription
4798
+ }, rest)
4799
+ );
4771
4800
  };
4772
4801
  var mapAvatarMediaSize = (size) => {
4773
4802
  switch (size) {
@@ -6748,7 +6777,98 @@ import {
6748
6777
  TextArea,
6749
6778
  TextareaWithDisplayFormat
6750
6779
  } from "@transferwise/components";
6751
- 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";
6752
6872
  var commonKeys = [
6753
6873
  "autoComplete",
6754
6874
  "autoCapitalize",
@@ -6765,6 +6885,9 @@ var commonKeys = [
6765
6885
  function VariableTextInput(inputProps) {
6766
6886
  const { id, value, control, onChange } = inputProps;
6767
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
+ }
6768
6891
  switch (control) {
6769
6892
  case "email":
6770
6893
  return /* @__PURE__ */ jsx100(TextInput, __spreadProps(__spreadValues({}, commonProps), { type: "email", onChange }));
@@ -6790,10 +6913,142 @@ function VariableTextInput(inputProps) {
6790
6913
  }
6791
6914
  }
6792
6915
  function TextInput(props) {
6793
- 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"]);
6794
6917
  const InputWithPattern = control === "textarea" ? TextareaWithDisplayFormat : InputWithDisplayFormat;
6795
6918
  const InputWithoutPattern = control === "textarea" ? TextArea : Input6;
6796
- 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
+ ] });
6797
7052
  }
6798
7053
 
6799
7054
  // ../renderers/src/TextInputRenderer.tsx
@@ -7005,7 +7260,7 @@ var LargeUploadRenderer = {
7005
7260
  // ../renderers/src/UpsellRenderer.tsx
7006
7261
  var import_classnames35 = __toESM(require_classnames());
7007
7262
  import { Nudge } from "@transferwise/components";
7008
- import { useState as useState20 } from "react";
7263
+ import { useState as useState21 } from "react";
7009
7264
  import { jsx as jsx104 } from "react/jsx-runtime";
7010
7265
  var UpsellRenderer = {
7011
7266
  canRenderType: "upsell",
@@ -7013,7 +7268,7 @@ var UpsellRenderer = {
7013
7268
  };
7014
7269
  function UpsellRendererComponent(props) {
7015
7270
  const { text, callToAction, media, margin, onDismiss, control, tags } = props;
7016
- const [isVisible, setIsVisible] = useState20(true);
7271
+ const [isVisible, setIsVisible] = useState21(true);
7017
7272
  return isVisible ? /* @__PURE__ */ jsx104(
7018
7273
  Nudge,
7019
7274
  {
@@ -7243,11 +7498,11 @@ var customEventsToAnalytics = {
7243
7498
 
7244
7499
  // src/dynamicFlow/useOnCopy.tsx
7245
7500
  import { useCallback as useCallback2 } from "react";
7246
- import { useIntl as useIntl21 } from "react-intl";
7501
+ import { useIntl as useIntl22 } from "react-intl";
7247
7502
 
7248
7503
  // src/dynamicFlow/messages.ts
7249
- import { defineMessages as defineMessages15 } from "react-intl";
7250
- var messages_default = defineMessages15({
7504
+ import { defineMessages as defineMessages16 } from "react-intl";
7505
+ var messages_default = defineMessages16({
7251
7506
  copied: {
7252
7507
  id: "df.wise.CopyFeedback.copy",
7253
7508
  defaultMessage: "Copied to clipboard",
@@ -7262,7 +7517,7 @@ var messages_default = defineMessages15({
7262
7517
 
7263
7518
  // src/dynamicFlow/useOnCopy.tsx
7264
7519
  var useOnCopy = () => {
7265
- const { formatMessage } = useIntl21();
7520
+ const { formatMessage } = useIntl22();
7266
7521
  const createSnackBar = useSnackBarIfAvailable();
7267
7522
  return useCallback2(
7268
7523
  (copiedContent) => {
@@ -7278,9 +7533,9 @@ var useOnCopy = () => {
7278
7533
 
7279
7534
  // src/dynamicFlow/useWiseHttpClient.tsx
7280
7535
  import { useCallback as useCallback3 } from "react";
7281
- import { useIntl as useIntl22 } from "react-intl";
7536
+ import { useIntl as useIntl23 } from "react-intl";
7282
7537
  var useWiseHttpClient = (httpClient) => {
7283
- const { locale } = useIntl22();
7538
+ const { locale } = useIntl23();
7284
7539
  return useCallback3(
7285
7540
  async (input, init = {}) => {
7286
7541
  const headers = new Headers(init.headers);
@@ -7360,13 +7615,13 @@ var openLinkInNewTab = (url) => {
7360
7615
  };
7361
7616
 
7362
7617
  // src/dynamicFlow/DynamicFlow.tsx
7363
- import { jsxs as jsxs40 } from "react/jsx-runtime";
7618
+ import { jsxs as jsxs41 } from "react/jsx-runtime";
7364
7619
  function DynamicFlow(props) {
7365
7620
  const { className = "" } = props;
7366
7621
  const dfProps = useWiseToCoreProps(props);
7367
7622
  const df = useDynamicFlow(dfProps);
7368
7623
  const { onContextMenu, contextMenu } = useDFContextMenu(df.controller);
7369
- return /* @__PURE__ */ jsxs40("div", { className, onContextMenu, children: [
7624
+ return /* @__PURE__ */ jsxs41("div", { className, onContextMenu, children: [
7370
7625
  df.view,
7371
7626
  contextMenu
7372
7627
  ] });