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

feat(plugin-types): removed old method and replaced with attributes

This commit is contained in:
alonso.torres 2024-09-26 14:50:48 +02:00 committed by Alonso Torres
parent 6adee1116a
commit 186629947e
15 changed files with 89 additions and 152 deletions

View file

@ -1,6 +1,6 @@
import type { PluginMessageEvent, PluginUIEvent } from './model.js';
penpot.ui.open('CONTRAST PLUGIN', `?theme=${penpot.getTheme()}`, {
penpot.ui.open('CONTRAST PLUGIN', `?theme=${penpot.theme}`, {
width: 285,
height: 525,
});
@ -10,8 +10,8 @@ penpot.ui.onMessage<PluginUIEvent>((message) => {
sendMessage({
type: 'init',
content: {
theme: penpot.getTheme(),
selection: penpot.getSelectedShapes(),
theme: penpot.theme,
selection: penpot.selection,
},
});
@ -20,7 +20,7 @@ penpot.ui.onMessage<PluginUIEvent>((message) => {
});
penpot.on('selectionchange', () => {
const shapes = penpot.getSelectedShapes();
const shapes = penpot.selection;
sendMessage({ type: 'selection', content: shapes });
initEvents();
@ -37,7 +37,7 @@ function initEvents() {
return penpot.on(
'shapechange',
() => {
const shapes = penpot.getSelectedShapes();
const shapes = penpot.selection;
sendMessage({ type: 'selection', content: shapes });
},
{ shapeId: shape.id }
@ -46,7 +46,7 @@ function initEvents() {
}
penpot.on('themechange', () => {
const theme = penpot.getTheme();
const theme = penpot.theme;
sendMessage({ type: 'theme', content: theme });
});

View file

@ -3,7 +3,7 @@ export default function () {
rectangle.x = penpot.viewport.center.x;
rectangle.y = penpot.viewport.center.y;
const shape = penpot.getPage()?.getShapeById(rectangle.id);
const shape = penpot.currentPage?.getShapeById(rectangle.id);
if (shape) {
penpot.library.local.createComponent([shape]);
}

View file

@ -1,6 +1,6 @@
export default function () {
async function createComment() {
const page = penpot.getPage();
const page = penpot.currentPage;
if (page) {
await page.addCommentThread('Hello world!', {
@ -11,7 +11,7 @@ export default function () {
}
async function replyComment() {
const page = penpot.getPage();
const page = penpot.currentPage;
if (page) {
const comments = await page.findCommentThreads({
@ -23,7 +23,7 @@ export default function () {
}
async function deleteComment() {
const page = penpot.getPage();
const page = penpot.currentPage;
if (page) {
const commentThreads = await page.findCommentThreads({

View file

@ -1,6 +1,6 @@
export default function () {
function createRulerGuides(): void {
const page = penpot.getPage();
const page = penpot.currentPage;
if (page) {
page.addRulerGuide('horizontal', penpot.viewport.center.x);
@ -9,7 +9,7 @@ export default function () {
}
function removeRulerGuides(): void {
const page = penpot.getPage();
const page = penpot.currentPage;
if (page) {
page.removeRulerGuide(page.rulerGuides[0]);

View file

@ -1,6 +1,6 @@
import type { PluginMessageEvent, PluginUIEvent } from './model.js';
penpot.ui.open('FEATHER ICONS PLUGIN', `?theme=${penpot.getTheme()}`, {
penpot.ui.open('FEATHER ICONS PLUGIN', `?theme=${penpot.theme}`, {
width: 292,
height: 540,
});

View file

@ -11,7 +11,7 @@ import {
generateCharacters,
} from './generator.js';
penpot.ui.open('LOREM IPSUM PLUGIN', `?theme=${penpot.getTheme()}`);
penpot.ui.open('LOREM IPSUM PLUGIN', `?theme=${penpot.theme}`);
penpot.on('themechange', (theme) => {
sendMessage({ type: 'theme', content: theme });

View file

@ -52,7 +52,7 @@ penpot.ui.onMessage<{ content: string; data: unknown }>(async (message) => {
});
penpot.on('pagechange', () => {
const page = penpot.getPage();
const page = penpot.currentPage;
const shapes = page?.findShapes();
penpot.ui.sendMessage({
@ -62,7 +62,7 @@ penpot.on('pagechange', () => {
});
penpot.on('filechange', () => {
const file = penpot.getFile();
const file = penpot.currentFile;
if (!file) {
return;
@ -77,7 +77,7 @@ penpot.on('filechange', () => {
});
penpot.on('selectionchange', () => {
const selection = penpot.getSelectedShapes();
const selection = penpot.selection;
const data: string | null =
selection.length === 1 ? selection[0].getPluginData('counter') : null;
const counter = data ? parseInt(data, 10) : 0;
@ -89,8 +89,8 @@ penpot.on('themechange', (theme) => {
});
function init() {
const page = penpot.getPage();
const file = penpot.getFile();
const page = penpot.currentPage;
const file = penpot.currentFile;
if (!page || !file) {
return;
@ -108,7 +108,7 @@ function init() {
pageId: page.id,
fileId: file.id,
revn: file.revn,
theme: penpot.getTheme(),
theme: penpot.theme,
selection,
counter,
},
@ -116,7 +116,7 @@ function init() {
}
function changeName(data: { id: string; name: string }) {
const shape = penpot.getPage()?.getShapeById('' + data.id);
const shape = penpot.currentPage?.getShapeById('' + data.id);
if (shape) {
shape.name = data.name;
}
@ -140,28 +140,28 @@ function createRect() {
}
function moveX(data: { id: string }) {
const shape = penpot.getPage()?.getShapeById('' + data.id);
const shape = penpot.currentPage?.getShapeById('' + data.id);
if (shape) {
shape.x += 100;
}
}
function moveY(data: { id: string }) {
const shape = penpot.getPage()?.getShapeById('' + data.id);
const shape = penpot.currentPage?.getShapeById('' + data.id);
if (shape) {
shape.y += 100;
}
}
function resizeW(data: { id: string }) {
const shape = penpot.getPage()?.getShapeById('' + data.id);
const shape = penpot.currentPage?.getShapeById('' + data.id);
if (shape) {
shape.resize(shape.width * 2, shape.height);
}
}
function resizeH(data: { id: string }) {
const shape = penpot.getPage()?.getShapeById('' + data.id);
const shape = penpot.currentPage?.getShapeById('' + data.id);
if (shape) {
shape.resize(shape.width, shape.height * 2);
}
@ -449,7 +449,7 @@ function createMargins() {
selected.addRulerGuide('vertical', width - 10);
selected.addRulerGuide('horizontal', 10);
selected.addRulerGuide('horizontal', height - 10);
} else {
} else if (page) {
console.log('bound', penpot.viewport.bounds);
const { x, y, width, height } = penpot.viewport.bounds;
page.addRulerGuide('vertical', x + 100);
@ -464,7 +464,7 @@ async function addComment() {
if (shape) {
const content = shape.name + ' - ' + Date.now();
const cthr = await penpot.currentPage.findCommentThreads();
const cthr = await penpot.currentPage?.findCommentThreads();
const th = cthr && cthr[0];
if (th) {
@ -476,13 +476,13 @@ async function addComment() {
}
} else {
console.log('Create new thread', content);
await penpot.currentPage.addCommentThread(content, shape.center);
await penpot.currentPage?.addCommentThread(content, shape.center);
}
}
}
async function exportFile() {
const data = await penpot.getFile()?.export('penpot');
const data = await penpot.currentFile?.export('penpot');
if (data) {
penpot.ui.sendMessage({

View file

@ -1,6 +1,6 @@
import { PluginMessageEvent } from './app/model';
penpot.ui.open('RENAME LAYER PLUGIN', `?theme=${penpot.getTheme()}`, {
penpot.ui.open('RENAME LAYER PLUGIN', `?theme=${penpot.theme}`, {
width: 290,
height: 550,
});
@ -55,9 +55,9 @@ penpot.ui.onMessage<PluginMessageEvent>((message) => {
});
function getShapes() {
return penpot.getSelectedShapes().length
? penpot.getSelectedShapes()
: penpot.getPage()?.findShapes();
return penpot.selection.length
? penpot.selection
: penpot.currentPage?.findShapes();
}
function resetSelection() {

View file

@ -1,7 +1,7 @@
import { GridLayout } from '@penpot/plugin-types';
import { PluginMessageEvent, TablePluginEvent } from './app/model';
penpot.ui.open('TABLE PLUGIN', `?theme=${penpot.getTheme()}`, {
penpot.ui.open('TABLE PLUGIN', `?theme=${penpot.theme}`, {
width: 280,
height: 610,
});
@ -219,7 +219,7 @@ function createFlexCell(
function pluginData(message: PluginMessageEvent) {
if (message.type === 'tableconfig') {
const { type, options } = message.content;
const page = penpot.getPage();
const page = penpot.currentPage;
if (type === 'save') {
page?.setPluginData('table-plugin', JSON.stringify(options));

View file

@ -688,7 +688,18 @@ export interface Context {
* console.log(rootShape);
* ```
*/
readonly root: Shape;
readonly root: Shape | null;
/**
* Retrieves file data from the current Penpot context. Requires `content:read` permission.
* @return Returns the file data or `null` if no file is available.
*
* @example
* ```js
* const fileData = context.currentFile;
* console.log(fileData);
* ```
*/
readonly currentFile: File | null;
/**
* The current page in the Penpot context. Requires `content:read` permission.
*
@ -698,7 +709,7 @@ export interface Context {
* console.log(currentPage);
* ```
*/
readonly currentPage: Page;
readonly currentPage: Page | null;
/**
* The viewport settings in the Penpot context.
*
@ -762,6 +773,17 @@ export interface Context {
*/
readonly activeUsers: ActiveUser[];
/**
* The current theme (light or dark) in Penpot.
*
* @example
* ```js
* const currentTheme = context.theme;
* console.log(currentTheme);
* ```
*/
readonly theme: Theme;
/**
* The currently selected shapes in Penpot. Requires `content:read` permission.
*
@ -773,51 +795,6 @@ export interface Context {
*/
selection: Shape[];
/**
* Retrieves file data from the current Penpot context. Requires `content:read` permission.
* @return Returns the file data or `null` if no file is available.
*
* @example
* ```js
* const fileData = context.getFile();
* console.log(fileData);
* ```
*/
getFile(): File | null;
/**
* Retrieves page data from the current Penpot context. Requires `content:read` permission.
* @return Returns the page data or `null` if no page is available.
*
* @example
* ```js
* const pageData = context.getPage();
* console.log(pageData);
* ```
*/
getPage(): Page | null;
/**
* Retrieves the IDs of the currently selected elements in Penpot. Requires `content:read` permission.
* @return Returns an array of IDs representing the selected elements.
*
* @example
* ```js
* const selectedIds = context.getSelected();
* console.log(selectedIds);
* ```
*/
getSelected(): string[];
/**
* Retrieves the shapes of the currently selected elements in Penpot. Requires `content:read` permission.
* @return Returns an array of shapes representing the selected elements.
*
* @example
* ```js
* const selectedShapes = context.getSelectedShapes();
* console.log(selectedShapes);
* ```
*/
getSelectedShapes(): Shape[];
/**
* Retrieves colors applied to the given shapes in Penpot. Requires `content:read` permission.
* @return Returns an array of colors and their shape information.
@ -840,18 +817,6 @@ export interface Context {
*/
replaceColor(shapes: Shape[], oldColor: Color, newColor: Color): void;
/**
* Retrieves the current theme (light or dark) in Penpot.
* @return Returns the current theme.
*
* @example
* ```js
* const currentTheme = context.getTheme();
* console.log(currentTheme);
* ```
*/
getTheme(): Theme;
/**
* Uploads media to Penpot and retrieves its image data. Requires `content:write` permission.
* @param name The name of the media.
@ -2774,7 +2739,7 @@ export interface Page extends PluginData {
*
* @example
* ```js
* const shape = penpot.getPage().getShapeById('shapeId');
* const shape = penpot.currentPage.getShapeById('shapeId');
* ```
*/
getShapeById(id: string): Shape | null;
@ -2785,7 +2750,7 @@ export interface Page extends PluginData {
* @param criteria
* @example
* ```js
* const shapes = penpot.getPage().findShapes({ name: 'exampleName' });
* const shapes = penpot.currentPage.findShapes({ name: 'exampleName' });
* ```
*/
findShapes(criteria?: {
@ -2815,7 +2780,7 @@ export interface Page extends PluginData {
*
* @example
* ```js
* const flow = penpot.getPage().createFlow('exampleFlow', board);
* const flow = penpot.currentPage.createFlow('exampleFlow', board);
* ```
*/
createFlow(name: string, board: Board): Flow;

View file

@ -130,12 +130,17 @@ export function createApi(
// Penpot State API
get root(): Shape {
get root(): Shape | null {
checkPermission('content:read');
return plugin.context.root;
},
get currentPage(): Page {
get currentFile(): File | null {
checkPermission('content:read');
return plugin.context.currentFile;
},
get currentPage(): Page | null {
checkPermission('content:read');
return plugin.context.currentPage;
},
@ -178,26 +183,6 @@ export function createApi(
return plugin.context.activeUsers;
},
getFile(): File | null {
checkPermission('content:read');
return plugin.context.getFile();
},
getPage(): Page | null {
checkPermission('content:read');
return plugin.context.getPage();
},
getSelected(): string[] {
checkPermission('content:read');
return plugin.context.getSelected();
},
getSelectedShapes(): Shape[] {
checkPermission('content:read');
return plugin.context.getSelectedShapes();
},
shapesColors(shapes: Shape[]): (Color & ColorShapeInfo)[] {
checkPermission('content:read');
return plugin.context.shapesColors(shapes);
@ -208,8 +193,8 @@ export function createApi(
return plugin.context.replaceColor(shapes, oldColor, newColor);
},
getTheme(): Theme {
return plugin.context.getTheme();
get theme(): Theme {
return plugin.context.theme;
},
createBoard(): Board {

View file

@ -1,6 +1,6 @@
import { expect, describe, vi } from 'vitest';
import { createApi } from './index.js';
import type { File } from '@penpot/plugin-types';
import type { File, Page, Shape } from '@penpot/plugin-types';
const mockUrl = 'http://fake.fake/';
@ -30,11 +30,10 @@ describe('Plugin api', () => {
registerListener: vi.fn(),
destroyListener: vi.fn(),
context: {
getFile: vi.fn(),
getPage: vi.fn(),
getSelected: vi.fn(),
getSelectedShapes: vi.fn(),
getTheme: vi.fn(() => 'dark'),
currentFile: null as File | null,
currentPage: null as Page | null,
selection: [] as Shape[],
theme: 'dark',
addListener: vi.fn().mockReturnValueOnce(Symbol()),
removeListener: vi.fn(),
},
@ -76,31 +75,17 @@ describe('Plugin api', () => {
api.penpot.on('selectionchange', callback);
}).toThrow();
});
it('get states', () => {
expect(() => {
api.penpot.getFile();
}).toThrow();
expect(() => {
api.penpot.getPage();
}).toThrow();
expect(() => {
api.penpot.getSelected();
}).toThrow();
});
});
it('get file state', () => {
const examplePage = {
name: 'test',
id: '123',
};
} as Page;
pluginManager.context.getPage.mockImplementation(() => examplePage);
pluginManager.context.currentPage = examplePage;
const pageState = api.penpot.getPage();
const pageState = api.penpot.currentPage;
expect(pageState).toEqual(examplePage);
});
@ -112,19 +97,22 @@ describe('Plugin api', () => {
revn: 0,
} as File;
pluginManager.context.getFile.mockImplementation(() => exampleFile);
pluginManager.context.currentFile = exampleFile;
const fileState = api.penpot.getFile();
const fileState = api.penpot.currentFile;
expect(fileState).toEqual(exampleFile);
});
it('get selection', () => {
const selection = ['123'];
const selection = [
{ id: '123', name: 'test' },
{ id: 'abc', name: 'test2' },
] as Shape[];
pluginManager.context.getSelected.mockImplementation(() => selection);
pluginManager.context.selection = selection;
const currentSelection = api.penpot.getSelected();
const currentSelection = api.penpot.selection;
expect(currentSelection).toEqual(selection);
});

View file

@ -61,7 +61,6 @@ describe('createPlugin', () => {
mockContext = {
addListener: vi.fn(),
removeListener: vi.fn(),
getTheme: vi.fn().mockReturnValue('light'),
} as unknown as Context;
onCloseCallback = vi.fn();

View file

@ -59,9 +59,9 @@ describe('createPluginManager', () => {
);
mockContext = {
theme: 'light',
addListener: vi.fn().mockReturnValue(Symbol()),
removeListener: vi.fn(),
getTheme: vi.fn().mockReturnValue('light'),
} as unknown as Context;
onCloseCallback = vi.fn();

View file

@ -79,7 +79,7 @@ export async function createPluginManager(
};
const openModal = (name: string, url: string, options?: OpenUIOptions) => {
const theme = context.getTheme() as 'light' | 'dark';
const theme = context.theme as 'light' | 'dark';
const modalUrl = getValidUrl(manifest.host, url);