61 lines
1.9 KiB
TypeScript
61 lines
1.9 KiB
TypeScript
import type { Renderer, ViewerSource } from "./types.ts";
|
|
|
|
/**
|
|
* What an action can see when it is offered and when it runs. `content` is the
|
|
* element the renderer drew into, so an action can read or print what is on
|
|
* screen rather than re-fetching the file.
|
|
*/
|
|
export interface ViewerActionContext {
|
|
host: HTMLElement;
|
|
content: HTMLElement;
|
|
source: ViewerSource;
|
|
/** Absent while the preview is still resolving, or when nothing could render. */
|
|
renderer?: Renderer;
|
|
kind?: string;
|
|
}
|
|
|
|
export interface ViewerAction {
|
|
/** Stable identifier; registering the same id again replaces the earlier one. */
|
|
id: string;
|
|
label: string;
|
|
/** Name from the built-in icon set. Falls back to one derived from the label. */
|
|
icon?: string;
|
|
/** Toolbar side: alongside the renderer's own controls, or with download. */
|
|
placement?: "controls" | "actions";
|
|
/** Offered only when this returns true. Defaults to always. */
|
|
when?: (context: ViewerActionContext) => boolean;
|
|
run: (context: ViewerActionContext) => void | Promise<void>;
|
|
}
|
|
|
|
const registered = new Map<string, ViewerAction>();
|
|
|
|
/**
|
|
* Adds a toolbar action to every viewer in the page. Returns an unregister
|
|
* function, so a component can add one for as long as it is mounted.
|
|
*
|
|
* ```ts
|
|
* registerViewerAction({
|
|
* id: "open-in-tab",
|
|
* label: "Open in new tab",
|
|
* when: ({ source }) => Boolean(source.src),
|
|
* run: ({ source }) => window.open(source.src, "_blank", "noopener"),
|
|
* });
|
|
* ```
|
|
*/
|
|
export function registerViewerAction(action: ViewerAction): () => void {
|
|
registered.set(action.id, action);
|
|
return () => {
|
|
if (registered.get(action.id) === action) registered.delete(action.id);
|
|
};
|
|
}
|
|
|
|
/** Globally registered actions, in registration order. */
|
|
export function viewerActions(): ViewerAction[] {
|
|
return [...registered.values()];
|
|
}
|
|
|
|
/** Testing helper: drops every globally registered action. */
|
|
export function clearViewerActions(): void {
|
|
registered.clear();
|
|
}
|