@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.
@@ -44,5 +44,7 @@
44
44
  "df.wise.group.currencies-with-account-details": "Currencies with account details",
45
45
  "df.wise.group.popular": "Popular",
46
46
  "df.wise.group.recent": "Recent",
47
+ "df.wise.ssnInput.hideValue": "Hide value",
48
+ "df.wise.ssnInput.showValue": "Show value",
47
49
  "df.wise.step.scrollToBottom": "Scroll to bottom"
48
50
  }
package/build/main.css CHANGED
@@ -387,6 +387,31 @@
387
387
  .df-prefer-container-queries {
388
388
  container-type: inline-size;
389
389
  }
390
+
391
+ .df-ssn-input-wrapper {
392
+ position: relative;
393
+ }
394
+
395
+ .df-ssn-input {
396
+ padding-right: 3.5rem;
397
+ }
398
+
399
+ .df-ssn-input-toggle {
400
+ align-items: center;
401
+ background: transparent;
402
+ border: 0;
403
+ color: inherit;
404
+ cursor: pointer;
405
+ display: flex;
406
+ height: 100%;
407
+ justify-content: center;
408
+ padding: 0;
409
+ position: absolute;
410
+ right: 0;
411
+ top: 0;
412
+ width: 3.5rem;
413
+ }
414
+
390
415
  .df-context-menu {
391
416
  position: fixed;
392
417
  z-index: 10;
package/build/main.js CHANGED
@@ -336,7 +336,7 @@ var recursivelyRemoveNullish = (element) => {
336
336
  };
337
337
 
338
338
  // src/dynamicFlow/useWiseToCoreProps.tsx
339
- var import_react30 = require("react");
339
+ var import_react31 = require("react");
340
340
 
341
341
  // src/dynamicFlow/getMergedRenderers.tsx
342
342
  var import_dynamic_flow_client2 = require("@wise/dynamic-flow-client");
@@ -6782,6 +6782,97 @@ var import_components69 = require("@transferwise/components");
6782
6782
 
6783
6783
  // ../renderers/src/components/VariableTextInput.tsx
6784
6784
  var import_components68 = require("@transferwise/components");
6785
+ var import_icons7 = require("@transferwise/icons");
6786
+ var import_react_intl36 = require("react-intl");
6787
+ var import_react27 = require("react");
6788
+
6789
+ // ../renderers/src/messages/ssn-input.messages.ts
6790
+ var import_react_intl35 = require("react-intl");
6791
+ var ssn_input_messages_default = (0, import_react_intl35.defineMessages)({
6792
+ showValue: {
6793
+ id: "df.wise.ssnInput.showValue",
6794
+ defaultMessage: "Show value",
6795
+ description: "Accessible label for showing a masked SSN or SIN value"
6796
+ },
6797
+ hideValue: {
6798
+ id: "df.wise.ssnInput.hideValue",
6799
+ defaultMessage: "Hide value",
6800
+ description: "Accessible label for hiding an SSN or SIN value"
6801
+ }
6802
+ });
6803
+
6804
+ // ../renderers/src/components/ssnInputUtils.ts
6805
+ function formatSsnValue(rawValue, displayFormat, isVisible) {
6806
+ if (!displayFormat) {
6807
+ return isVisible ? rawValue : "\u2022".repeat(rawValue.length);
6808
+ }
6809
+ return displayFormat.split("").reduce(
6810
+ ({ display, digitsUsed }, character) => {
6811
+ if (character === "*") {
6812
+ return digitsUsed < rawValue.length ? {
6813
+ display: `${display}${isVisible ? rawValue[digitsUsed] : "\u2022"}`,
6814
+ digitsUsed: digitsUsed + 1
6815
+ } : { display, digitsUsed };
6816
+ }
6817
+ return digitsUsed > 0 && digitsUsed < rawValue.length ? { display: `${display}${character}`, digitsUsed } : { display, digitsUsed };
6818
+ },
6819
+ { display: "", digitsUsed: 0 }
6820
+ ).display;
6821
+ }
6822
+ function getRawOffset(displayValue, displayOffset, rawValueLength) {
6823
+ return Math.min(
6824
+ displayValue.slice(0, displayOffset).split("").filter((character) => character === "\u2022" || /\d/.test(character)).length,
6825
+ rawValueLength
6826
+ );
6827
+ }
6828
+ function replaceSsnSelection(rawValue, displayValue, insertedValue, start, end, maxDigits) {
6829
+ const startOffset = getRawOffset(displayValue, start, rawValue.length);
6830
+ const endOffset = getRawOffset(displayValue, end, rawValue.length);
6831
+ const selectedLength = endOffset - startOffset;
6832
+ const availableCapacity = Math.max(0, maxDigits - (rawValue.length - selectedLength));
6833
+ const acceptedInsertedValue = insertedValue.slice(0, availableCapacity);
6834
+ if (!acceptedInsertedValue) {
6835
+ return void 0;
6836
+ }
6837
+ return {
6838
+ value: `${rawValue.slice(0, startOffset)}${acceptedInsertedValue}${rawValue.slice(endOffset)}`,
6839
+ caret: startOffset + acceptedInsertedValue.length
6840
+ };
6841
+ }
6842
+ function deleteSsnSelection(rawValue, displayValue, start, end, backward) {
6843
+ let startOffset = getRawOffset(displayValue, start, rawValue.length);
6844
+ let endOffset = getRawOffset(displayValue, end, rawValue.length);
6845
+ if (startOffset === endOffset) {
6846
+ if (backward) {
6847
+ startOffset = Math.max(0, startOffset - 1);
6848
+ } else {
6849
+ endOffset = Math.min(rawValue.length, endOffset + 1);
6850
+ }
6851
+ }
6852
+ return {
6853
+ value: `${rawValue.slice(0, startOffset)}${rawValue.slice(endOffset)}`,
6854
+ caret: startOffset
6855
+ };
6856
+ }
6857
+ function getDisplayOffset(displayValue, rawOffset) {
6858
+ if (rawOffset === 0) {
6859
+ return 0;
6860
+ }
6861
+ let displayOffset = 0;
6862
+ let digitsSeen = 0;
6863
+ for (const character of displayValue) {
6864
+ if (character === "\u2022" || /\d/.test(character)) {
6865
+ digitsSeen += 1;
6866
+ if (digitsSeen === rawOffset) {
6867
+ return displayOffset + 1;
6868
+ }
6869
+ }
6870
+ displayOffset += 1;
6871
+ }
6872
+ return displayOffset;
6873
+ }
6874
+
6875
+ // ../renderers/src/components/VariableTextInput.tsx
6785
6876
  var import_jsx_runtime100 = require("react/jsx-runtime");
6786
6877
  var commonKeys = [
6787
6878
  "autoComplete",
@@ -6799,6 +6890,9 @@ var commonKeys = [
6799
6890
  function VariableTextInput(inputProps) {
6800
6891
  const { id, value, control, onChange } = inputProps;
6801
6892
  const commonProps = __spreadProps(__spreadValues({}, pick(inputProps, ...commonKeys)), { name: id });
6893
+ if (control === "ssn-input") {
6894
+ return /* @__PURE__ */ (0, import_jsx_runtime100.jsx)(SsnInput, __spreadProps(__spreadValues({}, commonProps), { maxLength: inputProps.maxLength, onChange }));
6895
+ }
6802
6896
  switch (control) {
6803
6897
  case "email":
6804
6898
  return /* @__PURE__ */ (0, import_jsx_runtime100.jsx)(TextInput, __spreadProps(__spreadValues({}, commonProps), { type: "email", onChange }));
@@ -6824,10 +6918,142 @@ function VariableTextInput(inputProps) {
6824
6918
  }
6825
6919
  }
6826
6920
  function TextInput(props) {
6827
- const _a = props, { control, displayFormat, onChange } = _a, commonProps = __objRest(_a, ["control", "displayFormat", "onChange"]);
6921
+ const _a = props, { control, displayFormat, onChange, type } = _a, commonProps = __objRest(_a, ["control", "displayFormat", "onChange", "type"]);
6828
6922
  const InputWithPattern = control === "textarea" ? import_components68.TextareaWithDisplayFormat : import_components68.InputWithDisplayFormat;
6829
6923
  const InputWithoutPattern = control === "textarea" ? import_components68.TextArea : import_components68.Input;
6830
- return displayFormat ? /* @__PURE__ */ (0, import_jsx_runtime100.jsx)(InputWithPattern, __spreadProps(__spreadValues({ displayPattern: displayFormat }, commonProps), { onChange })) : /* @__PURE__ */ (0, import_jsx_runtime100.jsx)(InputWithoutPattern, __spreadProps(__spreadValues({}, commonProps), { onChange: (e) => onChange(e.target.value) }));
6924
+ return displayFormat ? /* @__PURE__ */ (0, import_jsx_runtime100.jsx)(InputWithPattern, __spreadProps(__spreadValues({ displayPattern: displayFormat }, commonProps), { onChange })) : /* @__PURE__ */ (0, import_jsx_runtime100.jsx)(InputWithoutPattern, __spreadProps(__spreadValues({}, commonProps), { type, onChange: (e) => onChange(e.target.value) }));
6925
+ }
6926
+ function SsnInput(props) {
6927
+ const _a = props, {
6928
+ displayFormat = "",
6929
+ maxLength,
6930
+ onChange,
6931
+ type: _type,
6932
+ value = ""
6933
+ } = _a, commonProps = __objRest(_a, [
6934
+ "displayFormat",
6935
+ "maxLength",
6936
+ "onChange",
6937
+ "type",
6938
+ "value"
6939
+ ]);
6940
+ const { formatMessage } = (0, import_react_intl36.useIntl)();
6941
+ const [isVisible, setIsVisible] = (0, import_react27.useState)(false);
6942
+ const [editVersion, setEditVersion] = (0, import_react27.useState)(0);
6943
+ const inputRef = (0, import_react27.useRef)(null);
6944
+ const selection = (0, import_react27.useRef)({ start: 0, end: 0 });
6945
+ const pendingCaret = (0, import_react27.useRef)(null);
6946
+ const maxDigits = displayFormat.split("").filter((character) => character === "*").length || maxLength || Infinity;
6947
+ const rawValue = value.replace(/\D/g, "");
6948
+ const formattedValue = formatSsnValue(rawValue, displayFormat, isVisible);
6949
+ const scheduleCaret = (rawOffset) => {
6950
+ pendingCaret.current = rawOffset;
6951
+ setEditVersion((version) => version + 1);
6952
+ };
6953
+ const replaceSelection = (insertedValue, start, end) => {
6954
+ const result = replaceSsnSelection(
6955
+ rawValue,
6956
+ formattedValue,
6957
+ insertedValue,
6958
+ start,
6959
+ end,
6960
+ maxDigits
6961
+ );
6962
+ if (!result) {
6963
+ return;
6964
+ }
6965
+ scheduleCaret(result.caret);
6966
+ onChange(result.value);
6967
+ };
6968
+ const deleteSelection = (start, end, backward) => {
6969
+ const result = deleteSsnSelection(rawValue, formattedValue, start, end, backward);
6970
+ scheduleCaret(result.caret);
6971
+ onChange(result.value);
6972
+ };
6973
+ (0, import_react27.useLayoutEffect)(() => {
6974
+ if (pendingCaret.current === null || !inputRef.current) {
6975
+ return;
6976
+ }
6977
+ inputRef.current.setSelectionRange(
6978
+ getDisplayOffset(formattedValue, pendingCaret.current),
6979
+ getDisplayOffset(formattedValue, pendingCaret.current)
6980
+ );
6981
+ pendingCaret.current = null;
6982
+ }, [editVersion, formattedValue, rawValue]);
6983
+ return /* @__PURE__ */ (0, import_jsx_runtime100.jsxs)("div", { className: "df-ssn-input-wrapper", children: [
6984
+ /* @__PURE__ */ (0, import_jsx_runtime100.jsx)(
6985
+ "input",
6986
+ __spreadProps(__spreadValues({
6987
+ ref: inputRef
6988
+ }, commonProps), {
6989
+ className: "form-control np-form-control np-input np-input--shape-rectangle df-ssn-input",
6990
+ type: "text",
6991
+ inputMode: "numeric",
6992
+ maxLength: displayFormat.length || maxLength,
6993
+ value: formattedValue,
6994
+ onChange: (event) => {
6995
+ const nextValue = event.currentTarget.value;
6996
+ const inputType = event.nativeEvent.inputType;
6997
+ const start = selection.current.start;
6998
+ const end = selection.current.end;
6999
+ if (isVisible || /^\d+$/.test(nextValue)) {
7000
+ const nextRawValue = nextValue.replace(/\D/g, "").slice(0, maxDigits);
7001
+ scheduleCaret(nextRawValue.length);
7002
+ onChange(nextRawValue);
7003
+ } else if ((inputType == null ? void 0 : inputType.startsWith("delete")) || nextValue.length < formattedValue.length) {
7004
+ deleteSelection(start, end, inputType === "deleteContentBackward");
7005
+ } else {
7006
+ replaceSelection(nextValue.replace(/\D/g, ""), start, end);
7007
+ }
7008
+ },
7009
+ onSelect: (event) => {
7010
+ var _a2, _b;
7011
+ selection.current = {
7012
+ start: (_a2 = event.currentTarget.selectionStart) != null ? _a2 : 0,
7013
+ end: (_b = event.currentTarget.selectionEnd) != null ? _b : 0
7014
+ };
7015
+ },
7016
+ onKeyDown: (event) => {
7017
+ var _a2, _b;
7018
+ selection.current = {
7019
+ start: (_a2 = event.currentTarget.selectionStart) != null ? _a2 : 0,
7020
+ end: (_b = event.currentTarget.selectionEnd) != null ? _b : 0
7021
+ };
7022
+ if (/^\d$/.test(event.key)) {
7023
+ event.preventDefault();
7024
+ replaceSelection(event.key, selection.current.start, selection.current.end);
7025
+ } else if (event.key === "Backspace") {
7026
+ event.preventDefault();
7027
+ deleteSelection(selection.current.start, selection.current.end, true);
7028
+ } else if (event.key === "Delete") {
7029
+ event.preventDefault();
7030
+ deleteSelection(selection.current.start, selection.current.end, false);
7031
+ }
7032
+ },
7033
+ onPaste: (event) => {
7034
+ var _a2, _b;
7035
+ event.preventDefault();
7036
+ selection.current = {
7037
+ start: (_a2 = event.currentTarget.selectionStart) != null ? _a2 : 0,
7038
+ end: (_b = event.currentTarget.selectionEnd) != null ? _b : 0
7039
+ };
7040
+ const pastedValue = event.clipboardData.getData("text").replace(/\D/g, "");
7041
+ replaceSelection(pastedValue, selection.current.start, selection.current.end);
7042
+ }
7043
+ })
7044
+ ),
7045
+ /* @__PURE__ */ (0, import_jsx_runtime100.jsx)(
7046
+ "button",
7047
+ {
7048
+ type: "button",
7049
+ className: "df-ssn-input-toggle",
7050
+ "aria-label": formatMessage(isVisible ? ssn_input_messages_default.hideValue : ssn_input_messages_default.showValue),
7051
+ "aria-pressed": isVisible,
7052
+ onClick: () => setIsVisible((visible) => !visible),
7053
+ children: isVisible ? /* @__PURE__ */ (0, import_jsx_runtime100.jsx)(import_icons7.EyeShut, { size: 24 }) : /* @__PURE__ */ (0, import_jsx_runtime100.jsx)(import_icons7.Eye, { size: 24 })
7054
+ }
7055
+ )
7056
+ ] });
6831
7057
  }
6832
7058
 
6833
7059
  // ../renderers/src/TextInputRenderer.tsx
@@ -7039,7 +7265,7 @@ var LargeUploadRenderer = {
7039
7265
  // ../renderers/src/UpsellRenderer.tsx
7040
7266
  var import_components71 = require("@transferwise/components");
7041
7267
  var import_classnames35 = __toESM(require_classnames());
7042
- var import_react27 = require("react");
7268
+ var import_react28 = require("react");
7043
7269
  var import_jsx_runtime104 = require("react/jsx-runtime");
7044
7270
  var UpsellRenderer = {
7045
7271
  canRenderType: "upsell",
@@ -7047,7 +7273,7 @@ var UpsellRenderer = {
7047
7273
  };
7048
7274
  function UpsellRendererComponent(props) {
7049
7275
  const { text, callToAction, media, margin, onDismiss, control, tags } = props;
7050
- const [isVisible, setIsVisible] = (0, import_react27.useState)(true);
7276
+ const [isVisible, setIsVisible] = (0, import_react28.useState)(true);
7051
7277
  return isVisible ? /* @__PURE__ */ (0, import_jsx_runtime104.jsx)(
7052
7278
  import_components71.Nudge,
7053
7279
  {
@@ -7276,12 +7502,12 @@ var customEventsToAnalytics = {
7276
7502
  };
7277
7503
 
7278
7504
  // src/dynamicFlow/useOnCopy.tsx
7279
- var import_react28 = require("react");
7280
- var import_react_intl36 = require("react-intl");
7505
+ var import_react29 = require("react");
7506
+ var import_react_intl38 = require("react-intl");
7281
7507
 
7282
7508
  // src/dynamicFlow/messages.ts
7283
- var import_react_intl35 = require("react-intl");
7284
- var messages_default = (0, import_react_intl35.defineMessages)({
7509
+ var import_react_intl37 = require("react-intl");
7510
+ var messages_default = (0, import_react_intl37.defineMessages)({
7285
7511
  copied: {
7286
7512
  id: "df.wise.CopyFeedback.copy",
7287
7513
  defaultMessage: "Copied to clipboard",
@@ -7296,9 +7522,9 @@ var messages_default = (0, import_react_intl35.defineMessages)({
7296
7522
 
7297
7523
  // src/dynamicFlow/useOnCopy.tsx
7298
7524
  var useOnCopy = () => {
7299
- const { formatMessage } = (0, import_react_intl36.useIntl)();
7525
+ const { formatMessage } = (0, import_react_intl38.useIntl)();
7300
7526
  const createSnackBar = useSnackBarIfAvailable();
7301
- return (0, import_react28.useCallback)(
7527
+ return (0, import_react29.useCallback)(
7302
7528
  (copiedContent) => {
7303
7529
  if (copiedContent) {
7304
7530
  createSnackBar({ text: formatMessage(messages_default.copied) });
@@ -7311,11 +7537,11 @@ var useOnCopy = () => {
7311
7537
  };
7312
7538
 
7313
7539
  // src/dynamicFlow/useWiseHttpClient.tsx
7314
- var import_react29 = require("react");
7315
- var import_react_intl37 = require("react-intl");
7540
+ var import_react30 = require("react");
7541
+ var import_react_intl39 = require("react-intl");
7316
7542
  var useWiseHttpClient = (httpClient) => {
7317
- const { locale } = (0, import_react_intl37.useIntl)();
7318
- return (0, import_react29.useCallback)(
7543
+ const { locale } = (0, import_react_intl39.useIntl)();
7544
+ return (0, import_react30.useCallback)(
7319
7545
  async (input, init = {}) => {
7320
7546
  const headers = new Headers(init.headers);
7321
7547
  headers.set("accept-language", locale);
@@ -7356,10 +7582,10 @@ var useWiseToCoreProps = (props) => {
7356
7582
  onLog
7357
7583
  } = props;
7358
7584
  const httpClient = useWiseHttpClient(customFetch);
7359
- const mergedRenderers = (0, import_react30.useMemo)(() => getMergedRenderers(props), [renderers]);
7585
+ const mergedRenderers = (0, import_react31.useMemo)(() => getMergedRenderers(props), [renderers]);
7360
7586
  const createSnackBar = useCreateSnackBar();
7361
- const logEvent = (0, import_react30.useMemo)(() => getLogEvent(onLog), [onLog]);
7362
- const trackEvent = (0, import_react30.useMemo)(() => getTrackEvent(onEvent, onAnalytics), [onEvent, onAnalytics]);
7587
+ const logEvent = (0, import_react31.useMemo)(() => getLogEvent(onLog), [onLog]);
7588
+ const trackEvent = (0, import_react31.useMemo)(() => getTrackEvent(onEvent, onAnalytics), [onEvent, onAnalytics]);
7363
7589
  const onCopy = useOnCopy();
7364
7590
  return __spreadProps(__spreadValues({}, props), {
7365
7591
  httpClient,
@@ -7407,14 +7633,14 @@ function DynamicFlow(props) {
7407
7633
  }
7408
7634
 
7409
7635
  // src/dynamicFlow/DynamicFlowWithRef.tsx
7410
- var import_react31 = require("react");
7636
+ var import_react32 = require("react");
7411
7637
  var import_dynamic_flow_client5 = require("@wise/dynamic-flow-client");
7412
7638
  var import_jsx_runtime109 = require("react/jsx-runtime");
7413
- var DynamicFlowWithRef = (0, import_react31.forwardRef)(function DynamicFlowWithRef2(props, ref) {
7639
+ var DynamicFlowWithRef = (0, import_react32.forwardRef)(function DynamicFlowWithRef2(props, ref) {
7414
7640
  const { className = "" } = props;
7415
7641
  const dfProps = useWiseToCoreProps(props);
7416
7642
  const df = (0, import_dynamic_flow_client5.useDynamicFlow)(dfProps);
7417
- (0, import_react31.useImperativeHandle)(
7643
+ (0, import_react32.useImperativeHandle)(
7418
7644
  ref,
7419
7645
  () => ({
7420
7646
  getValue: () => {