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:
parent
6adee1116a
commit
186629947e
15 changed files with 89 additions and 152 deletions
|
@ -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 });
|
||||
});
|
||||
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
|
|
|
@ -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({
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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,
|
||||
});
|
||||
|
|
|
@ -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 });
|
||||
|
|
|
@ -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({
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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));
|
||||
|
|
89
libs/plugin-types/index.d.ts
vendored
89
libs/plugin-types/index.d.ts
vendored
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue