piral-modals 1.0.0-pre.2296 → 1.0.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/LICENSE +1 -1
- package/README.md +8 -2
- package/esm/Modals.js +18 -18
- package/esm/Modals.js.map +1 -1
- package/esm/actions.js +5 -6
- package/esm/actions.js.map +1 -1
- package/esm/components.d.ts +3 -4
- package/esm/components.js +2 -2
- package/esm/components.js.map +1 -1
- package/esm/create.d.ts +13 -2
- package/esm/create.js +36 -31
- package/esm/create.js.map +1 -1
- package/esm/default.js +2 -2
- package/esm/default.js.map +1 -1
- package/esm/types.d.ts +36 -5
- package/lib/Modals.js +22 -21
- package/lib/Modals.js.map +1 -1
- package/lib/actions.js +5 -6
- package/lib/actions.js.map +1 -1
- package/lib/components.d.ts +3 -4
- package/lib/components.js +3 -3
- package/lib/components.js.map +1 -1
- package/lib/create.d.ts +13 -2
- package/lib/create.js +39 -34
- package/lib/create.js.map +1 -1
- package/lib/default.js +6 -4
- package/lib/default.js.map +1 -1
- package/lib/index.js +1 -1
- package/lib/types.d.ts +36 -5
- package/package.json +29 -6
- package/piral-modals.min.js +1 -0
- package/src/Modals.test.tsx +151 -85
- package/src/Modals.tsx +7 -9
- package/src/actions.test.ts +19 -18
- package/src/actions.ts +2 -2
- package/src/components.tsx +2 -4
- package/src/create.test.ts +7 -3
- package/src/create.ts +43 -23
- package/src/default.tsx +1 -1
- package/src/types.ts +36 -3
package/lib/create.js
CHANGED
|
@@ -1,59 +1,64 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createModalsApi = void 0;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
const actions = require("./actions");
|
|
5
|
+
const piral_core_1 = require("piral-core");
|
|
6
|
+
const default_1 = require("./default");
|
|
7
|
+
const Modals_1 = require("./Modals");
|
|
8
8
|
function getModalDialogs(dialogs) {
|
|
9
|
-
|
|
10
|
-
for (
|
|
11
|
-
|
|
12
|
-
modals["global-" + name_1] = {
|
|
9
|
+
const modals = {};
|
|
10
|
+
for (const { name, component, defaults, layout = {} } of dialogs) {
|
|
11
|
+
modals[`global-${name}`] = {
|
|
13
12
|
pilet: undefined,
|
|
14
|
-
name
|
|
15
|
-
component
|
|
16
|
-
defaults
|
|
13
|
+
name,
|
|
14
|
+
component,
|
|
15
|
+
defaults,
|
|
16
|
+
layout,
|
|
17
17
|
};
|
|
18
18
|
}
|
|
19
19
|
return modals;
|
|
20
20
|
}
|
|
21
|
+
function withModals(modals) {
|
|
22
|
+
return (state) => (Object.assign(Object.assign({}, state), { components: Object.assign({ ModalsHost: default_1.DefaultHost, ModalsDialog: default_1.DefaultDialog }, state.components), registry: Object.assign(Object.assign({}, state.registry), { modals }), modals: [] }));
|
|
23
|
+
}
|
|
21
24
|
/**
|
|
22
25
|
* Creates new Pilet API extensions for support modal dialogs.
|
|
23
26
|
*/
|
|
24
|
-
function createModalsApi(config) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
return function (context) {
|
|
27
|
+
function createModalsApi(config = {}) {
|
|
28
|
+
const { dialogs = [], selectId = (name) => `${name}-${~~(Math.random() * 10000)}` } = config;
|
|
29
|
+
return (context) => {
|
|
28
30
|
context.defineActions(actions);
|
|
29
|
-
context.dispatch(
|
|
30
|
-
return
|
|
31
|
-
|
|
31
|
+
context.dispatch((0, piral_core_1.withAll)(withModals(getModalDialogs(dialogs)), (0, piral_core_1.withRootExtension)('piral-modals', Modals_1.Modals)));
|
|
32
|
+
return (api, target) => {
|
|
33
|
+
const pilet = target.name;
|
|
32
34
|
return {
|
|
33
|
-
showModal
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
35
|
+
showModal(simpleName, options) {
|
|
36
|
+
const name = (0, piral_core_1.buildName)(pilet, simpleName);
|
|
37
|
+
const dialog = {
|
|
38
|
+
id: selectId(name),
|
|
39
|
+
name,
|
|
40
|
+
alternative: simpleName,
|
|
41
|
+
options,
|
|
42
|
+
close() {
|
|
43
|
+
context.closeModal(dialog);
|
|
40
44
|
},
|
|
41
45
|
};
|
|
42
46
|
context.openModal(dialog);
|
|
43
47
|
return dialog.close;
|
|
44
48
|
},
|
|
45
|
-
registerModal
|
|
46
|
-
|
|
49
|
+
registerModal(name, arg, defaults, layout = {}) {
|
|
50
|
+
const id = (0, piral_core_1.buildName)(pilet, name);
|
|
47
51
|
context.registerModal(id, {
|
|
48
|
-
pilet
|
|
49
|
-
name
|
|
50
|
-
component: piral_core_1.withApi(context, arg, api, 'modal'),
|
|
51
|
-
defaults
|
|
52
|
+
pilet,
|
|
53
|
+
name,
|
|
54
|
+
component: (0, piral_core_1.withApi)(context, arg, api, 'modal'),
|
|
55
|
+
defaults,
|
|
56
|
+
layout,
|
|
52
57
|
});
|
|
53
|
-
return
|
|
58
|
+
return () => api.unregisterModal(name);
|
|
54
59
|
},
|
|
55
|
-
unregisterModal
|
|
56
|
-
|
|
60
|
+
unregisterModal(name) {
|
|
61
|
+
const id = (0, piral_core_1.buildName)(pilet, name);
|
|
57
62
|
context.unregisterModal(id);
|
|
58
63
|
},
|
|
59
64
|
};
|
package/lib/create.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create.js","sourceRoot":"","sources":["../src/create.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"create.js","sourceRoot":"","sources":["../src/create.ts"],"names":[],"mappings":"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"}
|
package/lib/default.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.DefaultDialog = exports.DefaultHost = void 0;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
exports.
|
|
4
|
+
const React = require("react");
|
|
5
|
+
const piral_core_1 = require("piral-core");
|
|
6
|
+
const DefaultHost = (props) => (React.createElement("div", { className: "piral-modals-host" }, props.open && React.createElement("div", { className: "piral-modals-overlay" }, props.children)));
|
|
7
|
+
exports.DefaultHost = DefaultHost;
|
|
8
|
+
const DefaultDialog = (props) => (0, piral_core_1.defaultRender)(props.children);
|
|
9
|
+
exports.DefaultDialog = DefaultDialog;
|
|
8
10
|
//# sourceMappingURL=default.js.map
|
package/lib/default.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"default.js","sourceRoot":"","sources":["../src/default.tsx"],"names":[],"mappings":";;;AAAA
|
|
1
|
+
{"version":3,"file":"default.js","sourceRoot":"","sources":["../src/default.tsx"],"names":[],"mappings":";;;AAAA,+BAA+B;AAC/B,2CAA2C;AAGpC,MAAM,WAAW,GAA8B,CAAC,KAAK,EAAE,EAAE,CAAC,CAC/D,6BAAK,SAAS,EAAC,mBAAmB,IAC/B,KAAK,CAAC,IAAI,IAAI,6BAAK,SAAS,EAAC,sBAAsB,IAAE,KAAK,CAAC,QAAQ,CAAO,CACvE,CACP,CAAC;AAJW,QAAA,WAAW,eAItB;AAEK,MAAM,aAAa,GAAgC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAA,0BAAa,EAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;AAAtF,QAAA,aAAa,iBAAyE"}
|
package/lib/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
4
|
tslib_1.__exportStar(require("./create"), exports);
|
|
5
5
|
tslib_1.__exportStar(require("./components"), exports);
|
|
6
6
|
tslib_1.__exportStar(require("./Modals"), exports);
|
package/lib/types.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ComponentType } from 'react';
|
|
2
|
-
import { Dict, WrappedComponent, BaseComponentProps, BaseRegistration, Disposable, AnyComponent, RegistrationDisposer } from 'piral-core';
|
|
1
|
+
import type { ComponentType, ReactNode } from 'react';
|
|
2
|
+
import type { Dict, WrappedComponent, BaseComponentProps, BaseRegistration, Disposable, AnyComponent, RegistrationDisposer } from 'piral-core';
|
|
3
3
|
declare module 'piral-core/lib/types/custom' {
|
|
4
4
|
interface PiletCustomApi extends PiletModalsApi {
|
|
5
5
|
}
|
|
@@ -61,8 +61,29 @@ export interface ModalsHostProps {
|
|
|
61
61
|
* Callback to invoke closing the modal dialog.
|
|
62
62
|
*/
|
|
63
63
|
close(): void;
|
|
64
|
+
/**
|
|
65
|
+
* The dialogs to display.
|
|
66
|
+
*/
|
|
67
|
+
children?: ReactNode;
|
|
64
68
|
}
|
|
65
69
|
export interface ModalsDialogProps extends OpenModalDialog {
|
|
70
|
+
/**
|
|
71
|
+
* The layout options given for the current dialog.
|
|
72
|
+
*/
|
|
73
|
+
layout: ModalLayoutOptions;
|
|
74
|
+
/**
|
|
75
|
+
* The provided default options.
|
|
76
|
+
*/
|
|
77
|
+
defaults: any;
|
|
78
|
+
/**
|
|
79
|
+
* The content of the dialog to display.
|
|
80
|
+
*/
|
|
81
|
+
children?: ReactNode;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* The options provided for the dialog layout.
|
|
85
|
+
*/
|
|
86
|
+
export interface ModalLayoutOptions {
|
|
66
87
|
}
|
|
67
88
|
/**
|
|
68
89
|
* The error used when a registered modal dialog crashed.
|
|
@@ -80,8 +101,16 @@ export interface ModalErrorInfoProps {
|
|
|
80
101
|
* Callback for closing the modal programmatically.
|
|
81
102
|
*/
|
|
82
103
|
onClose(): void;
|
|
104
|
+
/**
|
|
105
|
+
* The name of the pilet emitting the error.
|
|
106
|
+
*/
|
|
107
|
+
pilet?: string;
|
|
83
108
|
}
|
|
84
109
|
export interface OpenModalDialog {
|
|
110
|
+
/**
|
|
111
|
+
* Gets the ID of the modal to open. For tracking its state.
|
|
112
|
+
*/
|
|
113
|
+
id: string;
|
|
85
114
|
/**
|
|
86
115
|
* Specifies the fully qualified name of the dialog to show.
|
|
87
116
|
*/
|
|
@@ -113,6 +142,7 @@ export interface ModalRegistration extends BaseRegistration {
|
|
|
113
142
|
name: string;
|
|
114
143
|
component: WrappedComponent<ModalComponentProps<any>>;
|
|
115
144
|
defaults: any;
|
|
145
|
+
layout: ModalLayoutOptions;
|
|
116
146
|
}
|
|
117
147
|
export interface BaseModalOptions {
|
|
118
148
|
}
|
|
@@ -120,8 +150,8 @@ export interface PiralCustomModalsMap {
|
|
|
120
150
|
}
|
|
121
151
|
export interface PiralModalsMap extends PiralCustomModalsMap {
|
|
122
152
|
}
|
|
123
|
-
export
|
|
124
|
-
export
|
|
153
|
+
export type ModalOptions<T> = T extends keyof PiralModalsMap ? PiralModalsMap[T] & BaseModalOptions : T extends string ? BaseModalOptions : T;
|
|
154
|
+
export type ModalComponentProps<T> = BaseComponentProps & BareModalComponentProps<ModalOptions<T>>;
|
|
125
155
|
export interface PiletModalsApi {
|
|
126
156
|
/**
|
|
127
157
|
* Shows a modal dialog with the given name.
|
|
@@ -137,8 +167,9 @@ export interface PiletModalsApi {
|
|
|
137
167
|
* @param name The name of the modal to register.
|
|
138
168
|
* @param Component The component to render the page.
|
|
139
169
|
* @param defaults Optionally, sets the default values for the inserted options.
|
|
170
|
+
* @param layout Optionally, sets the layout options for the dialog wrapper.
|
|
140
171
|
*/
|
|
141
|
-
registerModal<T>(name: T extends string ? T : string, Component: AnyComponent<ModalComponentProps<T>>, defaults?: ModalOptions<T
|
|
172
|
+
registerModal<T>(name: T extends string ? T : string, Component: AnyComponent<ModalComponentProps<T>>, defaults?: ModalOptions<T>, layout?: ModalLayoutOptions): RegistrationDisposer;
|
|
142
173
|
/**
|
|
143
174
|
* Unregisters a modal by its name.
|
|
144
175
|
* @param name The name that was previously registered.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "piral-modals",
|
|
3
|
-
"version": "1.0.0
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "Plugin for the display of modal dialogs in Piral.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"piral",
|
|
@@ -20,11 +20,29 @@
|
|
|
20
20
|
"module": "esm/index.js",
|
|
21
21
|
"main": "lib/index.js",
|
|
22
22
|
"typings": "lib/index.d.ts",
|
|
23
|
+
"exports": {
|
|
24
|
+
".": {
|
|
25
|
+
"import": "./esm/index.js",
|
|
26
|
+
"require": "./lib/index.js"
|
|
27
|
+
},
|
|
28
|
+
"./esm/*": {
|
|
29
|
+
"import": "./esm/*"
|
|
30
|
+
},
|
|
31
|
+
"./lib/*": {
|
|
32
|
+
"require": "./lib/*"
|
|
33
|
+
},
|
|
34
|
+
"./_/*": {
|
|
35
|
+
"import": "./esm/*.js",
|
|
36
|
+
"require": "./lib/*.js"
|
|
37
|
+
},
|
|
38
|
+
"./package.json": "./package.json"
|
|
39
|
+
},
|
|
23
40
|
"sideEffects": false,
|
|
24
41
|
"files": [
|
|
25
42
|
"esm",
|
|
26
43
|
"lib",
|
|
27
|
-
"src"
|
|
44
|
+
"src",
|
|
45
|
+
"piral-modals.min.js"
|
|
28
46
|
],
|
|
29
47
|
"repository": {
|
|
30
48
|
"type": "git",
|
|
@@ -34,17 +52,22 @@
|
|
|
34
52
|
"url": "https://github.com/smapiot/piral/issues"
|
|
35
53
|
},
|
|
36
54
|
"scripts": {
|
|
37
|
-
"
|
|
55
|
+
"cleanup": "rimraf esm lib piral-modals.min.js",
|
|
56
|
+
"build": "yarn build:bundle && yarn build:commonjs && yarn build:esnext",
|
|
57
|
+
"build:bundle": "esbuild src/index.ts --outfile=piral-modals.min.js --bundle --external:piral-core --external:react --minify --global-name=piralModals",
|
|
38
58
|
"build:commonjs": "tsc --project tsconfig.json --outDir lib --module commonjs",
|
|
39
59
|
"build:esnext": "tsc --project tsconfig.json --outDir esm --module esnext",
|
|
40
60
|
"typedoc": "typedoc --json ../../../docs/types/piral-modals.json src --exclude \"src/**/*.test.*\"",
|
|
41
61
|
"test": "echo \"Error: run tests from root\" && exit 1"
|
|
42
62
|
},
|
|
43
63
|
"devDependencies": {
|
|
44
|
-
"
|
|
64
|
+
"@types/react": "^18.0.0",
|
|
65
|
+
"piral-core": "^1.0.0",
|
|
66
|
+
"react": "^18.0.0"
|
|
45
67
|
},
|
|
46
68
|
"peerDependencies": {
|
|
47
|
-
"piral-core": "0.
|
|
69
|
+
"piral-core": "0.14.x || 0.15.x",
|
|
70
|
+
"react": ">=16.8.0"
|
|
48
71
|
},
|
|
49
|
-
"gitHead": "
|
|
72
|
+
"gitHead": "67d9a2920bd5231baf10bc87ae8985666b18fa3a"
|
|
50
73
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var piralModals=(()=>{var N=Object.create;var y=Object.defineProperty,$=Object.defineProperties,k=Object.getOwnPropertyDescriptor,E=Object.getOwnPropertyDescriptors,K=Object.getOwnPropertyNames,G=Object.getOwnPropertySymbols,L=Object.getPrototypeOf,H=Object.prototype.hasOwnProperty,T=Object.prototype.propertyIsEnumerable;var O=(o,t,a)=>t in o?y(o,t,{enumerable:!0,configurable:!0,writable:!0,value:a}):o[t]=a,e=(o,t)=>{for(var a in t||(t={}))H.call(t,a)&&O(o,a,t[a]);if(G)for(var a of G(t))T.call(t,a)&&O(o,a,t[a]);return o},i=(o,t)=>$(o,E(t)),S=o=>y(o,"__esModule",{value:!0});var g=(o=>typeof require!="undefined"?require:typeof Proxy!="undefined"?new Proxy(o,{get:(t,a)=>(typeof require!="undefined"?require:t)[a]}):o)(function(o){if(typeof require!="undefined")return require.apply(this,arguments);throw new Error('Dynamic require of "'+o+'" is not supported')});var v=(o,t)=>{S(o);for(var a in t)y(o,a,{get:t[a],enumerable:!0})},j=(o,t,a)=>{if(t&&typeof t=="object"||typeof t=="function")for(let l of K(t))!H.call(o,l)&&l!=="default"&&y(o,l,{get:()=>t[l],enumerable:!(a=k(t,l))||a.enumerable});return o},M=o=>j(S(y(o!=null?N(L(o)):{},"default",o&&o.__esModule&&"default"in o?{get:()=>o.default,enumerable:!0}:{value:o,enumerable:!0})),o);var Z={};v(Z,{Modals:()=>h,PiralModalsDialog:()=>b,PiralModalsHost:()=>R,createModalsApi:()=>Y});var P={};v(P,{closeModal:()=>z,openModal:()=>q,registerModal:()=>J,unregisterModal:()=>Q});var p=M(g("piral-core"));function q(o,t){o.dispatch(a=>i(e({},a),{modals:(0,p.prependItem)(a.modals,t)}))}function z(o,t){o.dispatch(a=>i(e({},a),{modals:(0,p.excludeOn)(a.modals,l=>l.id===t.id)}))}function J(o,t,a){o.dispatch(l=>i(e({},l),{registry:i(e({},l.registry),{modals:(0,p.withKey)(l.registry.modals,t,a)})}))}function Q(o,t){o.dispatch(a=>i(e({},a),{registry:i(e({},a.registry),{modals:(0,p.withoutKey)(a.registry.modals,t)})}))}var d=M(g("piral-core"));var x=M(g("react")),w=M(g("piral-core")),I=o=>x.createElement("div",{className:"piral-modals-host"},o.open&&x.createElement("div",{className:"piral-modals-overlay"},o.children)),B=o=>(0,w.defaultRender)(o.children);var D=M(g("react")),A=M(g("piral-core"));var C=M(g("piral-core")),R=(0,C.getPiralComponent)("ModalsHost"),b=(0,C.getPiralComponent)("ModalsDialog");function U(o){o.forEach(t=>t.close())}function V(o,t){if(t){let[a]=Object.keys(o).filter(l=>o[l].name===t).map(l=>o[l]);return a}}var h=()=>{let o=(0,A.useGlobalState)(r=>r.registry.modals),t=(0,A.useGlobalState)(r=>r.modals),a=()=>U(t),l=t.map(r=>{let s=o[r.name]||V(o,r.alternative),n=s&&s.component,c=s&&s.defaults,m=e(e({},c),r.options);return n&&D.createElement(b,i(e({},r),{options:m,defaults:s.defaults,layout:s.layout,key:r.name}),D.createElement(n,{onClose:r.close,options:m}))}).filter(Boolean),f=l.length>0;return D.createElement(R,{open:f,close:a},l)};h.displayName="Modals";function W(o){let t={};for(let{name:a,component:l,defaults:f,layout:r={}}of o)t[`global-${a}`]={pilet:void 0,name:a,component:l,defaults:f,layout:r};return t}function X(o){return t=>i(e({},t),{components:e({ModalsHost:I,ModalsDialog:B},t.components),registry:i(e({},t.registry),{modals:o}),modals:[]})}function Y(o={}){let{dialogs:t=[],selectId:a=l=>`${l}-${~~(Math.random()*1e4)}`}=o;return l=>(l.defineActions(P),l.dispatch((0,d.withAll)(X(W(t)),(0,d.withRootExtension)("piral-modals",h))),(f,r)=>{let s=r.name;return{showModal(n,c){let m=(0,d.buildName)(s,n),u={id:a(m),name:m,alternative:n,options:c,close(){l.closeModal(u)}};return l.openModal(u),u.close},registerModal(n,c,m,u={}){let F=(0,d.buildName)(s,n);return l.registerModal(F,{pilet:s,name:n,component:(0,d.withApi)(l,c,f,"modal"),defaults:m,layout:u}),()=>f.unregisterModal(n)},unregisterModal(n){let c=(0,d.buildName)(s,n);l.unregisterModal(c)}}})}return Z;})();
|
package/src/Modals.test.tsx
CHANGED
|
@@ -1,127 +1,193 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
-
import
|
|
2
|
+
import create from 'zustand';
|
|
3
|
+
import { StateContext } from 'piral-core';
|
|
4
|
+
import { render, fireEvent } from '@testing-library/react';
|
|
3
5
|
import { Modals } from './Modals';
|
|
4
|
-
import { PiralModalsHost } from './components';
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
7
|
+
function createMockContainer(registeredModals: Record<string, any>, openModals: Array<any>) {
|
|
8
|
+
const state = create(() => ({
|
|
9
|
+
components: {
|
|
10
|
+
ModalsHost: ({ open, children, close }) => (
|
|
11
|
+
<div role="host">
|
|
12
|
+
{open && (
|
|
13
|
+
<div role="overlay">
|
|
14
|
+
<button role="close" onClick={close}>
|
|
15
|
+
Close
|
|
16
|
+
</button>
|
|
17
|
+
{children}
|
|
18
|
+
</div>
|
|
19
|
+
)}
|
|
20
|
+
</div>
|
|
21
|
+
),
|
|
22
|
+
},
|
|
23
|
+
registry: {
|
|
24
|
+
modals: registeredModals,
|
|
25
|
+
},
|
|
26
|
+
modals: openModals,
|
|
27
|
+
}));
|
|
28
|
+
return {
|
|
29
|
+
context: {
|
|
30
|
+
on: jest.fn(),
|
|
31
|
+
off: jest.fn(),
|
|
32
|
+
emit: jest.fn(),
|
|
33
|
+
defineActions() {},
|
|
34
|
+
converters: {},
|
|
35
|
+
readState(select) {
|
|
36
|
+
return select(state.getState());
|
|
37
|
+
},
|
|
38
|
+
state,
|
|
39
|
+
dispatch(update) {
|
|
40
|
+
state.setState(update(state.getState()));
|
|
41
|
+
},
|
|
42
|
+
} as any,
|
|
43
|
+
api: {} as any,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
21
46
|
|
|
22
47
|
describe('Modals Component Shell Module', () => {
|
|
23
48
|
it('Should display nothing is nothing is there', () => {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
49
|
+
const { context } = createMockContainer({}, []);
|
|
50
|
+
const node = render(
|
|
51
|
+
<StateContext.Provider value={context}>
|
|
52
|
+
<Modals />
|
|
53
|
+
</StateContext.Provider>,
|
|
54
|
+
);
|
|
55
|
+
expect(node.queryByRole('overlay')).toBe(null);
|
|
28
56
|
});
|
|
29
57
|
|
|
30
58
|
it('Should display something if something is there and wanted', () => {
|
|
31
|
-
|
|
32
|
-
foo: {
|
|
33
|
-
component: () => <div />,
|
|
34
|
-
},
|
|
35
|
-
};
|
|
36
|
-
state.modals = [
|
|
59
|
+
const { context } = createMockContainer(
|
|
37
60
|
{
|
|
38
|
-
|
|
39
|
-
|
|
61
|
+
foo: {
|
|
62
|
+
component: () => <div />,
|
|
63
|
+
},
|
|
40
64
|
},
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
65
|
+
[
|
|
66
|
+
{
|
|
67
|
+
name: 'foo',
|
|
68
|
+
options: {},
|
|
69
|
+
},
|
|
70
|
+
],
|
|
71
|
+
);
|
|
72
|
+
const node = render(
|
|
73
|
+
<StateContext.Provider value={context}>
|
|
74
|
+
<Modals />
|
|
75
|
+
</StateContext.Provider>,
|
|
76
|
+
);
|
|
77
|
+
expect(node.queryByRole('overlay')).not.toBe(null);
|
|
44
78
|
});
|
|
45
79
|
|
|
46
80
|
it('Should display nothing if something is there and not wanted', () => {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
81
|
+
const { context } = createMockContainer(
|
|
82
|
+
{
|
|
83
|
+
foo: {
|
|
84
|
+
component: () => <div />,
|
|
85
|
+
},
|
|
50
86
|
},
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
const node =
|
|
54
|
-
|
|
87
|
+
[],
|
|
88
|
+
);
|
|
89
|
+
const node = render(
|
|
90
|
+
<StateContext.Provider value={context}>
|
|
91
|
+
<Modals />
|
|
92
|
+
</StateContext.Provider>,
|
|
93
|
+
);
|
|
94
|
+
expect(node.queryByRole('overlay')).toBe(null);
|
|
55
95
|
});
|
|
56
96
|
|
|
57
97
|
it('Should display something if something is there and wanted even indirectly', () => {
|
|
58
|
-
|
|
59
|
-
'abc:foo': {
|
|
60
|
-
component: () => <div />,
|
|
61
|
-
name: 'bar',
|
|
62
|
-
},
|
|
63
|
-
};
|
|
64
|
-
state.modals = [
|
|
98
|
+
const { context } = createMockContainer(
|
|
65
99
|
{
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
100
|
+
'abc:foo': {
|
|
101
|
+
component: () => <div />,
|
|
102
|
+
name: 'bar',
|
|
103
|
+
},
|
|
69
104
|
},
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
105
|
+
[
|
|
106
|
+
{
|
|
107
|
+
name: 'xyz:foo',
|
|
108
|
+
alternative: 'bar',
|
|
109
|
+
options: {},
|
|
110
|
+
},
|
|
111
|
+
],
|
|
112
|
+
);
|
|
113
|
+
const node = render(
|
|
114
|
+
<StateContext.Provider value={context}>
|
|
115
|
+
<Modals />
|
|
116
|
+
</StateContext.Provider>,
|
|
117
|
+
);
|
|
118
|
+
expect(node.queryByRole('overlay')).not.toBe(null);
|
|
73
119
|
});
|
|
74
120
|
|
|
75
121
|
it('Should display nothing is something is there and not wanted with indirection', () => {
|
|
76
|
-
|
|
77
|
-
'abc:foo': {
|
|
78
|
-
component: () => <div />,
|
|
79
|
-
name: 'qxz',
|
|
80
|
-
},
|
|
81
|
-
};
|
|
82
|
-
state.modals = [
|
|
122
|
+
const { context } = createMockContainer(
|
|
83
123
|
{
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
124
|
+
'abc:foo': {
|
|
125
|
+
component: () => <div />,
|
|
126
|
+
name: 'qxz',
|
|
127
|
+
},
|
|
87
128
|
},
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
129
|
+
[
|
|
130
|
+
{
|
|
131
|
+
name: 'xyz:foo',
|
|
132
|
+
alternative: 'bar',
|
|
133
|
+
options: {},
|
|
134
|
+
},
|
|
135
|
+
],
|
|
136
|
+
);
|
|
137
|
+
const node = render(
|
|
138
|
+
<StateContext.Provider value={context}>
|
|
139
|
+
<Modals />
|
|
140
|
+
</StateContext.Provider>,
|
|
141
|
+
);
|
|
142
|
+
expect(node.queryByRole('overlay')).toBe(null);
|
|
91
143
|
});
|
|
92
144
|
|
|
93
145
|
it('Should display nothing if nothing is available even if wanted', () => {
|
|
94
|
-
|
|
95
|
-
state.modals = [
|
|
146
|
+
const { context } = createMockContainer({}, [
|
|
96
147
|
{
|
|
97
148
|
name: 'foo',
|
|
98
149
|
options: {},
|
|
99
150
|
},
|
|
100
|
-
];
|
|
101
|
-
const node =
|
|
102
|
-
|
|
151
|
+
]);
|
|
152
|
+
const node = render(
|
|
153
|
+
<StateContext.Provider value={context}>
|
|
154
|
+
<Modals />
|
|
155
|
+
</StateContext.Provider>,
|
|
156
|
+
);
|
|
157
|
+
expect(node.queryByRole('overlay')).toBe(null);
|
|
103
158
|
});
|
|
104
159
|
|
|
105
160
|
it('Should close all available dialogs', () => {
|
|
106
161
|
const close = jest.fn();
|
|
107
|
-
|
|
108
|
-
state.modals = [
|
|
109
|
-
{
|
|
110
|
-
name: 'foo',
|
|
111
|
-
options: {},
|
|
112
|
-
close,
|
|
113
|
-
},
|
|
162
|
+
const { context } = createMockContainer(
|
|
114
163
|
{
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
164
|
+
foo: {
|
|
165
|
+
component: () => <div />,
|
|
166
|
+
},
|
|
167
|
+
bar: {
|
|
168
|
+
component: () => <div />,
|
|
169
|
+
},
|
|
118
170
|
},
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
171
|
+
[
|
|
172
|
+
{
|
|
173
|
+
name: 'foo',
|
|
174
|
+
options: {},
|
|
175
|
+
close,
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
name: 'bar',
|
|
179
|
+
options: {},
|
|
180
|
+
close,
|
|
181
|
+
},
|
|
182
|
+
],
|
|
183
|
+
);
|
|
184
|
+
const node = render(
|
|
185
|
+
<StateContext.Provider value={context}>
|
|
186
|
+
<Modals />
|
|
187
|
+
</StateContext.Provider>,
|
|
188
|
+
);
|
|
123
189
|
expect(close).toHaveBeenCalledTimes(0);
|
|
124
|
-
|
|
190
|
+
fireEvent.click(node.getByRole('close'));
|
|
125
191
|
expect(close).toHaveBeenCalledTimes(2);
|
|
126
192
|
});
|
|
127
193
|
});
|
package/src/Modals.tsx
CHANGED
|
@@ -28,21 +28,19 @@ export const Modals: React.FC = () => {
|
|
|
28
28
|
const reg = modals[n.name] || findModal(modals, n.alternative);
|
|
29
29
|
const Component = reg && reg.component;
|
|
30
30
|
const defaults = reg && reg.defaults;
|
|
31
|
+
const options = {
|
|
32
|
+
...defaults,
|
|
33
|
+
...n.options,
|
|
34
|
+
};
|
|
31
35
|
return (
|
|
32
36
|
Component && (
|
|
33
|
-
<PiralModalsDialog {...n} key={n.name}>
|
|
34
|
-
<Component
|
|
35
|
-
onClose={n.close}
|
|
36
|
-
options={{
|
|
37
|
-
...defaults,
|
|
38
|
-
...n.options,
|
|
39
|
-
}}
|
|
40
|
-
/>
|
|
37
|
+
<PiralModalsDialog {...n} options={options} defaults={reg.defaults} layout={reg.layout} key={n.name}>
|
|
38
|
+
<Component onClose={n.close} options={options} />
|
|
41
39
|
</PiralModalsDialog>
|
|
42
40
|
)
|
|
43
41
|
);
|
|
44
42
|
})
|
|
45
|
-
.filter(
|
|
43
|
+
.filter(Boolean);
|
|
46
44
|
const open = children.length > 0;
|
|
47
45
|
|
|
48
46
|
return (
|