@emailmaker/extensions-react 0.9.0-dev.1

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 ADDED
@@ -0,0 +1,72 @@
1
+ # ⚛️ `extensions-react`
2
+
3
+ `@emailmaker/extensions-react` нужен для React-плагинов.
4
+
5
+ ## Что в нем есть
6
+
7
+ - `ComponentRegistry`
8
+ - `createComponentIdentifier()`
9
+ - поддержка React-компонентов в API
10
+
11
+ ## Что можно делать
12
+
13
+ После установки пакета вы можете передавать JSX прямо в API:
14
+
15
+ ```ts
16
+ import { SettingsPanelApi } from '@emailmaker/extensions-app';
17
+ import '@emailmaker/extensions-react';
18
+
19
+ settingsPanel.showSettingsPanel({
20
+ content: <MyPanel />,
21
+ });
22
+ ```
23
+
24
+ ## Когда использовать JSX
25
+
26
+ Прямой JSX — лучший путь по умолчанию для React-плагина:
27
+
28
+ ```ts
29
+ settingsPanel.showSettingsPanel({
30
+ content: <MyPanel value={state} />,
31
+ });
32
+ ```
33
+
34
+ Он хорош, когда:
35
+
36
+ - не нужен стабильный `ComponentId`
37
+ - не нужен `override()`
38
+ - UI используется локально в одном месте
39
+
40
+ ## Когда использовать `ComponentRegistry`
41
+
42
+ `ComponentRegistry` нужен, если:
43
+
44
+ - компонент должен быть доступен по `ComponentId`
45
+ - нужна возможность `override()`
46
+ - компонент используется в нескольких местах через `{ type, props }`
47
+ - нужен стабильный идентификатор для контракта между частями плагина
48
+
49
+ Пример:
50
+
51
+ ```ts
52
+ import { createComponentIdentifier } from '@emailmaker/extensions-app';
53
+ import { ComponentRegistry } from '@emailmaker/extensions-react';
54
+
55
+ const PanelId = createComponentIdentifier<{ value: string }>('MyPanel');
56
+
57
+ ComponentRegistry.add(PanelId, MyPanel);
58
+
59
+ settingsPanel.showSettingsPanel({
60
+ content: {
61
+ type: PanelId,
62
+ props: { value: 'hello' },
63
+ },
64
+ });
65
+ ```
66
+
67
+ ## Короткое правило
68
+
69
+ - для React-плагина ставьте `@emailmaker/extensions-react`
70
+ - для обычного React UI чаще всего достаточно JSX
71
+ - если нужен идентификатор компонента, используйте `ComponentRegistry`
72
+
package/externals.json ADDED
@@ -0,0 +1,94 @@
1
+ {
2
+ "react": [
3
+ "promise __emailmaker__.modules",
4
+ "React"
5
+ ],
6
+ "react-dom": [
7
+ "promise __emailmaker__.modules",
8
+ "ReactDom"
9
+ ],
10
+ "react-dom/client": [
11
+ "promise __emailmaker__.modules",
12
+ "ReactDomClient"
13
+ ],
14
+ "react/jsx-runtime": [
15
+ "promise __emailmaker__.modules",
16
+ "ReactJsxRuntime"
17
+ ],
18
+ "react/jsx-dev-runtime": [
19
+ "promise __emailmaker__.modules",
20
+ "ReactJsxDevRuntime"
21
+ ],
22
+ "prop-types": [
23
+ "promise __emailmaker__.modules",
24
+ "PropTypes"
25
+ ],
26
+ "react-router-dom": [
27
+ "promise __emailmaker__.modules",
28
+ "ReactRouterDom"
29
+ ],
30
+ "antd": [
31
+ "promise __emailmaker__.modules",
32
+ "Antd"
33
+ ],
34
+ "@ant-design/icons": [
35
+ "promise __emailmaker__.modules",
36
+ "AntDesignIcons"
37
+ ],
38
+ "@ant-design/cssinjs": [
39
+ "promise __emailmaker__.modules",
40
+ "AntDesignCssinjs"
41
+ ],
42
+ "@ant-design/pro-layout": [
43
+ "promise __emailmaker__.modules",
44
+ "AntDesignProLayout"
45
+ ],
46
+ "classnames": [
47
+ "promise __emailmaker__.modules",
48
+ "Classnames"
49
+ ],
50
+ "dayjs": [
51
+ "promise __emailmaker__.modules",
52
+ "Dayjs"
53
+ ],
54
+ "uuid": [
55
+ "promise __emailmaker__.modules",
56
+ "Uuid"
57
+ ],
58
+ "@emailmaker/runtime/core": [
59
+ "promise __emailmaker__.modules",
60
+ "Core"
61
+ ],
62
+ "di": [
63
+ "promise __emailmaker__.modules",
64
+ "Core"
65
+ ],
66
+ "@emailmaker/runtime/di": [
67
+ "promise __emailmaker__.modules",
68
+ "Core"
69
+ ],
70
+ "disposable": [
71
+ "promise __emailmaker__.modules",
72
+ "Core"
73
+ ],
74
+ "@emailmaker/runtime/disposable": [
75
+ "promise __emailmaker__.modules",
76
+ "Core"
77
+ ],
78
+ "guid": [
79
+ "promise __emailmaker__.modules",
80
+ "Core"
81
+ ],
82
+ "@emailmaker/runtime/guid": [
83
+ "promise __emailmaker__.modules",
84
+ "Core"
85
+ ],
86
+ "app-core": [
87
+ "promise __emailmaker__.modules",
88
+ "Core"
89
+ ],
90
+ "@emailmaker/runtime/app-core": [
91
+ "promise __emailmaker__.modules",
92
+ "Core"
93
+ ]
94
+ }
package/index.js ADDED
@@ -0,0 +1,206 @@
1
+ import { Component as e, Fragment as t, createElement as n, createRef as r, isValidElement as i } from "react";
2
+ import { createComponentIdentifier as a } from "@emailmaker/extensions-app";
3
+ //#region \0rolldown/runtime.js
4
+ var o = Object.defineProperty, s = Object.getOwnPropertyDescriptor, c = Object.getOwnPropertyNames, l = Object.prototype.hasOwnProperty, u = (e, t) => {
5
+ let n = {};
6
+ for (var r in e) o(n, r, {
7
+ get: e[r],
8
+ enumerable: !0
9
+ });
10
+ return t || o(n, Symbol.toStringTag, { value: "Module" }), n;
11
+ }, d = (e, t, n, r) => {
12
+ if (t && typeof t == "object" || typeof t == "function") for (var i = c(t), a = 0, u = i.length, d; a < u; a++) d = i[a], !l.call(e, d) && d !== n && o(e, d, {
13
+ get: ((e) => t[e]).bind(null, d),
14
+ enumerable: !(r = s(t, d)) || r.enumerable
15
+ });
16
+ return e;
17
+ }, f = (e, t, n) => (d(e, t, "default"), n && d(n, t, "default")), p = /* @__PURE__ */ u({});
18
+ import * as m from "@emailmaker/runtime/di";
19
+ f(p, m);
20
+ //#endregion
21
+ //#region packages/extensions-core/components/DomComponentRegistry.ts
22
+ var h = class {
23
+ _factories = /* @__PURE__ */ new Map();
24
+ add(e, t) {
25
+ let n = e;
26
+ return this._factories.set(n, t), { dispose: () => {
27
+ this._factories.get(n) === t && this._factories.delete(n);
28
+ } };
29
+ }
30
+ get(e) {
31
+ return this._factories.get(e);
32
+ }
33
+ }, g = (0, p.createIdentifier)("DomComponentRegistry");
34
+ function _(e, t = g) {
35
+ return p.DependencyResolver.getOrCreateInstance(t, () => new h());
36
+ }
37
+ //#endregion
38
+ //#region packages/extensions-core/components/ComponentRegistry.ts
39
+ function v(e) {
40
+ return typeof e == "function";
41
+ }
42
+ function y(e) {
43
+ return i(e);
44
+ }
45
+ function b(e) {
46
+ return typeof e == "function" || y(e);
47
+ }
48
+ function x(e) {
49
+ return typeof e == "object" && !!e && "type" in e && "props" in e && !y(e);
50
+ }
51
+ function S(e, t) {
52
+ return n(e, t);
53
+ }
54
+ function C(t) {
55
+ return class extends e {
56
+ _ref = r();
57
+ _instance;
58
+ componentDidMount() {
59
+ this._ref.current && (this._instance = t(this.props), this._ref.current.appendChild(this._instance.node));
60
+ }
61
+ componentDidUpdate(e) {
62
+ this._instance?.update && this._instance.update(this.props);
63
+ }
64
+ componentWillUnmount() {
65
+ this._instance?.dispose && this._instance.dispose();
66
+ }
67
+ render() {
68
+ return n("div", { ref: this._ref });
69
+ }
70
+ };
71
+ }
72
+ var w = class {
73
+ _components = /* @__PURE__ */ new Map();
74
+ _domAdapters = /* @__PURE__ */ new Map();
75
+ constructor(e) {
76
+ this._domComponentRegistry = e;
77
+ }
78
+ add(e, t) {
79
+ return this.override(e, () => t);
80
+ }
81
+ addDom(e, t) {
82
+ let n = e;
83
+ this._domAdapters.delete(n);
84
+ let r = this._domComponentRegistry.add(e, t);
85
+ return { dispose: () => {
86
+ this._domAdapters.delete(n), r.dispose();
87
+ } };
88
+ }
89
+ override(e, t) {
90
+ let n = e, r = this._components.get(n);
91
+ r || (r = { replacers: [] }, this._components.set(n, r));
92
+ let i = () => {
93
+ let e = r.replacers.findIndex((e) => e.replacer === t);
94
+ e >= 0 && (r.replacers.splice(e, 1), this._recomputeComponent(n, r));
95
+ };
96
+ return r.replacers.push({
97
+ replacer: t,
98
+ dispose: i
99
+ }), this._recomputeComponent(n, r), { dispose: i };
100
+ }
101
+ _recomputeComponent(e, t) {
102
+ t.component = t.replacers.reduce((e, { replacer: t }) => t(e), void 0);
103
+ }
104
+ get(e) {
105
+ if (b(e)) return e;
106
+ let t = e, n = this._components.get(t);
107
+ if (n?.component) return n.component;
108
+ let r = this._domComponentRegistry.get(e);
109
+ if (r) {
110
+ let e = this._domAdapters.get(t);
111
+ return e || (e = C(r), this._domAdapters.set(t, e)), e;
112
+ }
113
+ }
114
+ _resolveComponentInput(e) {
115
+ if (e == null) return null;
116
+ if (typeof e == "number" || typeof e == "boolean" || y(e)) return e;
117
+ if (typeof e == "string") {
118
+ let t = this.get(e);
119
+ return y(t) ? t : t ? S(t) : e;
120
+ }
121
+ if (v(e)) return S(e);
122
+ if (x(e)) {
123
+ let t = this.get(e.type);
124
+ return y(t) ? t : t ? S(t, e.props) : null;
125
+ }
126
+ return null;
127
+ }
128
+ getReactNode(e) {
129
+ return this._resolveComponentInput(e);
130
+ }
131
+ getReactElement(e) {
132
+ let r = this._resolveComponentInput(e);
133
+ return y(r) ? r : typeof r == "string" || r == null || typeof r == "boolean" || typeof r == "number" ? n(t, null, r) : n(t, null);
134
+ }
135
+ }, T = (0, p.createIdentifier)("ComponentRegistry");
136
+ function E(e, t = T) {
137
+ return p.DependencyResolver.getOrCreateInstance(t, () => new w(_(p.DependencyResolver, g)));
138
+ }
139
+ //#endregion
140
+ //#region src/extensions/react/src/index.ts
141
+ (function(e) {
142
+ if (!(!e || typeof e != "object")) {
143
+ var t = e.__emailmaker__ ||= {}, n = t.__compat ||= {};
144
+ n.host = n.host || null, n.packages = n.packages || {}, n.warned = n.warned || {}, n.normalizeVersion ||= function(e) {
145
+ return String(e || "").split("-")[0] || "0.0.0";
146
+ }, n.parseVersion ||= function(e) {
147
+ var t = n.normalizeVersion(e).split(".");
148
+ return {
149
+ major: parseInt(t[0] || "0", 10),
150
+ minor: parseInt(t[1] || "0", 10),
151
+ patch: parseInt(t[2] || "0", 10)
152
+ };
153
+ }, n.compareVersions ||= function(e, t) {
154
+ var r = n.parseVersion(e), i = n.parseVersion(t);
155
+ return r.major === i.major ? r.minor === i.minor ? r.patch - i.patch : r.minor - i.minor : r.major - i.major;
156
+ }, n.satisfies ||= function(e, t) {
157
+ if (!t || t === "*" || t === "latest") return !0;
158
+ var r = n.normalizeVersion(e), i = String(t || "").trim();
159
+ if (!i) return !0;
160
+ if (i.charAt(0) === "^") {
161
+ var a = n.parseVersion(i.slice(1)), o = n.parseVersion(r);
162
+ return n.compareVersions(r, i.slice(1)) < 0 ? !1 : a.major > 0 ? o.major === a.major : a.minor > 0 ? o.major === 0 && o.minor === a.minor : o.major === 0 && o.minor === 0 && o.patch === a.patch;
163
+ }
164
+ return n.normalizeVersion(r) === n.normalizeVersion(i);
165
+ }, n.warnOnce ||= function(e, t, r) {
166
+ n.warned[e] || (n.warned[e] = !0, console.warn("[compat]", t, r || ""));
167
+ }, n.validateAll ||= function() {
168
+ var e = n.host, t = n.packages || {};
169
+ e && e.supports && Object.keys(t).forEach(function(r) {
170
+ var i = t[r], a = e.supports[r];
171
+ a && !n.satisfies(i.version, a) && n.warnOnce("host:" + r + ":" + i.version + ":" + a, "Host supports a different package version range.", {
172
+ packageId: r,
173
+ packageVersion: i.version,
174
+ supportedRange: a,
175
+ hostVersion: e.version
176
+ });
177
+ }), Object.keys(t).forEach(function(r) {
178
+ var i = t[r], a = i.requires || {};
179
+ Object.keys(a).forEach(function(o) {
180
+ var s = a[o], c = o === "host" ? e && e.version : t[o] && t[o].version;
181
+ c && (n.satisfies(c, s) || n.warnOnce(r + ":" + o + ":" + c + ":" + s, "Loaded package is outside the declared compatibility range.", {
182
+ packageId: r,
183
+ packageVersion: i.version,
184
+ targetId: o,
185
+ targetVersion: c,
186
+ requiredRange: s
187
+ }));
188
+ });
189
+ });
190
+ }, n.registerHost ||= function(e) {
191
+ n.host = e, n.validateAll();
192
+ }, n.registerPackage ||= function(e) {
193
+ n.packages[e.id] = e, n.validateAll();
194
+ }, t.__compat.registerPackage({
195
+ id: "extensions-react",
196
+ version: "0.9.0-dev.1",
197
+ requires: {
198
+ host: "^1.0.105",
199
+ "extensions-api": "^0.9.0"
200
+ }
201
+ });
202
+ }
203
+ })(typeof window < "u" ? window : typeof globalThis < "u" ? globalThis : void 0);
204
+ var D = E(p.DependencyResolver);
205
+ //#endregion
206
+ export { D as ComponentRegistry, a as createComponentIdentifier };
package/package.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "@emailmaker/extensions-react",
3
+ "version": "0.9.0-dev.1",
4
+ "private": false,
5
+ "description": "React adapter for the Emailmaker extensions API.",
6
+ "main": "index.js",
7
+ "types": "types.d.ts",
8
+ "author": "",
9
+ "license": "ISC",
10
+ "peerDependencies": {
11
+ "antd": "5.11.0",
12
+ "react": "18.2.0",
13
+ "react-dom": "18.2.0",
14
+ "@types/react": "18.2.70",
15
+ "@types/react-dom": "18.2.0",
16
+ "@emailmaker/runtime": "0.9.0-dev.1",
17
+ "@emailmaker/extensions-app": "0.9.0-dev.1"
18
+ }
19
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,17 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "es2016",
4
+ "jsx": "react",
5
+ "module": "NodeNext",
6
+ "moduleResolution": "nodenext",
7
+ "allowJs": true,
8
+ "esModuleInterop": true,
9
+ "forceConsistentCasingInFileNames": true,
10
+ "strict": true,
11
+ "skipLibCheck": false,
12
+ "outDir": "dist"
13
+ },
14
+ "files": [
15
+ "types.d.ts"
16
+ ]
17
+ }
package/types.d.ts ADDED
@@ -0,0 +1,65 @@
1
+ import * as React from "react";
2
+ import { ComponentId, ComponentType, IDisposable, createComponentIdentifier } from '@emailmaker/extensions-app';
3
+
4
+ declare module '@emailmaker/extensions-app' {
5
+ interface ComponentInputRegistry<Props = unknown> {
6
+ reactComponent: React.ComponentClass<Props> | React.FunctionComponent<Props>;
7
+ reactElement: React.ReactElement;
8
+ }
9
+ }
10
+ /**
11
+ * Type alias for either a React component type or a React element.
12
+ * @template P The type of the component's props.
13
+ */
14
+ type ReactNode<P> = React.ComponentClass<P> | React.FunctionComponent<P> | React.ReactElement;
15
+ /**
16
+ * Function type for replacing a component with another.
17
+ * @template P The type of the component's props.
18
+ * @param {ReactNode<P> | undefined} base - The original component to be replaced.
19
+ * @returns {ReactNode<P>} The new component replacing the original.
20
+ */
21
+ type ComponentReplacer<P> = (base: ReactNode<P> | undefined) => ReactNode<P>;
22
+ /**
23
+ * Component Registry interface for managing React components dynamically.
24
+ */
25
+ interface IComponentRegistry {
26
+ /**
27
+ * Adds a component to the registry.
28
+ * @template P The type of the component's props.
29
+ * @param {ComponentId<P>} id - The component identifier.
30
+ * @param {ReactNode<P>} component - The component instance.
31
+ * @returns {Disposable} A disposable instance to remove the component.
32
+ */
33
+ add<P>(id: ComponentId<P>, component: ReactNode<P>): IDisposable;
34
+ /**
35
+ * Overrides an existing component with a new replacer function.
36
+ * @template P The type of the component's props.
37
+ * @param {ComponentId<P>} id - The component identifier.
38
+ * @param {ComponentReplacer<P>} replacer - The replacer function.
39
+ * @returns {Disposable} A disposable instance for cleanup.
40
+ */
41
+ override<P>(id: ComponentId<P>, replacer: ComponentReplacer<P>): IDisposable;
42
+ /**
43
+ * Retrieves a registered component by its identifier.
44
+ * @template P The type of the component's props.
45
+ * @param {ComponentId<P> | ReactNode<P>} id - The component identifier or component instance.
46
+ * @returns {ReactNode<P> | undefined} The registered component or undefined if not found.
47
+ */
48
+ get<P>(id: ComponentId<P> | ReactNode<P>): ReactNode<P> | undefined;
49
+ /**
50
+ * Resolves a component into a ReactNode (React component instance or primitive value).
51
+ * @template P The type of the component's props.
52
+ * @param {ComponentType<P> | string | number | boolean | null | undefined} componentTypeObj - The component type object.
53
+ * @returns {React.ReactNode} The resolved React node.
54
+ */
55
+ getReactNode<P>(componentTypeObj: ComponentType<P> | string | number | boolean | null | undefined): React.ReactNode;
56
+ /**
57
+ * Resolves a component into a ReactElement.
58
+ * @template P The type of the component's props.
59
+ * @param {ComponentType<P>} componentTypeObj - The component type object.
60
+ * @returns {React.ReactElement} The resolved React element.
61
+ */
62
+ getReactElement<P>(componentTypeObj: ComponentType<P>): React.ReactElement;
63
+ }
64
+ declare const ComponentRegistry: IComponentRegistry;
65
+ export { ComponentRegistry, ComponentReplacer, IComponentRegistry, createComponentIdentifier };