@emailmaker/extensions-app 1.0.111-dev.7 → 1.0.111-dev.9
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 +143 -56
- package/index.js +60 -22
- package/package.json +2 -2
- package/types.d.ts +27 -6
package/README.md
CHANGED
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
## ⚙️ Требования
|
|
16
16
|
|
|
17
17
|
- Современный браузер с поддержкой **ES2015** (и выше)
|
|
18
|
-
- Node.js >=
|
|
19
|
-
- React и Ant Design подключаются через
|
|
18
|
+
- Node.js >= 20 (рекомендуется LTS; CLI-шаблон использует `tsx` и Vite/Webpack 5)
|
|
19
|
+
- React и Ant Design в плагине подключаются через `PluginDev` (alias/externals на runtime хоста из `@emailmaker/emailmaker/runtime/*`), а не отдельным npm-пакетом runtime
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
---
|
|
@@ -33,21 +33,39 @@
|
|
|
33
33
|
|
|
34
34
|
## 🔰 Быстрый старт
|
|
35
35
|
|
|
36
|
-
👉
|
|
36
|
+
👉 Рекомендуемый способ — **CLI** (`@emailmaker/cli`): согласованная структура, Vite/Webpack, app + sandbox, dev/release host.
|
|
37
37
|
|
|
38
38
|
```bash
|
|
39
|
-
|
|
40
|
-
cd
|
|
39
|
+
npx @emailmaker/cli my-plugin --kind plugin --preset advanced --bundler vite --target npm-package --output-dir ./my-plugin
|
|
40
|
+
cd my-plugin
|
|
41
41
|
npm install
|
|
42
42
|
npm run start
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
- Webpack / Vite
|
|
45
|
+
Сгенерированный проект включает:
|
|
46
|
+
- Webpack / Vite (по выбору)
|
|
47
47
|
- React + Ant Design
|
|
48
48
|
- TypeScript
|
|
49
49
|
- Структуру проекта, описанную ниже
|
|
50
50
|
|
|
51
|
+
Проверка release-сборки без ручного деплоя:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
npm run build
|
|
55
|
+
npm run start:release
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Альтернатива: пример из репозитория
|
|
59
|
+
|
|
60
|
+
[Готовый example](https://github.com/emailmaker/simple_plugin) можно клонировать для ознакомления; для новых плагинов предпочтительнее CLI-шаблон.
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
git clone https://github.com/emailmaker/simple_plugin
|
|
64
|
+
cd simple_plugin
|
|
65
|
+
npm install
|
|
66
|
+
npm run start
|
|
67
|
+
```
|
|
68
|
+
|
|
51
69
|
|
|
52
70
|
---
|
|
53
71
|
|
|
@@ -56,18 +74,19 @@ npm run start
|
|
|
56
74
|
### 📦 Основные пакеты
|
|
57
75
|
|
|
58
76
|
```bash
|
|
59
|
-
npm install @emailmaker/emailmaker @emailmaker/
|
|
77
|
+
npm install @emailmaker/emailmaker @emailmaker/extensions-app @emailmaker/extensions-react @emailmaker/extensions-sandbox
|
|
60
78
|
```
|
|
61
79
|
|
|
62
80
|
| Пакет | Назначение | Что экспортирует |
|
|
63
81
|
|-------|------------|------------------|
|
|
64
|
-
| `@emailmaker/emailmaker` | Основной пакет | `init()`, `prefetch()`, типы `IPlugin`, `Instance
|
|
65
|
-
| `@emailmaker/emailmaker/runtime` | Общие зависимости | React, ReactDOM, Ant Design и связанные модули |
|
|
82
|
+
| `@emailmaker/emailmaker` | Основной пакет | `init()`, `prefetch()`, типы `IPlugin`, `Instance`; runtime React/Ant Design — subpath `@emailmaker/emailmaker/runtime/*` (отдельный npm не нужен) |
|
|
66
83
|
| `@emailmaker/extensions-app` | API для app-плагинов | `pluginRegistry`, `DomComponentRegistry`, `ElementsApi`, `SettingsPanelApi`, `ModalApi` |
|
|
67
84
|
| `@emailmaker/extensions-react` | React API для плагинов | `ComponentRegistry`, `createComponentIdentifier()` |
|
|
68
85
|
| `@emailmaker/extensions-sandbox` | API для sandbox-плагинов | `App`, `MessageService`, `SyncService` |
|
|
69
86
|
|
|
70
|
-
`@emailmaker/ui-kit` ставится
|
|
87
|
+
`@emailmaker/ui-kit` ставится отдельно (devDependency в CLI-шаблоне), если плагин использует готовые UI-компоненты платформы.
|
|
88
|
+
|
|
89
|
+
> React и Ant Design в коде плагина импортируются как `react` / `antd`. `PluginDev` в dev/release подставляет runtime хоста через alias/externals — см. раздел «Сборка плагина».
|
|
71
90
|
|
|
72
91
|
### Импорты
|
|
73
92
|
|
|
@@ -93,8 +112,8 @@ import type { IPlugin, Instance } from '@emailmaker/emailmaker';
|
|
|
93
112
|
## Что обычно ставить
|
|
94
113
|
|
|
95
114
|
- если у вас обычный React-плагин, ставьте все пакеты из команды выше
|
|
96
|
-
- если используете UI Kit, добавьте
|
|
97
|
-
- если пишете только sandbox-часть,
|
|
115
|
+
- если используете UI Kit, добавьте ещё `@emailmaker/ui-kit`
|
|
116
|
+
- если пишете только sandbox-часть, достаточно main + `@emailmaker/extensions-sandbox`
|
|
98
117
|
|
|
99
118
|
> Для React-плагинов пакет `@emailmaker/extensions-react` нужен по умолчанию.
|
|
100
119
|
|
|
@@ -198,7 +217,7 @@ module.exports = {
|
|
|
198
217
|
|
|
199
218
|
Если release bundle неожиданно стал толстым или target `встраиваемый bundle` не загружается, начните с раздела `Troubleshooting`.
|
|
200
219
|
|
|
201
|
-
Типы для плагина всё равно собираются отдельно: CLI-шаблон запускает `build:types` и кладёт `dist/
|
|
220
|
+
Типы для плагина всё равно собираются отдельно: CLI-шаблон запускает `build:types` и кладёт `dist/public-types.d.ts` рядом с JS bundle, поэтому TypeScript support сохраняется и для browser/advanced targets.
|
|
202
221
|
|
|
203
222
|
### tsconfig.json
|
|
204
223
|
|
|
@@ -273,27 +292,35 @@ emailmaker.init({
|
|
|
273
292
|
|
|
274
293
|
## 📁 Структура проекта
|
|
275
294
|
|
|
295
|
+
CLI-шаблон (типичный layout):
|
|
296
|
+
|
|
276
297
|
```txt
|
|
277
|
-
plugin
|
|
278
|
-
├──
|
|
279
|
-
│
|
|
280
|
-
|
|
281
|
-
│
|
|
282
|
-
|
|
283
|
-
│
|
|
284
|
-
|
|
298
|
+
my-plugin/
|
|
299
|
+
├── src/
|
|
300
|
+
│ ├── app/ # UI-часть, взаимодействие с редактором
|
|
301
|
+
│ │ └── MyPlugin.tsx
|
|
302
|
+
│ ├── sandbox/ # Скрипт для DOM письма (отдельная сборка)
|
|
303
|
+
│ │ └── index.ts
|
|
304
|
+
│ ├── dev.tsx # Локальный debug host (редактор + плагин)
|
|
305
|
+
│ └── public-types.d.ts # Типы плагина для npm / augmentation
|
|
306
|
+
├── config/ # Vite/Webpack: dev host, release, sandbox
|
|
307
|
+
├── scripts/ # dev-runner, build-runner, release-runner, build-types
|
|
308
|
+
├── dist/ # Сборка app-плагина (+ public-types.d.ts)
|
|
309
|
+
└── package.json
|
|
285
310
|
```
|
|
286
311
|
|
|
287
|
-
-
|
|
288
|
-
- `app` — точка входа, из которой можно подключить скрипт sandbox:
|
|
312
|
+
- **`src/app`** — регистрация плагина, панели, работа с API редактора. Отсюда подключается sandbox:
|
|
289
313
|
|
|
290
314
|
```ts
|
|
291
315
|
const sandboxApi = this.editor.use('SandboxScriptApi');
|
|
292
316
|
sandboxApi.registerSandboxScript(this.options.publicPath + 'sandbox.js');
|
|
293
317
|
```
|
|
294
318
|
|
|
295
|
-
-
|
|
296
|
-
-
|
|
319
|
+
- **`src/sandbox`** — код в iframe; собирается отдельным entry (`build:sandbox`), без React.
|
|
320
|
+
- **`src/dev.tsx`** — локальный запуск `emailmaker` с плагином (`npm run start`).
|
|
321
|
+
- **`src/public-types.d.ts`** — `PluginTypeMap`, `Config`, опции; после `npm run build:types` копируется в `dist/public-types.d.ts`.
|
|
322
|
+
|
|
323
|
+
Общие идентификаторы событий app ↔ sandbox держите в `src/interfaces/` (или аналогичном shared-модуле внутри `src/`).
|
|
297
324
|
|
|
298
325
|
|
|
299
326
|
---
|
|
@@ -341,6 +368,24 @@ class TestPlugin implements IPlugin {
|
|
|
341
368
|
}
|
|
342
369
|
```
|
|
343
370
|
|
|
371
|
+
### Sandbox-часть
|
|
372
|
+
|
|
373
|
+
Скрипт в iframe (`@emailmaker/extensions-sandbox`) использует **упрощённый** lifecycle — без `required()`:
|
|
374
|
+
|
|
375
|
+
```ts
|
|
376
|
+
import { App } from '@emailmaker/extensions-sandbox';
|
|
377
|
+
import type { IPlugin } from '@emailmaker/extensions-sandbox';
|
|
378
|
+
|
|
379
|
+
class MyPluginSandbox implements IPlugin {
|
|
380
|
+
init() { /* ... */ }
|
|
381
|
+
afterInit?() { /* ... */ }
|
|
382
|
+
dispose() { /* ... */ }
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
App.registerPlugin('MyPluginSandbox', MyPluginSandbox);
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
|
|
344
389
|
|
|
345
390
|
---
|
|
346
391
|
|
|
@@ -493,10 +538,15 @@ elementsApi.insert({
|
|
|
493
538
|
Добавление новой панели настроек. Например, можно добавить панель которая будет отображаться при клике на элементе в sandbox.
|
|
494
539
|
|
|
495
540
|
```ts
|
|
541
|
+
import { createComponentIdentifier } from '@emailmaker/extensions-app';
|
|
542
|
+
|
|
543
|
+
const SettingsPanelId = createComponentIdentifier('MySettingsPanel');
|
|
544
|
+
// ComponentRegistry.add(SettingsPanelId, MySettingsPanel);
|
|
545
|
+
|
|
496
546
|
const panel = editor.use('SettingsPanelApi');
|
|
497
547
|
panel.showSettingsPanel({
|
|
498
548
|
content: {
|
|
499
|
-
type:
|
|
549
|
+
type: SettingsPanelId,
|
|
500
550
|
props: {...}
|
|
501
551
|
},
|
|
502
552
|
caption: 'Настройки',
|
|
@@ -513,7 +563,7 @@ panel.showSettingsPanel({
|
|
|
513
563
|
```ts
|
|
514
564
|
panel.showSettingsPanel({
|
|
515
565
|
instanceKey: blockUuid,
|
|
516
|
-
content: { type:
|
|
566
|
+
content: { type: SettingsPanelId, props: { blockUuid, settings } },
|
|
517
567
|
});
|
|
518
568
|
```
|
|
519
569
|
|
|
@@ -531,20 +581,30 @@ panel.showSettingsPanel({
|
|
|
531
581
|
> Интерфейс основан на модалках `Ant Design`
|
|
532
582
|
|
|
533
583
|
```ts
|
|
584
|
+
import { createComponentIdentifier } from '@emailmaker/extensions-app';
|
|
585
|
+
import { ComponentRegistry } from '@emailmaker/extensions-react';
|
|
586
|
+
|
|
587
|
+
const MyPanelId = createComponentIdentifier('MyPanel');
|
|
588
|
+
ComponentRegistry.add(MyPanelId, MyPanel);
|
|
589
|
+
|
|
534
590
|
const modal = editor.use('ModalApi');
|
|
535
591
|
modal.show({
|
|
536
592
|
title: 'Выбор группы',
|
|
537
593
|
content: {
|
|
538
|
-
type:
|
|
539
|
-
props: { groups, settings }
|
|
540
|
-
}
|
|
594
|
+
type: MyPanelId,
|
|
595
|
+
props: { groups, settings },
|
|
596
|
+
},
|
|
541
597
|
});
|
|
542
598
|
```
|
|
543
599
|
|
|
600
|
+
Для простого UI можно передать JSX напрямую (см. раздел `extensions-react`).
|
|
601
|
+
|
|
544
602
|
|
|
545
603
|
### EmailSettingsApi
|
|
546
604
|
|
|
547
|
-
> API для работы с настройками
|
|
605
|
+
> API для работы с настройками письма (редактор email / emailmaker). В widget-сценариях может быть недоступен.
|
|
606
|
+
|
|
607
|
+
Позволяет получать и изменять настройки внешнего вида письма и стили элементов контента.
|
|
548
608
|
|
|
549
609
|
API разделен на два типа методов:
|
|
550
610
|
- **Layout Settings** — настройки письма целиком (фон, ширина, адаптивность)
|
|
@@ -605,18 +665,25 @@ msg.send('MY_EVENT', { value: 123 });
|
|
|
605
665
|
msg.addListener('MY_EVENT', (data) => console.log(data));
|
|
606
666
|
```
|
|
607
667
|
|
|
608
|
-
|
|
668
|
+
Выносите имена событий в общий модуль (CLI-шаблон: `src/interfaces/`), чтобы app и sandbox использовали одни и те же строки:
|
|
669
|
+
|
|
670
|
+
```ts
|
|
671
|
+
// src/interfaces/messages.ts
|
|
672
|
+
export const MY_PLUGIN_UPDATE = 'my-plugin:update' as const;
|
|
673
|
+
|
|
674
|
+
export type MyPluginUpdatePayload = { text: string };
|
|
675
|
+
```
|
|
609
676
|
|
|
610
677
|
```ts
|
|
611
|
-
|
|
678
|
+
// app
|
|
679
|
+
msg.send(MY_PLUGIN_UPDATE, { text: 'hello' });
|
|
612
680
|
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
void,
|
|
616
|
-
void
|
|
617
|
-
>('Activate_Product_Settings');
|
|
681
|
+
// sandbox
|
|
682
|
+
messageService.addListener(MY_PLUGIN_UPDATE, (data) => { /* ... */ });
|
|
618
683
|
```
|
|
619
684
|
|
|
685
|
+
Тип payload задайте рядом с константой (`MyPluginUpdatePayload`) — отдельный runtime-пакет для идентификаторов не нужен.
|
|
686
|
+
|
|
620
687
|
|
|
621
688
|
### SandboxScriptApi
|
|
622
689
|
|
|
@@ -706,14 +773,17 @@ syncService.commit();
|
|
|
706
773
|
|
|
707
774
|
## 🧱 Регистрация UI компонентов
|
|
708
775
|
|
|
709
|
-
`ComponentRegistry` нужен, когда вы хотите зарегистрировать React-компонент и потом передавать его в API по идентификатору:
|
|
776
|
+
`ComponentRegistry` нужен, когда вы хотите зарегистрировать React-компонент и потом передавать его в API по **типизированному** идентификатору:
|
|
710
777
|
|
|
711
778
|
```ts
|
|
779
|
+
import { createComponentIdentifier } from '@emailmaker/extensions-app';
|
|
712
780
|
import { ComponentRegistry } from '@emailmaker/extensions-react';
|
|
713
781
|
|
|
714
|
-
|
|
782
|
+
const MyPanelId = createComponentIdentifier<{ groups: Group[] }>('MyPanel');
|
|
715
783
|
|
|
716
|
-
ComponentRegistry.
|
|
784
|
+
ComponentRegistry.add(MyPanelId, MyReactPanel);
|
|
785
|
+
|
|
786
|
+
ComponentRegistry.override(MyPanelId, (Base) => (props) => (
|
|
717
787
|
<div className="bordered"><Base {...props} /></div>
|
|
718
788
|
));
|
|
719
789
|
```
|
|
@@ -721,7 +791,7 @@ ComponentRegistry.override('MyPanel', (Base) => (props) => (
|
|
|
721
791
|
## Когда использовать
|
|
722
792
|
|
|
723
793
|
- если хотите просто показать React UI, чаще всего удобнее передать JSX напрямую
|
|
724
|
-
- если нужен `ComponentId
|
|
794
|
+
- если нужен стабильный `ComponentId` для `{ type, props }` — `createComponentIdentifier` + `ComponentRegistry`
|
|
725
795
|
- если UI без React, используйте `DomComponentRegistry`
|
|
726
796
|
|
|
727
797
|
Пример с JSX:
|
|
@@ -735,11 +805,21 @@ settingsPanel.showSettingsPanel({
|
|
|
735
805
|
});
|
|
736
806
|
```
|
|
737
807
|
|
|
808
|
+
Пример с идентификатором:
|
|
809
|
+
|
|
810
|
+
```ts
|
|
811
|
+
settingsPanel.showSettingsPanel({
|
|
812
|
+
content: { type: MyPanelId, props: { groups } },
|
|
813
|
+
});
|
|
814
|
+
```
|
|
815
|
+
|
|
738
816
|
|
|
739
817
|
---
|
|
740
818
|
|
|
741
819
|
## 🎨 UI Kit
|
|
742
820
|
|
|
821
|
+
В **коде плагина** импортируйте компоненты из `@emailmaker/ui-kit`. В **release-сборке** `PluginDev` externalizes ui-kit на singleton хоста: `@emailmaker/emailmaker/ui-kit` (отдельно ставить main subpath не нужно).
|
|
822
|
+
|
|
743
823
|
### ColorPicker — минимальный пример
|
|
744
824
|
|
|
745
825
|
Растягивается на ширину родителя (Form.Item, колонку и т.д.) — дополнительный inline-style для ширины не нужен.
|
|
@@ -893,7 +973,7 @@ emailmaker.init({
|
|
|
893
973
|
|
|
894
974
|
> При множественной инициализации действует принцип «first-write wins» — опции фиксируются при первом создании экземпляра.
|
|
895
975
|
|
|
896
|
-
CLI-шаблон уже собирает типы отдельно (`npm run build:types`) и публикует `dist/
|
|
976
|
+
CLI-шаблон уже собирает типы отдельно (`npm run build:types`) и публикует `dist/public-types.d.ts` рядом с JS bundle, поэтому поддержку TypeScript стоит считать частью любого release target, а не только npm/ESM сценария.
|
|
897
977
|
|
|
898
978
|
### Расширение Config
|
|
899
979
|
|
|
@@ -940,7 +1020,7 @@ settingsPanel.showSettingsPanel({
|
|
|
940
1020
|
|
|
941
1021
|
### `--dev` / `--dev-packages`
|
|
942
1022
|
|
|
943
|
-
**Самый частый флаг для разработки:** подставляет **dev**-версии внутренних npm-пакетов (`@emailmaker/*`), которые в шаблонах задаются с dist-tag `dev` вместо `latest`. Используйте, когда нужны свежие предрелизные сборки экосистемы.
|
|
1023
|
+
**Самый частый флаг для разработки:** подставляет **dev**-версии внутренних npm-пакетов (`@emailmaker-internal/*`), которые в шаблонах задаются с dist-tag `dev` вместо `latest`. Используйте, когда нужны свежие предрелизные сборки экосистемы.
|
|
944
1024
|
|
|
945
1025
|
```bash
|
|
946
1026
|
npx @emailmaker/cli my-plugin --kind plugin --preset advanced --bundler vite --target npm-package --dev --output-dir ./my-plugin
|
|
@@ -959,8 +1039,8 @@ npx @emailmaker/cli my-plugin --kind plugin --preset advanced --bundler vite --t
|
|
|
959
1039
|
| `--advanced-profile` | Для `--stand-mode advanced`: `subpath`, `shadow-dom`, `umd`. |
|
|
960
1040
|
| `--preset` | Шаблон плагина: `minimal` или `advanced`. |
|
|
961
1041
|
| `--bundler` | `vite` или `webpack` — сборщик в шаблоне. |
|
|
962
|
-
| `--target` | Поставка плагина: `npm-package`, `browser`, `advanced
|
|
963
|
-
| `--advanced-target` |
|
|
1042
|
+
| `--target` | Поставка плагина: `npm-package`, `browser`, `advanced` (**`advanced` — только webpack**; у Vite доступны `npm-package` и `browser`). |
|
|
1043
|
+
| `--advanced-target` | Для `--target advanced` (только webpack): `async-globals` или `legacy-async-globals`. |
|
|
964
1044
|
| `--app` | Идентификатор приложения (`REACT_APP_NAME`), как в монорепозитории; в опубликованном CLI может быть скрыт. |
|
|
965
1045
|
| `--output-dir` | Каталог, куда положить сгенерированный проект. |
|
|
966
1046
|
| `--output-base` | Базовый каталог: внутри него будет создана папка проекта. |
|
|
@@ -977,7 +1057,7 @@ npx @emailmaker/cli --help
|
|
|
977
1057
|
- интерактивный wizard и неинтерактивный запуск;
|
|
978
1058
|
- генерация проекта плагина и демо-стендов;
|
|
979
1059
|
- шаблоны под **vite** и **webpack**;
|
|
980
|
-
- выбор способа поставки плагина: npm-модуль, браузерный
|
|
1060
|
+
- выбор способа поставки плагина: npm-модуль, браузерный bundle (`browser`), режим **advanced** (webpack-only).
|
|
981
1061
|
|
|
982
1062
|
## Основные режимы
|
|
983
1063
|
|
|
@@ -1035,7 +1115,14 @@ npx @emailmaker/cli my-plugin --kind plugin --preset advanced --bundler vite --t
|
|
|
1035
1115
|
|
|
1036
1116
|
Обычно это значит, что dev host использует `PluginDev({ externals: false })`, а release target уже требует runtime contract.
|
|
1037
1117
|
|
|
1038
|
-
|
|
1118
|
+
Проверьте локально через CLI-шаблон:
|
|
1119
|
+
|
|
1120
|
+
```bash
|
|
1121
|
+
npm run build
|
|
1122
|
+
npm run start:release
|
|
1123
|
+
```
|
|
1124
|
+
|
|
1125
|
+
Также проверьте:
|
|
1039
1126
|
|
|
1040
1127
|
- target сборки в CLI / config
|
|
1041
1128
|
- release config для `src/index.ts`
|
|
@@ -1080,20 +1167,20 @@ npx @emailmaker/cli my-plugin --kind plugin --preset advanced --bundler vite --t
|
|
|
1080
1167
|
- **Externals не работают в dev server**
|
|
1081
1168
|
> В serve-режиме externals должны быть отключены: `PluginDev({ externals: false })`. Зависимости резолвятся из runtime через alias.
|
|
1082
1169
|
|
|
1083
|
-
- **ESM output не грузится через `<script>`**
|
|
1084
|
-
> ESM-сборка содержит `import
|
|
1170
|
+
- **ESM output не грузится через обычный `<script>`**
|
|
1171
|
+
> ESM-сборка содержит `import`. Используйте `<script type="module">`, npm-интеграцию или target **browser** (`PluginDev({ externals: 'globals' })`, UMD bundle).
|
|
1085
1172
|
|
|
1086
|
-
- **
|
|
1087
|
-
> Runtime должен быть загружен до плагина. Подключайте
|
|
1173
|
+
- **Browser/UMD-плагин: «Cannot read property of undefined»**
|
|
1174
|
+
> Runtime хоста должен быть загружен до плагина. Подключайте через npm + lazy import, либо декларативно `{ type: 'umd', url: '…', name: 'MyPlugin', resolve: 'registry' }` (с `pluginRegistry.add`).
|
|
1088
1175
|
|
|
1089
1176
|
- **Не загружаются JS/CSS / iframe не отображается**
|
|
1090
1177
|
> Проверьте `publicPath` и подключение основного плагина (`VitePlugin` / `WebpackPlugin`). В serve-режиме он обслуживает статику из `node_modules/`.
|
|
1091
1178
|
|
|
1092
1179
|
- **Панель или компонент не отображается**
|
|
1093
|
-
> Убедитесь в регистрации через `ComponentRegistry`.
|
|
1180
|
+
> Убедитесь в регистрации через `ComponentRegistry` и `createComponentIdentifier`.
|
|
1094
1181
|
|
|
1095
1182
|
- **Событие не обрабатывается**
|
|
1096
|
-
> Проверьте подписку на событие в `MessageService
|
|
1183
|
+
> Проверьте подписку на событие в `MessageService` и совпадение строковых id в app и sandbox.
|
|
1097
1184
|
|
|
1098
1185
|
- **Изменения в iframe теряются**
|
|
1099
1186
|
> Не забывайте вызывать `syncService.commit()`.
|
|
@@ -1104,7 +1191,7 @@ npx @emailmaker/cli my-plugin --kind plugin --preset advanced --bundler vite --t
|
|
|
1104
1191
|
|
|
1105
1192
|
**С `externals.json` на `PluginDev`:**
|
|
1106
1193
|
|
|
1107
|
-
|
|
1194
|
+
Для **новых** проектов используйте только `PluginDev`. Файл `externals.json` в экосистеме остаётся legacy-следом; не подключайте его вручную в Vite-шаблонах.
|
|
1108
1195
|
|
|
1109
1196
|
**С `pluginRegistry.add` на прямой класс:**
|
|
1110
1197
|
|
package/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import "react";
|
|
1
2
|
//#region packages/runtime-core/disposable/index.ts
|
|
2
3
|
var e = class e {
|
|
3
4
|
_isDisposed = !1;
|
|
@@ -400,6 +401,43 @@ function w(e = c()) {
|
|
|
400
401
|
}
|
|
401
402
|
var T = new y(() => w());
|
|
402
403
|
//#endregion
|
|
404
|
+
//#region packages/extensions-core/identifiers/index.ts
|
|
405
|
+
function E(e) {
|
|
406
|
+
return u(e);
|
|
407
|
+
}
|
|
408
|
+
E("HANDLE_ATOM_INSERT"), E("SETTINGS_PANEL_EVENT"), E("MODAL_SHOW_EVENT"), E("MODAL_CLOSE_EVENT"), E("MODAL_UPDATE_EVENT");
|
|
409
|
+
//#endregion
|
|
410
|
+
//#region packages/extensions-core/utils/blockInjectInfo.ts
|
|
411
|
+
function D(e) {
|
|
412
|
+
if (e.meta !== void 0 && e.meta !== null && typeof e.meta == "object") return e.meta;
|
|
413
|
+
let t = e.catalogExtra?.meta;
|
|
414
|
+
if (typeof t == "object" && t) return t;
|
|
415
|
+
}
|
|
416
|
+
function O(e, t) {
|
|
417
|
+
let n = e.insertFrom ?? t?.type, r = t?.blockId ?? (e.id != null && e.id !== "" ? String(e.id) : void 0), i = t?.project ?? (e.project !== void 0 && e.project !== null ? String(e.project) : void 0);
|
|
418
|
+
return {
|
|
419
|
+
type: t?.type ?? n,
|
|
420
|
+
insertFrom: n,
|
|
421
|
+
name: t?.name ?? e.name,
|
|
422
|
+
blockId: r,
|
|
423
|
+
project: i,
|
|
424
|
+
fragmentRole: e.fragmentRole,
|
|
425
|
+
id: r,
|
|
426
|
+
title: e.title ?? void 0,
|
|
427
|
+
blockType: e.type,
|
|
428
|
+
meta: D(e)
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
function k(e, t) {
|
|
432
|
+
return t ? O(t, e) : {
|
|
433
|
+
type: e.type,
|
|
434
|
+
name: e.name,
|
|
435
|
+
blockId: e.blockId,
|
|
436
|
+
project: e.project,
|
|
437
|
+
insertFrom: e.type
|
|
438
|
+
};
|
|
439
|
+
}
|
|
440
|
+
//#endregion
|
|
403
441
|
//#region src/extensions/api/src/index.ts
|
|
404
442
|
(function(e) {
|
|
405
443
|
if (!(!e || typeof e != "object")) {
|
|
@@ -456,12 +494,12 @@ var T = new y(() => w());
|
|
|
456
494
|
n.packages[e.id] = e, n.validateAll();
|
|
457
495
|
}, t.__compat.registerPackage({
|
|
458
496
|
id: "extensions-api",
|
|
459
|
-
version: "1.0.111-dev.
|
|
497
|
+
version: "1.0.111-dev.9",
|
|
460
498
|
requires: { host: "^1.0.105" }
|
|
461
499
|
});
|
|
462
500
|
}
|
|
463
501
|
})(typeof window < "u" ? window : typeof globalThis < "u" ? globalThis : void 0);
|
|
464
|
-
function
|
|
502
|
+
function A(e, t, n, r) {
|
|
465
503
|
if (typeof r.value == "function") {
|
|
466
504
|
Object.defineProperty(e, n, {
|
|
467
505
|
value: r.value.bind(t),
|
|
@@ -489,50 +527,50 @@ function E(e, t, n, r) {
|
|
|
489
527
|
enumerable: !1
|
|
490
528
|
});
|
|
491
529
|
}
|
|
492
|
-
function
|
|
530
|
+
function j(e, t, n) {
|
|
493
531
|
let r = t.use(n), i = /* @__PURE__ */ new Set(), a = [r];
|
|
494
532
|
for (let e = Object.getPrototypeOf(r); e && e !== Object.prototype; e = Object.getPrototypeOf(e)) a.push(e);
|
|
495
533
|
for (let t of a) for (let n of Reflect.ownKeys(t)) {
|
|
496
534
|
if (n === "constructor" || i.has(n)) continue;
|
|
497
535
|
let a = Object.getOwnPropertyDescriptor(t, n);
|
|
498
|
-
a && (i.add(n),
|
|
536
|
+
a && (i.add(n), A(e, r, n, a));
|
|
499
537
|
}
|
|
500
538
|
}
|
|
501
|
-
function
|
|
539
|
+
function M() {
|
|
502
540
|
return typeof globalThis.crypto?.randomUUID == "function" ? globalThis.crypto.randomUUID() : `component-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
|
|
503
541
|
}
|
|
504
|
-
var
|
|
542
|
+
var N = class {
|
|
505
543
|
constructor(e) {
|
|
506
|
-
|
|
544
|
+
j(this, e, "SandboxScriptApi");
|
|
507
545
|
}
|
|
508
|
-
},
|
|
546
|
+
}, P = class {
|
|
509
547
|
constructor(e) {
|
|
510
|
-
|
|
548
|
+
j(this, e, "ElementsApi");
|
|
511
549
|
}
|
|
512
|
-
},
|
|
550
|
+
}, F = class {
|
|
513
551
|
constructor(e) {
|
|
514
|
-
|
|
552
|
+
j(this, e, "BlocksApi");
|
|
515
553
|
}
|
|
516
|
-
},
|
|
554
|
+
}, I = class {
|
|
517
555
|
constructor(e) {
|
|
518
|
-
|
|
556
|
+
j(this, e, "MessageService");
|
|
519
557
|
}
|
|
520
|
-
},
|
|
558
|
+
}, L = class {
|
|
521
559
|
constructor(e) {
|
|
522
|
-
|
|
560
|
+
j(this, e, "SettingsPanelApi");
|
|
523
561
|
}
|
|
524
|
-
},
|
|
562
|
+
}, R = class {
|
|
525
563
|
constructor(e) {
|
|
526
|
-
|
|
564
|
+
j(this, e, "ModalApi");
|
|
527
565
|
}
|
|
528
|
-
},
|
|
566
|
+
}, z = class {
|
|
529
567
|
constructor(e) {
|
|
530
|
-
|
|
568
|
+
j(this, e, "EmailSettingsApi");
|
|
531
569
|
}
|
|
532
570
|
};
|
|
533
|
-
function
|
|
571
|
+
function B(e = M()) {
|
|
534
572
|
return e;
|
|
535
573
|
}
|
|
536
|
-
var
|
|
574
|
+
var V = S(_), H = "1.0.111-dev.9";
|
|
537
575
|
//#endregion
|
|
538
|
-
export {
|
|
576
|
+
export { F as BlocksApi, V as DomComponentRegistry, P as ElementsApi, z as EmailSettingsApi, I as MessageService, R as ModalApi, N as SandboxScriptApi, L as SettingsPanelApi, O as blockInsertContextToInjectInfo, B as createComponentIdentifier, k as mergeBlockInjectAck, T as pluginRegistry, H as version };
|
package/package.json
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "types.d.ts",
|
|
7
7
|
"name": "@emailmaker/extensions-app",
|
|
8
|
-
"version": "1.0.111-dev.
|
|
8
|
+
"version": "1.0.111-dev.9",
|
|
9
9
|
"dependencies": {
|
|
10
|
-
"@emailmaker/emailmaker": "1.0.111-dev.
|
|
10
|
+
"@emailmaker/emailmaker": "1.0.111-dev.9"
|
|
11
11
|
}
|
|
12
12
|
}
|
package/types.d.ts
CHANGED
|
@@ -53,11 +53,22 @@ interface IDisposable$1 {
|
|
|
53
53
|
* Payload for `BlocksApi.handleInject` when a block/structure was inserted in the sandbox
|
|
54
54
|
* (mirrors `application_block_inserted` message data).
|
|
55
55
|
*/
|
|
56
|
-
interface BlockInjectInfo {
|
|
56
|
+
interface BlockInjectInfo$1 {
|
|
57
|
+
/** Editor catalog route (project / template / common / structure path) — same as legacy iframe `type`. */
|
|
57
58
|
type?: string;
|
|
59
|
+
/** Alias of {@link type} when enriched on the app side. */
|
|
60
|
+
insertFrom?: string;
|
|
58
61
|
name?: string;
|
|
59
62
|
blockId?: string;
|
|
60
63
|
project?: string;
|
|
64
|
+
fragmentRole?: 'block' | 'structure';
|
|
65
|
+
/** Catalog block id (same as {@link blockId} when known). */
|
|
66
|
+
id?: string;
|
|
67
|
+
title?: string | null;
|
|
68
|
+
/** REST / API block taxonomy — not the same as {@link type}. */
|
|
69
|
+
blockType?: string;
|
|
70
|
+
/** Host-only metadata (`Block.meta` / `setBlockMeta` on the embedder side). */
|
|
71
|
+
meta?: Record<string, unknown>;
|
|
61
72
|
}
|
|
62
73
|
/**
|
|
63
74
|
* Context passed to ElementsApi.handleBeforeInject before element (atom) HTML is sent to the iframe.
|
|
@@ -72,7 +83,7 @@ interface ElementInsertContext extends Record<string, unknown> {
|
|
|
72
83
|
* Context passed to BlocksApi.handleBeforeInject before block HTML is sent to the iframe.
|
|
73
84
|
* `insertFrom` is the editor catalog route (e.g. project / template / common), not REST Block.type taxonomy.
|
|
74
85
|
*/
|
|
75
|
-
interface BlockInsertContext extends Record<string, unknown> {
|
|
86
|
+
interface BlockInsertContext$1 extends Record<string, unknown> {
|
|
76
87
|
html: string;
|
|
77
88
|
insertFrom?: string;
|
|
78
89
|
fragmentRole?: 'block' | 'structure';
|
|
@@ -106,6 +117,8 @@ interface BlockInsertContext extends Record<string, unknown> {
|
|
|
106
117
|
project_title?: string;
|
|
107
118
|
project_author?: string;
|
|
108
119
|
isAmp?: boolean;
|
|
120
|
+
/** Host-only metadata (not sent to iframe). */
|
|
121
|
+
meta?: Record<string, unknown>;
|
|
109
122
|
/** Remaining catalog/API fields not mapped above (shallow copy). */
|
|
110
123
|
catalogExtra?: Record<string, unknown>;
|
|
111
124
|
}
|
|
@@ -117,12 +130,14 @@ interface IBlocksApi {
|
|
|
117
130
|
* Runs before block HTML is posted to the iframe. Listeners receive a mutable context; they may
|
|
118
131
|
* mutate `html` and related fields or return a partial object to merge (SaveEmitter-style).
|
|
119
132
|
*/
|
|
120
|
-
handleBeforeInject(listener: (ctx: BlockInsertContext) => MayBePromise$1<Partial<BlockInsertContext> | void>, priority?: number, thisArg?: unknown): IDisposable$1;
|
|
133
|
+
handleBeforeInject(listener: (ctx: BlockInsertContext$1) => MayBePromise$1<Partial<BlockInsertContext$1> | void>, priority?: number, thisArg?: unknown): IDisposable$1;
|
|
121
134
|
/**
|
|
122
|
-
* Fires after a block or structure was inserted in the sandbox
|
|
135
|
+
* Fires after a block or structure was inserted in the sandbox.
|
|
136
|
+
* Payload is enriched on the app shell (incl. `meta`, `insertFrom`, `blockType`) from pending insert context;
|
|
137
|
+
* iframe only sends a minimal ack on `application_block_inserted`.
|
|
123
138
|
* Does not allow changing markup; use {@link handleBeforeInject} to transform HTML before postMessage.
|
|
124
139
|
*/
|
|
125
|
-
handleInject(listener: (info: BlockInjectInfo) => void, priority?: number, thisArg?: unknown): IDisposable$1;
|
|
140
|
+
handleInject(listener: (info: BlockInjectInfo$1) => void, priority?: number, thisArg?: unknown): IDisposable$1;
|
|
126
141
|
}
|
|
127
142
|
/**
|
|
128
143
|
* Information about an element.
|
|
@@ -177,6 +192,8 @@ interface IElementsApi {
|
|
|
177
192
|
html: string;
|
|
178
193
|
}) => void, priority?: number, thisArg?: unknown): IDisposable$1;
|
|
179
194
|
}
|
|
195
|
+
/** Minimal sandbox ack for `application_block_inserted` (iframe → app). */
|
|
196
|
+
type BlockInsertSandboxAck$1 = Pick<BlockInjectInfo$1, 'type' | 'name' | 'blockId' | 'project'>;
|
|
180
197
|
/**
|
|
181
198
|
* API for interacting with the MessageService.
|
|
182
199
|
* Provides methods to send and receive messages, as well as manage event listeners.
|
|
@@ -364,6 +381,10 @@ interface ISettingsPanelApi {
|
|
|
364
381
|
*/
|
|
365
382
|
closeSettingsPanel(): void;
|
|
366
383
|
}
|
|
384
|
+
/** @see extensions-core `blockInsertContextToInjectInfo` */
|
|
385
|
+
declare function blockInsertContextToInjectInfo(ctx: BlockInsertContext, ack?: BlockInsertSandboxAck): BlockInjectInfo;
|
|
386
|
+
/** @see extensions-core `mergeBlockInjectAck` */
|
|
387
|
+
declare function mergeBlockInjectAck(ack: BlockInsertSandboxAck, ctx?: BlockInsertContext | null): BlockInjectInfo;
|
|
367
388
|
/**
|
|
368
389
|
* Unique identifier for a UI component.
|
|
369
390
|
* @template P The component's props type.
|
|
@@ -654,4 +675,4 @@ declare module '@emailmaker/emailmaker' {
|
|
|
654
675
|
}
|
|
655
676
|
declare const pluginRegistry: PluginRegistry;
|
|
656
677
|
declare const version: string;
|
|
657
|
-
export { BlocksApi, ComponentId, ComponentInput, ComponentInputRegistry, ComponentType, DomComponentRegistry, ElementsApi, EmailContentStyles, EmailLayoutSettings, EmailSettingsApi, type IDisposable, IDomComponent, IDomComponentFactory, IDomComponentRegistry, type ISandboxScriptHandle, Identifier, MayBePromise, MessageService, ModalApi, SandboxScriptApi, SettingsPanelApi, createComponentIdentifier, pluginRegistry, version };
|
|
678
|
+
export { type BlockInjectInfo$1 as BlockInjectInfo, type BlockInsertContext$1 as BlockInsertContext, type BlockInsertSandboxAck$1 as BlockInsertSandboxAck, BlocksApi, ComponentId, ComponentInput, ComponentInputRegistry, ComponentType, DomComponentRegistry, type ElementInsertContext, ElementsApi, EmailContentStyles, EmailLayoutSettings, EmailSettingsApi, type IBlocksApi, type IDisposable, IDomComponent, IDomComponentFactory, IDomComponentRegistry, type IElementsApi, type ISandboxScriptHandle, Identifier, MayBePromise, MessageService, ModalApi, SandboxScriptApi, SettingsPanelApi, blockInsertContextToInjectInfo, createComponentIdentifier, mergeBlockInjectAck, pluginRegistry, version };
|