mirror of
https://github.com/penpot/penpot-plugins.git
synced 2025-01-08 16:00:27 -05:00
fix: multi plugin dev support
This commit is contained in:
parent
8e7a44c5be
commit
50d11177a6
4 changed files with 48 additions and 12 deletions
|
@ -33,7 +33,7 @@ export const validEvents = [
|
||||||
|
|
||||||
export let uiMessagesCallbacks: Callback<unknown>[] = [];
|
export let uiMessagesCallbacks: Callback<unknown>[] = [];
|
||||||
|
|
||||||
let modal: PluginModalElement | null = null;
|
let modals = new Set<PluginModalElement>([]);
|
||||||
|
|
||||||
const eventListeners: Map<string, Callback<unknown>[]> = new Map();
|
const eventListeners: Map<string, Callback<unknown>[]> = new Map();
|
||||||
|
|
||||||
|
@ -47,17 +47,23 @@ export function triggerEvent(
|
||||||
type: keyof EventsMap,
|
type: keyof EventsMap,
|
||||||
message: EventsMap[keyof EventsMap]
|
message: EventsMap[keyof EventsMap]
|
||||||
) {
|
) {
|
||||||
if (type === 'themechange' && modal) {
|
if (type === 'themechange') {
|
||||||
modal.setTheme(message as PenpotTheme);
|
modals.forEach((modal) => {
|
||||||
|
modal.setTheme(message as PenpotTheme);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
const listeners = eventListeners.get(type) || [];
|
const listeners = eventListeners.get(type) || [];
|
||||||
listeners.forEach((listener) => listener(message));
|
listeners.forEach((listener) => listener(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createApi(context: PenpotContext, manifest: Manifest): Penpot {
|
export function createApi(context: PenpotContext, manifest: Manifest): Penpot {
|
||||||
|
let modal: PluginModalElement | null = null;
|
||||||
|
|
||||||
const closePlugin = () => {
|
const closePlugin = () => {
|
||||||
modal?.removeEventListener('close', closePlugin);
|
|
||||||
if (modal) {
|
if (modal) {
|
||||||
|
modals.delete(modal);
|
||||||
|
|
||||||
|
modal.removeEventListener('close', closePlugin);
|
||||||
modal.remove();
|
modal.remove();
|
||||||
}
|
}
|
||||||
uiMessagesCallbacks = [];
|
uiMessagesCallbacks = [];
|
||||||
|
@ -87,6 +93,8 @@ export function createApi(context: PenpotContext, manifest: Manifest): Penpot {
|
||||||
modal.addEventListener('close', closePlugin, {
|
modal.addEventListener('close', closePlugin, {
|
||||||
once: true,
|
once: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modals.add(modal);
|
||||||
},
|
},
|
||||||
|
|
||||||
sendMessage(message: unknown) {
|
sendMessage(message: unknown) {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
export const dragHandler = (el: HTMLElement) => {
|
export const dragHandler = (el: HTMLElement, move?: () => void) => {
|
||||||
let currentTranslate = { x: 0, y: 0 };
|
let currentTranslate = { x: 0, y: 0 };
|
||||||
let initialTranslate = { x: 0, y: 0 };
|
let initialTranslate = { x: 0, y: 0 };
|
||||||
let initialClientPosition = { x: 0, y: 0 };
|
let initialClientPosition = { x: 0, y: 0 };
|
||||||
|
@ -11,6 +11,8 @@ export const dragHandler = (el: HTMLElement) => {
|
||||||
currentTranslate = { x: deltaX, y: deltaY };
|
currentTranslate = { x: deltaX, y: deltaY };
|
||||||
|
|
||||||
el.style.transform = `translate(${deltaX}px, ${deltaY}px)`;
|
el.style.transform = `translate(${deltaX}px, ${deltaY}px)`;
|
||||||
|
|
||||||
|
move?.();
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleMouseUp = () => {
|
const handleMouseUp = () => {
|
||||||
|
|
|
@ -5,7 +5,8 @@ import { loadManifest, loadManifestCode } from './parse-manifest.js';
|
||||||
import { Manifest } from './models/manifest.model.js';
|
import { Manifest } from './models/manifest.model.js';
|
||||||
|
|
||||||
let isLockedDown = false;
|
let isLockedDown = false;
|
||||||
let lastApi: ReturnType<typeof createApi> | undefined;
|
let createdApis: ReturnType<typeof createApi>[] = [];
|
||||||
|
const multiPlugin = false;
|
||||||
|
|
||||||
let pluginContext: PenpotContext | null = null;
|
let pluginContext: PenpotContext | null = null;
|
||||||
|
|
||||||
|
@ -22,15 +23,18 @@ export const ɵloadPlugin = async function (manifest: Manifest) {
|
||||||
hardenIntrinsics();
|
hardenIntrinsics();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lastApi) {
|
if (createdApis && !multiPlugin) {
|
||||||
lastApi.closePlugin();
|
createdApis.forEach((pluginApi) => {
|
||||||
|
pluginApi.closePlugin();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pluginContext) {
|
if (pluginContext) {
|
||||||
lastApi = createApi(pluginContext, manifest);
|
const pluginApi = createApi(pluginContext, manifest);
|
||||||
|
createdApis.push(pluginApi);
|
||||||
|
|
||||||
const c = new Compartment({
|
const c = new Compartment({
|
||||||
penpot: harden(lastApi),
|
penpot: harden(pluginApi),
|
||||||
fetch: window.fetch.bind(window),
|
fetch: window.fetch.bind(window),
|
||||||
console: harden(window.console),
|
console: harden(window.console),
|
||||||
Math: harden(Math),
|
Math: harden(Math),
|
||||||
|
@ -49,7 +53,10 @@ export const ɵloadPlugin = async function (manifest: Manifest) {
|
||||||
c.evaluate(code);
|
c.evaluate(code);
|
||||||
|
|
||||||
const listenerId: symbol = pluginContext.addListener('finish', () => {
|
const listenerId: symbol = pluginContext.addListener('finish', () => {
|
||||||
lastApi?.closePlugin();
|
createdApis.forEach((pluginApi) => {
|
||||||
|
pluginApi.closePlugin();
|
||||||
|
});
|
||||||
|
|
||||||
pluginContext?.removeListener(listenerId);
|
pluginContext?.removeListener(listenerId);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -24,6 +24,20 @@ export class PluginModalElement extends HTMLElement {
|
||||||
this.#dragEvents?.();
|
this.#dragEvents?.();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
calculateZIndex() {
|
||||||
|
const modals = document.querySelectorAll<HTMLElement>('plugin-modal');
|
||||||
|
|
||||||
|
const zIndexModals = Array.from(modals)
|
||||||
|
.filter((modal) => modal !== this)
|
||||||
|
.map((modal) => {
|
||||||
|
return Number(modal.style.zIndex);
|
||||||
|
});
|
||||||
|
|
||||||
|
const maxZIndex = Math.max(...zIndexModals, 0);
|
||||||
|
|
||||||
|
this.style.zIndex = (maxZIndex + 1).toString();
|
||||||
|
}
|
||||||
|
|
||||||
connectedCallback() {
|
connectedCallback() {
|
||||||
const title = this.getAttribute('title');
|
const title = this.getAttribute('title');
|
||||||
const iframeSrc = this.getAttribute('iframe-src');
|
const iframeSrc = this.getAttribute('iframe-src');
|
||||||
|
@ -43,7 +57,10 @@ export class PluginModalElement extends HTMLElement {
|
||||||
this.#wrapper.style.inlineSize = `${width}px`;
|
this.#wrapper.style.inlineSize = `${width}px`;
|
||||||
this.#wrapper.style.blockSize = `${height}px`;
|
this.#wrapper.style.blockSize = `${height}px`;
|
||||||
|
|
||||||
this.#dragEvents = dragHandler(this.#wrapper);
|
// move modal to the top
|
||||||
|
this.#dragEvents = dragHandler(this.#wrapper, () => {
|
||||||
|
this.calculateZIndex();
|
||||||
|
});
|
||||||
|
|
||||||
const header = document.createElement('div');
|
const header = document.createElement('div');
|
||||||
header.classList.add('header');
|
header.classList.add('header');
|
||||||
|
@ -100,6 +117,8 @@ export class PluginModalElement extends HTMLElement {
|
||||||
style.textContent = modalCss;
|
style.textContent = modalCss;
|
||||||
|
|
||||||
this.shadowRoot.appendChild(style);
|
this.shadowRoot.appendChild(style);
|
||||||
|
|
||||||
|
this.calculateZIndex();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue