@wise/dynamic-flow-client-internal 5.0.0 → 5.1.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/README.md CHANGED
@@ -19,7 +19,7 @@ npm install @wise/dynamic-flow-client-internal
19
19
  pnpm install @wise/dynamic-flow-client-internal
20
20
  ```
21
21
 
22
- 2. Install required peer dependencies (if not already installed). Please refer to setup instructions for `@transferwise/components` and `@transferwise/neptune-css` if installing up for the first time.
22
+ 2. Install required peer dependencies (if not already installed). Please refer to setup instructions for `@transferwise/components` and `@transferwise/neptune-css` if installing for the first time.
23
23
 
24
24
  ```
25
25
  # yarn
@@ -37,9 +37,14 @@ pnpm install @transferwise/components @transferwise/formatting @transferwise/ico
37
37
 
38
38
  **Note:** Keep in mind that some of these dependencies have their own peer dependencies. Don't forget to install those, for instance: `@transferwise/components` needs `@wise/art` and `@wise/components-theming`.
39
39
 
40
+ 3. In addition to the design system styles, you need to import the DynamicFlow styles once into your application. You can do this either via JavaScript or CSS.
41
+
40
42
  ```js
41
- // Should be imported once in your application
42
- import '@wise/dynamic-flow-client-internal/build/main.css';
43
+ import '@wise/dynamic-flow-client-internal/main.css'; // JavaScript
44
+ ```
45
+
46
+ ```css
47
+ @import url('@wise/dynamic-flow-client-internal/build/main.css'); /* CSS */
43
48
  ```
44
49
 
45
50
  The `DynamicFlow` component must be wraped in a Neptune `Provider` to support localisation, a `ThemeProvider` to provide theming, and a `SnackbarProvider` to ensure snackbars display correctly. Translations should be imported from both components and dynamic flows, merged, and passed to the `Provider` component (as below).
@@ -50,15 +55,15 @@ The `DynamicFlow` component must be wraped in a Neptune `Provider` to support lo
50
55
  import {
51
56
  Provider,
52
57
  SnackbarProvider,
53
- translations as componentTranslations,
58
+ translations as dsTranslations,
54
59
  } from '@transferwise/components';
55
60
  import { getLocalisedMessages } from '@transferwise/crab/client';
56
61
  import {
57
62
  DynamicFlow,
58
- translations as dynamicFlowsTranslations,
63
+ translations as dfTranslations,
59
64
  } from '@wise/dynamic-flow-client-internal';
60
65
 
61
- const messages = getLocalisedMessages(locale, [componentTranslations, dynamicFlowsTranslations]);
66
+ const messages = getLocalisedMessages(locale, [dsTranslations, dfTranslations]);
62
67
 
63
68
  return (
64
69
  <Provider i18n={{ locale, messages }}>
@@ -91,17 +96,17 @@ You'll need to merge the '@transferwise/components' translations with the '@wise
91
96
  import {
92
97
  Provider,
93
98
  SnackbarProvider,
94
- translations as componentTranslations,
99
+ translations as dsTranslations,
95
100
  } from '@transferwise/components';
96
101
  import {
97
102
  DynamicFlow,
98
- translations as dynamicFlowsTranslations,
103
+ translations as dfTranslations,
99
104
  } from '@wise/dynamic-flow-client-internal';
100
105
 
101
106
  // create your messages object
102
107
  const messages: Record<string, string> = {
103
- ...(componentTranslations[lang] || componentTranslations[lang.replace('-', '_')] || componentTranslations[lang.substring(0, 2)] || {}),
104
- ...(translations[lang] || translations[lang.replace('-', '_')] || translations[lang.substring(0, 2)] || {}),
108
+ ...(dsTranslations[lang] || dsTranslations[lang.replace('-', '_')] || dsTranslations[lang.substring(0, 2)] || {}),
109
+ ...(dfTranslations[lang] || dfTranslations[lang.replace('-', '_')] || dfTranslations[lang.substring(0, 2)] || {}),
105
110
  }
106
111
 
107
112
  return (
@@ -203,13 +208,13 @@ const mockCustomFetch = (input, init) => Promise.resolve(new Response(JSON.strin
203
208
 
204
209
  ### Telemetry
205
210
 
206
- The `DynamicFlow` component accepts two optional props: `onEvent` and `onLog` which can be used to track and log.
211
+ The `DynamicFlow` component accepts two optional props: `onAnalytics` and `onLog` which can be used to track and log.
207
212
 
208
213
  In the example below we send tracking events to Mixpanel and logging events to Rollbar.
209
214
 
210
215
  ```tsx
211
216
  <DynamicFlow
212
- onEvent={(event, props) => mixpanel.track(event, props)}
217
+ onAnalytics={(event, props) => mixpanel.track(event, props)}
213
218
  onLog={(level, message, extra) => Rollbar[level](message, extra)}
214
219
  />
215
220
  ```
@@ -217,7 +222,7 @@ In the example below we send tracking events to Mixpanel and logging events to R
217
222
  Alternatively, you can log to the browser console:
218
223
 
219
224
  ```ts
220
- onEvent={(event, props) => console.log(event, props)}
225
+ onAnalytics={(event, props) => console.log(event, props)}
221
226
  onLog={(level, message, extra) => {
222
227
  const levelToConsole = {
223
228
  critical: console.error,
@@ -230,56 +235,36 @@ onLog={(level, message, extra) => {
230
235
  }}
231
236
  ```
232
237
 
233
- ### Loader configuration
234
-
235
- By default, DF will display a loading animation (The `Loader` component from Neptune) when the first step is loading. It will not display it during refresh-on-change or while submitting forms.
236
-
237
- You can change the defaults by passing a `loaderConfig` prop:
238
-
239
- ```ts
240
- type LoaderConfig = {
241
- size?: `xs | sm | md | lg | xl`;
242
- initial?: boolean;
243
- submission?: boolean;
244
- };
245
- ```
246
-
247
- | property | type | notes | default |
248
- | ------------ | ------- | ------------------------------------------------------------------------------ | ------- |
249
- | `size` | string | The size of the Loader component. | `xl` |
250
- | `initial` | boolean | Whether or not to display the Loader component while loading the initial step. | true |
251
- | `submission` | boolean | Whether or not to display the Loader component during form submissions. | false |
252
-
253
- ## DynamicFragment
238
+ ## DynamicForm Component
254
239
 
255
- If you need to get the submittable data outside of a submission, you can use the `DynamicFragment` component. This will give you access to two methods: `getValue` and `validate` via a [ref](https://react.dev/reference/react/useRef). For example:
240
+ If you need to get the submittable data outside of a submission, you can use the `DynamicForm` component. This will give you access to two methods: `getValue` and `validate` via a [ref](https://react.dev/reference/react/useRef). For example:
256
241
 
257
242
  ```tsx
258
- import type { DynamicFragmentController } from '@wise/dynamic-flow-client-internal';
259
- import { DynamicFragment } from '@wise/dynamic-flow-client-internal';
243
+ import type { DynamicFormController } from '@wise/dynamic-flow-client-internal';
244
+ import { DynamicForm } from '@wise/dynamic-flow-client-internal';
260
245
  import { useRef } from 'react';
261
246
 
262
247
  function DynamicFlowWithRef() {
263
- const ref = useRef<DynamicFragmentController>(null);
248
+ const ref = useRef<DynamicFormController>(null);
264
249
 
265
250
  return (
266
- <>
267
- <DynamicFragment
251
+ <div>
252
+ <DynamicForm
268
253
  ref={ref}
269
254
  flowId={"id"}
270
255
  customFetch={fetch}
271
- initialStep={selectedStep}
272
- onValueChange={async () => {
273
- const value = (await ref.current?.getValue()) ?? null);
256
+ initialStep={myStep}
257
+ onValueChange={ async () => {
258
+ const value = (await ref.current?.getValue()) ?? null;
274
259
  console.log('Value changed to', JSON.stringify(value));
275
260
  }}
276
261
  onCompletion={(error) => console.error(error)}
277
262
  onCompletion={() => console.log('Completed')}
278
263
  />
279
264
  <Button
280
- onClick={async () => {
265
+ onClick={ async () => {
281
266
  // This will get the value, whether or not the form is valid
282
- const value = (await ref.current?.getValue()) ?? null);
267
+ const value = (await ref.current?.getValue()) ?? null;
283
268
 
284
269
  // This will trigger validation of the form and show any validation messages to the user.
285
270
  // The response is a boolean indicating whether or not the form is valid.
@@ -290,7 +275,7 @@ function DynamicFlowWithRef() {
290
275
  >
291
276
  Log value
292
277
  </Button>
293
- </>
278
+ </div>
294
279
  );
295
280
  }
296
281
  ```
package/build/main.js CHANGED
@@ -1584,7 +1584,7 @@ function MoneyInputRendererComponent(props) {
1584
1584
  ),
1585
1585
  placeholder: (_a = parseFloatOrNull(placeholder)) != null ? _a : void 0,
1586
1586
  onAmountChange: (newAmount) => {
1587
- onAmountChange(String(newAmount));
1587
+ onAmountChange(newAmount !== null ? String(newAmount) : null);
1588
1588
  },
1589
1589
  onCurrencyChange: (item) => {
1590
1590
  const selectedIndex = Number.parseInt(item.value, 10);
@@ -3749,7 +3749,7 @@ var messages_default = (0, import_react_intl26.defineMessages)({
3749
3749
  // src/dynamicFlow/telemetry/app-version.ts
3750
3750
  var appVersion = (
3751
3751
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
3752
- typeof process !== "undefined" ? "5.0.0" : "0.0.0"
3752
+ typeof process !== "undefined" ? "5.1.0" : "0.0.0"
3753
3753
  );
3754
3754
 
3755
3755
  // src/dynamicFlow/telemetry/getLogEvent.ts
package/build/main.mjs CHANGED
@@ -1572,7 +1572,7 @@ function MoneyInputRendererComponent(props) {
1572
1572
  ),
1573
1573
  placeholder: (_a = parseFloatOrNull(placeholder)) != null ? _a : void 0,
1574
1574
  onAmountChange: (newAmount) => {
1575
- onAmountChange(String(newAmount));
1575
+ onAmountChange(newAmount !== null ? String(newAmount) : null);
1576
1576
  },
1577
1577
  onCurrencyChange: (item) => {
1578
1578
  const selectedIndex = Number.parseInt(item.value, 10);
@@ -3743,7 +3743,7 @@ var messages_default = defineMessages12({
3743
3743
  // src/dynamicFlow/telemetry/app-version.ts
3744
3744
  var appVersion = (
3745
3745
  // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
3746
- typeof process !== "undefined" ? "5.0.0" : "0.0.0"
3746
+ typeof process !== "undefined" ? "5.1.0" : "0.0.0"
3747
3747
  );
3748
3748
 
3749
3749
  // src/dynamicFlow/telemetry/getLogEvent.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wise/dynamic-flow-client-internal",
3
- "version": "5.0.0",
3
+ "version": "5.1.0",
4
4
  "description": "Dynamic Flow web client for Wise",
5
5
  "license": "Apache-2.0",
6
6
  "main": "./build/main.js",
@@ -16,7 +16,8 @@
16
16
  "import": "./build/main.mjs",
17
17
  "require": "./build/main.js"
18
18
  },
19
- "./build/main.css": "./build/main.css"
19
+ "./build/main.css": "./build/main.css",
20
+ "./main.css": "./build/main.css"
20
21
  },
21
22
  "sideEffects": [
22
23
  "*.css"
@@ -30,40 +31,28 @@
30
31
  "url": "git+https://github.com/transferwise/dynamic-flow.git"
31
32
  },
32
33
  "devDependencies": {
33
- "@babel/core": "7.28.5",
34
- "@babel/plugin-syntax-flow": "7.27.1",
35
- "@babel/plugin-transform-react-jsx": "7.27.1",
36
- "@babel/preset-env": "7.28.5",
37
- "@babel/preset-react": "7.28.5",
38
- "@babel/preset-typescript": "7.28.5",
39
- "@chromatic-com/storybook": "4.1.2",
34
+ "@chromatic-com/storybook": "4.1.3",
40
35
  "@formatjs/cli": "^6.7.4",
41
- "@storybook/addon-a11y": "^9.1.16",
42
- "@storybook/addon-docs": "^9.1.16",
43
- "@storybook/addon-links": "^9.1.16",
44
- "@storybook/react-vite": "9.1.16",
36
+ "@storybook/addon-a11y": "^10.1.4",
37
+ "@storybook/addon-docs": "^10.1.4",
38
+ "@storybook/addon-links": "^10.1.4",
39
+ "@storybook/react-vite": "10.1.4",
45
40
  "@testing-library/dom": "10.4.1",
46
41
  "@testing-library/jest-dom": "6.9.1",
47
42
  "@testing-library/react": "16.3.0",
48
43
  "@testing-library/user-event": "14.6.1",
49
- "@transferwise/components": "46.113.1",
44
+ "@transferwise/components": "^46.115.1",
50
45
  "@transferwise/formatting": "^2.13.4",
51
46
  "@transferwise/icons": "4.0.0",
52
- "@transferwise/neptune-css": "14.25.1",
53
- "@types/jest": "30.0.0",
54
- "@types/react": "18.3.26",
47
+ "@transferwise/neptune-css": "14.25.2",
48
+ "@types/react": "18.3.27",
55
49
  "@types/react-dom": "18.3.7",
56
50
  "@wise/art": "2.24.7",
57
- "@wise/components-theming": "^1.8.0",
58
- "babel-jest": "30.2.0",
51
+ "@wise/components-theming": "^1.9.0",
59
52
  "currency-flags": "4.0.7",
60
53
  "esbuild": "0.27.0",
61
- "eslint-plugin-storybook": "9.1.16",
62
- "framer-motion": "^12.23.24",
63
- "jest": "30.2.0",
64
- "jest-environment-jsdom": "30.2.0",
65
- "jest-fetch-mock": "^3.0.3",
66
- "jest-watch-typeahead": "^3.0.1",
54
+ "eslint-plugin-storybook": "10.1.4",
55
+ "framer-motion": "^12.23.25",
67
56
  "npm-run-all2": "8.0.4",
68
57
  "postcss": "^8.5.6",
69
58
  "postcss-cli": "^11.0.1",
@@ -71,16 +60,18 @@
71
60
  "react": "18.3.1",
72
61
  "react-dom": "18.3.1",
73
62
  "react-intl": "6.8.9",
74
- "storybook": "^9.1.16",
75
- "stylelint": "16.25.0",
63
+ "storybook": "^10.1.4",
64
+ "stylelint": "16.26.1",
76
65
  "stylelint-config-standard": "36.0.1",
77
66
  "stylelint-no-unsupported-browser-features": "8.0.5",
78
67
  "stylelint-value-no-unknown-custom-properties": "6.0.1",
79
- "tsx": "4.20.6",
68
+ "tsx": "4.21.0",
80
69
  "typescript": "5.9.3",
81
- "@wise/dynamic-flow-types": "4.0.0",
70
+ "vitest": "4.0.15",
71
+ "vitest-fetch-mock": "0.4.5",
82
72
  "@wise/dynamic-flow-fixtures": "0.0.1",
83
- "@wise/dynamic-flow-renderers": "0.0.0"
73
+ "@wise/dynamic-flow-renderers": "0.0.0",
74
+ "@wise/dynamic-flow-types": "4.1.0"
84
75
  },
85
76
  "peerDependencies": {
86
77
  "@transferwise/components": "^46.104.0",
@@ -94,8 +85,8 @@
94
85
  "react-intl": "^6"
95
86
  },
96
87
  "dependencies": {
97
- "@wise/dynamic-flow-client": "5.0.0",
98
- "@wise/dynamic-flow-types": "4.0.0"
88
+ "@wise/dynamic-flow-client": "5.1.0",
89
+ "@wise/dynamic-flow-types": "4.1.0"
99
90
  },
100
91
  "scripts": {
101
92
  "dev": "pnpm build:visual-tests && storybook dev -p 3005",
@@ -106,10 +97,10 @@
106
97
  "build:messages-source": "formatjs extract '../renderers/src/**/{*.messages,messages}.{js,ts}' './src/**/{*.messages,messages}.{js,ts}' --out-file src/i18n/en.json --format simple && prettier --find-config-path --write src/i18n/*.json",
107
98
  "build:compiled-messages": "mkdir -p build/i18n && cp src/i18n/*.json build/i18n",
108
99
  "build:visual-tests": "tsx ./scripts/build-visual-tests.mjs",
109
- "test": "pnpm test:once",
110
- "test:once": "jest --config jest.config.js --env=jsdom --passWithNoTests",
111
- "test:coverage": "jest --config jest.config.js --env=jsdom --coverage",
112
- "test:watch": "pnpm test:once --watch",
100
+ "test": "npm-run-all test:once",
101
+ "test:once": "vitest run",
102
+ "test:coverage": "vitest run --coverage",
103
+ "test:watch": "vitest",
113
104
  "types": "pnpm tsc",
114
105
  "types:watch": "pnpm tsc --watch",
115
106
  "lint": "npm-run-all lint:ts lint:css",