From e17b6365fc707562043f97de5a5d37e8a4fc74ff Mon Sep 17 00:00:00 2001 From: Andrew Pouliot Date: Wed, 13 Nov 2019 18:27:35 -0500 Subject: [PATCH] Update API from figma.d.ts v1 update 5 (#40301) * Update from figma.d.ts. Changes: ran prettier based on settings in this repo, added void return type as necessary. * Use any directly for ClientStorage --- types/figma/figma-tests.ts | 12 ++ types/figma/index.d.ts | 346 +++++++++++++++++++++---------------- 2 files changed, 210 insertions(+), 148 deletions(-) diff --git a/types/figma/figma-tests.ts b/types/figma/figma-tests.ts index fd9ff165a2..bedd95aad1 100644 --- a/types/figma/figma-tests.ts +++ b/types/figma/figma-tests.ts @@ -1,3 +1,15 @@ const frame = figma.createFrame(); frame.appendChild(figma.createRectangle()); + +figma.on('selectionchange', () => { + figma.currentPage.selection; +}); + +figma.clientStorage.setAsync('happy', true); +figma.clientStorage.setAsync('happy', { a: 123 }); + +async () => { + const { a } = await figma.clientStorage.getAsync('happy'); +}; + figma.closePlugin(); diff --git a/types/figma/index.d.ts b/types/figma/index.d.ts index cd59c0d74f..aed3b57cb9 100644 --- a/types/figma/index.d.ts +++ b/types/figma/index.d.ts @@ -8,17 +8,20 @@ // While changes to the types aren't breaking changes to how plugins run, // it is preferable to coordinate breaking type changes with breaking API changes. +// Figma Plugin API version 1, update 5 + // Global variable with Figma's plugin API. declare const figma: PluginAPI; declare const __html__: string; interface PluginAPI { - readonly apiVersion: "1.0.0"; + readonly apiVersion: '1.0.0'; readonly command: string; - readonly root: DocumentNode; readonly viewport: ViewportAPI; closePlugin(message?: string): void; + notify(message: string, options?: NotificationOptions): NotificationHandler; + showUI(html: string, options?: ShowUIOptions): void; readonly ui: UIAPI; @@ -27,8 +30,13 @@ interface PluginAPI { getNodeById(id: string): BaseNode | null; getStyleById(id: string): BaseStyle | null; + readonly root: DocumentNode; currentPage: PageNode; + on(type: 'selectionchange' | 'currentpagechange' | 'close', callback: () => void): void; + once(type: 'selectionchange' | 'currentpagechange' | 'close', callback: () => void): void; + off(type: 'selectionchange' | 'currentpagechange' | 'close', callback: () => void): void; + readonly mixed: symbol; createRectangle(): RectangleNode; @@ -38,17 +46,27 @@ interface PluginAPI { createStar(): StarNode; createVector(): VectorNode; createText(): TextNode; - createBooleanOperation(): BooleanOperationNode; createFrame(): FrameNode; createComponent(): ComponentNode; createPage(): PageNode; createSlice(): SliceNode; + /** + * [DEPRECATED]: This API often fails to create a valid boolean operation. Use figma.union, figma.subtract, figma.intersect and figma.exclude instead. + */ + createBooleanOperation(): BooleanOperationNode; createPaintStyle(): PaintStyle; createTextStyle(): TextStyle; createEffectStyle(): EffectStyle; createGridStyle(): GridStyle; + // The styles are returned in the same order as displayed in the UI. Only + // local styles are returned. Never styles from team library. + getLocalPaintStyles(): PaintStyle[]; + getLocalTextStyles(): TextStyle[]; + getLocalEffectStyles(): EffectStyle[]; + getLocalGridStyles(): GridStyle[]; + importComponentByKeyAsync(key: string): Promise; importStyleByKeyAsync(key: string): Promise; @@ -63,27 +81,43 @@ interface PluginAPI { group(nodes: ReadonlyArray, parent: BaseNode & ChildrenMixin, index?: number): FrameNode; flatten(nodes: ReadonlyArray, parent?: BaseNode & ChildrenMixin, index?: number): VectorNode; + + union(nodes: ReadonlyArray, parent: BaseNode & ChildrenMixin, index?: number): BooleanOperationNode; + subtract(nodes: ReadonlyArray, parent: BaseNode & ChildrenMixin, index?: number): BooleanOperationNode; + intersect(nodes: ReadonlyArray, parent: BaseNode & ChildrenMixin, index?: number): BooleanOperationNode; + exclude(nodes: ReadonlyArray, parent: BaseNode & ChildrenMixin, index?: number): BooleanOperationNode; } interface ClientStorageAPI { - getAsync(key: string): Promise; // remember that any could be undefined + getAsync(key: string): Promise; setAsync(key: string, value: any): Promise; } +interface NotificationOptions { + timeout?: number; +} + +interface NotificationHandler { + cancel: () => void; +} + interface ShowUIOptions { visible?: boolean; width?: number; height?: number; + position?: 'default' | 'last' | 'auto'; // PROPOSED API ONLY } interface UIPostMessageOptions { - targetOrigin?: string; + origin?: string; } interface OnMessageProperties { - sourceOrigin: string; + origin: string; } +type MessageEventHandler = (pluginMessage: any, props: OnMessageProperties) => void; + interface UIAPI { show(): void; hide(): void; @@ -91,11 +125,14 @@ interface UIAPI { close(): void; postMessage(pluginMessage: any, options?: UIPostMessageOptions): void; - onmessage: ((pluginMessage: any, props: OnMessageProperties) => void) | undefined; + onmessage: MessageEventHandler | undefined; + on(type: 'message', callback: MessageEventHandler): void; + once(type: 'message', callback: MessageEventHandler): void; + off(type: 'message', callback: MessageEventHandler): void; } interface ViewportAPI { - center: { x: number, y: number }; + center: { x: number; y: number }; zoom: number; scrollAndZoomIntoView(nodes: ReadonlyArray): void; } @@ -103,10 +140,7 @@ interface ViewportAPI { //////////////////////////////////////////////////////////////////////////////// // Datatypes -type Transform = [ - [number, number, number], - [number, number, number] -]; +type Transform = [[number, number, number], [number, number, number]]; interface Vector { readonly x: number; @@ -131,9 +165,9 @@ interface FontName { readonly style: string; } -type TextCase = "ORIGINAL" | "UPPER" | "LOWER" | "TITLE"; +type TextCase = 'ORIGINAL' | 'UPPER' | 'LOWER' | 'TITLE'; -type TextDecoration = "NONE" | "UNDERLINE" | "STRIKETHROUGH"; +type TextDecoration = 'NONE' | 'UNDERLINE' | 'STRIKETHROUGH'; interface ArcData { readonly startingAngle: number; @@ -142,7 +176,7 @@ interface ArcData { } interface ShadowEffect { - readonly type: "DROP_SHADOW" | "INNER_SHADOW"; + readonly type: 'DROP_SHADOW' | 'INNER_SHADOW'; readonly color: RGBA; readonly offset: Vector; readonly radius: number; @@ -151,14 +185,14 @@ interface ShadowEffect { } interface BlurEffect { - readonly type: "LAYER_BLUR" | "BACKGROUND_BLUR"; + readonly type: 'LAYER_BLUR' | 'BACKGROUND_BLUR'; readonly radius: number; readonly visible: boolean; } type Effect = ShadowEffect | BlurEffect; -type ConstraintType = "MIN" | "CENTER" | "MAX" | "STRETCH" | "SCALE"; +type ConstraintType = 'MIN' | 'CENTER' | 'MAX' | 'STRETCH' | 'SCALE'; interface Constraints { readonly horizontal: ConstraintType; @@ -171,17 +205,17 @@ interface ColorStop { } interface ImageFilters { - exposure?: number; - contrast?: number; - saturation?: number; - temperature?: number; - tint?: number; - highlights?: number; - shadows?: number; + readonly exposure?: number; + readonly contrast?: number; + readonly saturation?: number; + readonly temperature?: number; + readonly tint?: number; + readonly highlights?: number; + readonly shadows?: number; } interface SolidPaint { - readonly type: "SOLID"; + readonly type: 'SOLID'; readonly color: RGB; readonly visible?: boolean; @@ -190,7 +224,7 @@ interface SolidPaint { } interface GradientPaint { - readonly type: "GRADIENT_LINEAR" | "GRADIENT_RADIAL" | "GRADIENT_ANGULAR" | "GRADIENT_DIAMOND"; + readonly type: 'GRADIENT_LINEAR' | 'GRADIENT_RADIAL' | 'GRADIENT_ANGULAR' | 'GRADIENT_DIAMOND'; readonly gradientTransform: Transform; readonly gradientStops: ReadonlyArray; @@ -200,8 +234,8 @@ interface GradientPaint { } interface ImagePaint { - readonly type: "IMAGE"; - readonly scaleMode: "FILL" | "FIT" | "CROP" | "TILE"; + readonly type: 'IMAGE'; + readonly scaleMode: 'FILL' | 'FIT' | 'CROP' | 'TILE'; readonly imageHash: string | null; readonly imageTransform?: Transform; // setting for "CROP" readonly scalingFactor?: number; // setting for "TILE" @@ -215,25 +249,25 @@ interface ImagePaint { type Paint = SolidPaint | GradientPaint | ImagePaint; interface Guide { - readonly axis: "X" | "Y"; + readonly axis: 'X' | 'Y'; readonly offset: number; } interface RowsColsLayoutGrid { - readonly pattern: "ROWS" | "COLUMNS"; - readonly alignment: "MIN" | "MAX" | "STRETCH" | "CENTER"; + readonly pattern: 'ROWS' | 'COLUMNS'; + readonly alignment: 'MIN' | 'MAX' | 'STRETCH' | 'CENTER'; readonly gutterSize: number; - readonly count: number; // Infinity when "Auto" is set in the UI + readonly count: number; // Infinity when "Auto" is set in the UI readonly sectionSize?: number; // Not set for alignment: "STRETCH" - readonly offset?: number; // Not set for alignment: "CENTER" + readonly offset?: number; // Not set for alignment: "CENTER" readonly visible?: boolean; readonly color?: RGBA; } interface GridLayoutGrid { - readonly pattern: "GRID"; + readonly pattern: 'GRID'; readonly sectionSize: number; readonly visible?: boolean; @@ -243,35 +277,35 @@ interface GridLayoutGrid { type LayoutGrid = RowsColsLayoutGrid | GridLayoutGrid; interface ExportSettingsConstraints { - type: "SCALE" | "WIDTH" | "HEIGHT"; + type: 'SCALE' | 'WIDTH' | 'HEIGHT'; value: number; } interface ExportSettingsImage { - format: "JPG" | "PNG"; - contentsOnly?: boolean; // defaults to true + format: 'JPG' | 'PNG'; + contentsOnly?: boolean; // defaults to true suffix?: string; constraint?: ExportSettingsConstraints; } interface ExportSettingsSVG { - format: "SVG"; - contentsOnly?: boolean; // defaults to true + format: 'SVG'; + contentsOnly?: boolean; // defaults to true suffix?: string; - svgOutlineText?: boolean; // defaults to true - svgIdAttribute?: boolean; // defaults to false + svgOutlineText?: boolean; // defaults to true + svgIdAttribute?: boolean; // defaults to false svgSimplifyStroke?: boolean; // defaults to true } interface ExportSettingsPDF { - format: "PDF"; - contentsOnly?: boolean; // defaults to true + format: 'PDF'; + contentsOnly?: boolean; // defaults to true suffix?: string; } type ExportSettings = ExportSettingsImage | ExportSettingsSVG | ExportSettingsPDF; -type WindingRule = "NONZERO" | "EVENODD"; +type WindingRule = 'NONZERO' | 'EVENODD'; interface VectorVertex { readonly x: number; @@ -285,8 +319,8 @@ interface VectorVertex { interface VectorSegment { readonly start: number; readonly end: number; - readonly tangentStart?: Vector; // Defaults to { x: 0, y: 0 } - readonly tangentEnd?: Vector; // Defaults to { x: 0, y: 0 } + readonly tangentStart?: Vector; // Defaults to { x: 0, y: 0 } + readonly tangentEnd?: Vector; // Defaults to { x: 0, y: 0 } } interface VectorRegion { @@ -301,7 +335,7 @@ interface VectorNetwork { } interface VectorPath { - readonly windingRule: WindingRule | "NONE"; + readonly windingRule: WindingRule | 'NONE'; readonly data: string; } @@ -309,36 +343,38 @@ type VectorPaths = ReadonlyArray; interface LetterSpacing { readonly value: number; - readonly unit: "PIXELS" | "PERCENT"; + readonly unit: 'PIXELS' | 'PERCENT'; } -type LineHeight = { - readonly value: number; - readonly unit: "PIXELS" | "PERCENT"; -} | { - readonly unit: "AUTO" -}; +type LineHeight = + | { + readonly value: number; + readonly unit: 'PIXELS' | 'PERCENT'; + } + | { + readonly unit: 'AUTO'; + }; type BlendMode = - "PASS_THROUGH" | - "NORMAL" | - "DARKEN" | - "MULTIPLY" | - "LINEAR_BURN" | - "COLOR_BURN" | - "LIGHTEN" | - "SCREEN" | - "LINEAR_DODGE" | - "COLOR_DODGE" | - "OVERLAY" | - "SOFT_LIGHT" | - "HARD_LIGHT" | - "DIFFERENCE" | - "EXCLUSION" | - "HUE" | - "SATURATION" | - "COLOR" | - "LUMINOSITY"; + | 'PASS_THROUGH' + | 'NORMAL' + | 'DARKEN' + | 'MULTIPLY' + | 'LINEAR_BURN' + | 'COLOR_BURN' + | 'LIGHTEN' + | 'SCREEN' + | 'LINEAR_DODGE' + | 'COLOR_DODGE' + | 'OVERLAY' + | 'SOFT_LIGHT' + | 'HARD_LIGHT' + | 'DIFFERENCE' + | 'EXCLUSION' + | 'HUE' + | 'SATURATION' + | 'COLOR' + | 'LUMINOSITY'; interface Font { fontName: FontName; @@ -370,13 +406,13 @@ interface SceneNodeMixin { } interface ChildrenMixin { - readonly children: ReadonlyArray; + readonly children: ReadonlyArray; - appendChild(child: BaseNode): void; - insertChild(index: number, child: BaseNode): void; + appendChild(child: SceneNode): void; + insertChild(index: number, child: SceneNode): void; - findAll(callback?: (node: BaseNode) => boolean): ReadonlyArray; - findOne(callback: (node: BaseNode) => boolean): BaseNode | null; + findAll(callback?: (node: SceneNode) => boolean): SceneNode[]; + findOne(callback: (node: SceneNode) => boolean): SceneNode | null; } interface ConstraintMixin { @@ -414,15 +450,15 @@ interface FrameMixin { backgroundStyleId: string; } -type StrokeCap = "NONE" | "ROUND" | "SQUARE" | "ARROW_LINES" | "ARROW_EQUILATERAL"; -type StrokeJoin = "MITER" | "BEVEL" | "ROUND"; -type HandleMirroring = "NONE" | "ANGLE" | "ANGLE_AND_LENGTH"; +type StrokeCap = 'NONE' | 'ROUND' | 'SQUARE' | 'ARROW_LINES' | 'ARROW_EQUILATERAL'; +type StrokeJoin = 'MITER' | 'BEVEL' | 'ROUND'; +type HandleMirroring = 'NONE' | 'ANGLE' | 'ANGLE_AND_LENGTH'; interface GeometryMixin { fills: ReadonlyArray | symbol; strokes: ReadonlyArray; strokeWeight: number; - strokeAlign: "CENTER" | "INSIDE" | "OUTSIDE"; + strokeAlign: 'CENTER' | 'INSIDE' | 'OUTSIDE'; strokeCap: StrokeCap | symbol; strokeJoin: StrokeJoin | symbol; dashPattern: ReadonlyArray; @@ -436,48 +472,65 @@ interface CornerMixin { } interface ExportMixin { - exportSettings: ExportSettings[]; + exportSettings: ReadonlyArray; exportAsync(settings?: ExportSettings): Promise; // Defaults to PNG format } -interface DefaultShapeMixin extends -BaseNodeMixin, SceneNodeMixin, -BlendMixin, GeometryMixin, LayoutMixin, ExportMixin { -} +interface DefaultShapeMixin + extends BaseNodeMixin, + SceneNodeMixin, + BlendMixin, + GeometryMixin, + LayoutMixin, + ExportMixin {} -interface DefaultContainerMixin extends -BaseNodeMixin, SceneNodeMixin, -ChildrenMixin, FrameMixin, -BlendMixin, ConstraintMixin, LayoutMixin, ExportMixin { -} +interface DefaultContainerMixin + extends BaseNodeMixin, + SceneNodeMixin, + ChildrenMixin, + FrameMixin, + BlendMixin, + ConstraintMixin, + LayoutMixin, + ExportMixin {} //////////////////////////////////////////////////////////////////////////////// // Nodes -interface DocumentNode extends BaseNodeMixin, ChildrenMixin { - readonly type: "DOCUMENT"; +interface DocumentNode extends BaseNodeMixin { + readonly type: 'DOCUMENT'; + + readonly children: ReadonlyArray; + + appendChild(child: PageNode): void; + insertChild(index: number, child: PageNode): void; + + findAll(callback?: (node: PageNode | SceneNode) => boolean): Array; + findOne(callback: (node: PageNode | SceneNode) => boolean): PageNode | SceneNode | null; } interface PageNode extends BaseNodeMixin, ChildrenMixin, ExportMixin { - readonly type: "PAGE"; + readonly type: 'PAGE'; clone(): PageNode; guides: ReadonlyArray; selection: ReadonlyArray; + + backgrounds: ReadonlyArray; } interface FrameNode extends DefaultContainerMixin { - readonly type: "FRAME" | "GROUP"; + readonly type: 'FRAME' | 'GROUP'; clone(): FrameNode; } interface SliceNode extends BaseNodeMixin, SceneNodeMixin, LayoutMixin, ExportMixin { - readonly type: "SLICE"; + readonly type: 'SLICE'; clone(): SliceNode; } interface RectangleNode extends DefaultShapeMixin, ConstraintMixin, CornerMixin { - readonly type: "RECTANGLE"; + readonly type: 'RECTANGLE'; clone(): RectangleNode; topLeftRadius: number; topRightRadius: number; @@ -486,31 +539,31 @@ interface RectangleNode extends DefaultShapeMixin, ConstraintMixin, CornerMixin } interface LineNode extends DefaultShapeMixin, ConstraintMixin { - readonly type: "LINE"; + readonly type: 'LINE'; clone(): LineNode; } interface EllipseNode extends DefaultShapeMixin, ConstraintMixin, CornerMixin { - readonly type: "ELLIPSE"; + readonly type: 'ELLIPSE'; clone(): EllipseNode; arcData: ArcData; } interface PolygonNode extends DefaultShapeMixin, ConstraintMixin, CornerMixin { - readonly type: "POLYGON"; + readonly type: 'POLYGON'; clone(): PolygonNode; pointCount: number; } interface StarNode extends DefaultShapeMixin, ConstraintMixin, CornerMixin { - readonly type: "STAR"; + readonly type: 'STAR'; clone(): StarNode; pointCount: number; innerRadius: number; } interface VectorNode extends DefaultShapeMixin, ConstraintMixin, CornerMixin { - readonly type: "VECTOR"; + readonly type: 'VECTOR'; clone(): VectorNode; vectorNetwork: VectorNetwork; vectorPaths: VectorPaths; @@ -518,13 +571,13 @@ interface VectorNode extends DefaultShapeMixin, ConstraintMixin, CornerMixin { } interface TextNode extends DefaultShapeMixin, ConstraintMixin { - readonly type: "TEXT"; + readonly type: 'TEXT'; clone(): TextNode; characters: string; readonly hasMissingFont: boolean; - textAlignHorizontal: "LEFT" | "CENTER" | "RIGHT" | "JUSTIFIED"; - textAlignVertical: "TOP" | "CENTER" | "BOTTOM"; - textAutoResize: "NONE" | "WIDTH_AND_HEIGHT" | "HEIGHT"; + textAlignHorizontal: 'LEFT' | 'CENTER' | 'RIGHT' | 'JUSTIFIED'; + textAlignVertical: 'TOP' | 'CENTER' | 'BOTTOM'; + textAutoResize: 'NONE' | 'WIDTH_AND_HEIGHT' | 'HEIGHT'; paragraphIndent: number; paragraphSpacing: number; autoRename: boolean; @@ -558,7 +611,7 @@ interface TextNode extends DefaultShapeMixin, ConstraintMixin { } interface ComponentNode extends DefaultContainerMixin { - readonly type: "COMPONENT"; + readonly type: 'COMPONENT'; clone(): ComponentNode; createInstance(): InstanceNode; @@ -567,57 +620,54 @@ interface ComponentNode extends DefaultContainerMixin { readonly key: string; // The key to use with "importComponentByKeyAsync" } -interface InstanceNode extends DefaultContainerMixin { - readonly type: "INSTANCE"; +interface InstanceNode extends DefaultContainerMixin { + readonly type: 'INSTANCE'; clone(): InstanceNode; masterComponent: ComponentNode; } interface BooleanOperationNode extends DefaultShapeMixin, ChildrenMixin, CornerMixin { - readonly type: "BOOLEAN_OPERATION"; + readonly type: 'BOOLEAN_OPERATION'; clone(): BooleanOperationNode; - booleanOperation: "UNION" | "INTERSECT" | "SUBTRACT" | "EXCLUDE"; + booleanOperation: 'UNION' | 'INTERSECT' | 'SUBTRACT' | 'EXCLUDE'; } -type BaseNode = - DocumentNode | - PageNode | - SceneNode; +type BaseNode = DocumentNode | PageNode | SceneNode; type SceneNode = - SliceNode | - FrameNode | - ComponentNode | - InstanceNode | - BooleanOperationNode | - VectorNode | - StarNode | - LineNode | - EllipseNode | - PolygonNode | - RectangleNode | - TextNode; + | SliceNode + | FrameNode + | ComponentNode + | InstanceNode + | BooleanOperationNode + | VectorNode + | StarNode + | LineNode + | EllipseNode + | PolygonNode + | RectangleNode + | TextNode; type NodeType = - "DOCUMENT" | - "PAGE" | - "SLICE" | - "FRAME" | - "GROUP" | - "COMPONENT" | - "INSTANCE" | - "BOOLEAN_OPERATION" | - "VECTOR" | - "STAR" | - "LINE" | - "ELLIPSE" | - "POLYGON" | - "RECTANGLE" | - "TEXT"; + | 'DOCUMENT' + | 'PAGE' + | 'SLICE' + | 'FRAME' + | 'GROUP' + | 'COMPONENT' + | 'INSTANCE' + | 'BOOLEAN_OPERATION' + | 'VECTOR' + | 'STAR' + | 'LINE' + | 'ELLIPSE' + | 'POLYGON' + | 'RECTANGLE' + | 'TEXT'; //////////////////////////////////////////////////////////////////////////////// // Styles -type StyleType = "PAINT" | "TEXT" | "EFFECT" | "GRID"; +type StyleType = 'PAINT' | 'TEXT' | 'EFFECT' | 'GRID'; interface BaseStyle { readonly id: string; @@ -630,12 +680,12 @@ interface BaseStyle { } interface PaintStyle extends BaseStyle { - type: "PAINT"; + type: 'PAINT'; paints: ReadonlyArray; } interface TextStyle extends BaseStyle { - type: "TEXT"; + type: 'TEXT'; fontSize: number; textDecoration: TextDecoration; fontName: FontName; @@ -647,12 +697,12 @@ interface TextStyle extends BaseStyle { } interface EffectStyle extends BaseStyle { - type: "EFFECT"; + type: 'EFFECT'; effects: ReadonlyArray; } interface GridStyle extends BaseStyle { - type: "GRID"; + type: 'GRID'; layoutGrids: ReadonlyArray; }