0
Fork 0
mirror of https://github.com/penpot/penpot-plugins.git synced 2025-01-06 14:50:21 -05:00

feat: change plugins to use new api

This commit is contained in:
alonso.torres 2024-04-15 16:13:29 +02:00 committed by Alonso Torres
parent 988b3c6b40
commit f92b923585
9 changed files with 78 additions and 83 deletions

View file

@ -4,7 +4,7 @@ import './app.element.css';
export class AppElement extends HTMLElement {
public static observedAttributes = [];
public page: any;
public shapes: any;
calculateContrast(firstColor: string, secondColor: string) {
const luminosityFirstColor = this.getLuminosity(firstColor);
@ -136,24 +136,9 @@ export class AppElement extends HTMLElement {
}
}
initCalculate(selection: string[]) {
const shapes =
this.page.objects['#00000000-0000-0000-0000-000000000000'].shapes;
const index1 = shapes.findIndex((shape: any) => {
return shape === selection[0];
});
const index2 = shapes.findIndex((shape: any) => {
return shape === selection[1];
});
if (index1 < index2) {
selection = [selection[1], selection[0]];
}
const obj0 = this.page.objects['#' + selection[0]]?.fills?.[0]?.fillColor;
const obj1 = this.page.objects['#' + selection[1]]?.fills?.[0]?.fillColor;
initCalculate(shapes: any) {
const obj0 = shapes[0]?.fills?.[0]?.fillColor;
const obj1 = shapes[1]?.fills?.[0]?.fillColor;
if (obj0 && obj1) {
this.calculateContrast(obj0, obj1);
@ -162,25 +147,21 @@ export class AppElement extends HTMLElement {
connectedCallback() {
window.addEventListener('message', (event) => {
if (event.data.type === 'selection') {
if (event.data.content.length === 2) {
this.initCalculate(event.data.content);
if (event.data.type === 'init') {
this.setAttribute('data-theme', event.data.content.theme);
if (event.data.content.selection.length >= 2) {
this.initCalculate(event.data.content.shapes);
}
} else if (event.data.type === 'selection') {
if (event.data.content.shapes.length >= 2) {
this.initCalculate(event.data.content.shapes);
} else {
this.setColors(null, null);
this.setResult('0');
this.setA11yTags(0);
}
} else if (event.data.type === 'page') {
this.page = event.data.content;
} else if (event.data.type === 'init') {
this.setAttribute('data-theme', event.data.content.theme);
this.page = event.data.content.page;
if (event.data.content.selection.length === 2) {
this.initCalculate(event.data.content.selection);
}
} else if (event.data.type === 'theme') {
this.setAttribute('data-theme', event.data.content);
this.setAttribute('data-theme', event.data.content.theme);
}
});

View file

@ -5,36 +5,22 @@ penpot.ui.open('Contrast plugin', 'http://localhost:4210', {
penpot.ui.onMessage<{ content: string }>((message) => {
if (message.content === 'ready') {
const pageState = penpot.getPageState();
const fileState = penpot.getFileState();
if (!pageState || !fileState) {
return;
}
penpot.ui.sendMessage({
type: 'init',
content: {
name: pageState.name,
pageId: pageState.id,
page: pageState,
fileId: fileState.id,
revn: fileState.revn,
theme: penpot.getTheme(),
selection: penpot.getSelection(),
shapes: penpot.getSelectedShapes(),
},
});
}
});
penpot.on('selectionchange', (id) => {
penpot.ui.sendMessage({ type: 'selection', content: id });
penpot.on('selectionchange', () => {
const shapes = penpot.getSelectedShapes();
penpot.ui.sendMessage({ type: 'selection', content: { shapes } });
});
penpot.on('themechange', (theme) => {
penpot.ui.sendMessage({ type: 'theme', content: theme });
});
penpot.on('pagechange', (page) => {
penpot.ui.sendMessage({ type: 'page', content: page });
penpot.on('themechange', () => {
const theme = penpot.getTheme();
penpot.ui.sendMessage({ type: 'theme', content: { theme } });
});

View file

@ -27,13 +27,14 @@ penpot.ui.onMessage<{ content: string }>((message) => {
fileId: fileState.id,
revn: fileState.revn,
theme: penpot.getTheme(),
selection: penpot.getSelection(),
selection: penpot.getSelected(),
},
});
}
});
penpot.on('pagechange', (page) => {
penpot.on('pagechange', () => {
const page = penpot.getPage();
penpot.ui.sendMessage({
type: 'page',
content: {
@ -43,7 +44,8 @@ penpot.on('pagechange', (page) => {
});
});
penpot.on('filechange', (file) => {
penpot.on('filechange', () => {
const file = penpot.getFile();
penpot.ui.sendMessage({
type: 'file',
content: {
@ -54,10 +56,12 @@ penpot.on('filechange', (file) => {
});
});
penpot.on('selectionchange', (selected) => {
penpot.on('selectionchange', () => {
const selected = penpot.getSelected();
penpot.ui.sendMessage({ type: 'selection', content: selected });
});
penpot.on('themechange', (theme) => {
penpot.on('themechange', () => {
const theme = penpot.getTheme();
penpot.ui.sendMessage({ type: 'theme', content: theme });
});

View file

@ -29,8 +29,8 @@ penpot.ui.onMessage<{ content: string }>((message) => {
});
penpot.on('pagechange', () => {
const page = penpot.getPage();
const shapes = page.findShapes();
const page = penpot.getPage();
const shapes = page?.findShapes();
penpot.ui.sendMessage({
type: 'page',
@ -49,7 +49,6 @@ penpot.on('filechange', () => {
});
penpot.on('selectionchange', () => {
// const selected = await penpot.queryObject({id: selection[0]});
const selected: string[] = penpot.getSelected();
penpot.ui.sendMessage({ type: 'selection', content: selected });
});

View file

@ -1,14 +1,24 @@
export interface PenpotPage {
name: string;
export interface PenpotFile {
id: string;
name: string;
revn: number;
}
export interface PenpotPage {
id: string;
name: string;
findShapes(): PenpotShape[];
}
export interface PenpotFile {
name: string;
export interface PenpotFill {
fillColor: string;
fillOpacity: number;
}
export interface PenpotShape {
id: string;
revn: number;
name: string;
fills: PenpotFill[]
}
export interface EventsMap {
@ -45,6 +55,7 @@ export interface Penpot {
getPage: () => PenpotPage | null;
getCurrentPage: () => PenpotPage | null;
getSelected: () => string[];
getSelectedShapes(): PenpotShape[];
getTheme: () => PenpotTheme;
fetch: typeof fetch;
}

View file

@ -2,6 +2,7 @@ import type { Penpot, EventsMap } from '@penpot/plugin-types';
import { Manifest, Permissions } from '../models/manifest.model';
import { OpenUIOptions } from '../models/open-ui-options.model';
import { setModalTheme } from '../create-modal';
import openUIApi from './openUI.api';
import z from 'zod';
@ -30,6 +31,9 @@ export function triggerEvent(
type: keyof EventsMap,
message: EventsMap[keyof EventsMap]
) {
if (type === 'themechange' && modal) {
setModalTheme(modal, message);
}
const listeners = eventListeners.get(type) || [];
listeners.forEach((listener) => listener(message));
}
@ -53,8 +57,9 @@ export function createApi(context: PenpotContext, manifest: Manifest) {
const penpot: Penpot = {
ui: {
open: (name: string, url: string, options: OpenUIOptions) => {
const theme = context.getTheme() as 'dark' | 'light';
const theme = context.getTheme() as 'light' | 'dark';
modal = openUIApi(name, url, theme, options);
setModalTheme(modal, theme);
modal.addEventListener('close', closePlugin, {
once: true,
@ -71,7 +76,6 @@ export function createApi(context: PenpotContext, manifest: Manifest) {
onMessage: <T>(callback: (message: T) => void) => {
z.function().parse(callback);
uiMessagesCallbacks.push(callback as Callback<unknown>);
},
},
@ -104,7 +108,6 @@ export function createApi(context: PenpotContext, manifest: Manifest) {
}
const listeners = eventListeners.get(type) || [];
listeners.push(callback as Callback<unknown>);
eventListeners.set(type, listeners);
},
@ -145,6 +148,11 @@ export function createApi(context: PenpotContext, manifest: Manifest) {
return context.getSelected();
},
getSelectedShapes(): PenpotShape[] {
checkPermission('selection:read');
return context.getSelectedShapes();
},
getTheme(): PenpotTheme {
return context.getTheme();
},

View file

@ -1,10 +1,6 @@
import { expect, describe, vi } from 'vitest';
import {
createApi,
setFileState,
setPageState,
setSelection,
setTheme,
triggerEvent,
uiMessagesCallbacks,
} from './index.js';
@ -29,7 +25,16 @@ vi.hoisted(() => {
});
describe('Plugin api', () => {
const api = createApi({
const mockContext = {
addListener: vi.fn(),
getFile: vi.fn(),
getPage: vi.fn(),
getSelected: vi.fn(),
getSelectedShapes: vi.fn(),
getTheme: vi.fn(() => 'dark'),
};
const api = createApi(mockContext, {
name: 'test',
code: '',
permissions: ['page:read', 'file:read', 'selection:read'],
@ -209,9 +214,9 @@ describe('Plugin api', () => {
id: '123',
};
setPageState(examplePage);
mockContext.getPage.mockImplementation(() => examplePage);
const pageState = api.getPageState();
const pageState = api.getPage();
expect(pageState).toEqual(examplePage);
});
@ -223,9 +228,9 @@ describe('Plugin api', () => {
revn: 0,
} as FileState;
setFileState(exampleFile);
mockContext.getFile.mockImplementation(() => exampleFile);
const fileState = api.getFileState();
const fileState = api.getFile();
expect(fileState).toEqual(exampleFile);
});
@ -233,9 +238,9 @@ describe('Plugin api', () => {
it('get selection', () => {
const selection = ['123'];
setSelection(selection);
mockContext.getSelected.mockImplementation(() => selection);
const currentSelection = api.getSelection();
const currentSelection = api.getSelected();
expect(currentSelection).toEqual(selection);
});
@ -246,12 +251,11 @@ describe('Plugin api', () => {
const options = { width: 100, height: 100 };
const openUIApiMock = vi.mocked(openUIApi);
mockContext.getTheme.mockImplementation(() => 'light');
api.ui.open(name, url, options);
setTheme('light');
const modalMock = openUIApiMock.mock.results[0].value;
expect(modalMock.setAttribute).toHaveBeenCalledWith('data-theme', 'light');
expect(modalMock.setAttribute).toHaveBeenCalledTimes(1);
expect(api.getTheme()).toBe('light');

View file

@ -8,6 +8,7 @@ export declare global {
getCurrentPage(): PenpotPage;
getPage(): PenpotPage;
getSelected(): string[];
getSelectedShapes(): PenpotShape[];
getTheme(): PenpotTheme;
}
}

View file

@ -6,6 +6,7 @@
"start": "npx nx run plugins-runtime:build --watch & npx nx run plugins-runtime:preview",
"start:example": "npx nx run example-plugin:build --watch & npx nx run example-plugin:preview",
"start:read-plugin": "npx nx run poc-state-read-plugin:build --watch & npx nx run poc-state-read-plugin:preview",
"start:contrast-plugin": "npx nx run contrast-plugin:build --watch & npx nx run contrast-plugin:preview",
"start:rpc-api": "npx nx serve rpc-api",
"start:styles-example": "npx nx run example-styles:serve --port 4202",
"build": "npx nx build plugins-runtime --emptyOutDir=true",