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:
parent
988b3c6b40
commit
f92b923585
9 changed files with 78 additions and 83 deletions
|
@ -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);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -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 } });
|
||||
});
|
||||
|
|
|
@ -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 });
|
||||
});
|
||||
|
|
|
@ -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 });
|
||||
});
|
||||
|
|
21
libs/plugin-types/index.d.ts
vendored
21
libs/plugin-types/index.d.ts
vendored
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
},
|
||||
|
|
|
@ -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');
|
||||
|
|
1
libs/plugins-runtime/src/lib/global.d.ts
vendored
1
libs/plugins-runtime/src/lib/global.d.ts
vendored
|
@ -8,6 +8,7 @@ export declare global {
|
|||
getCurrentPage(): PenpotPage;
|
||||
getPage(): PenpotPage;
|
||||
getSelected(): string[];
|
||||
getSelectedShapes(): PenpotShape[];
|
||||
getTheme(): PenpotTheme;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
Loading…
Reference in a new issue