piral-forms 1.9.2-beta.8358 → 1.9.2-beta.8388
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/lib/useForm.d.ts +3 -3
- package/lib/useForm.js +3 -3
- package/lib/useForm.js.map +1 -1
- package/lib/usePrompt.d.ts +3 -3
- package/lib/usePrompt.js +5 -4
- package/lib/usePrompt.js.map +1 -1
- package/lib/withForm.js +5 -4
- package/lib/withForm.js.map +1 -1
- package/package.json +6 -7
- package/piral-forms.min.js +1 -1
- package/src/create.test.tsx +2 -2
- package/src/useForm.ts +4 -5
- package/src/usePrompt.ts +7 -7
- package/src/withForm.test.tsx +8 -13
- package/src/withForm.tsx +7 -6
package/lib/useForm.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { NavigationApi } from 'piral-core';
|
|
2
2
|
import { FormProps, InputFormOptions } from './types';
|
|
3
3
|
/**
|
|
4
4
|
* Hook for using a form locally that blocks if a transition is performed.
|
|
5
5
|
* @param initialData The initial data of the form.
|
|
6
|
-
* @param
|
|
6
|
+
* @param navigation The navigation API.
|
|
7
7
|
* @param options The options used for creating the form.
|
|
8
8
|
* @param existingId The existing id of the form, if any.
|
|
9
9
|
*/
|
|
10
|
-
export declare function useForm<TFormData>(initialData: TFormData,
|
|
10
|
+
export declare function useForm<TFormData>(initialData: TFormData, navigation: NavigationApi, options: InputFormOptions<TFormData, any>, existingId?: string): FormProps<TFormData>;
|
package/lib/useForm.js
CHANGED
|
@@ -86,16 +86,16 @@ function createProps(id, state, updateState, options) {
|
|
|
86
86
|
/**
|
|
87
87
|
* Hook for using a form locally that blocks if a transition is performed.
|
|
88
88
|
* @param initialData The initial data of the form.
|
|
89
|
-
* @param
|
|
89
|
+
* @param navigation The navigation API.
|
|
90
90
|
* @param options The options used for creating the form.
|
|
91
91
|
* @param existingId The existing id of the form, if any.
|
|
92
92
|
*/
|
|
93
|
-
export function useForm(initialData,
|
|
93
|
+
export function useForm(initialData, navigation, options, existingId) {
|
|
94
94
|
const { silent, message = defaultMessage } = options;
|
|
95
95
|
const [id] = useState(existingId || generateId);
|
|
96
96
|
const state = useGlobalState((m) => m.forms[id] || createDefaultState(initialData));
|
|
97
97
|
const updateState = useAction('updateFormState');
|
|
98
|
-
usePrompt(!silent && state.changed,
|
|
98
|
+
usePrompt(!silent && state.changed, navigation, message);
|
|
99
99
|
useEffect(() => {
|
|
100
100
|
updateState(id, state, {
|
|
101
101
|
active: true,
|
package/lib/useForm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useForm.js","sourceRoot":"","sources":["../src/useForm.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useForm.js","sourceRoot":"","sources":["../src/useForm.ts"],"names":[],"mappings":"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"}
|
package/lib/usePrompt.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { NavigationApi, NavigationListener } from 'piral-core';
|
|
2
2
|
import { PromptMessage } from './types';
|
|
3
3
|
/**
|
|
4
4
|
* Hook to notify the user in case of potential data loss when
|
|
5
5
|
* performing a page transition (internal or external).
|
|
6
6
|
* @param active True if the prompt should be shown, otherwise false.
|
|
7
|
-
* @param
|
|
7
|
+
* @param navigation The navigation API.
|
|
8
8
|
* @param message The message to display when the prompt is shown.
|
|
9
9
|
*/
|
|
10
|
-
export declare function usePrompt(active: boolean,
|
|
10
|
+
export declare function usePrompt(active: boolean, navigation: NavigationApi, message: PromptMessage, onTransition?: NavigationListener): void;
|
package/lib/usePrompt.js
CHANGED
|
@@ -4,10 +4,10 @@ import { isfunc } from 'piral-core';
|
|
|
4
4
|
* Hook to notify the user in case of potential data loss when
|
|
5
5
|
* performing a page transition (internal or external).
|
|
6
6
|
* @param active True if the prompt should be shown, otherwise false.
|
|
7
|
-
* @param
|
|
7
|
+
* @param navigation The navigation API.
|
|
8
8
|
* @param message The message to display when the prompt is shown.
|
|
9
9
|
*/
|
|
10
|
-
export function usePrompt(active,
|
|
10
|
+
export function usePrompt(active, navigation, message, onTransition) {
|
|
11
11
|
useEffect(() => {
|
|
12
12
|
if (active) {
|
|
13
13
|
const beforeUnload = (ev) => {
|
|
@@ -15,8 +15,9 @@ export function usePrompt(active, history, message, onTransition) {
|
|
|
15
15
|
ev.returnValue = msg;
|
|
16
16
|
return msg;
|
|
17
17
|
};
|
|
18
|
-
const unlisten = onTransition &&
|
|
19
|
-
const
|
|
18
|
+
const unlisten = onTransition && navigation.listen(onTransition);
|
|
19
|
+
const blocker = typeof message === 'function' ? message : () => message;
|
|
20
|
+
const unblock = message && navigation.block(blocker);
|
|
20
21
|
window.addEventListener('beforeunload', beforeUnload);
|
|
21
22
|
return () => {
|
|
22
23
|
unlisten && unlisten();
|
package/lib/usePrompt.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePrompt.js","sourceRoot":"","sources":["../src/usePrompt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAClC,OAAO,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"usePrompt.js","sourceRoot":"","sources":["../src/usePrompt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAClC,OAAO,EAAE,MAAM,EAAwD,MAAM,YAAY,CAAC;AAG1F;;;;;;GAMG;AACH,MAAM,UAAU,SAAS,CACvB,MAAe,EACf,UAAyB,EACzB,OAAsB,EACtB,YAAiC;IAEjC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,MAAM,EAAE,CAAC;YACX,MAAM,YAAY,GAAG,CAAC,EAAqB,EAAE,EAAE;gBAC7C,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;gBAClD,EAAE,CAAC,WAAW,GAAG,GAAG,CAAC;gBACrB,OAAO,GAAG,CAAC;YACb,CAAC,CAAC;YACF,MAAM,QAAQ,GAAG,YAAY,IAAI,UAAU,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;YACjE,MAAM,OAAO,GAAG,OAAO,OAAO,KAAK,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC;YACxE,MAAM,OAAO,GAAG,OAAO,IAAI,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACrD,MAAM,CAAC,gBAAgB,CAAC,cAAc,EAAE,YAAY,CAAC,CAAC;YACtD,OAAO,GAAG,EAAE;gBACV,QAAQ,IAAI,QAAQ,EAAE,CAAC;gBACvB,OAAO,IAAI,OAAO,EAAE,CAAC;gBACrB,MAAM,CAAC,mBAAmB,CAAC,cAAc,EAAE,YAAY,CAAC,CAAC;YAC3D,CAAC,CAAC;QACJ,CAAC;QAED,OAAO,GAAG,EAAE,GAAE,CAAC,CAAC;IAClB,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AACxB,CAAC"}
|
package/lib/withForm.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import { RegisteredLoadingIndicator, RegisteredErrorInfo } from 'piral-core';
|
|
2
|
+
import { RegisteredLoadingIndicator, RegisteredErrorInfo, useGlobalStateContext } from 'piral-core';
|
|
4
3
|
import { useForm } from './useForm';
|
|
5
4
|
import { usePromise } from './usePromise';
|
|
6
5
|
export function withForm(Component, options) {
|
|
7
6
|
const FormView = (props) => {
|
|
8
|
-
const
|
|
7
|
+
const { navigation } = useGlobalStateContext();
|
|
8
|
+
const formProps = useForm(props.initialData, navigation, options);
|
|
9
9
|
return (React.createElement("form", { onSubmit: formProps.submit },
|
|
10
10
|
React.createElement(Component, { ...props, ...formProps })));
|
|
11
11
|
};
|
|
@@ -22,6 +22,7 @@ export function withForm(Component, options) {
|
|
|
22
22
|
return React.createElement(RegisteredErrorInfo, { type: "form", error: error });
|
|
23
23
|
}
|
|
24
24
|
};
|
|
25
|
-
|
|
25
|
+
FormLoader.displayName = `withForm(${Component.displayName ?? 'Component'})`;
|
|
26
|
+
return FormLoader;
|
|
26
27
|
}
|
|
27
28
|
//# sourceMappingURL=withForm.js.map
|
package/lib/withForm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"withForm.js","sourceRoot":"","sources":["../src/withForm.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"withForm.js","sourceRoot":"","sources":["../src/withForm.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,0BAA0B,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AACpG,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG1C,MAAM,UAAU,QAAQ,CACtB,SAA6D,EAC7D,OAAoD;IAEpD,MAAM,QAAQ,GAAkD,CAAC,KAAK,EAAE,EAAE;QACxE,MAAM,EAAE,UAAU,EAAE,GAAG,qBAAqB,EAAE,CAAC;QAC/C,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;QAClE,OAAO,CACL,8BAAM,QAAQ,EAAE,SAAS,CAAC,MAAM;YAC9B,oBAAC,SAAS,OAAK,KAAK,KAAM,SAAS,GAAI,CAClC,CACR,CAAC;IACJ,CAAC,CAAC;IACF,MAAM,UAAU,GAAqB,CAAC,KAAK,EAAE,EAAE;QAC7C,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,OAAO,CAAC;QACxC,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,UAAU,CAAC,GAAG,EAAE,CAC/C,OAAO,QAAQ,KAAK,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAC9E,CAAC;QAEF,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,oBAAC,0BAA0B,OAAG,CAAC;QACxC,CAAC;aAAM,IAAI,IAAI,EAAE,CAAC;YAChB,OAAO,oBAAC,QAAQ,OAAK,KAAK,EAAE,WAAW,EAAE,IAAI,GAAI,CAAC;QACpD,CAAC;aAAM,CAAC;YACN,OAAO,oBAAC,mBAAmB,IAAC,IAAI,EAAC,MAAM,EAAC,KAAK,EAAE,KAAK,GAAI,CAAC;QAC3D,CAAC;IACH,CAAC,CAAC;IACF,UAAU,CAAC,WAAW,GAAG,YAAY,SAAS,CAAC,WAAW,IAAI,WAAW,GAAG,CAAC;IAE7E,OAAO,UAAU,CAAC;AACpB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "piral-forms",
|
|
3
|
-
"version": "1.9.2-beta.
|
|
3
|
+
"version": "1.9.2-beta.8388",
|
|
4
4
|
"description": "Plugin for providing advanced form support in Piral.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"piral",
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
"exports": {
|
|
23
23
|
".": "./lib/index.js",
|
|
24
24
|
"./lib/*": {
|
|
25
|
-
"
|
|
26
|
-
"
|
|
25
|
+
"types": "./lib/*.d.ts",
|
|
26
|
+
"import": "./lib/*"
|
|
27
27
|
},
|
|
28
28
|
"./package.json": "./package.json"
|
|
29
29
|
},
|
|
@@ -52,9 +52,8 @@
|
|
|
52
52
|
"@types/history": "^4.7.8",
|
|
53
53
|
"@types/react": "^18.0.0",
|
|
54
54
|
"@types/react-router-dom": "^5.1.6",
|
|
55
|
-
"piral-core": "1.9.2-beta.
|
|
56
|
-
"react": "^18.0.0"
|
|
57
|
-
"react-router-dom": "^5.2.0"
|
|
55
|
+
"piral-core": "1.9.2-beta.8388",
|
|
56
|
+
"react": "^18.0.0"
|
|
58
57
|
},
|
|
59
|
-
"gitHead": "
|
|
58
|
+
"gitHead": "25023f913ae9423c9cecd23e44d70e959ff58c8a"
|
|
60
59
|
}
|
package/piral-forms.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
var piralForms=(()=>{var
|
|
1
|
+
var piralForms=(()=>{var A=Object.create;var F=Object.defineProperty;var C=Object.getOwnPropertyDescriptor;var N=Object.getOwnPropertyNames;var E=Object.getPrototypeOf,U=Object.prototype.hasOwnProperty;var f=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(r,o)=>(typeof require<"u"?require:r)[o]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+t+'" is not supported')});var v=(t,r)=>{for(var o in r)F(t,o,{get:r[o],enumerable:!0})},S=(t,r,o,a)=>{if(r&&typeof r=="object"||typeof r=="function")for(let e of N(r))!U.call(t,e)&&e!==o&&F(t,e,{get:()=>r[e],enumerable:!(a=C(r,e))||a.enumerable});return t};var O=(t,r,o)=>(o=t!=null?A(E(t)):{},S(r||!t||!t.__esModule?F(o,"default",{value:t,enumerable:!0}):o,t)),L=t=>S(F({},"__esModule",{value:!0}),t);var K={};v(K,{createFormsApi:()=>V,useForm:()=>b,usePrompt:()=>T,withForm:()=>h});var P={};v(P,{updateFormState:()=>k});var d=f("piral-core");function w(t,r){return r.active===!1&&!t.submitting?d.removeIndicator:t.active||t.submitting||t.changed?t:d.removeIndicator}function k(t,r,o,a){t.dispatch(e=>{let i={...o,...e.forms[r]||{},...a},n=w(i,a);return{...e,forms:(0,d.updateKey)(e.forms,r,n)}})}var p=O(f("react")),l=f("piral-core");var D=f("react"),u=f("piral-core");var x=f("react"),y=f("piral-core");function T(t,r,o,a){(0,x.useEffect)(()=>{if(t){let e=s=>{let c=(0,y.isfunc)(o)?o():o;return s.returnValue=c,c},i=a&&r.listen(a),n=typeof o=="function"?o:()=>o,m=o&&r.block(n);return window.addEventListener("beforeunload",e),()=>{i&&i(),m&&m(),window.removeEventListener("beforeunload",e)}}return()=>{}},[t,o])}var G="Are you sure you want to discard the form data?";function q(t){return{active:!0,currentData:t,initialData:t,changed:!1,submitting:!1,error:void 0}}function R(t,r,o,a,e){let{onChange:i}=e;o(t,r,{currentData:a,changed:!(0,u.isSame)(a,r.initialData),error:void 0}),(0,u.isfunc)(i)&&Promise.resolve(i(a)).then(n=>{let m={...a,...n};o(t,r,{currentData:m,changed:!(0,u.isSame)(m,r.initialData),error:void 0})}).catch(n=>o(t,r,{error:n}))}function M(t,r,o,a){let{onSubmit:e,wait:i}=a;o(t,r,{changed:!!i,submitting:!0}),(0,u.isfunc)(e)&&Promise.resolve(e(r.currentData)).then(()=>o(t,r,{initialData:r.currentData,changed:!1,submitting:!1})).catch(n=>o(t,r,{error:n,changed:!0,submitting:!1}))}function B(t,r,o,a){return{changed:r.changed,formData:r.currentData,error:r.error,submit(e){return e&&e.preventDefault(),r.changed&&M(t,r,o,a),!1},submitting:r.submitting,reset(){o(t,r,{currentData:r.initialData,changed:!1,error:void 0})},setFormData(e){R(t,r,o,{...r.currentData,...e},a)},changeForm(e){let{name:i,value:n}=e.target;R(t,r,o,{...r.currentData,[i]:n},a)}}}function b(t,r,o,a){let{silent:e,message:i=G}=o,[n]=(0,D.useState)(a||u.generateId),m=(0,u.useGlobalState)(c=>c.forms[n]||q(t)),s=(0,u.useAction)("updateFormState");return T(!e&&m.changed,r,i),(0,D.useEffect)(()=>(s(n,m,{active:!0}),()=>s(n,m,{active:!1})),[m.submitting]),B(n,m,s,o)}var g=f("react");function I(t){let[r,o]=(0,g.useState)({loading:!0,data:void 0,error:void 0});return(0,g.useEffect)(()=>{let a=!1;return t().then(e=>!a&&o({data:e,error:void 0,loading:!1}),e=>!a&&o({data:void 0,error:e,loading:!1})),()=>{a=!0}},[]),r}function h(t,r){let o=e=>{let{navigation:i}=(0,l.useGlobalStateContext)(),n=b(e.initialData,i,r);return p.createElement("form",{onSubmit:n.submit},p.createElement(t,{...e,...n}))},a=e=>{let{loadData:i,emptyData:n}=r,{loading:m,data:s,error:c}=I(()=>typeof i!="function"?Promise.resolve(n):i(e));return m?p.createElement(l.RegisteredLoadingIndicator,null):s?p.createElement(o,{...e,initialData:s}):p.createElement(l.RegisteredErrorInfo,{type:"form",error:c})};return a.displayName=`withForm(${t.displayName??"Component"})`,a}function V(t={}){return r=>(r.defineActions(P),r.dispatch(o=>({...o,forms:{}})),{createForm(o){return a=>h(a,o)}})}return L(K);})();
|
package/src/create.test.tsx
CHANGED
|
@@ -18,7 +18,7 @@ function createMockContainer() {
|
|
|
18
18
|
emit: vitest.fn(),
|
|
19
19
|
defineActions() {},
|
|
20
20
|
state,
|
|
21
|
-
dispatch(update) {
|
|
21
|
+
dispatch(update: any) {
|
|
22
22
|
state.setState(update(state.getState()));
|
|
23
23
|
},
|
|
24
24
|
} as any,
|
|
@@ -38,6 +38,6 @@ describe('Create Forms API Extensions', () => {
|
|
|
38
38
|
},
|
|
39
39
|
});
|
|
40
40
|
const NewComponent = create(StubComponent);
|
|
41
|
-
expect(NewComponent.displayName).toBe('
|
|
41
|
+
expect(NewComponent.displayName).toBe('withForm(StubComponent)');
|
|
42
42
|
});
|
|
43
43
|
});
|
package/src/useForm.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import type { History } from 'history';
|
|
2
1
|
import { useState, useEffect, FormEvent } from 'react';
|
|
3
|
-
import { isfunc, useAction, useGlobalState, isSame, generateId } from 'piral-core';
|
|
2
|
+
import { isfunc, useAction, useGlobalState, isSame, generateId, NavigationApi } from 'piral-core';
|
|
4
3
|
import { usePrompt } from './usePrompt';
|
|
5
4
|
import { FormProps, InputFormOptions, FormDataState } from './types';
|
|
6
5
|
|
|
@@ -124,13 +123,13 @@ function createProps<TFormData>(
|
|
|
124
123
|
/**
|
|
125
124
|
* Hook for using a form locally that blocks if a transition is performed.
|
|
126
125
|
* @param initialData The initial data of the form.
|
|
127
|
-
* @param
|
|
126
|
+
* @param navigation The navigation API.
|
|
128
127
|
* @param options The options used for creating the form.
|
|
129
128
|
* @param existingId The existing id of the form, if any.
|
|
130
129
|
*/
|
|
131
130
|
export function useForm<TFormData>(
|
|
132
131
|
initialData: TFormData,
|
|
133
|
-
|
|
132
|
+
navigation: NavigationApi,
|
|
134
133
|
options: InputFormOptions<TFormData, any>,
|
|
135
134
|
existingId?: string,
|
|
136
135
|
) {
|
|
@@ -138,7 +137,7 @@ export function useForm<TFormData>(
|
|
|
138
137
|
const [id] = useState(existingId || generateId);
|
|
139
138
|
const state = useGlobalState((m) => m.forms[id] || createDefaultState(initialData));
|
|
140
139
|
const updateState = useAction('updateFormState');
|
|
141
|
-
usePrompt(!silent && state.changed,
|
|
140
|
+
usePrompt(!silent && state.changed, navigation, message);
|
|
142
141
|
useEffect(() => {
|
|
143
142
|
updateState(id, state, {
|
|
144
143
|
active: true,
|
package/src/usePrompt.ts
CHANGED
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
import { useEffect } from 'react';
|
|
2
|
-
import { isfunc } from 'piral-core';
|
|
3
|
-
import type { History, Location } from 'history';
|
|
2
|
+
import { isfunc, NavigationApi, NavigationListener, NavigationBlocker } from 'piral-core';
|
|
4
3
|
import { PromptMessage } from './types';
|
|
5
4
|
|
|
6
5
|
/**
|
|
7
6
|
* Hook to notify the user in case of potential data loss when
|
|
8
7
|
* performing a page transition (internal or external).
|
|
9
8
|
* @param active True if the prompt should be shown, otherwise false.
|
|
10
|
-
* @param
|
|
9
|
+
* @param navigation The navigation API.
|
|
11
10
|
* @param message The message to display when the prompt is shown.
|
|
12
11
|
*/
|
|
13
12
|
export function usePrompt(
|
|
14
13
|
active: boolean,
|
|
15
|
-
|
|
14
|
+
navigation: NavigationApi,
|
|
16
15
|
message: PromptMessage,
|
|
17
|
-
onTransition?:
|
|
16
|
+
onTransition?: NavigationListener,
|
|
18
17
|
) {
|
|
19
18
|
useEffect(() => {
|
|
20
19
|
if (active) {
|
|
@@ -23,8 +22,9 @@ export function usePrompt(
|
|
|
23
22
|
ev.returnValue = msg;
|
|
24
23
|
return msg;
|
|
25
24
|
};
|
|
26
|
-
const unlisten = onTransition &&
|
|
27
|
-
const
|
|
25
|
+
const unlisten = onTransition && navigation.listen(onTransition);
|
|
26
|
+
const blocker = typeof message === 'function' ? message : () => message;
|
|
27
|
+
const unblock = message && navigation.block(blocker);
|
|
28
28
|
window.addEventListener('beforeunload', beforeUnload);
|
|
29
29
|
return () => {
|
|
30
30
|
unlisten && unlisten();
|
package/src/withForm.test.tsx
CHANGED
|
@@ -6,7 +6,6 @@ import * as piralCore from 'piral-core';
|
|
|
6
6
|
import * as useForm from './useForm';
|
|
7
7
|
import * as usePromise from './usePromise';
|
|
8
8
|
import { describe, it, expect, vitest } from 'vitest';
|
|
9
|
-
import { MemoryRouter } from 'react-router-dom';
|
|
10
9
|
import { render } from '@testing-library/react';
|
|
11
10
|
import { withForm } from './withForm';
|
|
12
11
|
|
|
@@ -14,13 +13,6 @@ vitest.mock('piral-core');
|
|
|
14
13
|
vitest.mock('./useForm');
|
|
15
14
|
vitest.mock('./usePromise');
|
|
16
15
|
|
|
17
|
-
const mountWithRouter = (node, url = '/') =>
|
|
18
|
-
render(
|
|
19
|
-
<MemoryRouter initialEntries={[url]} initialIndex={0}>
|
|
20
|
-
{node}
|
|
21
|
-
</MemoryRouter>,
|
|
22
|
-
);
|
|
23
|
-
|
|
24
16
|
const StubComponent: React.FC<{ data: any }> = () => <div role="component" />;
|
|
25
17
|
StubComponent.displayName = 'StubComponent';
|
|
26
18
|
|
|
@@ -32,6 +24,9 @@ ErrorComponent.displayName = 'ErrorComponent';
|
|
|
32
24
|
|
|
33
25
|
(piralCore as any).RegisteredErrorInfo = ErrorComponent;
|
|
34
26
|
(piralCore as any).RegisteredLoadingIndicator = LoaderComponent;
|
|
27
|
+
(piralCore as any).useGlobalStateContext = vitest.fn(() => ({
|
|
28
|
+
navigation: {},
|
|
29
|
+
}));
|
|
35
30
|
|
|
36
31
|
describe('withForm Module', () => {
|
|
37
32
|
it('shows error component if nothing is loading and no data is available', () => {
|
|
@@ -47,7 +42,7 @@ describe('withForm Module', () => {
|
|
|
47
42
|
(useForm as any).useForm = usedForm;
|
|
48
43
|
(usePromise as any).usePromise = usedPromise;
|
|
49
44
|
const Component: any = withForm(StubComponent, options);
|
|
50
|
-
const node =
|
|
45
|
+
const node = render(<Component />);
|
|
51
46
|
expect(node.getAllByRole('error').length).toBe(1);
|
|
52
47
|
});
|
|
53
48
|
|
|
@@ -64,7 +59,7 @@ describe('withForm Module', () => {
|
|
|
64
59
|
(useForm as any).useForm = usedForm;
|
|
65
60
|
(usePromise as any).usePromise = usedPromise;
|
|
66
61
|
const Component: any = withForm(StubComponent, options);
|
|
67
|
-
const node =
|
|
62
|
+
const node = render(<Component />);
|
|
68
63
|
expect(node.getAllByRole('component').length).toBe(1);
|
|
69
64
|
});
|
|
70
65
|
|
|
@@ -81,7 +76,7 @@ describe('withForm Module', () => {
|
|
|
81
76
|
(useForm as any).useForm = usedForm;
|
|
82
77
|
(usePromise as any).usePromise = usedPromise;
|
|
83
78
|
const Component: any = withForm(StubComponent, options);
|
|
84
|
-
const node =
|
|
79
|
+
const node = render(<Component />);
|
|
85
80
|
expect(node.getAllByRole('loader').length).toBe(1);
|
|
86
81
|
});
|
|
87
82
|
|
|
@@ -102,7 +97,7 @@ describe('withForm Module', () => {
|
|
|
102
97
|
(usePromise as any).usePromise = usedPromise;
|
|
103
98
|
const options: any = { emptyData: {}, loadData };
|
|
104
99
|
const Component: any = withForm(StubComponent, options);
|
|
105
|
-
|
|
100
|
+
render(<Component />);
|
|
106
101
|
expect(usedPromise).toHaveBeenCalledTimes(1);
|
|
107
102
|
expect(loadData).toHaveBeenCalledTimes(1);
|
|
108
103
|
});
|
|
@@ -124,7 +119,7 @@ describe('withForm Module', () => {
|
|
|
124
119
|
(usePromise as any).usePromise = usedPromise;
|
|
125
120
|
const options: any = { emptyData: {}, loadData };
|
|
126
121
|
const Component: any = withForm(StubComponent, options);
|
|
127
|
-
|
|
122
|
+
render(<Component />);
|
|
128
123
|
expect(usedPromise).toHaveBeenCalledTimes(1);
|
|
129
124
|
});
|
|
130
125
|
});
|
package/src/withForm.tsx
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
import { RegisteredLoadingIndicator, RegisteredErrorInfo } from 'piral-core';
|
|
2
|
+
import { RegisteredLoadingIndicator, RegisteredErrorInfo, useGlobalStateContext } from 'piral-core';
|
|
4
3
|
import { useForm } from './useForm';
|
|
5
4
|
import { usePromise } from './usePromise';
|
|
6
5
|
import { InputFormOptions, FormProps } from './types';
|
|
@@ -9,15 +8,16 @@ export function withForm<TFormData, TRequiredProps, TProps extends TRequiredProp
|
|
|
9
8
|
Component: React.ComponentType<TProps & FormProps<TFormData>>,
|
|
10
9
|
options: InputFormOptions<TFormData, TRequiredProps>,
|
|
11
10
|
): React.FC<TProps> {
|
|
12
|
-
const FormView: React.FC<TProps &
|
|
13
|
-
const
|
|
11
|
+
const FormView: React.FC<TProps & { initialData: TFormData }> = (props) => {
|
|
12
|
+
const { navigation } = useGlobalStateContext();
|
|
13
|
+
const formProps = useForm(props.initialData, navigation, options);
|
|
14
14
|
return (
|
|
15
15
|
<form onSubmit={formProps.submit}>
|
|
16
16
|
<Component {...props} {...formProps} />
|
|
17
17
|
</form>
|
|
18
18
|
);
|
|
19
19
|
};
|
|
20
|
-
const FormLoader: React.FC<TProps
|
|
20
|
+
const FormLoader: React.FC<TProps> = (props) => {
|
|
21
21
|
const { loadData, emptyData } = options;
|
|
22
22
|
const { loading, data, error } = usePromise(() =>
|
|
23
23
|
typeof loadData !== 'function' ? Promise.resolve(emptyData) : loadData(props),
|
|
@@ -31,6 +31,7 @@ export function withForm<TFormData, TRequiredProps, TProps extends TRequiredProp
|
|
|
31
31
|
return <RegisteredErrorInfo type="form" error={error} />;
|
|
32
32
|
}
|
|
33
33
|
};
|
|
34
|
+
FormLoader.displayName = `withForm(${Component.displayName ?? 'Component'})`;
|
|
34
35
|
|
|
35
|
-
return
|
|
36
|
+
return FormLoader;
|
|
36
37
|
}
|