@embedpdf/plugin-commands 3.0.0-next.15 → 3.0.0-next.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/standard.cjs +6 -9
- package/dist/standard.cjs.map +1 -1
- package/dist/standard.d.cts +0 -2
- package/dist/standard.d.ts +0 -2
- package/dist/standard.js +6 -9
- package/dist/standard.js.map +1 -1
- package/package.json +9 -10
package/dist/standard.cjs
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
let _embedpdf_core = require("@embedpdf/core");
|
|
3
|
-
let _embedpdf_plugin_actions_contract = require("@embedpdf/plugin-actions/contract");
|
|
4
3
|
let _embedpdf_plugin_annotation_contract = require("@embedpdf/plugin-annotation/contract");
|
|
5
4
|
let _embedpdf_plugin_interaction_contract = require("@embedpdf/plugin-interaction/contract");
|
|
6
5
|
let _embedpdf_plugin_selection_contract = require("@embedpdf/plugin-selection/contract");
|
|
@@ -10,10 +9,10 @@ let _embedpdf_plugin_stage_contract = require("@embedpdf/plugin-stage/contract")
|
|
|
10
9
|
* @embedpdf/plugin-commands/standard — the commands every viewer has: zoom,
|
|
11
10
|
* pages, view rotation, a command for every tool, copy, delete, download and
|
|
12
11
|
* print, with shortcuts, and labels in EmbedPDF's eight languages (the i18n
|
|
13
|
-
* plugin has the strings).
|
|
14
|
-
* file download
|
|
15
|
-
*
|
|
16
|
-
*
|
|
12
|
+
* plugin has the strings). Two of them reach the browser (the clipboard, a
|
|
13
|
+
* file download), which plugins never touch, so each framework's `/commands`
|
|
14
|
+
* builds them with its platform: that is the `standardCommands` an app
|
|
15
|
+
* imports. Print goes through the kernel, which has the host's printer.
|
|
17
16
|
*/
|
|
18
17
|
const stageOf = (context) => context.tryGet(_embedpdf_plugin_stage_contract.StageToken);
|
|
19
18
|
const interactionOf = (context) => context.tryGet(_embedpdf_plugin_interaction_contract.InteractionToken);
|
|
@@ -223,10 +222,8 @@ function createStandardCommands(platform) {
|
|
|
223
222
|
categories: ["document"],
|
|
224
223
|
allowed: (context) => context.tryGet(_embedpdf_core.DocumentsToken)?.canPrint() ?? true,
|
|
225
224
|
notAllowedKey: "commands.notAllowed.doc-print",
|
|
226
|
-
run: (context) => {
|
|
227
|
-
|
|
228
|
-
if (actions) return actions.runDocumentVerb("print", () => platform.print());
|
|
229
|
-
platform.print();
|
|
225
|
+
run: async (context) => {
|
|
226
|
+
await context.get(_embedpdf_core.DocumentsToken).print(context.documentId ?? void 0, { signal: context.signal });
|
|
230
227
|
},
|
|
231
228
|
enabled: (context) => context.documentId !== null
|
|
232
229
|
}
|
package/dist/standard.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"standard.cjs","names":["StageToken","InteractionToken","AnnotationToken","SelectionToken","DocumentsToken","ActionsToken"],"sources":["../src/standard.ts"],"sourcesContent":["/**\n * @embedpdf/plugin-commands/standard — the commands every viewer has: zoom,\n * pages, view rotation, a command for every tool, copy, delete, download and\n * print, with shortcuts, and labels in EmbedPDF's eight languages (the i18n\n * plugin has the strings). Three of them reach the browser (the clipboard, a\n * file download, the print dialog), which plugins never touch, so each\n * framework's `/commands` builds them with its platform: that is the\n * `standardCommands` an app imports.\n */\nimport { DocumentsToken } from '@embedpdf/core';\nimport { ActionsToken } from '@embedpdf/plugin-actions/contract';\nimport { AnnotationToken } from '@embedpdf/plugin-annotation/contract';\nimport { InteractionToken, type Tool } from '@embedpdf/plugin-interaction/contract';\nimport { SelectionToken, type SelectionCapability } from '@embedpdf/plugin-selection/contract';\nimport { StageToken } from '@embedpdf/plugin-stage/contract';\n\nimport type { CommandContext, CommandDef, CommandFamily } from './contract';\n\n/** What the standard commands need from the browser. */\nexport interface StandardCommandsPlatform {\n /** Copy the selected text to the clipboard. */\n copySelection(selection: SelectionCapability): Promise<unknown>;\n /** Give the user the bytes as a file download. */\n saveFile(bytes: Uint8Array, fileName: string): void;\n /** Open the print dialog. */\n print(): void;\n}\n\nconst stageOf = (context: CommandContext) => context.tryGet(StageToken);\nconst interactionOf = (context: CommandContext) => context.tryGet(InteractionToken);\n\n/** Enabled while the document has a Stage. */\nconst hasStage = (context: CommandContext): boolean => stageOf(context) !== null;\n\n/** The ids of a tool list, made once per list, which keeps its identity while the tools don't change. */\nconst toolIds = new WeakMap<readonly Tool[], readonly string[]>();\nconst idsOf = (tools: readonly Tool[]): readonly string[] => {\n let ids = toolIds.get(tools);\n if (!ids) {\n ids = tools.map((tool) => tool.id);\n toolIds.set(tools, ids);\n }\n return ids;\n};\n\n/**\n * Whether the user may use a tool: one that draws annotations needs permission to create them.\n * A tool another plugin owns asks nothing here; that plugin refuses its own gesture.\n */\nconst mayUseTool = (context: CommandContext, toolId: string): boolean => {\n const annotation = context.tryGet(AnnotationToken);\n return !annotation?.tools.get(toolId) || annotation.canCreate();\n};\n\n/** Switching to a tool: active while it's the tool, there only when the document has it. */\nconst toolCommand = (toolId: string): Omit<CommandDef, 'id' | 'shortcut'> => ({\n labelKey: `commands.tool.${toolId}`,\n label: toolId,\n icon: toolId,\n categories: ['tool'],\n run: (context) => interactionOf(context)?.activateTool(toolId),\n active: (context) => interactionOf(context)?.getActiveToolId() === toolId,\n visible: (context) => interactionOf(context)?.hasTool(toolId) ?? false,\n enabled: (context) => mayUseTool(context, toolId),\n});\n\n/** `tool:<id>` for every tool the document has. */\nconst toolCommands: CommandFamily = {\n prefix: 'tool:',\n names: (context) => {\n const interaction = interactionOf(context);\n return interaction ? idsOf(interaction.listTools()) : [];\n },\n command: toolCommand,\n};\n\n/** The standard commands, with the browser's part from `platform`. */\nexport function createStandardCommands(\n platform: StandardCommandsPlatform,\n): readonly (CommandDef | CommandFamily)[] {\n return [\n // ── zoom ──\n {\n id: 'zoom:in',\n labelKey: 'commands.zoom.in',\n label: 'Zoom in',\n icon: 'zoom-in',\n shortcut: ['Mod+=', 'Mod+NumpadAdd'],\n categories: ['zoom'],\n run: (context) => stageOf(context)?.zoomIn(),\n enabled: hasStage,\n },\n {\n id: 'zoom:out',\n labelKey: 'commands.zoom.out',\n label: 'Zoom out',\n icon: 'zoom-out',\n shortcut: ['Mod+-', 'Mod+NumpadSubtract'],\n categories: ['zoom'],\n run: (context) => stageOf(context)?.zoomOut(),\n enabled: hasStage,\n },\n {\n id: 'zoom:fit-width',\n labelKey: 'commands.zoom.fitWidth',\n label: 'Fit width',\n icon: 'fit-width',\n categories: ['zoom'],\n run: (context) => stageOf(context)?.fitWidth(),\n active: (context) => stageOf(context)?.getZoomMode() === 'fit-width',\n enabled: hasStage,\n },\n {\n id: 'zoom:fit-page',\n labelKey: 'commands.zoom.fitPage',\n label: 'Fit page',\n icon: 'fit-page',\n categories: ['zoom'],\n run: (context) => stageOf(context)?.fitPage(),\n active: (context) => stageOf(context)?.getZoomMode() === 'fit-page',\n enabled: hasStage,\n },\n\n // ── pages ──\n {\n id: 'page:next',\n labelKey: 'commands.page.next',\n label: 'Next page',\n icon: 'next-page',\n shortcut: 'ArrowRight',\n categories: ['page'],\n run: (context) => stageOf(context)?.nextPage(),\n enabled: (context) => stageOf(context)?.canGoNext() ?? false,\n },\n {\n id: 'page:previous',\n labelKey: 'commands.page.previous',\n label: 'Previous page',\n icon: 'previous-page',\n shortcut: 'ArrowLeft',\n categories: ['page'],\n run: (context) => stageOf(context)?.previousPage(),\n enabled: (context) => stageOf(context)?.canGoPrevious() ?? false,\n },\n {\n id: 'page:first',\n labelKey: 'commands.page.first',\n label: 'First page',\n icon: 'first-page',\n shortcut: 'Home',\n categories: ['page'],\n run: (context) => stageOf(context)?.goToFirstPage(),\n enabled: (context) => stageOf(context)?.canGoPrevious() ?? false,\n },\n {\n id: 'page:last',\n labelKey: 'commands.page.last',\n label: 'Last page',\n icon: 'last-page',\n shortcut: 'End',\n categories: ['page'],\n run: (context) => stageOf(context)?.goToLastPage(),\n enabled: (context) => stageOf(context)?.canGoNext() ?? false,\n },\n\n // ── view rotation: how the pages show, nothing written to the PDF ──\n {\n id: 'view:rotate-clockwise',\n labelKey: 'commands.view.rotateClockwise',\n label: 'Rotate clockwise',\n icon: 'rotate-clockwise',\n categories: ['view'],\n run: (context) => stageOf(context)?.rotateViewBy(90),\n enabled: hasStage,\n },\n {\n id: 'view:rotate-counterclockwise',\n labelKey: 'commands.view.rotateCounterclockwise',\n label: 'Rotate counterclockwise',\n icon: 'rotate-counterclockwise',\n categories: ['view'],\n run: (context) => stageOf(context)?.rotateViewBy(-90),\n enabled: hasStage,\n },\n\n // ── tools: the two built-in ones have shortcuts; the family covers every other ──\n { ...toolCommand('pointer'), id: 'tool:pointer', shortcut: 'V' },\n { ...toolCommand('pan'), id: 'tool:pan', shortcut: 'H' },\n toolCommands,\n\n // ── selections ──\n {\n id: 'selection:copy',\n labelKey: 'commands.selection.copy',\n label: 'Copy',\n icon: 'copy',\n shortcut: 'Mod+C',\n categories: ['selection'],\n run: (context) => platform.copySelection(context.get(SelectionToken)),\n // `canCopy()` in `enabled`, not `allowed`: a refused command keeps its keys, and Mod+C\n // with nothing selected in the viewer belongs to the page. The clipboard wiring says\n // when a selection may not be copied.\n enabled: (context) => {\n const selection = context.tryGet(SelectionToken);\n return !!selection && selection.hasSelection() && selection.canCopy();\n },\n },\n {\n id: 'annotation:delete',\n labelKey: 'commands.annotation.delete',\n label: 'Delete',\n icon: 'delete',\n shortcut: ['Delete', 'Backspace'],\n categories: ['annotation'],\n run: (context) => context.get(AnnotationToken).selection.delete({ signal: context.signal }),\n enabled: (context) => {\n const annotation = context.tryGet(AnnotationToken);\n if (!annotation) return false;\n const selected = annotation.selection.list();\n // `isEditable`: the annotation plugin's `editable` setting lets people change it by hand.\n return (\n selected.length > 0 &&\n selected.every(({ ref }) => annotation.canDelete(ref) && annotation.isEditable(ref))\n );\n },\n },\n\n // ── the document ──\n {\n id: 'document:download',\n labelKey: 'commands.document.download',\n label: 'Download',\n icon: 'download',\n shortcut: 'Mod+S',\n categories: ['document'],\n allowed: (context) => context.tryGet(DocumentsToken)?.canDownload() ?? true,\n notAllowedKey: 'commands.notAllowed.doc-download',\n run: async (context) => {\n const documents = context.get(DocumentsToken);\n const id = context.documentId ?? undefined;\n const bytes = await documents.download(id, { signal: context.signal });\n platform.saveFile(bytes, fileNameOf(documents.get(id)?.name));\n },\n enabled: (context) => context.documentId !== null,\n },\n {\n id: 'document:print',\n labelKey: 'commands.document.print',\n label: 'Print',\n icon: 'print',\n shortcut: 'Mod+P',\n categories: ['document'],\n allowed: (context) => context.tryGet(DocumentsToken)?.canPrint() ?? true,\n notAllowedKey: 'commands.notAllowed.doc-print',\n // The document's own print actions run around the dialog when the\n // actions plugin is there.\n run: (context) => {\n const actions = context.tryGet(ActionsToken);\n if (actions) return actions.runDocumentVerb('print', () => platform.print());\n platform.print();\n },\n enabled: (context) => context.documentId !== null,\n },\n ];\n}\n\n/** The download's file name: the document's name, ending in `.pdf`. */\nfunction fileNameOf(name: string | undefined): string {\n if (!name) return 'document.pdf';\n return /\\.pdf$/i.test(name) ? name : `${name}.pdf`;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AA4BA,MAAM,WAAW,YAA4B,QAAQ,OAAOA,gCAAAA,UAAU;AACtE,MAAM,iBAAiB,YAA4B,QAAQ,OAAOC,sCAAAA,gBAAgB;;AAGlF,MAAM,YAAY,YAAqC,QAAQ,OAAO,MAAM;;AAG5E,MAAM,0BAAU,IAAI,QAA4C;AAChE,MAAM,SAAS,UAA8C;CAC3D,IAAI,MAAM,QAAQ,IAAI,KAAK;CAC3B,IAAI,CAAC,KAAK;EACR,MAAM,MAAM,KAAK,SAAS,KAAK,EAAE;EACjC,QAAQ,IAAI,OAAO,GAAG;CACxB;CACA,OAAO;AACT;;;;;AAMA,MAAM,cAAc,SAAyB,WAA4B;CACvE,MAAM,aAAa,QAAQ,OAAOC,qCAAAA,eAAe;CACjD,OAAO,CAAC,YAAY,MAAM,IAAI,MAAM,KAAK,WAAW,UAAU;AAChE;;AAGA,MAAM,eAAe,YAAyD;CAC5E,UAAU,iBAAiB;CAC3B,OAAO;CACP,MAAM;CACN,YAAY,CAAC,MAAM;CACnB,MAAM,YAAY,cAAc,OAAO,CAAC,EAAE,aAAa,MAAM;CAC7D,SAAS,YAAY,cAAc,OAAO,CAAC,EAAE,gBAAgB,MAAM;CACnE,UAAU,YAAY,cAAc,OAAO,CAAC,EAAE,QAAQ,MAAM,KAAK;CACjE,UAAU,YAAY,WAAW,SAAS,MAAM;AAClD;;AAGA,MAAM,eAA8B;CAClC,QAAQ;CACR,QAAQ,YAAY;EAClB,MAAM,cAAc,cAAc,OAAO;EACzC,OAAO,cAAc,MAAM,YAAY,UAAU,CAAC,IAAI,CAAC;CACzD;CACA,SAAS;AACX;;AAGA,SAAgB,uBACd,UACyC;CACzC,OAAO;EAEL;GACE,IAAI;GACJ,UAAU;GACV,OAAO;GACP,MAAM;GACN,UAAU,CAAC,SAAS,eAAe;GACnC,YAAY,CAAC,MAAM;GACnB,MAAM,YAAY,QAAQ,OAAO,CAAC,EAAE,OAAO;GAC3C,SAAS;EACX;EACA;GACE,IAAI;GACJ,UAAU;GACV,OAAO;GACP,MAAM;GACN,UAAU,CAAC,SAAS,oBAAoB;GACxC,YAAY,CAAC,MAAM;GACnB,MAAM,YAAY,QAAQ,OAAO,CAAC,EAAE,QAAQ;GAC5C,SAAS;EACX;EACA;GACE,IAAI;GACJ,UAAU;GACV,OAAO;GACP,MAAM;GACN,YAAY,CAAC,MAAM;GACnB,MAAM,YAAY,QAAQ,OAAO,CAAC,EAAE,SAAS;GAC7C,SAAS,YAAY,QAAQ,OAAO,CAAC,EAAE,YAAY,MAAM;GACzD,SAAS;EACX;EACA;GACE,IAAI;GACJ,UAAU;GACV,OAAO;GACP,MAAM;GACN,YAAY,CAAC,MAAM;GACnB,MAAM,YAAY,QAAQ,OAAO,CAAC,EAAE,QAAQ;GAC5C,SAAS,YAAY,QAAQ,OAAO,CAAC,EAAE,YAAY,MAAM;GACzD,SAAS;EACX;EAGA;GACE,IAAI;GACJ,UAAU;GACV,OAAO;GACP,MAAM;GACN,UAAU;GACV,YAAY,CAAC,MAAM;GACnB,MAAM,YAAY,QAAQ,OAAO,CAAC,EAAE,SAAS;GAC7C,UAAU,YAAY,QAAQ,OAAO,CAAC,EAAE,UAAU,KAAK;EACzD;EACA;GACE,IAAI;GACJ,UAAU;GACV,OAAO;GACP,MAAM;GACN,UAAU;GACV,YAAY,CAAC,MAAM;GACnB,MAAM,YAAY,QAAQ,OAAO,CAAC,EAAE,aAAa;GACjD,UAAU,YAAY,QAAQ,OAAO,CAAC,EAAE,cAAc,KAAK;EAC7D;EACA;GACE,IAAI;GACJ,UAAU;GACV,OAAO;GACP,MAAM;GACN,UAAU;GACV,YAAY,CAAC,MAAM;GACnB,MAAM,YAAY,QAAQ,OAAO,CAAC,EAAE,cAAc;GAClD,UAAU,YAAY,QAAQ,OAAO,CAAC,EAAE,cAAc,KAAK;EAC7D;EACA;GACE,IAAI;GACJ,UAAU;GACV,OAAO;GACP,MAAM;GACN,UAAU;GACV,YAAY,CAAC,MAAM;GACnB,MAAM,YAAY,QAAQ,OAAO,CAAC,EAAE,aAAa;GACjD,UAAU,YAAY,QAAQ,OAAO,CAAC,EAAE,UAAU,KAAK;EACzD;EAGA;GACE,IAAI;GACJ,UAAU;GACV,OAAO;GACP,MAAM;GACN,YAAY,CAAC,MAAM;GACnB,MAAM,YAAY,QAAQ,OAAO,CAAC,EAAE,aAAa,EAAE;GACnD,SAAS;EACX;EACA;GACE,IAAI;GACJ,UAAU;GACV,OAAO;GACP,MAAM;GACN,YAAY,CAAC,MAAM;GACnB,MAAM,YAAY,QAAQ,OAAO,CAAC,EAAE,aAAa,GAAG;GACpD,SAAS;EACX;EAGA;GAAE,GAAG,YAAY,SAAS;GAAG,IAAI;GAAgB,UAAU;EAAI;EAC/D;GAAE,GAAG,YAAY,KAAK;GAAG,IAAI;GAAY,UAAU;EAAI;EACvD;EAGA;GACE,IAAI;GACJ,UAAU;GACV,OAAO;GACP,MAAM;GACN,UAAU;GACV,YAAY,CAAC,WAAW;GACxB,MAAM,YAAY,SAAS,cAAc,QAAQ,IAAIC,oCAAAA,cAAc,CAAC;GAIpE,UAAU,YAAY;IACpB,MAAM,YAAY,QAAQ,OAAOA,oCAAAA,cAAc;IAC/C,OAAO,CAAC,CAAC,aAAa,UAAU,aAAa,KAAK,UAAU,QAAQ;GACtE;EACF;EACA;GACE,IAAI;GACJ,UAAU;GACV,OAAO;GACP,MAAM;GACN,UAAU,CAAC,UAAU,WAAW;GAChC,YAAY,CAAC,YAAY;GACzB,MAAM,YAAY,QAAQ,IAAID,qCAAAA,eAAe,CAAC,CAAC,UAAU,OAAO,EAAE,QAAQ,QAAQ,OAAO,CAAC;GAC1F,UAAU,YAAY;IACpB,MAAM,aAAa,QAAQ,OAAOA,qCAAAA,eAAe;IACjD,IAAI,CAAC,YAAY,OAAO;IACxB,MAAM,WAAW,WAAW,UAAU,KAAK;IAE3C,OACE,SAAS,SAAS,KAClB,SAAS,OAAO,EAAE,UAAU,WAAW,UAAU,GAAG,KAAK,WAAW,WAAW,GAAG,CAAC;GAEvF;EACF;EAGA;GACE,IAAI;GACJ,UAAU;GACV,OAAO;GACP,MAAM;GACN,UAAU;GACV,YAAY,CAAC,UAAU;GACvB,UAAU,YAAY,QAAQ,OAAOE,eAAAA,cAAc,CAAC,EAAE,YAAY,KAAK;GACvE,eAAe;GACf,KAAK,OAAO,YAAY;IACtB,MAAM,YAAY,QAAQ,IAAIA,eAAAA,cAAc;IAC5C,MAAM,KAAK,QAAQ,cAAc,KAAA;IACjC,MAAM,QAAQ,MAAM,UAAU,SAAS,IAAI,EAAE,QAAQ,QAAQ,OAAO,CAAC;IACrE,SAAS,SAAS,OAAO,WAAW,UAAU,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC;GAC9D;GACA,UAAU,YAAY,QAAQ,eAAe;EAC/C;EACA;GACE,IAAI;GACJ,UAAU;GACV,OAAO;GACP,MAAM;GACN,UAAU;GACV,YAAY,CAAC,UAAU;GACvB,UAAU,YAAY,QAAQ,OAAOA,eAAAA,cAAc,CAAC,EAAE,SAAS,KAAK;GACpE,eAAe;GAGf,MAAM,YAAY;IAChB,MAAM,UAAU,QAAQ,OAAOC,kCAAAA,YAAY;IAC3C,IAAI,SAAS,OAAO,QAAQ,gBAAgB,eAAe,SAAS,MAAM,CAAC;IAC3E,SAAS,MAAM;GACjB;GACA,UAAU,YAAY,QAAQ,eAAe;EAC/C;CACF;AACF;;AAGA,SAAS,WAAW,MAAkC;CACpD,IAAI,CAAC,MAAM,OAAO;CAClB,OAAO,UAAU,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK;AAC/C"}
|
|
1
|
+
{"version":3,"file":"standard.cjs","names":["StageToken","InteractionToken","AnnotationToken","SelectionToken","DocumentsToken"],"sources":["../src/standard.ts"],"sourcesContent":["/**\n * @embedpdf/plugin-commands/standard — the commands every viewer has: zoom,\n * pages, view rotation, a command for every tool, copy, delete, download and\n * print, with shortcuts, and labels in EmbedPDF's eight languages (the i18n\n * plugin has the strings). Two of them reach the browser (the clipboard, a\n * file download), which plugins never touch, so each framework's `/commands`\n * builds them with its platform: that is the `standardCommands` an app\n * imports. Print goes through the kernel, which has the host's printer.\n */\nimport { DocumentsToken } from '@embedpdf/core';\nimport { AnnotationToken } from '@embedpdf/plugin-annotation/contract';\nimport { InteractionToken, type Tool } from '@embedpdf/plugin-interaction/contract';\nimport { SelectionToken, type SelectionCapability } from '@embedpdf/plugin-selection/contract';\nimport { StageToken } from '@embedpdf/plugin-stage/contract';\n\nimport type { CommandContext, CommandDef, CommandFamily } from './contract';\n\n/** What the standard commands need from the browser. */\nexport interface StandardCommandsPlatform {\n /** Copy the selected text to the clipboard. */\n copySelection(selection: SelectionCapability): Promise<unknown>;\n /** Give the user the bytes as a file download. */\n saveFile(bytes: Uint8Array, fileName: string): void;\n}\n\nconst stageOf = (context: CommandContext) => context.tryGet(StageToken);\nconst interactionOf = (context: CommandContext) => context.tryGet(InteractionToken);\n\n/** Enabled while the document has a Stage. */\nconst hasStage = (context: CommandContext): boolean => stageOf(context) !== null;\n\n/** The ids of a tool list, made once per list, which keeps its identity while the tools don't change. */\nconst toolIds = new WeakMap<readonly Tool[], readonly string[]>();\nconst idsOf = (tools: readonly Tool[]): readonly string[] => {\n let ids = toolIds.get(tools);\n if (!ids) {\n ids = tools.map((tool) => tool.id);\n toolIds.set(tools, ids);\n }\n return ids;\n};\n\n/**\n * Whether the user may use a tool: one that draws annotations needs permission to create them.\n * A tool another plugin owns asks nothing here; that plugin refuses its own gesture.\n */\nconst mayUseTool = (context: CommandContext, toolId: string): boolean => {\n const annotation = context.tryGet(AnnotationToken);\n return !annotation?.tools.get(toolId) || annotation.canCreate();\n};\n\n/** Switching to a tool: active while it's the tool, there only when the document has it. */\nconst toolCommand = (toolId: string): Omit<CommandDef, 'id' | 'shortcut'> => ({\n labelKey: `commands.tool.${toolId}`,\n label: toolId,\n icon: toolId,\n categories: ['tool'],\n run: (context) => interactionOf(context)?.activateTool(toolId),\n active: (context) => interactionOf(context)?.getActiveToolId() === toolId,\n visible: (context) => interactionOf(context)?.hasTool(toolId) ?? false,\n enabled: (context) => mayUseTool(context, toolId),\n});\n\n/** `tool:<id>` for every tool the document has. */\nconst toolCommands: CommandFamily = {\n prefix: 'tool:',\n names: (context) => {\n const interaction = interactionOf(context);\n return interaction ? idsOf(interaction.listTools()) : [];\n },\n command: toolCommand,\n};\n\n/** The standard commands, with the browser's part from `platform`. */\nexport function createStandardCommands(\n platform: StandardCommandsPlatform,\n): readonly (CommandDef | CommandFamily)[] {\n return [\n // ── zoom ──\n {\n id: 'zoom:in',\n labelKey: 'commands.zoom.in',\n label: 'Zoom in',\n icon: 'zoom-in',\n shortcut: ['Mod+=', 'Mod+NumpadAdd'],\n categories: ['zoom'],\n run: (context) => stageOf(context)?.zoomIn(),\n enabled: hasStage,\n },\n {\n id: 'zoom:out',\n labelKey: 'commands.zoom.out',\n label: 'Zoom out',\n icon: 'zoom-out',\n shortcut: ['Mod+-', 'Mod+NumpadSubtract'],\n categories: ['zoom'],\n run: (context) => stageOf(context)?.zoomOut(),\n enabled: hasStage,\n },\n {\n id: 'zoom:fit-width',\n labelKey: 'commands.zoom.fitWidth',\n label: 'Fit width',\n icon: 'fit-width',\n categories: ['zoom'],\n run: (context) => stageOf(context)?.fitWidth(),\n active: (context) => stageOf(context)?.getZoomMode() === 'fit-width',\n enabled: hasStage,\n },\n {\n id: 'zoom:fit-page',\n labelKey: 'commands.zoom.fitPage',\n label: 'Fit page',\n icon: 'fit-page',\n categories: ['zoom'],\n run: (context) => stageOf(context)?.fitPage(),\n active: (context) => stageOf(context)?.getZoomMode() === 'fit-page',\n enabled: hasStage,\n },\n\n // ── pages ──\n {\n id: 'page:next',\n labelKey: 'commands.page.next',\n label: 'Next page',\n icon: 'next-page',\n shortcut: 'ArrowRight',\n categories: ['page'],\n run: (context) => stageOf(context)?.nextPage(),\n enabled: (context) => stageOf(context)?.canGoNext() ?? false,\n },\n {\n id: 'page:previous',\n labelKey: 'commands.page.previous',\n label: 'Previous page',\n icon: 'previous-page',\n shortcut: 'ArrowLeft',\n categories: ['page'],\n run: (context) => stageOf(context)?.previousPage(),\n enabled: (context) => stageOf(context)?.canGoPrevious() ?? false,\n },\n {\n id: 'page:first',\n labelKey: 'commands.page.first',\n label: 'First page',\n icon: 'first-page',\n shortcut: 'Home',\n categories: ['page'],\n run: (context) => stageOf(context)?.goToFirstPage(),\n enabled: (context) => stageOf(context)?.canGoPrevious() ?? false,\n },\n {\n id: 'page:last',\n labelKey: 'commands.page.last',\n label: 'Last page',\n icon: 'last-page',\n shortcut: 'End',\n categories: ['page'],\n run: (context) => stageOf(context)?.goToLastPage(),\n enabled: (context) => stageOf(context)?.canGoNext() ?? false,\n },\n\n // ── view rotation: how the pages show, nothing written to the PDF ──\n {\n id: 'view:rotate-clockwise',\n labelKey: 'commands.view.rotateClockwise',\n label: 'Rotate clockwise',\n icon: 'rotate-clockwise',\n categories: ['view'],\n run: (context) => stageOf(context)?.rotateViewBy(90),\n enabled: hasStage,\n },\n {\n id: 'view:rotate-counterclockwise',\n labelKey: 'commands.view.rotateCounterclockwise',\n label: 'Rotate counterclockwise',\n icon: 'rotate-counterclockwise',\n categories: ['view'],\n run: (context) => stageOf(context)?.rotateViewBy(-90),\n enabled: hasStage,\n },\n\n // ── tools: the two built-in ones have shortcuts; the family covers every other ──\n { ...toolCommand('pointer'), id: 'tool:pointer', shortcut: 'V' },\n { ...toolCommand('pan'), id: 'tool:pan', shortcut: 'H' },\n toolCommands,\n\n // ── selections ──\n {\n id: 'selection:copy',\n labelKey: 'commands.selection.copy',\n label: 'Copy',\n icon: 'copy',\n shortcut: 'Mod+C',\n categories: ['selection'],\n run: (context) => platform.copySelection(context.get(SelectionToken)),\n // `canCopy()` in `enabled`, not `allowed`: a refused command keeps its keys, and Mod+C\n // with nothing selected in the viewer belongs to the page. The clipboard wiring says\n // when a selection may not be copied.\n enabled: (context) => {\n const selection = context.tryGet(SelectionToken);\n return !!selection && selection.hasSelection() && selection.canCopy();\n },\n },\n {\n id: 'annotation:delete',\n labelKey: 'commands.annotation.delete',\n label: 'Delete',\n icon: 'delete',\n shortcut: ['Delete', 'Backspace'],\n categories: ['annotation'],\n run: (context) => context.get(AnnotationToken).selection.delete({ signal: context.signal }),\n enabled: (context) => {\n const annotation = context.tryGet(AnnotationToken);\n if (!annotation) return false;\n const selected = annotation.selection.list();\n // `isEditable`: the annotation plugin's `editable` setting lets people change it by hand.\n return (\n selected.length > 0 &&\n selected.every(({ ref }) => annotation.canDelete(ref) && annotation.isEditable(ref))\n );\n },\n },\n\n // ── the document ──\n {\n id: 'document:download',\n labelKey: 'commands.document.download',\n label: 'Download',\n icon: 'download',\n shortcut: 'Mod+S',\n categories: ['document'],\n allowed: (context) => context.tryGet(DocumentsToken)?.canDownload() ?? true,\n notAllowedKey: 'commands.notAllowed.doc-download',\n run: async (context) => {\n const documents = context.get(DocumentsToken);\n const id = context.documentId ?? undefined;\n const bytes = await documents.download(id, { signal: context.signal });\n platform.saveFile(bytes, fileNameOf(documents.get(id)?.name));\n },\n enabled: (context) => context.documentId !== null,\n },\n {\n id: 'document:print',\n labelKey: 'commands.document.print',\n label: 'Print',\n icon: 'print',\n shortcut: 'Mod+P',\n categories: ['document'],\n allowed: (context) => context.tryGet(DocumentsToken)?.canPrint() ?? true,\n notAllowedKey: 'commands.notAllowed.doc-print',\n // The kernel prints the document's pages, and runs the document's own\n // print actions around the dialog when the actions plugin is there.\n run: async (context) => {\n const documents = context.get(DocumentsToken);\n await documents.print(context.documentId ?? undefined, { signal: context.signal });\n },\n enabled: (context) => context.documentId !== null,\n },\n ];\n}\n\n/** The download's file name: the document's name, ending in `.pdf`. */\nfunction fileNameOf(name: string | undefined): string {\n if (!name) return 'document.pdf';\n return /\\.pdf$/i.test(name) ? name : `${name}.pdf`;\n}\n"],"mappings":"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"}
|
package/dist/standard.d.cts
CHANGED
|
@@ -7,8 +7,6 @@ interface StandardCommandsPlatform {
|
|
|
7
7
|
copySelection(selection: SelectionCapability): Promise<unknown>;
|
|
8
8
|
/** Give the user the bytes as a file download. */
|
|
9
9
|
saveFile(bytes: Uint8Array, fileName: string): void;
|
|
10
|
-
/** Open the print dialog. */
|
|
11
|
-
print(): void;
|
|
12
10
|
}
|
|
13
11
|
/** The standard commands, with the browser's part from `platform`. */
|
|
14
12
|
declare function createStandardCommands(platform: StandardCommandsPlatform): readonly (CommandDef | CommandFamily)[];
|
package/dist/standard.d.ts
CHANGED
|
@@ -7,8 +7,6 @@ interface StandardCommandsPlatform {
|
|
|
7
7
|
copySelection(selection: SelectionCapability): Promise<unknown>;
|
|
8
8
|
/** Give the user the bytes as a file download. */
|
|
9
9
|
saveFile(bytes: Uint8Array, fileName: string): void;
|
|
10
|
-
/** Open the print dialog. */
|
|
11
|
-
print(): void;
|
|
12
10
|
}
|
|
13
11
|
/** The standard commands, with the browser's part from `platform`. */
|
|
14
12
|
declare function createStandardCommands(platform: StandardCommandsPlatform): readonly (CommandDef | CommandFamily)[];
|
package/dist/standard.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { DocumentsToken } from "@embedpdf/core";
|
|
2
|
-
import { ActionsToken } from "@embedpdf/plugin-actions/contract";
|
|
3
2
|
import { AnnotationToken } from "@embedpdf/plugin-annotation/contract";
|
|
4
3
|
import { InteractionToken } from "@embedpdf/plugin-interaction/contract";
|
|
5
4
|
import { SelectionToken } from "@embedpdf/plugin-selection/contract";
|
|
@@ -9,10 +8,10 @@ import { StageToken } from "@embedpdf/plugin-stage/contract";
|
|
|
9
8
|
* @embedpdf/plugin-commands/standard — the commands every viewer has: zoom,
|
|
10
9
|
* pages, view rotation, a command for every tool, copy, delete, download and
|
|
11
10
|
* print, with shortcuts, and labels in EmbedPDF's eight languages (the i18n
|
|
12
|
-
* plugin has the strings).
|
|
13
|
-
* file download
|
|
14
|
-
*
|
|
15
|
-
*
|
|
11
|
+
* plugin has the strings). Two of them reach the browser (the clipboard, a
|
|
12
|
+
* file download), which plugins never touch, so each framework's `/commands`
|
|
13
|
+
* builds them with its platform: that is the `standardCommands` an app
|
|
14
|
+
* imports. Print goes through the kernel, which has the host's printer.
|
|
16
15
|
*/
|
|
17
16
|
const stageOf = (context) => context.tryGet(StageToken);
|
|
18
17
|
const interactionOf = (context) => context.tryGet(InteractionToken);
|
|
@@ -222,10 +221,8 @@ function createStandardCommands(platform) {
|
|
|
222
221
|
categories: ["document"],
|
|
223
222
|
allowed: (context) => context.tryGet(DocumentsToken)?.canPrint() ?? true,
|
|
224
223
|
notAllowedKey: "commands.notAllowed.doc-print",
|
|
225
|
-
run: (context) => {
|
|
226
|
-
|
|
227
|
-
if (actions) return actions.runDocumentVerb("print", () => platform.print());
|
|
228
|
-
platform.print();
|
|
224
|
+
run: async (context) => {
|
|
225
|
+
await context.get(DocumentsToken).print(context.documentId ?? void 0, { signal: context.signal });
|
|
229
226
|
},
|
|
230
227
|
enabled: (context) => context.documentId !== null
|
|
231
228
|
}
|
package/dist/standard.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"standard.js","names":[],"sources":["../src/standard.ts"],"sourcesContent":["/**\n * @embedpdf/plugin-commands/standard — the commands every viewer has: zoom,\n * pages, view rotation, a command for every tool, copy, delete, download and\n * print, with shortcuts, and labels in EmbedPDF's eight languages (the i18n\n * plugin has the strings). Three of them reach the browser (the clipboard, a\n * file download, the print dialog), which plugins never touch, so each\n * framework's `/commands` builds them with its platform: that is the\n * `standardCommands` an app imports.\n */\nimport { DocumentsToken } from '@embedpdf/core';\nimport { ActionsToken } from '@embedpdf/plugin-actions/contract';\nimport { AnnotationToken } from '@embedpdf/plugin-annotation/contract';\nimport { InteractionToken, type Tool } from '@embedpdf/plugin-interaction/contract';\nimport { SelectionToken, type SelectionCapability } from '@embedpdf/plugin-selection/contract';\nimport { StageToken } from '@embedpdf/plugin-stage/contract';\n\nimport type { CommandContext, CommandDef, CommandFamily } from './contract';\n\n/** What the standard commands need from the browser. */\nexport interface StandardCommandsPlatform {\n /** Copy the selected text to the clipboard. */\n copySelection(selection: SelectionCapability): Promise<unknown>;\n /** Give the user the bytes as a file download. */\n saveFile(bytes: Uint8Array, fileName: string): void;\n /** Open the print dialog. */\n print(): void;\n}\n\nconst stageOf = (context: CommandContext) => context.tryGet(StageToken);\nconst interactionOf = (context: CommandContext) => context.tryGet(InteractionToken);\n\n/** Enabled while the document has a Stage. */\nconst hasStage = (context: CommandContext): boolean => stageOf(context) !== null;\n\n/** The ids of a tool list, made once per list, which keeps its identity while the tools don't change. */\nconst toolIds = new WeakMap<readonly Tool[], readonly string[]>();\nconst idsOf = (tools: readonly Tool[]): readonly string[] => {\n let ids = toolIds.get(tools);\n if (!ids) {\n ids = tools.map((tool) => tool.id);\n toolIds.set(tools, ids);\n }\n return ids;\n};\n\n/**\n * Whether the user may use a tool: one that draws annotations needs permission to create them.\n * A tool another plugin owns asks nothing here; that plugin refuses its own gesture.\n */\nconst mayUseTool = (context: CommandContext, toolId: string): boolean => {\n const annotation = context.tryGet(AnnotationToken);\n return !annotation?.tools.get(toolId) || annotation.canCreate();\n};\n\n/** Switching to a tool: active while it's the tool, there only when the document has it. */\nconst toolCommand = (toolId: string): Omit<CommandDef, 'id' | 'shortcut'> => ({\n labelKey: `commands.tool.${toolId}`,\n label: toolId,\n icon: toolId,\n categories: ['tool'],\n run: (context) => interactionOf(context)?.activateTool(toolId),\n active: (context) => interactionOf(context)?.getActiveToolId() === toolId,\n visible: (context) => interactionOf(context)?.hasTool(toolId) ?? false,\n enabled: (context) => mayUseTool(context, toolId),\n});\n\n/** `tool:<id>` for every tool the document has. */\nconst toolCommands: CommandFamily = {\n prefix: 'tool:',\n names: (context) => {\n const interaction = interactionOf(context);\n return interaction ? idsOf(interaction.listTools()) : [];\n },\n command: toolCommand,\n};\n\n/** The standard commands, with the browser's part from `platform`. */\nexport function createStandardCommands(\n platform: StandardCommandsPlatform,\n): readonly (CommandDef | CommandFamily)[] {\n return [\n // ── zoom ──\n {\n id: 'zoom:in',\n labelKey: 'commands.zoom.in',\n label: 'Zoom in',\n icon: 'zoom-in',\n shortcut: ['Mod+=', 'Mod+NumpadAdd'],\n categories: ['zoom'],\n run: (context) => stageOf(context)?.zoomIn(),\n enabled: hasStage,\n },\n {\n id: 'zoom:out',\n labelKey: 'commands.zoom.out',\n label: 'Zoom out',\n icon: 'zoom-out',\n shortcut: ['Mod+-', 'Mod+NumpadSubtract'],\n categories: ['zoom'],\n run: (context) => stageOf(context)?.zoomOut(),\n enabled: hasStage,\n },\n {\n id: 'zoom:fit-width',\n labelKey: 'commands.zoom.fitWidth',\n label: 'Fit width',\n icon: 'fit-width',\n categories: ['zoom'],\n run: (context) => stageOf(context)?.fitWidth(),\n active: (context) => stageOf(context)?.getZoomMode() === 'fit-width',\n enabled: hasStage,\n },\n {\n id: 'zoom:fit-page',\n labelKey: 'commands.zoom.fitPage',\n label: 'Fit page',\n icon: 'fit-page',\n categories: ['zoom'],\n run: (context) => stageOf(context)?.fitPage(),\n active: (context) => stageOf(context)?.getZoomMode() === 'fit-page',\n enabled: hasStage,\n },\n\n // ── pages ──\n {\n id: 'page:next',\n labelKey: 'commands.page.next',\n label: 'Next page',\n icon: 'next-page',\n shortcut: 'ArrowRight',\n categories: ['page'],\n run: (context) => stageOf(context)?.nextPage(),\n enabled: (context) => stageOf(context)?.canGoNext() ?? false,\n },\n {\n id: 'page:previous',\n labelKey: 'commands.page.previous',\n label: 'Previous page',\n icon: 'previous-page',\n shortcut: 'ArrowLeft',\n categories: ['page'],\n run: (context) => stageOf(context)?.previousPage(),\n enabled: (context) => stageOf(context)?.canGoPrevious() ?? false,\n },\n {\n id: 'page:first',\n labelKey: 'commands.page.first',\n label: 'First page',\n icon: 'first-page',\n shortcut: 'Home',\n categories: ['page'],\n run: (context) => stageOf(context)?.goToFirstPage(),\n enabled: (context) => stageOf(context)?.canGoPrevious() ?? false,\n },\n {\n id: 'page:last',\n labelKey: 'commands.page.last',\n label: 'Last page',\n icon: 'last-page',\n shortcut: 'End',\n categories: ['page'],\n run: (context) => stageOf(context)?.goToLastPage(),\n enabled: (context) => stageOf(context)?.canGoNext() ?? false,\n },\n\n // ── view rotation: how the pages show, nothing written to the PDF ──\n {\n id: 'view:rotate-clockwise',\n labelKey: 'commands.view.rotateClockwise',\n label: 'Rotate clockwise',\n icon: 'rotate-clockwise',\n categories: ['view'],\n run: (context) => stageOf(context)?.rotateViewBy(90),\n enabled: hasStage,\n },\n {\n id: 'view:rotate-counterclockwise',\n labelKey: 'commands.view.rotateCounterclockwise',\n label: 'Rotate counterclockwise',\n icon: 'rotate-counterclockwise',\n categories: ['view'],\n run: (context) => stageOf(context)?.rotateViewBy(-90),\n enabled: hasStage,\n },\n\n // ── tools: the two built-in ones have shortcuts; the family covers every other ──\n { ...toolCommand('pointer'), id: 'tool:pointer', shortcut: 'V' },\n { ...toolCommand('pan'), id: 'tool:pan', shortcut: 'H' },\n toolCommands,\n\n // ── selections ──\n {\n id: 'selection:copy',\n labelKey: 'commands.selection.copy',\n label: 'Copy',\n icon: 'copy',\n shortcut: 'Mod+C',\n categories: ['selection'],\n run: (context) => platform.copySelection(context.get(SelectionToken)),\n // `canCopy()` in `enabled`, not `allowed`: a refused command keeps its keys, and Mod+C\n // with nothing selected in the viewer belongs to the page. The clipboard wiring says\n // when a selection may not be copied.\n enabled: (context) => {\n const selection = context.tryGet(SelectionToken);\n return !!selection && selection.hasSelection() && selection.canCopy();\n },\n },\n {\n id: 'annotation:delete',\n labelKey: 'commands.annotation.delete',\n label: 'Delete',\n icon: 'delete',\n shortcut: ['Delete', 'Backspace'],\n categories: ['annotation'],\n run: (context) => context.get(AnnotationToken).selection.delete({ signal: context.signal }),\n enabled: (context) => {\n const annotation = context.tryGet(AnnotationToken);\n if (!annotation) return false;\n const selected = annotation.selection.list();\n // `isEditable`: the annotation plugin's `editable` setting lets people change it by hand.\n return (\n selected.length > 0 &&\n selected.every(({ ref }) => annotation.canDelete(ref) && annotation.isEditable(ref))\n );\n },\n },\n\n // ── the document ──\n {\n id: 'document:download',\n labelKey: 'commands.document.download',\n label: 'Download',\n icon: 'download',\n shortcut: 'Mod+S',\n categories: ['document'],\n allowed: (context) => context.tryGet(DocumentsToken)?.canDownload() ?? true,\n notAllowedKey: 'commands.notAllowed.doc-download',\n run: async (context) => {\n const documents = context.get(DocumentsToken);\n const id = context.documentId ?? undefined;\n const bytes = await documents.download(id, { signal: context.signal });\n platform.saveFile(bytes, fileNameOf(documents.get(id)?.name));\n },\n enabled: (context) => context.documentId !== null,\n },\n {\n id: 'document:print',\n labelKey: 'commands.document.print',\n label: 'Print',\n icon: 'print',\n shortcut: 'Mod+P',\n categories: ['document'],\n allowed: (context) => context.tryGet(DocumentsToken)?.canPrint() ?? true,\n notAllowedKey: 'commands.notAllowed.doc-print',\n // The document's own print actions run around the dialog when the\n // actions plugin is there.\n run: (context) => {\n const actions = context.tryGet(ActionsToken);\n if (actions) return actions.runDocumentVerb('print', () => platform.print());\n platform.print();\n },\n enabled: (context) => context.documentId !== null,\n },\n ];\n}\n\n/** The download's file name: the document's name, ending in `.pdf`. */\nfunction fileNameOf(name: string | undefined): string {\n if (!name) return 'document.pdf';\n return /\\.pdf$/i.test(name) ? name : `${name}.pdf`;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"standard.js","names":[],"sources":["../src/standard.ts"],"sourcesContent":["/**\n * @embedpdf/plugin-commands/standard — the commands every viewer has: zoom,\n * pages, view rotation, a command for every tool, copy, delete, download and\n * print, with shortcuts, and labels in EmbedPDF's eight languages (the i18n\n * plugin has the strings). Two of them reach the browser (the clipboard, a\n * file download), which plugins never touch, so each framework's `/commands`\n * builds them with its platform: that is the `standardCommands` an app\n * imports. Print goes through the kernel, which has the host's printer.\n */\nimport { DocumentsToken } from '@embedpdf/core';\nimport { AnnotationToken } from '@embedpdf/plugin-annotation/contract';\nimport { InteractionToken, type Tool } from '@embedpdf/plugin-interaction/contract';\nimport { SelectionToken, type SelectionCapability } from '@embedpdf/plugin-selection/contract';\nimport { StageToken } from '@embedpdf/plugin-stage/contract';\n\nimport type { CommandContext, CommandDef, CommandFamily } from './contract';\n\n/** What the standard commands need from the browser. */\nexport interface StandardCommandsPlatform {\n /** Copy the selected text to the clipboard. */\n copySelection(selection: SelectionCapability): Promise<unknown>;\n /** Give the user the bytes as a file download. */\n saveFile(bytes: Uint8Array, fileName: string): void;\n}\n\nconst stageOf = (context: CommandContext) => context.tryGet(StageToken);\nconst interactionOf = (context: CommandContext) => context.tryGet(InteractionToken);\n\n/** Enabled while the document has a Stage. */\nconst hasStage = (context: CommandContext): boolean => stageOf(context) !== null;\n\n/** The ids of a tool list, made once per list, which keeps its identity while the tools don't change. */\nconst toolIds = new WeakMap<readonly Tool[], readonly string[]>();\nconst idsOf = (tools: readonly Tool[]): readonly string[] => {\n let ids = toolIds.get(tools);\n if (!ids) {\n ids = tools.map((tool) => tool.id);\n toolIds.set(tools, ids);\n }\n return ids;\n};\n\n/**\n * Whether the user may use a tool: one that draws annotations needs permission to create them.\n * A tool another plugin owns asks nothing here; that plugin refuses its own gesture.\n */\nconst mayUseTool = (context: CommandContext, toolId: string): boolean => {\n const annotation = context.tryGet(AnnotationToken);\n return !annotation?.tools.get(toolId) || annotation.canCreate();\n};\n\n/** Switching to a tool: active while it's the tool, there only when the document has it. */\nconst toolCommand = (toolId: string): Omit<CommandDef, 'id' | 'shortcut'> => ({\n labelKey: `commands.tool.${toolId}`,\n label: toolId,\n icon: toolId,\n categories: ['tool'],\n run: (context) => interactionOf(context)?.activateTool(toolId),\n active: (context) => interactionOf(context)?.getActiveToolId() === toolId,\n visible: (context) => interactionOf(context)?.hasTool(toolId) ?? false,\n enabled: (context) => mayUseTool(context, toolId),\n});\n\n/** `tool:<id>` for every tool the document has. */\nconst toolCommands: CommandFamily = {\n prefix: 'tool:',\n names: (context) => {\n const interaction = interactionOf(context);\n return interaction ? idsOf(interaction.listTools()) : [];\n },\n command: toolCommand,\n};\n\n/** The standard commands, with the browser's part from `platform`. */\nexport function createStandardCommands(\n platform: StandardCommandsPlatform,\n): readonly (CommandDef | CommandFamily)[] {\n return [\n // ── zoom ──\n {\n id: 'zoom:in',\n labelKey: 'commands.zoom.in',\n label: 'Zoom in',\n icon: 'zoom-in',\n shortcut: ['Mod+=', 'Mod+NumpadAdd'],\n categories: ['zoom'],\n run: (context) => stageOf(context)?.zoomIn(),\n enabled: hasStage,\n },\n {\n id: 'zoom:out',\n labelKey: 'commands.zoom.out',\n label: 'Zoom out',\n icon: 'zoom-out',\n shortcut: ['Mod+-', 'Mod+NumpadSubtract'],\n categories: ['zoom'],\n run: (context) => stageOf(context)?.zoomOut(),\n enabled: hasStage,\n },\n {\n id: 'zoom:fit-width',\n labelKey: 'commands.zoom.fitWidth',\n label: 'Fit width',\n icon: 'fit-width',\n categories: ['zoom'],\n run: (context) => stageOf(context)?.fitWidth(),\n active: (context) => stageOf(context)?.getZoomMode() === 'fit-width',\n enabled: hasStage,\n },\n {\n id: 'zoom:fit-page',\n labelKey: 'commands.zoom.fitPage',\n label: 'Fit page',\n icon: 'fit-page',\n categories: ['zoom'],\n run: (context) => stageOf(context)?.fitPage(),\n active: (context) => stageOf(context)?.getZoomMode() === 'fit-page',\n enabled: hasStage,\n },\n\n // ── pages ──\n {\n id: 'page:next',\n labelKey: 'commands.page.next',\n label: 'Next page',\n icon: 'next-page',\n shortcut: 'ArrowRight',\n categories: ['page'],\n run: (context) => stageOf(context)?.nextPage(),\n enabled: (context) => stageOf(context)?.canGoNext() ?? false,\n },\n {\n id: 'page:previous',\n labelKey: 'commands.page.previous',\n label: 'Previous page',\n icon: 'previous-page',\n shortcut: 'ArrowLeft',\n categories: ['page'],\n run: (context) => stageOf(context)?.previousPage(),\n enabled: (context) => stageOf(context)?.canGoPrevious() ?? false,\n },\n {\n id: 'page:first',\n labelKey: 'commands.page.first',\n label: 'First page',\n icon: 'first-page',\n shortcut: 'Home',\n categories: ['page'],\n run: (context) => stageOf(context)?.goToFirstPage(),\n enabled: (context) => stageOf(context)?.canGoPrevious() ?? false,\n },\n {\n id: 'page:last',\n labelKey: 'commands.page.last',\n label: 'Last page',\n icon: 'last-page',\n shortcut: 'End',\n categories: ['page'],\n run: (context) => stageOf(context)?.goToLastPage(),\n enabled: (context) => stageOf(context)?.canGoNext() ?? false,\n },\n\n // ── view rotation: how the pages show, nothing written to the PDF ──\n {\n id: 'view:rotate-clockwise',\n labelKey: 'commands.view.rotateClockwise',\n label: 'Rotate clockwise',\n icon: 'rotate-clockwise',\n categories: ['view'],\n run: (context) => stageOf(context)?.rotateViewBy(90),\n enabled: hasStage,\n },\n {\n id: 'view:rotate-counterclockwise',\n labelKey: 'commands.view.rotateCounterclockwise',\n label: 'Rotate counterclockwise',\n icon: 'rotate-counterclockwise',\n categories: ['view'],\n run: (context) => stageOf(context)?.rotateViewBy(-90),\n enabled: hasStage,\n },\n\n // ── tools: the two built-in ones have shortcuts; the family covers every other ──\n { ...toolCommand('pointer'), id: 'tool:pointer', shortcut: 'V' },\n { ...toolCommand('pan'), id: 'tool:pan', shortcut: 'H' },\n toolCommands,\n\n // ── selections ──\n {\n id: 'selection:copy',\n labelKey: 'commands.selection.copy',\n label: 'Copy',\n icon: 'copy',\n shortcut: 'Mod+C',\n categories: ['selection'],\n run: (context) => platform.copySelection(context.get(SelectionToken)),\n // `canCopy()` in `enabled`, not `allowed`: a refused command keeps its keys, and Mod+C\n // with nothing selected in the viewer belongs to the page. The clipboard wiring says\n // when a selection may not be copied.\n enabled: (context) => {\n const selection = context.tryGet(SelectionToken);\n return !!selection && selection.hasSelection() && selection.canCopy();\n },\n },\n {\n id: 'annotation:delete',\n labelKey: 'commands.annotation.delete',\n label: 'Delete',\n icon: 'delete',\n shortcut: ['Delete', 'Backspace'],\n categories: ['annotation'],\n run: (context) => context.get(AnnotationToken).selection.delete({ signal: context.signal }),\n enabled: (context) => {\n const annotation = context.tryGet(AnnotationToken);\n if (!annotation) return false;\n const selected = annotation.selection.list();\n // `isEditable`: the annotation plugin's `editable` setting lets people change it by hand.\n return (\n selected.length > 0 &&\n selected.every(({ ref }) => annotation.canDelete(ref) && annotation.isEditable(ref))\n );\n },\n },\n\n // ── the document ──\n {\n id: 'document:download',\n labelKey: 'commands.document.download',\n label: 'Download',\n icon: 'download',\n shortcut: 'Mod+S',\n categories: ['document'],\n allowed: (context) => context.tryGet(DocumentsToken)?.canDownload() ?? true,\n notAllowedKey: 'commands.notAllowed.doc-download',\n run: async (context) => {\n const documents = context.get(DocumentsToken);\n const id = context.documentId ?? undefined;\n const bytes = await documents.download(id, { signal: context.signal });\n platform.saveFile(bytes, fileNameOf(documents.get(id)?.name));\n },\n enabled: (context) => context.documentId !== null,\n },\n {\n id: 'document:print',\n labelKey: 'commands.document.print',\n label: 'Print',\n icon: 'print',\n shortcut: 'Mod+P',\n categories: ['document'],\n allowed: (context) => context.tryGet(DocumentsToken)?.canPrint() ?? true,\n notAllowedKey: 'commands.notAllowed.doc-print',\n // The kernel prints the document's pages, and runs the document's own\n // print actions around the dialog when the actions plugin is there.\n run: async (context) => {\n const documents = context.get(DocumentsToken);\n await documents.print(context.documentId ?? undefined, { signal: context.signal });\n },\n enabled: (context) => context.documentId !== null,\n },\n ];\n}\n\n/** The download's file name: the document's name, ending in `.pdf`. */\nfunction fileNameOf(name: string | undefined): string {\n if (!name) return 'document.pdf';\n return /\\.pdf$/i.test(name) ? name : `${name}.pdf`;\n}\n"],"mappings":";;;;;;;;;;;;;;;AAyBA,MAAM,WAAW,YAA4B,QAAQ,OAAO,UAAU;AACtE,MAAM,iBAAiB,YAA4B,QAAQ,OAAO,gBAAgB;;AAGlF,MAAM,YAAY,YAAqC,QAAQ,OAAO,MAAM;;AAG5E,MAAM,0BAAU,IAAI,QAA4C;AAChE,MAAM,SAAS,UAA8C;CAC3D,IAAI,MAAM,QAAQ,IAAI,KAAK;CAC3B,IAAI,CAAC,KAAK;EACR,MAAM,MAAM,KAAK,SAAS,KAAK,EAAE;EACjC,QAAQ,IAAI,OAAO,GAAG;CACxB;CACA,OAAO;AACT;;;;;AAMA,MAAM,cAAc,SAAyB,WAA4B;CACvE,MAAM,aAAa,QAAQ,OAAO,eAAe;CACjD,OAAO,CAAC,YAAY,MAAM,IAAI,MAAM,KAAK,WAAW,UAAU;AAChE;;AAGA,MAAM,eAAe,YAAyD;CAC5E,UAAU,iBAAiB;CAC3B,OAAO;CACP,MAAM;CACN,YAAY,CAAC,MAAM;CACnB,MAAM,YAAY,cAAc,OAAO,CAAC,EAAE,aAAa,MAAM;CAC7D,SAAS,YAAY,cAAc,OAAO,CAAC,EAAE,gBAAgB,MAAM;CACnE,UAAU,YAAY,cAAc,OAAO,CAAC,EAAE,QAAQ,MAAM,KAAK;CACjE,UAAU,YAAY,WAAW,SAAS,MAAM;AAClD;;AAGA,MAAM,eAA8B;CAClC,QAAQ;CACR,QAAQ,YAAY;EAClB,MAAM,cAAc,cAAc,OAAO;EACzC,OAAO,cAAc,MAAM,YAAY,UAAU,CAAC,IAAI,CAAC;CACzD;CACA,SAAS;AACX;;AAGA,SAAgB,uBACd,UACyC;CACzC,OAAO;EAEL;GACE,IAAI;GACJ,UAAU;GACV,OAAO;GACP,MAAM;GACN,UAAU,CAAC,SAAS,eAAe;GACnC,YAAY,CAAC,MAAM;GACnB,MAAM,YAAY,QAAQ,OAAO,CAAC,EAAE,OAAO;GAC3C,SAAS;EACX;EACA;GACE,IAAI;GACJ,UAAU;GACV,OAAO;GACP,MAAM;GACN,UAAU,CAAC,SAAS,oBAAoB;GACxC,YAAY,CAAC,MAAM;GACnB,MAAM,YAAY,QAAQ,OAAO,CAAC,EAAE,QAAQ;GAC5C,SAAS;EACX;EACA;GACE,IAAI;GACJ,UAAU;GACV,OAAO;GACP,MAAM;GACN,YAAY,CAAC,MAAM;GACnB,MAAM,YAAY,QAAQ,OAAO,CAAC,EAAE,SAAS;GAC7C,SAAS,YAAY,QAAQ,OAAO,CAAC,EAAE,YAAY,MAAM;GACzD,SAAS;EACX;EACA;GACE,IAAI;GACJ,UAAU;GACV,OAAO;GACP,MAAM;GACN,YAAY,CAAC,MAAM;GACnB,MAAM,YAAY,QAAQ,OAAO,CAAC,EAAE,QAAQ;GAC5C,SAAS,YAAY,QAAQ,OAAO,CAAC,EAAE,YAAY,MAAM;GACzD,SAAS;EACX;EAGA;GACE,IAAI;GACJ,UAAU;GACV,OAAO;GACP,MAAM;GACN,UAAU;GACV,YAAY,CAAC,MAAM;GACnB,MAAM,YAAY,QAAQ,OAAO,CAAC,EAAE,SAAS;GAC7C,UAAU,YAAY,QAAQ,OAAO,CAAC,EAAE,UAAU,KAAK;EACzD;EACA;GACE,IAAI;GACJ,UAAU;GACV,OAAO;GACP,MAAM;GACN,UAAU;GACV,YAAY,CAAC,MAAM;GACnB,MAAM,YAAY,QAAQ,OAAO,CAAC,EAAE,aAAa;GACjD,UAAU,YAAY,QAAQ,OAAO,CAAC,EAAE,cAAc,KAAK;EAC7D;EACA;GACE,IAAI;GACJ,UAAU;GACV,OAAO;GACP,MAAM;GACN,UAAU;GACV,YAAY,CAAC,MAAM;GACnB,MAAM,YAAY,QAAQ,OAAO,CAAC,EAAE,cAAc;GAClD,UAAU,YAAY,QAAQ,OAAO,CAAC,EAAE,cAAc,KAAK;EAC7D;EACA;GACE,IAAI;GACJ,UAAU;GACV,OAAO;GACP,MAAM;GACN,UAAU;GACV,YAAY,CAAC,MAAM;GACnB,MAAM,YAAY,QAAQ,OAAO,CAAC,EAAE,aAAa;GACjD,UAAU,YAAY,QAAQ,OAAO,CAAC,EAAE,UAAU,KAAK;EACzD;EAGA;GACE,IAAI;GACJ,UAAU;GACV,OAAO;GACP,MAAM;GACN,YAAY,CAAC,MAAM;GACnB,MAAM,YAAY,QAAQ,OAAO,CAAC,EAAE,aAAa,EAAE;GACnD,SAAS;EACX;EACA;GACE,IAAI;GACJ,UAAU;GACV,OAAO;GACP,MAAM;GACN,YAAY,CAAC,MAAM;GACnB,MAAM,YAAY,QAAQ,OAAO,CAAC,EAAE,aAAa,GAAG;GACpD,SAAS;EACX;EAGA;GAAE,GAAG,YAAY,SAAS;GAAG,IAAI;GAAgB,UAAU;EAAI;EAC/D;GAAE,GAAG,YAAY,KAAK;GAAG,IAAI;GAAY,UAAU;EAAI;EACvD;EAGA;GACE,IAAI;GACJ,UAAU;GACV,OAAO;GACP,MAAM;GACN,UAAU;GACV,YAAY,CAAC,WAAW;GACxB,MAAM,YAAY,SAAS,cAAc,QAAQ,IAAI,cAAc,CAAC;GAIpE,UAAU,YAAY;IACpB,MAAM,YAAY,QAAQ,OAAO,cAAc;IAC/C,OAAO,CAAC,CAAC,aAAa,UAAU,aAAa,KAAK,UAAU,QAAQ;GACtE;EACF;EACA;GACE,IAAI;GACJ,UAAU;GACV,OAAO;GACP,MAAM;GACN,UAAU,CAAC,UAAU,WAAW;GAChC,YAAY,CAAC,YAAY;GACzB,MAAM,YAAY,QAAQ,IAAI,eAAe,CAAC,CAAC,UAAU,OAAO,EAAE,QAAQ,QAAQ,OAAO,CAAC;GAC1F,UAAU,YAAY;IACpB,MAAM,aAAa,QAAQ,OAAO,eAAe;IACjD,IAAI,CAAC,YAAY,OAAO;IACxB,MAAM,WAAW,WAAW,UAAU,KAAK;IAE3C,OACE,SAAS,SAAS,KAClB,SAAS,OAAO,EAAE,UAAU,WAAW,UAAU,GAAG,KAAK,WAAW,WAAW,GAAG,CAAC;GAEvF;EACF;EAGA;GACE,IAAI;GACJ,UAAU;GACV,OAAO;GACP,MAAM;GACN,UAAU;GACV,YAAY,CAAC,UAAU;GACvB,UAAU,YAAY,QAAQ,OAAO,cAAc,CAAC,EAAE,YAAY,KAAK;GACvE,eAAe;GACf,KAAK,OAAO,YAAY;IACtB,MAAM,YAAY,QAAQ,IAAI,cAAc;IAC5C,MAAM,KAAK,QAAQ,cAAc,KAAA;IACjC,MAAM,QAAQ,MAAM,UAAU,SAAS,IAAI,EAAE,QAAQ,QAAQ,OAAO,CAAC;IACrE,SAAS,SAAS,OAAO,WAAW,UAAU,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC;GAC9D;GACA,UAAU,YAAY,QAAQ,eAAe;EAC/C;EACA;GACE,IAAI;GACJ,UAAU;GACV,OAAO;GACP,MAAM;GACN,UAAU;GACV,YAAY,CAAC,UAAU;GACvB,UAAU,YAAY,QAAQ,OAAO,cAAc,CAAC,EAAE,SAAS,KAAK;GACpE,eAAe;GAGf,KAAK,OAAO,YAAY;IAEtB,MADkB,QAAQ,IAAI,cAChB,CAAC,CAAC,MAAM,QAAQ,cAAc,KAAA,GAAW,EAAE,QAAQ,QAAQ,OAAO,CAAC;GACnF;GACA,UAAU,YAAY,QAAQ,eAAe;EAC/C;CACF;AACF;;AAGA,SAAS,WAAW,MAAkC;CACpD,IAAI,CAAC,MAAM,OAAO;CAClB,OAAO,UAAU,KAAK,IAAI,IAAI,OAAO,GAAG,KAAK;AAC/C"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@embedpdf/plugin-commands",
|
|
3
|
-
"version": "3.0.0-next.
|
|
3
|
+
"version": "3.0.0-next.16",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "The commands: one name per action of the viewer, with its label, icon, state and shortcut, which toolbars, menus, a command palette and the keyboard all show and run. A command's state is read from live state, so every reader follows the kernel's one change stream. `/standard` has the commands every viewer has.",
|
|
6
6
|
"type": "module",
|
|
@@ -30,15 +30,14 @@
|
|
|
30
30
|
"dist"
|
|
31
31
|
],
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@embedpdf/
|
|
34
|
-
"@embedpdf/core
|
|
35
|
-
"@embedpdf/plugin-
|
|
36
|
-
"@embedpdf/plugin-
|
|
37
|
-
"@embedpdf/
|
|
38
|
-
"@embedpdf/plugin-
|
|
39
|
-
"@embedpdf/plugin-
|
|
40
|
-
"@embedpdf/plugin-stage": "3.0.0-next.
|
|
41
|
-
"@embedpdf/plugin-selection": "3.0.0-next.15"
|
|
33
|
+
"@embedpdf/plugin-i18n": "3.0.0-next.16",
|
|
34
|
+
"@embedpdf/core": "3.0.0-next.16",
|
|
35
|
+
"@embedpdf/plugin-annotation": "3.0.0-next.16",
|
|
36
|
+
"@embedpdf/plugin-selection": "3.0.0-next.16",
|
|
37
|
+
"@embedpdf/core-ui": "3.0.0-next.16",
|
|
38
|
+
"@embedpdf/plugin-shell": "3.0.0-next.16",
|
|
39
|
+
"@embedpdf/plugin-interaction": "3.0.0-next.16",
|
|
40
|
+
"@embedpdf/plugin-stage": "3.0.0-next.16"
|
|
42
41
|
},
|
|
43
42
|
"devDependencies": {
|
|
44
43
|
"typescript": "^5.0.0",
|