0
Fork 0
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:
Juanfran 2024-05-31 12:53:25 +02:00
parent 8e7a44c5be
commit 50d11177a6
4 changed files with 48 additions and 12 deletions

View file

@ -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) {

View file

@ -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 = () => {

View file

@ -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 {

View file

@ -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();
} }
} }