@wordpress/plugins 5.6.0 → 5.7.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/CHANGELOG.md +2 -0
- package/README.md +6 -0
- package/build/components/plugin-area/index.js +54 -60
- package/build/components/plugin-area/index.js.map +1 -1
- package/build-module/components/plugin-area/index.js +50 -57
- package/build-module/components/plugin-area/index.js.map +1 -1
- package/package.json +7 -6
- package/src/components/plugin-area/index.js +56 -69
- package/src/components/test/plugin-area.js +117 -0
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -13,6 +13,8 @@ var _memize = _interopRequireDefault(require("memize"));
|
|
|
13
13
|
|
|
14
14
|
var _hooks = require("@wordpress/hooks");
|
|
15
15
|
|
|
16
|
+
var _isShallowEqual = _interopRequireDefault(require("@wordpress/is-shallow-equal"));
|
|
17
|
+
|
|
16
18
|
var _pluginContext = require("../plugin-context");
|
|
17
19
|
|
|
18
20
|
var _pluginErrorBoundary = require("../plugin-error-boundary");
|
|
@@ -30,10 +32,16 @@ var _api = require("../../api");
|
|
|
30
32
|
/**
|
|
31
33
|
* Internal dependencies
|
|
32
34
|
*/
|
|
33
|
-
|
|
35
|
+
const getPluginContext = (0, _memize.default)((icon, name) => ({
|
|
36
|
+
icon,
|
|
37
|
+
name
|
|
38
|
+
}));
|
|
34
39
|
/**
|
|
35
40
|
* A component that renders all plugin fills in a hidden div.
|
|
36
41
|
*
|
|
42
|
+
* @param {Object} props
|
|
43
|
+
* @param {string|undefined} props.scope
|
|
44
|
+
* @param {Function|undefined} props.onError
|
|
37
45
|
* @example
|
|
38
46
|
* ```js
|
|
39
47
|
* // Using ES5 syntax
|
|
@@ -65,69 +73,55 @@ var _api = require("../../api");
|
|
|
65
73
|
*
|
|
66
74
|
* @return {WPComponent} The component to be rendered.
|
|
67
75
|
*/
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
};
|
|
77
|
-
});
|
|
78
|
-
this.state = this.getCurrentPluginsState();
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
getCurrentPluginsState() {
|
|
76
|
+
|
|
77
|
+
function PluginArea(_ref) {
|
|
78
|
+
let {
|
|
79
|
+
scope,
|
|
80
|
+
onError
|
|
81
|
+
} = _ref;
|
|
82
|
+
const store = (0, _element.useMemo)(() => {
|
|
83
|
+
let lastValue;
|
|
82
84
|
return {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
return {
|
|
90
|
-
Plugin: render,
|
|
91
|
-
context: this.memoizedContext(name, icon)
|
|
85
|
+
subscribe(listener) {
|
|
86
|
+
(0, _hooks.addAction)('plugins.pluginRegistered', 'core/plugins/plugin-area/plugins-registered', listener);
|
|
87
|
+
(0, _hooks.addAction)('plugins.pluginUnregistered', 'core/plugins/plugin-area/plugins-unregistered', listener);
|
|
88
|
+
return () => {
|
|
89
|
+
(0, _hooks.removeAction)('plugins.pluginRegistered', 'core/plugins/plugin-area/plugins-registered');
|
|
90
|
+
(0, _hooks.removeAction)('plugins.pluginUnregistered', 'core/plugins/plugin-area/plugins-unregistered');
|
|
92
91
|
};
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
(0, _hooks.removeAction)('plugins.pluginRegistered', 'core/plugins/plugin-area/plugins-registered');
|
|
104
|
-
(0, _hooks.removeAction)('plugins.pluginUnregistered', 'core/plugins/plugin-area/plugins-unregistered');
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
setPlugins() {
|
|
108
|
-
this.setState(this.getCurrentPluginsState);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
render() {
|
|
112
|
-
return (0, _element.createElement)("div", {
|
|
113
|
-
style: {
|
|
114
|
-
display: 'none'
|
|
92
|
+
},
|
|
93
|
+
|
|
94
|
+
getValue() {
|
|
95
|
+
const nextValue = (0, _api.getPlugins)(scope);
|
|
96
|
+
|
|
97
|
+
if (!(0, _isShallowEqual.default)(lastValue, nextValue)) {
|
|
98
|
+
lastValue = nextValue;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return lastValue;
|
|
115
102
|
}
|
|
116
|
-
}, this.state.plugins.map(_ref2 => {
|
|
117
|
-
let {
|
|
118
|
-
context,
|
|
119
|
-
Plugin
|
|
120
|
-
} = _ref2;
|
|
121
|
-
return (0, _element.createElement)(_pluginContext.PluginContextProvider, {
|
|
122
|
-
key: context.name,
|
|
123
|
-
value: context
|
|
124
|
-
}, (0, _element.createElement)(_pluginErrorBoundary.PluginErrorBoundary, {
|
|
125
|
-
name: context.name,
|
|
126
|
-
onError: this.props.onError
|
|
127
|
-
}, (0, _element.createElement)(Plugin, null)));
|
|
128
|
-
}));
|
|
129
|
-
}
|
|
130
103
|
|
|
104
|
+
};
|
|
105
|
+
}, [scope]);
|
|
106
|
+
const plugins = (0, _element.useSyncExternalStore)(store.subscribe, store.getValue);
|
|
107
|
+
return (0, _element.createElement)("div", {
|
|
108
|
+
style: {
|
|
109
|
+
display: 'none'
|
|
110
|
+
}
|
|
111
|
+
}, plugins.map(_ref2 => {
|
|
112
|
+
let {
|
|
113
|
+
icon,
|
|
114
|
+
name,
|
|
115
|
+
render: Plugin
|
|
116
|
+
} = _ref2;
|
|
117
|
+
return (0, _element.createElement)(_pluginContext.PluginContextProvider, {
|
|
118
|
+
key: name,
|
|
119
|
+
value: getPluginContext(icon, name)
|
|
120
|
+
}, (0, _element.createElement)(_pluginErrorBoundary.PluginErrorBoundary, {
|
|
121
|
+
name: name,
|
|
122
|
+
onError: onError
|
|
123
|
+
}, (0, _element.createElement)(Plugin, null)));
|
|
124
|
+
}));
|
|
131
125
|
}
|
|
132
126
|
|
|
133
127
|
var _default = PluginArea;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["@wordpress/plugins/src/components/plugin-area/index.js"],"names":["
|
|
1
|
+
{"version":3,"sources":["@wordpress/plugins/src/components/plugin-area/index.js"],"names":["getPluginContext","icon","name","PluginArea","scope","onError","store","lastValue","subscribe","listener","getValue","nextValue","plugins","display","map","render","Plugin"],"mappings":";;;;;;;;;AAQA;;AALA;;AAMA;;AACA;;AAKA;;AACA;;AACA;;AAjBA;AACA;AACA;;AAGA;AACA;AACA;;AAKA;AACA;AACA;AAKA,MAAMA,gBAAgB,GAAG,qBAAS,CAAEC,IAAF,EAAQC,IAAR,MAAoB;AAAED,EAAAA,IAAF;AAAQC,EAAAA;AAAR,CAApB,CAAT,CAAzB;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AACA,SAASC,UAAT,OAA0C;AAAA,MAArB;AAAEC,IAAAA,KAAF;AAASC,IAAAA;AAAT,GAAqB;AACzC,QAAMC,KAAK,GAAG,sBAAS,MAAM;AAC5B,QAAIC,SAAJ;AAEA,WAAO;AACNC,MAAAA,SAAS,CAAEC,QAAF,EAAa;AACrB,8BACC,0BADD,EAEC,6CAFD,EAGCA,QAHD;AAKA,8BACC,4BADD,EAEC,+CAFD,EAGCA,QAHD;AAKA,eAAO,MAAM;AACZ,mCACC,0BADD,EAEC,6CAFD;AAIA,mCACC,4BADD,EAEC,+CAFD;AAIA,SATD;AAUA,OAtBK;;AAuBNC,MAAAA,QAAQ,GAAG;AACV,cAAMC,SAAS,GAAG,qBAAYP,KAAZ,CAAlB;;AAEA,YAAK,CAAE,6BAAgBG,SAAhB,EAA2BI,SAA3B,CAAP,EAAgD;AAC/CJ,UAAAA,SAAS,GAAGI,SAAZ;AACA;;AAED,eAAOJ,SAAP;AACA;;AA/BK,KAAP;AAiCA,GApCa,EAoCX,CAAEH,KAAF,CApCW,CAAd;AAsCA,QAAMQ,OAAO,GAAG,mCAAsBN,KAAK,CAACE,SAA5B,EAAuCF,KAAK,CAACI,QAA7C,CAAhB;AAEA,SACC;AAAK,IAAA,KAAK,EAAG;AAAEG,MAAAA,OAAO,EAAE;AAAX;AAAb,KACGD,OAAO,CAACE,GAAR,CAAa;AAAA,QAAE;AAAEb,MAAAA,IAAF;AAAQC,MAAAA,IAAR;AAAca,MAAAA,MAAM,EAAEC;AAAtB,KAAF;AAAA,WACd,4BAAC,oCAAD;AACC,MAAA,GAAG,EAAGd,IADP;AAEC,MAAA,KAAK,EAAGF,gBAAgB,CAAEC,IAAF,EAAQC,IAAR;AAFzB,OAIC,4BAAC,wCAAD;AAAqB,MAAA,IAAI,EAAGA,IAA5B;AAAmC,MAAA,OAAO,EAAGG;AAA7C,OACC,4BAAC,MAAD,OADD,CAJD,CADc;AAAA,GAAb,CADH,CADD;AAcA;;eAEcF,U","sourcesContent":["/**\n * External dependencies\n */\nimport memoize from 'memize';\n\n/**\n * WordPress dependencies\n */\nimport { useMemo, useSyncExternalStore } from '@wordpress/element';\nimport { addAction, removeAction } from '@wordpress/hooks';\nimport isShallowEqual from '@wordpress/is-shallow-equal';\n\n/**\n * Internal dependencies\n */\nimport { PluginContextProvider } from '../plugin-context';\nimport { PluginErrorBoundary } from '../plugin-error-boundary';\nimport { getPlugins } from '../../api';\n\nconst getPluginContext = memoize( ( icon, name ) => ( { icon, name } ) );\n\n/**\n * A component that renders all plugin fills in a hidden div.\n *\n * @param {Object} props\n * @param {string|undefined} props.scope\n * @param {Function|undefined} props.onError\n * @example\n * ```js\n * // Using ES5 syntax\n * var el = wp.element.createElement;\n * var PluginArea = wp.plugins.PluginArea;\n *\n * function Layout() {\n * \treturn el(\n * \t\t'div',\n * \t\t{ scope: 'my-page' },\n * \t\t'Content of the page',\n * \t\tPluginArea\n * \t);\n * }\n * ```\n *\n * @example\n * ```js\n * // Using ESNext syntax\n * import { PluginArea } from '@wordpress/plugins';\n *\n * const Layout = () => (\n * \t<div>\n * \t\tContent of the page\n * \t\t<PluginArea scope=\"my-page\" />\n * \t</div>\n * );\n * ```\n *\n * @return {WPComponent} The component to be rendered.\n */\nfunction PluginArea( { scope, onError } ) {\n\tconst store = useMemo( () => {\n\t\tlet lastValue;\n\n\t\treturn {\n\t\t\tsubscribe( listener ) {\n\t\t\t\taddAction(\n\t\t\t\t\t'plugins.pluginRegistered',\n\t\t\t\t\t'core/plugins/plugin-area/plugins-registered',\n\t\t\t\t\tlistener\n\t\t\t\t);\n\t\t\t\taddAction(\n\t\t\t\t\t'plugins.pluginUnregistered',\n\t\t\t\t\t'core/plugins/plugin-area/plugins-unregistered',\n\t\t\t\t\tlistener\n\t\t\t\t);\n\t\t\t\treturn () => {\n\t\t\t\t\tremoveAction(\n\t\t\t\t\t\t'plugins.pluginRegistered',\n\t\t\t\t\t\t'core/plugins/plugin-area/plugins-registered'\n\t\t\t\t\t);\n\t\t\t\t\tremoveAction(\n\t\t\t\t\t\t'plugins.pluginUnregistered',\n\t\t\t\t\t\t'core/plugins/plugin-area/plugins-unregistered'\n\t\t\t\t\t);\n\t\t\t\t};\n\t\t\t},\n\t\t\tgetValue() {\n\t\t\t\tconst nextValue = getPlugins( scope );\n\n\t\t\t\tif ( ! isShallowEqual( lastValue, nextValue ) ) {\n\t\t\t\t\tlastValue = nextValue;\n\t\t\t\t}\n\n\t\t\t\treturn lastValue;\n\t\t\t},\n\t\t};\n\t}, [ scope ] );\n\n\tconst plugins = useSyncExternalStore( store.subscribe, store.getValue );\n\n\treturn (\n\t\t<div style={ { display: 'none' } }>\n\t\t\t{ plugins.map( ( { icon, name, render: Plugin } ) => (\n\t\t\t\t<PluginContextProvider\n\t\t\t\t\tkey={ name }\n\t\t\t\t\tvalue={ getPluginContext( icon, name ) }\n\t\t\t\t>\n\t\t\t\t\t<PluginErrorBoundary name={ name } onError={ onError }>\n\t\t\t\t\t\t<Plugin />\n\t\t\t\t\t</PluginErrorBoundary>\n\t\t\t\t</PluginContextProvider>\n\t\t\t) ) }\n\t\t</div>\n\t);\n}\n\nexport default PluginArea;\n"]}
|
|
@@ -8,8 +8,9 @@ import memoize from 'memize';
|
|
|
8
8
|
* WordPress dependencies
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import {
|
|
11
|
+
import { useMemo, useSyncExternalStore } from '@wordpress/element';
|
|
12
12
|
import { addAction, removeAction } from '@wordpress/hooks';
|
|
13
|
+
import isShallowEqual from '@wordpress/is-shallow-equal';
|
|
13
14
|
/**
|
|
14
15
|
* Internal dependencies
|
|
15
16
|
*/
|
|
@@ -17,9 +18,16 @@ import { addAction, removeAction } from '@wordpress/hooks';
|
|
|
17
18
|
import { PluginContextProvider } from '../plugin-context';
|
|
18
19
|
import { PluginErrorBoundary } from '../plugin-error-boundary';
|
|
19
20
|
import { getPlugins } from '../../api';
|
|
21
|
+
const getPluginContext = memoize((icon, name) => ({
|
|
22
|
+
icon,
|
|
23
|
+
name
|
|
24
|
+
}));
|
|
20
25
|
/**
|
|
21
26
|
* A component that renders all plugin fills in a hidden div.
|
|
22
27
|
*
|
|
28
|
+
* @param {Object} props
|
|
29
|
+
* @param {string|undefined} props.scope
|
|
30
|
+
* @param {Function|undefined} props.onError
|
|
23
31
|
* @example
|
|
24
32
|
* ```js
|
|
25
33
|
* // Using ES5 syntax
|
|
@@ -52,69 +60,54 @@ import { getPlugins } from '../../api';
|
|
|
52
60
|
* @return {WPComponent} The component to be rendered.
|
|
53
61
|
*/
|
|
54
62
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
icon
|
|
63
|
-
};
|
|
64
|
-
});
|
|
65
|
-
this.state = this.getCurrentPluginsState();
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
getCurrentPluginsState() {
|
|
63
|
+
function PluginArea(_ref) {
|
|
64
|
+
let {
|
|
65
|
+
scope,
|
|
66
|
+
onError
|
|
67
|
+
} = _ref;
|
|
68
|
+
const store = useMemo(() => {
|
|
69
|
+
let lastValue;
|
|
69
70
|
return {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
return {
|
|
77
|
-
Plugin: render,
|
|
78
|
-
context: this.memoizedContext(name, icon)
|
|
71
|
+
subscribe(listener) {
|
|
72
|
+
addAction('plugins.pluginRegistered', 'core/plugins/plugin-area/plugins-registered', listener);
|
|
73
|
+
addAction('plugins.pluginUnregistered', 'core/plugins/plugin-area/plugins-unregistered', listener);
|
|
74
|
+
return () => {
|
|
75
|
+
removeAction('plugins.pluginRegistered', 'core/plugins/plugin-area/plugins-registered');
|
|
76
|
+
removeAction('plugins.pluginUnregistered', 'core/plugins/plugin-area/plugins-unregistered');
|
|
79
77
|
};
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
}
|
|
78
|
+
},
|
|
83
79
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
addAction('plugins.pluginUnregistered', 'core/plugins/plugin-area/plugins-unregistered', this.setPlugins);
|
|
87
|
-
}
|
|
80
|
+
getValue() {
|
|
81
|
+
const nextValue = getPlugins(scope);
|
|
88
82
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
}
|
|
83
|
+
if (!isShallowEqual(lastValue, nextValue)) {
|
|
84
|
+
lastValue = nextValue;
|
|
85
|
+
}
|
|
93
86
|
|
|
94
|
-
|
|
95
|
-
this.setState(this.getCurrentPluginsState);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
render() {
|
|
99
|
-
return createElement("div", {
|
|
100
|
-
style: {
|
|
101
|
-
display: 'none'
|
|
87
|
+
return lastValue;
|
|
102
88
|
}
|
|
103
|
-
}, this.state.plugins.map(_ref2 => {
|
|
104
|
-
let {
|
|
105
|
-
context,
|
|
106
|
-
Plugin
|
|
107
|
-
} = _ref2;
|
|
108
|
-
return createElement(PluginContextProvider, {
|
|
109
|
-
key: context.name,
|
|
110
|
-
value: context
|
|
111
|
-
}, createElement(PluginErrorBoundary, {
|
|
112
|
-
name: context.name,
|
|
113
|
-
onError: this.props.onError
|
|
114
|
-
}, createElement(Plugin, null)));
|
|
115
|
-
}));
|
|
116
|
-
}
|
|
117
89
|
|
|
90
|
+
};
|
|
91
|
+
}, [scope]);
|
|
92
|
+
const plugins = useSyncExternalStore(store.subscribe, store.getValue);
|
|
93
|
+
return createElement("div", {
|
|
94
|
+
style: {
|
|
95
|
+
display: 'none'
|
|
96
|
+
}
|
|
97
|
+
}, plugins.map(_ref2 => {
|
|
98
|
+
let {
|
|
99
|
+
icon,
|
|
100
|
+
name,
|
|
101
|
+
render: Plugin
|
|
102
|
+
} = _ref2;
|
|
103
|
+
return createElement(PluginContextProvider, {
|
|
104
|
+
key: name,
|
|
105
|
+
value: getPluginContext(icon, name)
|
|
106
|
+
}, createElement(PluginErrorBoundary, {
|
|
107
|
+
name: name,
|
|
108
|
+
onError: onError
|
|
109
|
+
}, createElement(Plugin, null)));
|
|
110
|
+
}));
|
|
118
111
|
}
|
|
119
112
|
|
|
120
113
|
export default PluginArea;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["@wordpress/plugins/src/components/plugin-area/index.js"],"names":["memoize","
|
|
1
|
+
{"version":3,"sources":["@wordpress/plugins/src/components/plugin-area/index.js"],"names":["memoize","useMemo","useSyncExternalStore","addAction","removeAction","isShallowEqual","PluginContextProvider","PluginErrorBoundary","getPlugins","getPluginContext","icon","name","PluginArea","scope","onError","store","lastValue","subscribe","listener","getValue","nextValue","plugins","display","map","render","Plugin"],"mappings":";;AAAA;AACA;AACA;AACA,OAAOA,OAAP,MAAoB,QAApB;AAEA;AACA;AACA;;AACA,SAASC,OAAT,EAAkBC,oBAAlB,QAA8C,oBAA9C;AACA,SAASC,SAAT,EAAoBC,YAApB,QAAwC,kBAAxC;AACA,OAAOC,cAAP,MAA2B,6BAA3B;AAEA;AACA;AACA;;AACA,SAASC,qBAAT,QAAsC,mBAAtC;AACA,SAASC,mBAAT,QAAoC,0BAApC;AACA,SAASC,UAAT,QAA2B,WAA3B;AAEA,MAAMC,gBAAgB,GAAGT,OAAO,CAAE,CAAEU,IAAF,EAAQC,IAAR,MAAoB;AAAED,EAAAA,IAAF;AAAQC,EAAAA;AAAR,CAApB,CAAF,CAAhC;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AACA,SAASC,UAAT,OAA0C;AAAA,MAArB;AAAEC,IAAAA,KAAF;AAASC,IAAAA;AAAT,GAAqB;AACzC,QAAMC,KAAK,GAAGd,OAAO,CAAE,MAAM;AAC5B,QAAIe,SAAJ;AAEA,WAAO;AACNC,MAAAA,SAAS,CAAEC,QAAF,EAAa;AACrBf,QAAAA,SAAS,CACR,0BADQ,EAER,6CAFQ,EAGRe,QAHQ,CAAT;AAKAf,QAAAA,SAAS,CACR,4BADQ,EAER,+CAFQ,EAGRe,QAHQ,CAAT;AAKA,eAAO,MAAM;AACZd,UAAAA,YAAY,CACX,0BADW,EAEX,6CAFW,CAAZ;AAIAA,UAAAA,YAAY,CACX,4BADW,EAEX,+CAFW,CAAZ;AAIA,SATD;AAUA,OAtBK;;AAuBNe,MAAAA,QAAQ,GAAG;AACV,cAAMC,SAAS,GAAGZ,UAAU,CAAEK,KAAF,CAA5B;;AAEA,YAAK,CAAER,cAAc,CAAEW,SAAF,EAAaI,SAAb,CAArB,EAAgD;AAC/CJ,UAAAA,SAAS,GAAGI,SAAZ;AACA;;AAED,eAAOJ,SAAP;AACA;;AA/BK,KAAP;AAiCA,GApCoB,EAoClB,CAAEH,KAAF,CApCkB,CAArB;AAsCA,QAAMQ,OAAO,GAAGnB,oBAAoB,CAAEa,KAAK,CAACE,SAAR,EAAmBF,KAAK,CAACI,QAAzB,CAApC;AAEA,SACC;AAAK,IAAA,KAAK,EAAG;AAAEG,MAAAA,OAAO,EAAE;AAAX;AAAb,KACGD,OAAO,CAACE,GAAR,CAAa;AAAA,QAAE;AAAEb,MAAAA,IAAF;AAAQC,MAAAA,IAAR;AAAca,MAAAA,MAAM,EAAEC;AAAtB,KAAF;AAAA,WACd,cAAC,qBAAD;AACC,MAAA,GAAG,EAAGd,IADP;AAEC,MAAA,KAAK,EAAGF,gBAAgB,CAAEC,IAAF,EAAQC,IAAR;AAFzB,OAIC,cAAC,mBAAD;AAAqB,MAAA,IAAI,EAAGA,IAA5B;AAAmC,MAAA,OAAO,EAAGG;AAA7C,OACC,cAAC,MAAD,OADD,CAJD,CADc;AAAA,GAAb,CADH,CADD;AAcA;;AAED,eAAeF,UAAf","sourcesContent":["/**\n * External dependencies\n */\nimport memoize from 'memize';\n\n/**\n * WordPress dependencies\n */\nimport { useMemo, useSyncExternalStore } from '@wordpress/element';\nimport { addAction, removeAction } from '@wordpress/hooks';\nimport isShallowEqual from '@wordpress/is-shallow-equal';\n\n/**\n * Internal dependencies\n */\nimport { PluginContextProvider } from '../plugin-context';\nimport { PluginErrorBoundary } from '../plugin-error-boundary';\nimport { getPlugins } from '../../api';\n\nconst getPluginContext = memoize( ( icon, name ) => ( { icon, name } ) );\n\n/**\n * A component that renders all plugin fills in a hidden div.\n *\n * @param {Object} props\n * @param {string|undefined} props.scope\n * @param {Function|undefined} props.onError\n * @example\n * ```js\n * // Using ES5 syntax\n * var el = wp.element.createElement;\n * var PluginArea = wp.plugins.PluginArea;\n *\n * function Layout() {\n * \treturn el(\n * \t\t'div',\n * \t\t{ scope: 'my-page' },\n * \t\t'Content of the page',\n * \t\tPluginArea\n * \t);\n * }\n * ```\n *\n * @example\n * ```js\n * // Using ESNext syntax\n * import { PluginArea } from '@wordpress/plugins';\n *\n * const Layout = () => (\n * \t<div>\n * \t\tContent of the page\n * \t\t<PluginArea scope=\"my-page\" />\n * \t</div>\n * );\n * ```\n *\n * @return {WPComponent} The component to be rendered.\n */\nfunction PluginArea( { scope, onError } ) {\n\tconst store = useMemo( () => {\n\t\tlet lastValue;\n\n\t\treturn {\n\t\t\tsubscribe( listener ) {\n\t\t\t\taddAction(\n\t\t\t\t\t'plugins.pluginRegistered',\n\t\t\t\t\t'core/plugins/plugin-area/plugins-registered',\n\t\t\t\t\tlistener\n\t\t\t\t);\n\t\t\t\taddAction(\n\t\t\t\t\t'plugins.pluginUnregistered',\n\t\t\t\t\t'core/plugins/plugin-area/plugins-unregistered',\n\t\t\t\t\tlistener\n\t\t\t\t);\n\t\t\t\treturn () => {\n\t\t\t\t\tremoveAction(\n\t\t\t\t\t\t'plugins.pluginRegistered',\n\t\t\t\t\t\t'core/plugins/plugin-area/plugins-registered'\n\t\t\t\t\t);\n\t\t\t\t\tremoveAction(\n\t\t\t\t\t\t'plugins.pluginUnregistered',\n\t\t\t\t\t\t'core/plugins/plugin-area/plugins-unregistered'\n\t\t\t\t\t);\n\t\t\t\t};\n\t\t\t},\n\t\t\tgetValue() {\n\t\t\t\tconst nextValue = getPlugins( scope );\n\n\t\t\t\tif ( ! isShallowEqual( lastValue, nextValue ) ) {\n\t\t\t\t\tlastValue = nextValue;\n\t\t\t\t}\n\n\t\t\t\treturn lastValue;\n\t\t\t},\n\t\t};\n\t}, [ scope ] );\n\n\tconst plugins = useSyncExternalStore( store.subscribe, store.getValue );\n\n\treturn (\n\t\t<div style={ { display: 'none' } }>\n\t\t\t{ plugins.map( ( { icon, name, render: Plugin } ) => (\n\t\t\t\t<PluginContextProvider\n\t\t\t\t\tkey={ name }\n\t\t\t\t\tvalue={ getPluginContext( icon, name ) }\n\t\t\t\t>\n\t\t\t\t\t<PluginErrorBoundary name={ name } onError={ onError }>\n\t\t\t\t\t\t<Plugin />\n\t\t\t\t\t</PluginErrorBoundary>\n\t\t\t\t</PluginContextProvider>\n\t\t\t) ) }\n\t\t</div>\n\t);\n}\n\nexport default PluginArea;\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wordpress/plugins",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.7.0",
|
|
4
4
|
"description": "Plugins module for WordPress.",
|
|
5
5
|
"author": "The WordPress Contributors",
|
|
6
6
|
"license": "GPL-2.0-or-later",
|
|
@@ -26,10 +26,11 @@
|
|
|
26
26
|
"react-native": "src/index",
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@babel/runtime": "^7.16.0",
|
|
29
|
-
"@wordpress/compose": "^6.
|
|
30
|
-
"@wordpress/element": "^5.
|
|
31
|
-
"@wordpress/hooks": "^3.
|
|
32
|
-
"@wordpress/icons": "^9.
|
|
29
|
+
"@wordpress/compose": "^6.7.0",
|
|
30
|
+
"@wordpress/element": "^5.7.0",
|
|
31
|
+
"@wordpress/hooks": "^3.30.0",
|
|
32
|
+
"@wordpress/icons": "^9.21.0",
|
|
33
|
+
"@wordpress/is-shallow-equal": "^4.30.0",
|
|
33
34
|
"memize": "^1.1.0"
|
|
34
35
|
},
|
|
35
36
|
"peerDependencies": {
|
|
@@ -38,5 +39,5 @@
|
|
|
38
39
|
"publishConfig": {
|
|
39
40
|
"access": "public"
|
|
40
41
|
},
|
|
41
|
-
"gitHead": "
|
|
42
|
+
"gitHead": "d5c28a67b11e91e3e4b8e90346bfcb90909364d6"
|
|
42
43
|
}
|
|
@@ -6,8 +6,9 @@ import memoize from 'memize';
|
|
|
6
6
|
/**
|
|
7
7
|
* WordPress dependencies
|
|
8
8
|
*/
|
|
9
|
-
import {
|
|
9
|
+
import { useMemo, useSyncExternalStore } from '@wordpress/element';
|
|
10
10
|
import { addAction, removeAction } from '@wordpress/hooks';
|
|
11
|
+
import isShallowEqual from '@wordpress/is-shallow-equal';
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* Internal dependencies
|
|
@@ -16,9 +17,14 @@ import { PluginContextProvider } from '../plugin-context';
|
|
|
16
17
|
import { PluginErrorBoundary } from '../plugin-error-boundary';
|
|
17
18
|
import { getPlugins } from '../../api';
|
|
18
19
|
|
|
20
|
+
const getPluginContext = memoize( ( icon, name ) => ( { icon, name } ) );
|
|
21
|
+
|
|
19
22
|
/**
|
|
20
23
|
* A component that renders all plugin fills in a hidden div.
|
|
21
24
|
*
|
|
25
|
+
* @param {Object} props
|
|
26
|
+
* @param {string|undefined} props.scope
|
|
27
|
+
* @param {Function|undefined} props.onError
|
|
22
28
|
* @example
|
|
23
29
|
* ```js
|
|
24
30
|
* // Using ES5 syntax
|
|
@@ -50,80 +56,61 @@ import { getPlugins } from '../../api';
|
|
|
50
56
|
*
|
|
51
57
|
* @return {WPComponent} The component to be rendered.
|
|
52
58
|
*/
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
this.setPlugins = this.setPlugins.bind( this );
|
|
58
|
-
this.memoizedContext = memoize( ( name, icon ) => {
|
|
59
|
-
return {
|
|
60
|
-
name,
|
|
61
|
-
icon,
|
|
62
|
-
};
|
|
63
|
-
} );
|
|
64
|
-
this.state = this.getCurrentPluginsState();
|
|
65
|
-
}
|
|
59
|
+
function PluginArea( { scope, onError } ) {
|
|
60
|
+
const store = useMemo( () => {
|
|
61
|
+
let lastValue;
|
|
66
62
|
|
|
67
|
-
getCurrentPluginsState() {
|
|
68
63
|
return {
|
|
69
|
-
|
|
70
|
-
(
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
64
|
+
subscribe( listener ) {
|
|
65
|
+
addAction(
|
|
66
|
+
'plugins.pluginRegistered',
|
|
67
|
+
'core/plugins/plugin-area/plugins-registered',
|
|
68
|
+
listener
|
|
69
|
+
);
|
|
70
|
+
addAction(
|
|
71
|
+
'plugins.pluginUnregistered',
|
|
72
|
+
'core/plugins/plugin-area/plugins-unregistered',
|
|
73
|
+
listener
|
|
74
|
+
);
|
|
75
|
+
return () => {
|
|
76
|
+
removeAction(
|
|
77
|
+
'plugins.pluginRegistered',
|
|
78
|
+
'core/plugins/plugin-area/plugins-registered'
|
|
79
|
+
);
|
|
80
|
+
removeAction(
|
|
81
|
+
'plugins.pluginUnregistered',
|
|
82
|
+
'core/plugins/plugin-area/plugins-unregistered'
|
|
83
|
+
);
|
|
84
|
+
};
|
|
85
|
+
},
|
|
86
|
+
getValue() {
|
|
87
|
+
const nextValue = getPlugins( scope );
|
|
79
88
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
'core/plugins/plugin-area/plugins-registered',
|
|
84
|
-
this.setPlugins
|
|
85
|
-
);
|
|
86
|
-
addAction(
|
|
87
|
-
'plugins.pluginUnregistered',
|
|
88
|
-
'core/plugins/plugin-area/plugins-unregistered',
|
|
89
|
-
this.setPlugins
|
|
90
|
-
);
|
|
91
|
-
}
|
|
89
|
+
if ( ! isShallowEqual( lastValue, nextValue ) ) {
|
|
90
|
+
lastValue = nextValue;
|
|
91
|
+
}
|
|
92
92
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
);
|
|
98
|
-
removeAction(
|
|
99
|
-
'plugins.pluginUnregistered',
|
|
100
|
-
'core/plugins/plugin-area/plugins-unregistered'
|
|
101
|
-
);
|
|
102
|
-
}
|
|
93
|
+
return lastValue;
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
}, [ scope ] );
|
|
103
97
|
|
|
104
|
-
|
|
105
|
-
this.setState( this.getCurrentPluginsState );
|
|
106
|
-
}
|
|
98
|
+
const plugins = useSyncExternalStore( store.subscribe, store.getValue );
|
|
107
99
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
>
|
|
116
|
-
<
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
</PluginContextProvider>
|
|
123
|
-
) ) }
|
|
124
|
-
</div>
|
|
125
|
-
);
|
|
126
|
-
}
|
|
100
|
+
return (
|
|
101
|
+
<div style={ { display: 'none' } }>
|
|
102
|
+
{ plugins.map( ( { icon, name, render: Plugin } ) => (
|
|
103
|
+
<PluginContextProvider
|
|
104
|
+
key={ name }
|
|
105
|
+
value={ getPluginContext( icon, name ) }
|
|
106
|
+
>
|
|
107
|
+
<PluginErrorBoundary name={ name } onError={ onError }>
|
|
108
|
+
<Plugin />
|
|
109
|
+
</PluginErrorBoundary>
|
|
110
|
+
</PluginContextProvider>
|
|
111
|
+
) ) }
|
|
112
|
+
</div>
|
|
113
|
+
);
|
|
127
114
|
}
|
|
128
115
|
|
|
129
116
|
export default PluginArea;
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* External dependencies
|
|
3
|
+
*/
|
|
4
|
+
import { act, render, cleanup } from '@testing-library/react';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Internal dependencies
|
|
8
|
+
*/
|
|
9
|
+
import { getPlugins, unregisterPlugin, registerPlugin } from '../../api';
|
|
10
|
+
import PluginArea from '../plugin-area';
|
|
11
|
+
|
|
12
|
+
describe( 'PluginArea', () => {
|
|
13
|
+
afterEach( () => {
|
|
14
|
+
// Unmount components before unregistering the plugins.
|
|
15
|
+
// RTL uses top-level `afterEach` for cleanup, executed after this teardown.
|
|
16
|
+
cleanup();
|
|
17
|
+
getPlugins().forEach( ( plugin ) => {
|
|
18
|
+
unregisterPlugin( plugin.name );
|
|
19
|
+
} );
|
|
20
|
+
getPlugins( 'my-app' ).forEach( ( plugin ) => {
|
|
21
|
+
unregisterPlugin( plugin.name );
|
|
22
|
+
} );
|
|
23
|
+
} );
|
|
24
|
+
|
|
25
|
+
const TestComponent = ( { content } ) => {
|
|
26
|
+
return `plugin: ${ content }.`;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
test( 'renders unscoped plugin', () => {
|
|
30
|
+
registerPlugin( 'unscoped', {
|
|
31
|
+
render: () => <TestComponent content="unscoped" />,
|
|
32
|
+
icon: 'smiley',
|
|
33
|
+
} );
|
|
34
|
+
|
|
35
|
+
const { container } = render( <PluginArea /> );
|
|
36
|
+
|
|
37
|
+
expect( container ).toHaveTextContent( 'plugin: unscoped.' );
|
|
38
|
+
} );
|
|
39
|
+
|
|
40
|
+
test( 'renders scoped plugin', () => {
|
|
41
|
+
registerPlugin( 'scoped', {
|
|
42
|
+
render: () => <TestComponent content="scoped" />,
|
|
43
|
+
icon: 'smiley',
|
|
44
|
+
scope: 'my-app',
|
|
45
|
+
} );
|
|
46
|
+
|
|
47
|
+
const { container } = render( <PluginArea scope="my-app" /> );
|
|
48
|
+
|
|
49
|
+
expect( container ).toHaveTextContent( 'plugin: scoped.' );
|
|
50
|
+
} );
|
|
51
|
+
|
|
52
|
+
test( 'rerenders when a new plugin is registered', () => {
|
|
53
|
+
registerPlugin( 'foo', {
|
|
54
|
+
render: () => <TestComponent content="foo" />,
|
|
55
|
+
icon: 'smiley',
|
|
56
|
+
scope: 'my-app',
|
|
57
|
+
} );
|
|
58
|
+
|
|
59
|
+
const { container } = render( <PluginArea scope="my-app" /> );
|
|
60
|
+
|
|
61
|
+
act( () => {
|
|
62
|
+
registerPlugin( 'bar', {
|
|
63
|
+
render: () => <TestComponent content="bar" />,
|
|
64
|
+
icon: 'smiley',
|
|
65
|
+
scope: 'my-app',
|
|
66
|
+
} );
|
|
67
|
+
} );
|
|
68
|
+
|
|
69
|
+
expect( container ).toHaveTextContent( 'plugin: bar.' );
|
|
70
|
+
} );
|
|
71
|
+
|
|
72
|
+
test( 'rerenders when a plugin is unregistered', () => {
|
|
73
|
+
registerPlugin( 'one', {
|
|
74
|
+
render: () => <TestComponent content="one" />,
|
|
75
|
+
icon: 'smiley',
|
|
76
|
+
scope: 'my-app',
|
|
77
|
+
} );
|
|
78
|
+
registerPlugin( 'two', {
|
|
79
|
+
render: () => <TestComponent content="two" />,
|
|
80
|
+
icon: 'smiley',
|
|
81
|
+
scope: 'my-app',
|
|
82
|
+
} );
|
|
83
|
+
|
|
84
|
+
const { container } = render( <PluginArea scope="my-app" /> );
|
|
85
|
+
|
|
86
|
+
expect( container ).toHaveTextContent( 'plugin: one.plugin: two.' );
|
|
87
|
+
|
|
88
|
+
act( () => {
|
|
89
|
+
unregisterPlugin( 'one' );
|
|
90
|
+
} );
|
|
91
|
+
|
|
92
|
+
expect( container ).toHaveTextContent( 'plugin: two.' );
|
|
93
|
+
} );
|
|
94
|
+
|
|
95
|
+
test( 'does not rerender when a plugin is added to a different scope', () => {
|
|
96
|
+
const ComponentSpy = jest.fn( ( { content } ) => {
|
|
97
|
+
return `plugin: ${ content }.`;
|
|
98
|
+
} );
|
|
99
|
+
|
|
100
|
+
registerPlugin( 'scoped', {
|
|
101
|
+
render: () => <ComponentSpy content="scoped" />,
|
|
102
|
+
icon: 'smiley',
|
|
103
|
+
scope: 'my-app',
|
|
104
|
+
} );
|
|
105
|
+
|
|
106
|
+
render( <PluginArea scope="my-app" /> );
|
|
107
|
+
|
|
108
|
+
act( () => {
|
|
109
|
+
registerPlugin( 'unscoped', {
|
|
110
|
+
render: () => <TestComponent content="unscoped" />,
|
|
111
|
+
icon: 'smiley',
|
|
112
|
+
} );
|
|
113
|
+
} );
|
|
114
|
+
|
|
115
|
+
expect( ComponentSpy ).toHaveBeenCalledTimes( 1 );
|
|
116
|
+
} );
|
|
117
|
+
} );
|