UNPKG

forma-embedded-view-sdk

Version:

The Forma Embedded View SDK is a JavaScript library for creating custom extensions in Autodesk Forma (previously Spacemaker).

394 lines (393 loc) 13.5 kB
import { AnalysisApi } from "./analysis.js"; import { AreaMetricsApi } from "./areaMetrics.js"; import { AuthApi } from "./auth/auth.js"; import { ColorbarApi } from "./colorbar.js"; import { ElementsApi } from "./elements.js"; import { ExperimentalApi } from "./experimental/index.js"; import { ExtensionsApi } from "./extensions.js"; import { GeneratorsApi } from "./generators.js"; import { GeoDataApi } from "./geodata.js"; import { GeometryApi } from "./geometry.js"; import { IframeMessenger, type CreateSubscriptionResult } from "./iframe-messenger.js"; import { IntegrateApi } from "./integrate.js"; import { LibraryApi } from "./library.js"; import { PredictiveAnalysisApi } from "./predictive-analysis.js"; import { ProjectApi } from "./project.js"; import { ProposalApi } from "./proposal.js"; import { CameraApi } from "./scene/camera.js"; import { DesignToolApi } from "./scene/design-tool.js"; import { RenderApi } from "./scene/render.js"; import { SunApi } from "./scene/sun.js"; import { TerrainApi } from "./scene/terrain.js"; import { SelectionApi } from "./selection.js"; import type { EventHandler, RequestHandler, SubscribeHandler } from "./types.js"; export declare const defaultAllowedOrigins: (string | RegExp)[]; export declare function checkAllowedOrigin(origin: string, allowedOrigins: Readonly<typeof defaultAllowedOrigins>): boolean; export type EmbeddedViewSdkConfig = Readonly<{ debug?: boolean | undefined; origin?: string | undefined; allowedOrigins?: readonly string[] | undefined; }>; export declare class EmbeddedViewSdk { #private; readonly config?: EmbeddedViewSdkConfig | undefined; source: Window; readonly origin: string; /** * Experimental APIs are subject to change at any time without notice. * * Do not rely on experimental APIs in production code. */ experimental: ExperimentalApi; analysis: AnalysisApi; extensions: ExtensionsApi; elements: ElementsApi; generators: GeneratorsApi; geometry: GeometryApi; integrateElements: IntegrateApi; library: LibraryApi; project: ProjectApi; proposal: ProposalApi; camera: CameraApi; sun: SunApi; terrain: TerrainApi; render: RenderApi; selection: SelectionApi; areaMetrics: AreaMetricsApi; predictiveAnalysis: PredictiveAnalysisApi; designTool: DesignToolApi; auth: AuthApi; colorbar: ColorbarApi; geoData: GeoDataApi; constructor(config?: EmbeddedViewSdkConfig | undefined); ping(): Promise<string>; /** * @hidden * @internal */ getIframeMessenger(): IframeMessenger; getProjectId(): string; getExtensionId(): string; /** * Get the region for which the current Forma project is hosted. * If you're using the Forma API, you need to use this to determine * the `X-Ads-Region` header value. The possible values are `US` and `EMEA` * @returns "EMEA" or "US" */ getRegion(): "EMEA" | "US"; /** * Get the preferred presentation unit system for the project. * It is important to note that all programmatic interfaces operate with metric units. * This value should be used to determine the default unit system for the UI. * If this value is imperial, you should convert and dispaly results in imperial units in the UI. */ getPresentationUnitSystem(): Promise<"metric" | "imperial">; /** * Check for access to perform edit operations in the current project. * * @example * ```js * const canEdit = await Forma.getCanEdit() * if (canEdit) { * await Forma.proposal.addElement({ urn }) * } else { * console.log("User need to have collaborator or admin role to add elements") * } * ``` */ getCanEdit(): Promise<boolean>; /** * Check for access to view the current project's hub * @example * ```js * const canViewHub = await Forma.getCanViewHub() * if (canViewHub) { * const projectData = await Forma.project.get() * await Forma.extensions.storage.getTextObject({ * key: "some-key", * authcontext: projectData.hubId * }) * } * ``` */ getCanViewHub(): Promise<boolean>; /** * Check for access to edit the current project's hub * @example * ```js * const canViewHub = await Forma.getCanEditHub() * if (canEditHub) { * const projectData = await Forma.project.get() * await Forma.extensions.storage.setObject({ * key: "some-key", * authcontext: projectData.hubId, * data: "some awesome data" * }) * } * ``` */ getCanEditHub(): Promise<boolean>; /** * Retrieve the embedded view ID used to identify this embedded view. * * You can set a custom embedded view ID when dynamically opening * an embedded view inside a floating panel. */ getEmbeddedViewId(): string; static getHostOrigin(): string; /** * @hidden * @internal * * @remarks * This method allows only one handler to be registered per action. * Registering a new handler for the same action will replace the existing handler. */ setRequestHandler(name: string, handler: RequestHandler): void; /** * @hidden * @internal */ deleteRequestHandler(name: string): boolean; /** * @hidden * @internal * * @remarks * This method allows only one handler to be registered per action. * Registering a new handler for the same action will replace the existing handler. */ setEventHandler(name: string, handler: EventHandler): void; /** * @hidden * @internal */ deleteEventHandler(name: string): boolean; /** * @hidden * @internal * * @remarks * This method allows only one handler to be registered per action. * Registering a new handler for the same action will replace the existing handler. */ setSubscribeHandler(name: string, handler: SubscribeHandler): void; /** * @hidden * @internal */ deleteSubscribeHandler(name: string): boolean; /** * @hidden * @internal */ sendRequest<T, R>(action: string, payload: T, transfer?: Transferable[]): Promise<R>; /** * @hidden * @internal */ sendEvent<T>(action: string, payload: T, transfer?: Transferable[]): Promise<void>; /** * @hidden * @internal */ createSubscription<T, O extends Record<string, unknown> = Record<string, unknown>>(name: string, handler: (event: T) => void, options?: O): Promise<CreateSubscriptionResult>; /** * Open another embedded view in a floating panel. * * The embedded view will be owned by the current embedded view, * and automatically closed when the current embedded view is closed. * * To wait for the embedded view to be ready or being closed, listen to * the relevant events via {@link onEmbeddedViewStateChange} * before invoking this method. Methods such as {@link createMessagePort} * will automatically wait for the embedded view to be ready. * * If the URL is invalid or the embedded view cannot be initialized, * the state of the embedded view will remain open and not connected, * until the user closes the panel which triggers the closed state. * * @experimental */ openFloatingPanel(options: { embeddedViewId: string; url: string; /** * Title shown for the floating panel. */ title?: string | undefined; /** * The initial size of the floating panel. * * The panel will be shrinked if it cannot fit within the main area. */ preferredSize?: { width: number; height: number; } | undefined; /** * The initial position of the floating panel. */ placement?: { type: "right"; /** * Offset from the top position of the current embedded view. * * This allows to position the floating panel at the * same top position as e.g. a clicked button. * * `Element.getBoundingClientRect().top` can be used to * calculate a value for this. * * @defaultValue 0 */ offsetTop?: number | undefined; } | { type: "fullscreen"; } | { /** * Position the floating panel in center of the available view. */ type: "center"; } | undefined; /** * Absolute URL to an icon. * * The icon will be displayed as a square (currently 24x24 pixels). * * @defaultValue A generic icon. */ iconUrl?: string | undefined; /** * Hide the icon. * * @defaultValue false */ hideIcon?: boolean | undefined; /** * Disable the minimize functionality. * * @defaultValue false */ disableMinimize?: boolean | undefined; /** * Disable the resize functionality. * * @defaultValue false */ disableResize?: boolean | undefined; /** * Minimum width for a resizable floating panel. * * This is the width of the embedded view, so the actual * panel width will be larger to include the spacing around. * * Can not be specified below the default value. * * Can not be specified above 400. * * @defaultValue 100 */ minimumWidth?: number | undefined; /** * Minimum height for a resizable floating panel. * * This is the height of the embedded view, so the actual * panel height will be larger to include the header and * spacing around. * * Can not be specified below the default value. * * Can not be specified above 400. * * @defaultValue 60 */ minimumHeight?: number | undefined; }): Promise<void>; /** * Close an embedded view belonging to this extension. * * Currently only floating panels can be closed. * * If the embedded view is not open this will still resolve successfully. * * @experimental */ closeEmbeddedView(options: { embeddedViewId: string; }): Promise<void>; /** * Listen to when the state of an embedded view belonging to the current * extension changes. * * @experimental */ onEmbeddedViewStateChange(handler: (payload: { embeddedViewId: string; state: "opened" | "connected" | "disconnected" | "closed"; }) => void): Promise<CreateSubscriptionResult>; /** * Register a handler to be called when the embedded view is closing. * It will be called before the embedded view is removed from the DOM. * The handler must resolve before the timeout duration. * * @example * const { unsubscribe } = Forma.onEmbeddedViewClosing(async ({ timeoutDuration }) => { * await new Promise((resolve) => setTimeout(() => { * console.log(`The embedded view will be removed from DOM within ${timeoutDuration}ms`) * resolve(null) * }, 5000)) * }) * * // Later, when you want to stop listening for changes: * unsubscribe() * * @param handler function to be called when the embedded view is closing. The handler must resolve before the timeout duration. * @returns { unsubscribe: () => void } object with an `unsubscribe` method to stop subscribing to the event * * @remarks * This will not function when the user closes the tab or browser gracefully. * To ensure robustness, please also handle these events. * Learn more at [Window: beforeunload event](https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event). * * @experimental */ onEmbeddedViewClosing(handler: (payload: { timeoutDuration: number; }) => Promise<void>): CreateSubscriptionResult; /** * Create a MessagePort that can be used to communicate directly with * another embedded view belonging to the current extension. * * The other embedded view must have called the {@link onMessagePort} method * during initialization for this to succeeed. * * @see https://developer.mozilla.org/en-US/docs/Web/API/Channel_Messaging_API * @experimental */ createMessagePort(options: { /** * The ID of the embedded view to communicate with. */ embeddedViewId: string; /** * Optional name for the port. Can be used if setting * up multiple ports to distinguish between them. */ portName?: string | undefined; }): Promise<MessagePort>; /** * Receive a MessagePort initiated from {@link createMessagePort}. * * The first time this is called, the handler will receive any * queued message ports. * * @returns A function that can be used to unsubscribe. * * @experimental */ onMessagePort(handler: (payload: { portName?: string | undefined; port: MessagePort; }) => void): () => void; }