@embedpdf/plugin-commands 3.0.0-next.13 → 3.0.0-next.15
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/contract/host.cjs +18 -0
- package/dist/contract/host.cjs.map +1 -0
- package/dist/contract/host.d.cts +3 -0
- package/dist/contract/host.d.ts +3 -0
- package/dist/contract/host.js +13 -0
- package/dist/contract/host.js.map +1 -0
- package/dist/contract-BlOznyrj.cjs +91 -0
- package/dist/contract-BlOznyrj.cjs.map +1 -0
- package/dist/contract-Cj5BTtO7.js +56 -0
- package/dist/contract-Cj5BTtO7.js.map +1 -0
- package/dist/contract-DAV5VR3P.d.cts +295 -0
- package/dist/contract-DAV5VR3P.d.ts +295 -0
- package/dist/contract.cjs +5 -1
- package/dist/contract.d.cts +2 -2
- package/dist/contract.d.ts +2 -2
- package/dist/contract.js +2 -2
- package/dist/host-contract-Cqz-V6kP.d.cts +29 -0
- package/dist/host-contract-DkuusR8r.d.ts +29 -0
- package/dist/index.cjs +463 -130
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -11
- package/dist/index.d.ts +9 -11
- package/dist/index.js +461 -130
- package/dist/index.js.map +1 -1
- package/dist/standard.cjs +243 -0
- package/dist/standard.cjs.map +1 -0
- package/dist/standard.d.cts +17 -0
- package/dist/standard.d.ts +17 -0
- package/dist/standard.js +242 -0
- package/dist/standard.js.map +1 -0
- package/package.json +19 -6
- package/dist/contract-CSIfF6wC.d.cts +0 -137
- package/dist/contract-CSIfF6wC.d.ts +0 -137
- package/dist/contract-DYlaVyVk.cjs +0 -25
- package/dist/contract-DYlaVyVk.cjs.map +0 -1
- package/dist/contract-UFgXphIQ.js +0 -14
- package/dist/contract-UFgXphIQ.js.map +0 -1
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_contract = require("../contract-BlOznyrj.cjs");
|
|
3
|
+
//#region src/host-contract.ts
|
|
4
|
+
/**
|
|
5
|
+
* @embedpdf/plugin-commands/contract/host — the host lens: the keystroke
|
|
6
|
+
* matcher and the menu a command opens, for the toolbar's "More" menu. The
|
|
7
|
+
* same runtime token as the public contract, typed wider.
|
|
8
|
+
*/
|
|
9
|
+
const CommandsToken = (0, require("@embedpdf/core").createHostToken)(require_contract.CommandsToken);
|
|
10
|
+
//#endregion
|
|
11
|
+
exports.COMMANDS_DEFAULTS = require_contract.COMMANDS_DEFAULTS;
|
|
12
|
+
exports.CommandsToken = CommandsToken;
|
|
13
|
+
exports.boundCommandOf = require_contract.boundCommandOf;
|
|
14
|
+
exports.resolvedCommandsEqual = require_contract.resolvedCommandsEqual;
|
|
15
|
+
exports.unknownCommandWarning = require_contract.unknownCommandWarning;
|
|
16
|
+
exports.unregisteredCommand = require_contract.unregisteredCommand;
|
|
17
|
+
|
|
18
|
+
//# sourceMappingURL=host.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host.cjs","names":["PublicCommandsToken"],"sources":["../../src/host-contract.ts"],"sourcesContent":["/**\n * @embedpdf/plugin-commands/contract/host — the host lens: the keystroke\n * matcher and the menu a command opens, for the toolbar's \"More\" menu. The\n * same runtime token as the public contract, typed wider.\n */\nimport { createHostToken } from '@embedpdf/core';\nimport type { KeyStroke } from '@embedpdf/core-ui';\n\nimport type { CommandId, CommandRefusal, CommandsCapability } from './contract';\nimport { CommandsToken as PublicCommandsToken } from './token';\n\nexport * from './contract';\n\n/** The command a keystroke's shortcut names, and why it won't run when it's refused. */\nexport interface ShortcutMatch {\n readonly commandId: CommandId;\n /** Set when the command is turned off or not allowed; `null` when it may run (or just can't right now). */\n readonly refusal: CommandRefusal | null;\n}\n\nexport interface CommandsHostCapability extends CommandsCapability {\n /**\n * The command whose shortcut a keystroke matches, for the active document, or `null`. Of\n * several with the same keys, one that isn't refused wins; a refused one counts only while\n * its `visible` says it would show. With `inTextField` (the key was typed in one), only a\n * command whose `shortcutInTextFields` says so matches.\n */\n matchStroke(\n stroke: KeyStroke,\n options: { isMac: boolean; inTextField?: boolean },\n ): ShortcutMatch | null;\n /** The menu a command opens, for the \"More\" menu's nested menus; `null` for an unknown id. */\n getMenuTarget(id: CommandId): { menu?: string } | null;\n}\n\nexport const CommandsToken = createHostToken<CommandsHostCapability>(PublicCommandsToken);\n"],"mappings":";;;;;;;;AAmCA,MAAa,iBAAA,2BAAA,CAAA,CAAA,gBAAA,CAAwDA,iBAAAA,aAAmB"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { S as unregisteredCommand, _ as RegisterCommandOptions, a as CommandExecutedEvent, b as resolvedCommandsEqual, c as CommandId, d as CommandsConfig, f as CommandsSettings, g as NotAllowedMode, h as IconAccent, i as CommandDef, l as CommandRefusal, m as ExecuteResult, n as COMMANDS_DEFAULTS, o as CommandExecutionFailedEvent, p as ExecuteOptions, r as CommandContext, s as CommandFamily, t as BoundCommand, u as CommandsCapability, v as ResolvedCommand, x as unknownCommandWarning, y as boundCommandOf } from "../contract-DAV5VR3P.cjs";
|
|
2
|
+
import { n as CommandsToken, r as ShortcutMatch, t as CommandsHostCapability } from "../host-contract-Cqz-V6kP.cjs";
|
|
3
|
+
export { BoundCommand, COMMANDS_DEFAULTS, CommandContext, CommandDef, CommandExecutedEvent, CommandExecutionFailedEvent, CommandFamily, CommandId, CommandRefusal, CommandsCapability, CommandsConfig, CommandsHostCapability, CommandsSettings, CommandsToken, ExecuteOptions, ExecuteResult, IconAccent, NotAllowedMode, RegisterCommandOptions, ResolvedCommand, ShortcutMatch, boundCommandOf, resolvedCommandsEqual, unknownCommandWarning, unregisteredCommand };
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { S as unregisteredCommand, _ as RegisterCommandOptions, a as CommandExecutedEvent, b as resolvedCommandsEqual, c as CommandId, d as CommandsConfig, f as CommandsSettings, g as NotAllowedMode, h as IconAccent, i as CommandDef, l as CommandRefusal, m as ExecuteResult, n as COMMANDS_DEFAULTS, o as CommandExecutionFailedEvent, p as ExecuteOptions, r as CommandContext, s as CommandFamily, t as BoundCommand, u as CommandsCapability, v as ResolvedCommand, x as unknownCommandWarning, y as boundCommandOf } from "../contract-DAV5VR3P.js";
|
|
2
|
+
import { n as CommandsToken, r as ShortcutMatch, t as CommandsHostCapability } from "../host-contract-DkuusR8r.js";
|
|
3
|
+
export { BoundCommand, COMMANDS_DEFAULTS, CommandContext, CommandDef, CommandExecutedEvent, CommandExecutionFailedEvent, CommandFamily, CommandId, CommandRefusal, CommandsCapability, CommandsConfig, CommandsHostCapability, CommandsSettings, CommandsToken, ExecuteOptions, ExecuteResult, IconAccent, NotAllowedMode, RegisterCommandOptions, ResolvedCommand, ShortcutMatch, boundCommandOf, resolvedCommandsEqual, unknownCommandWarning, unregisteredCommand };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { a as unregisteredCommand, i as unknownCommandWarning, n as boundCommandOf, o as CommandsToken$1, r as resolvedCommandsEqual, t as COMMANDS_DEFAULTS } from "../contract-Cj5BTtO7.js";
|
|
2
|
+
import { createHostToken } from "@embedpdf/core";
|
|
3
|
+
//#region src/host-contract.ts
|
|
4
|
+
/**
|
|
5
|
+
* @embedpdf/plugin-commands/contract/host — the host lens: the keystroke
|
|
6
|
+
* matcher and the menu a command opens, for the toolbar's "More" menu. The
|
|
7
|
+
* same runtime token as the public contract, typed wider.
|
|
8
|
+
*/
|
|
9
|
+
const CommandsToken = createHostToken(CommandsToken$1);
|
|
10
|
+
//#endregion
|
|
11
|
+
export { COMMANDS_DEFAULTS, CommandsToken, boundCommandOf, resolvedCommandsEqual, unknownCommandWarning, unregisteredCommand };
|
|
12
|
+
|
|
13
|
+
//# sourceMappingURL=host.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host.js","names":["PublicCommandsToken"],"sources":["../../src/host-contract.ts"],"sourcesContent":["/**\n * @embedpdf/plugin-commands/contract/host — the host lens: the keystroke\n * matcher and the menu a command opens, for the toolbar's \"More\" menu. The\n * same runtime token as the public contract, typed wider.\n */\nimport { createHostToken } from '@embedpdf/core';\nimport type { KeyStroke } from '@embedpdf/core-ui';\n\nimport type { CommandId, CommandRefusal, CommandsCapability } from './contract';\nimport { CommandsToken as PublicCommandsToken } from './token';\n\nexport * from './contract';\n\n/** The command a keystroke's shortcut names, and why it won't run when it's refused. */\nexport interface ShortcutMatch {\n readonly commandId: CommandId;\n /** Set when the command is turned off or not allowed; `null` when it may run (or just can't right now). */\n readonly refusal: CommandRefusal | null;\n}\n\nexport interface CommandsHostCapability extends CommandsCapability {\n /**\n * The command whose shortcut a keystroke matches, for the active document, or `null`. Of\n * several with the same keys, one that isn't refused wins; a refused one counts only while\n * its `visible` says it would show. With `inTextField` (the key was typed in one), only a\n * command whose `shortcutInTextFields` says so matches.\n */\n matchStroke(\n stroke: KeyStroke,\n options: { isMac: boolean; inTextField?: boolean },\n ): ShortcutMatch | null;\n /** The menu a command opens, for the \"More\" menu's nested menus; `null` for an unknown id. */\n getMenuTarget(id: CommandId): { menu?: string } | null;\n}\n\nexport const CommandsToken = createHostToken<CommandsHostCapability>(PublicCommandsToken);\n"],"mappings":";;;;;;;;AAmCA,MAAa,gBAAgB,gBAAwCA,eAAmB"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
let _embedpdf_core = require("@embedpdf/core");
|
|
2
|
+
let _embedpdf_core_ui = require("@embedpdf/core-ui");
|
|
3
|
+
//#region src/token.ts
|
|
4
|
+
/** The package token, created once here; `contract.ts` re-exports it and
|
|
5
|
+
* `host-contract.ts` widens it to the host capability. */
|
|
6
|
+
const CommandsToken = (0, _embedpdf_core.createCapabilityToken)("commands", { hint: `add commandsPlugin() from '@embedpdf/plugin-commands' to your plugins list` });
|
|
7
|
+
//#endregion
|
|
8
|
+
//#region src/contract.ts
|
|
9
|
+
/**
|
|
10
|
+
* Whether two resolved commands show the same, for readers that compare what a command looks
|
|
11
|
+
* like rather than which object holds it (a group of commands, or one command for two documents).
|
|
12
|
+
*/
|
|
13
|
+
const resolvedCommandsEqual = (left, right) => {
|
|
14
|
+
if (left === right) return true;
|
|
15
|
+
if (!left || !right) return false;
|
|
16
|
+
return left.id === right.id && left.label === right.label && left.icon === right.icon && left.iconAccent?.primary === right.iconAccent?.primary && left.iconAccent?.secondary === right.iconAccent?.secondary && left.menu === right.menu && left.enabled === right.enabled && left.active === right.active && left.visible === right.visible && left.disabledReason === right.disabledReason && left.shortcuts.length === right.shortcuts.length && left.shortcuts.every((shortcut, index) => shortcut === right.shortcuts[index]);
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* What a component or a toolbar draws for a command id no plugin registered: labelled with its
|
|
20
|
+
* id, neither enabled nor visible, the way a turned-off command is.
|
|
21
|
+
*/
|
|
22
|
+
const unregisteredCommand = (id) => ({
|
|
23
|
+
id,
|
|
24
|
+
label: id,
|
|
25
|
+
shortcuts: [],
|
|
26
|
+
enabled: false,
|
|
27
|
+
active: false,
|
|
28
|
+
visible: false,
|
|
29
|
+
categories: []
|
|
30
|
+
});
|
|
31
|
+
/** What a component that asks for an id no plugin registered hears, in development. */
|
|
32
|
+
const unknownCommandWarning = (id, known) => `no command "${id}"${(0, _embedpdf_core_ui.didYouMean)(id, known)}: it shows as neither visible nor enabled`;
|
|
33
|
+
/**
|
|
34
|
+
* A resolved command, bound for a button: `run` executes it through `execute`, and `shortcut` is
|
|
35
|
+
* its first shortcut formatted for the platform. Which platform is the caller's to know
|
|
36
|
+
* (`isMacPlatform()` in `@embedpdf/web`).
|
|
37
|
+
*/
|
|
38
|
+
function boundCommandOf(command, execute, options) {
|
|
39
|
+
const [first] = command.shortcuts;
|
|
40
|
+
return {
|
|
41
|
+
...command,
|
|
42
|
+
run: () => execute(command.id),
|
|
43
|
+
shortcut: first === void 0 ? null : (0, _embedpdf_core_ui.formatShortcut)(first, { isMac: options.isMac })
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/** What the commands settings are when the app registers none. */
|
|
47
|
+
const COMMANDS_DEFAULTS = {
|
|
48
|
+
commands: [],
|
|
49
|
+
disabledCategories: [],
|
|
50
|
+
disabledCommands: [],
|
|
51
|
+
notAllowed: "hide"
|
|
52
|
+
};
|
|
53
|
+
//#endregion
|
|
54
|
+
Object.defineProperty(exports, "COMMANDS_DEFAULTS", {
|
|
55
|
+
enumerable: true,
|
|
56
|
+
get: function() {
|
|
57
|
+
return COMMANDS_DEFAULTS;
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
Object.defineProperty(exports, "CommandsToken", {
|
|
61
|
+
enumerable: true,
|
|
62
|
+
get: function() {
|
|
63
|
+
return CommandsToken;
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
Object.defineProperty(exports, "boundCommandOf", {
|
|
67
|
+
enumerable: true,
|
|
68
|
+
get: function() {
|
|
69
|
+
return boundCommandOf;
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
Object.defineProperty(exports, "resolvedCommandsEqual", {
|
|
73
|
+
enumerable: true,
|
|
74
|
+
get: function() {
|
|
75
|
+
return resolvedCommandsEqual;
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
Object.defineProperty(exports, "unknownCommandWarning", {
|
|
79
|
+
enumerable: true,
|
|
80
|
+
get: function() {
|
|
81
|
+
return unknownCommandWarning;
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
Object.defineProperty(exports, "unregisteredCommand", {
|
|
85
|
+
enumerable: true,
|
|
86
|
+
get: function() {
|
|
87
|
+
return unregisteredCommand;
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
//# sourceMappingURL=contract-BlOznyrj.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract-BlOznyrj.cjs","names":[],"sources":["../src/token.ts","../src/contract.ts"],"sourcesContent":["/** The package token, created once here; `contract.ts` re-exports it and\n * `host-contract.ts` widens it to the host capability. */\nimport { createCapabilityToken } from '@embedpdf/core';\n\nimport type { CommandsCapability } from './contract';\n\nexport const CommandsToken = createCapabilityToken<CommandsCapability>('commands', {\n hint: `add commandsPlugin() from '@embedpdf/plugin-commands' to your plugins list`,\n});\n","/**\n * @embedpdf/plugin-commands/contract — the commands that toolbars, menus,\n * shortcuts and a command palette all show and run.\n *\n * A command's state is read from live state: `resolveCommand` asks the other\n * capabilities when it's called, so every reader follows the kernel's one\n * change stream, with no events. Definitions hold functions, so they live in\n * the settings and the plugin's registry, never in state.\n */\nimport type {\n CapabilityToken,\n DeepPartial,\n EventHook,\n OperationOptions,\n Permission,\n PluginErrorInfo,\n SettingsApi,\n Unsubscribe,\n} from '@embedpdf/core';\nimport { didYouMean, formatShortcut } from '@embedpdf/core-ui';\n\nexport { CommandsToken } from './token';\n\nexport type CommandId = string;\n\n/**\n * What a command's derivations and `run` see: capabilities resolved for the command's document\n * (the one named, else the document in scope, else the active one).\n */\nexport interface CommandContext {\n /** The command's document, or `null` when none is open. */\n readonly documentId: string | null;\n /** What the caller passed: `execute(id, { args })`. */\n readonly args?: unknown;\n /** Fires when the caller cancels `execute()`: pass it on to the calls `run` makes. */\n readonly signal?: AbortSignal;\n /** A capability, for the command's document when the plugin is document-scoped. Throws when it isn't available. */\n get<T>(token: CapabilityToken<T>): T;\n /** Like `get`, but `null` when the capability isn't available (no plugin, no document). */\n tryGet<T>(token: CapabilityToken<T>): T | null;\n}\n\n/**\n * Up to two colors that go with a command's icon, such as a tool's current color: data a\n * renderer may use (tint the icon, show a swatch), like `icon` itself.\n */\nexport interface IconAccent {\n /** The mark: a stroke, the markup or the text color. */\n readonly primary?: string;\n /** The fill, when there is one. */\n readonly secondary?: string;\n}\n\n/** One command, as you define it. */\nexport interface CommandDef {\n /** A unique name, by convention `area:action`: `'zoom:in'`, `'review:approve'`. */\n readonly id: string;\n /** What the user sees. With `labelKey` too, it's what shows when no language has the key. */\n readonly label?: string;\n /**\n * A translation key for the label, read through the i18n plugin. Without the plugin, or a\n * string for the key, the command shows `label`, else the key.\n */\n readonly labelKey?: string;\n /** Your icon's name; your buttons turn it into an icon. */\n readonly icon?: string;\n /** Colors for the icon, read from live state like `active`. */\n readonly iconAccent?: (context: CommandContext) => IconAccent | null;\n /** A key such as `'Mod+K'` (`Mod` is Cmd on a Mac, Ctrl elsewhere), or a list of them. */\n readonly shortcut?: string | readonly string[];\n /**\n * Whether its shortcut also runs while the cursor is in a text field where the shortcuts\n * listen (a search box, a comment), as the viewer's Find does. Default false: a key typed in\n * a field is the field's.\n */\n readonly shortcutInTextFields?: boolean;\n /**\n * The features it belongs to, so turning one off turns it off: `['annotations.highlight']`.\n * Turning off a feature turns off every feature under it, on whole dotted parts: `annotations`\n * covers `annotations.highlight`, not `annotationsExtra`.\n */\n readonly categories?: readonly string[];\n /**\n * The scope permissions it needs, such as `'doc.annotate.modify'`, checked against its\n * document. Without them it's hidden, or shown disabled with its reason under the\n * `notAllowed: 'disable'` setting. With no document open there is nothing to check.\n */\n readonly requires?: readonly Permission[];\n /**\n * Whether the session may run it, from the plugins' `can*` checks\n * (`documents.canPrint()`), for a command whose permission is a plugin's to know. When it\n * says no, the command isn't allowed, as with `requires`. Asked only while a document is\n * open; one that throws allows it.\n */\n readonly allowed?: (context: CommandContext) => boolean;\n /**\n * The translation key of the sentence that says why `allowed` refused it, with `{label}` for\n * its label: `'commands.notAllowed.doc-print'`. Without it, or a string for it,\n * `commands.notAllowed.default`.\n */\n readonly notAllowedKey?: string;\n\n // ── what the command opens ───────────────────────────────────────────────\n // A command that opens a panel, menu or dialog says so instead of opening\n // it in `run`: it then needs no `run`, it shows as active while the surface\n // is open, and a button can show that it opens a menu.\n /** Opens and closes a menu of yours, by its id. */\n readonly menu?: string;\n /**\n * Opens and closes a panel, closing the others with the same `exclusive` tag. With `focus`,\n * opening it asks for the cursor (the shell's `open(id, { focus: true })`).\n */\n readonly panel?:\n | string\n | { readonly id: string; readonly exclusive?: string; readonly focus?: boolean };\n /** Opens and closes a dialog; one dialog is open at a time. */\n readonly modal?: string;\n\n // ── read from live state, again whenever anything changes ────────────────\n /** When it can run. Default: always. */\n readonly enabled?: (context: CommandContext) => boolean;\n /** When it shows as pressed, such as the current tool. */\n readonly active?: (context: CommandContext) => boolean;\n /** When it shows at all. Default: always. */\n readonly visible?: (context: CommandContext) => boolean;\n\n /** What it does; `execute()` resolves once it has. Not needed for a `menu`, `panel` or `modal`. */\n readonly run?: (context: CommandContext) => void | Promise<unknown>;\n}\n\n/**\n * A command for each of a set of names, made from one definition, such as `tool:<id>` for every\n * tool a document has. Its commands resolve and run like any other, and `listCommands()` lists\n * one per name. A command defined with the same id wins over the family's.\n */\nexport interface CommandFamily {\n /** Where the commands' ids start: `'tool:'` makes `tool:highlight`. */\n readonly prefix: string;\n /** The names the command's document has, in order. Return the same array while nothing changed. */\n readonly names: (context: CommandContext) => readonly string[];\n /** The command for one name. A family's commands have no shortcuts. */\n readonly command: (name: string) => Omit<CommandDef, 'id' | 'shortcut'>;\n}\n\n/** A command as a button shows it: everything read for its document. */\nexport interface ResolvedCommand {\n readonly id: string;\n readonly label: string;\n readonly icon?: string;\n readonly iconAccent?: IconAccent;\n readonly shortcuts: readonly string[];\n readonly menu?: string;\n readonly enabled: boolean;\n readonly active: boolean;\n readonly visible: boolean;\n readonly categories: readonly string[];\n /**\n * Why it's disabled, as a sentence for its tooltip: set when the scope doesn't allow it and\n * the `notAllowed` setting is `'disable'`.\n */\n readonly disabledReason?: string;\n}\n\n/**\n * Why a command won't run whatever the moment: it's turned off in this viewer\n * (`disabledCategories`, `disabledCommands`), or the scope doesn't allow it (`requires`).\n * A command that only can't run right now (`enabled`, `visible`) has no refusal.\n */\nexport interface CommandRefusal {\n readonly reason: 'turned-off' | 'not-allowed';\n /** A sentence for the user, translated through the i18n plugin when it's there. */\n readonly message: string;\n}\n\n/**\n * Whether two resolved commands show the same, for readers that compare what a command looks\n * like rather than which object holds it (a group of commands, or one command for two documents).\n */\nexport const resolvedCommandsEqual = (\n left: ResolvedCommand | null,\n right: ResolvedCommand | null,\n): boolean => {\n if (left === right) return true;\n if (!left || !right) return false;\n return (\n left.id === right.id &&\n left.label === right.label &&\n left.icon === right.icon &&\n left.iconAccent?.primary === right.iconAccent?.primary &&\n left.iconAccent?.secondary === right.iconAccent?.secondary &&\n left.menu === right.menu &&\n left.enabled === right.enabled &&\n left.active === right.active &&\n left.visible === right.visible &&\n left.disabledReason === right.disabledReason &&\n left.shortcuts.length === right.shortcuts.length &&\n left.shortcuts.every((shortcut, index) => shortcut === right.shortcuts[index])\n );\n};\n\n/**\n * What a component or a toolbar draws for a command id no plugin registered: labelled with its\n * id, neither enabled nor visible, the way a turned-off command is.\n */\nexport const unregisteredCommand = (id: CommandId): ResolvedCommand => ({\n id,\n label: id,\n shortcuts: [],\n enabled: false,\n active: false,\n visible: false,\n categories: [],\n});\n\n/** What a component that asks for an id no plugin registered hears, in development. */\nexport const unknownCommandWarning = (id: CommandId, known: Iterable<CommandId>): string =>\n `no command \"${id}\"${didYouMean(id, known)}: it shows as neither visible nor enabled`;\n\n/** A command with everything a button needs: what it shows, `run`, and its shortcut for a tooltip. */\nexport interface BoundCommand extends ResolvedCommand {\n /** Run the command for the document it was read for. */\n readonly run: () => Promise<ExecuteResult>;\n /** Its first shortcut, formatted for the platform (`'⌘K'` on a Mac, `'Ctrl+K'` elsewhere), or `null`. */\n readonly shortcut: string | null;\n}\n\n/**\n * A resolved command, bound for a button: `run` executes it through `execute`, and `shortcut` is\n * its first shortcut formatted for the platform. Which platform is the caller's to know\n * (`isMacPlatform()` in `@embedpdf/web`).\n */\nexport function boundCommandOf(\n command: ResolvedCommand,\n execute: (id: CommandId) => Promise<ExecuteResult>,\n options: { readonly isMac: boolean },\n): BoundCommand {\n const [first] = command.shortcuts;\n return {\n ...command,\n run: () => execute(command.id),\n shortcut: first === undefined ? null : formatShortcut(first, { isMac: options.isMac }),\n };\n}\n\n/**\n * The commands plugin's settings. `commandsPlugin(config)` registers them over\n * {@link COMMANDS_DEFAULTS}, and `updateSettings()` changes them while the app runs.\n */\nexport interface CommandsSettings {\n /** The commands your viewer has. A later definition with an id that's taken replaces the earlier one. */\n readonly commands: readonly (CommandDef | CommandFamily)[];\n /**\n * Categories turned off, with every category under them: their commands are hidden and\n * refused wherever they appear.\n */\n readonly disabledCategories: readonly string[];\n /** Commands turned off one by one, by id: hidden and refused wherever they appear. */\n readonly disabledCommands: readonly CommandId[];\n /**\n * What a command the scope doesn't allow does: `'hide'` leaves it out, `'disable'` shows it\n * disabled, with the reason in its `disabledReason`.\n */\n readonly notAllowed: NotAllowedMode;\n}\n\n/** How a command shows when the scope doesn't allow it: hidden, or disabled with its reason. */\nexport type NotAllowedMode = 'hide' | 'disable';\n\n/** What the commands settings are when the app registers none. */\nexport const COMMANDS_DEFAULTS: CommandsSettings = {\n commands: [],\n disabledCategories: [],\n disabledCommands: [],\n notAllowed: 'hide',\n};\n\n/** What `commandsPlugin(config)` takes: any of the settings, merged over the defaults. */\nexport type CommandsConfig = DeepPartial<CommandsSettings>;\n\nexport interface RegisterCommandOptions {\n /** Replace a command with the same id; without it, a taken id throws `conflict`. */\n replace?: boolean;\n}\n\nexport interface ExecuteOptions extends OperationOptions {\n /** The document to run it for; the document in scope, else the active one, when left out. */\n documentId?: string;\n /** Passed to the command's `run` and derivations as `args`. */\n args?: unknown;\n}\n\n/** How `execute()` went: it ran, or it was refused before running, and why. */\nexport type ExecuteResult =\n | { readonly status: 'executed' }\n | { readonly status: 'rejected'; readonly reason: 'not-found' | 'disabled' | 'hidden' };\n\n// ── events ──\nexport interface CommandExecutedEvent {\n readonly commandId: CommandId;\n readonly documentId: string | null;\n readonly args: unknown;\n}\nexport interface CommandExecutionFailedEvent {\n readonly commandId: CommandId;\n readonly documentId: string | null;\n readonly error: PluginErrorInfo;\n}\n\n/**\n * The commands. A call that leaves out the document is for the document in scope when the\n * capability was resolved for one (`ctx.forDocument`, a `<DocumentScope>`), and for the active\n * document otherwise.\n */\nexport interface CommandsCapability extends SettingsApi<CommandsSettings> {\n // ── the commands ──\n /**\n * Add a command while the app runs, and get a function that removes it. A taken id throws\n * `conflict` unless `replace`.\n */\n registerCommand(definition: CommandDef, options?: RegisterCommandOptions): Unsubscribe;\n /** `registerCommand` for several definitions; the function removes all of them. */\n registerCommands(\n definitions: readonly CommandDef[],\n options?: RegisterCommandOptions,\n ): Unsubscribe;\n /** Whether a command has this id; with a family, every id that starts with its prefix does. */\n hasCommand(id: CommandId): boolean;\n /** A command as you defined it, or `null`. */\n getCommand(id: CommandId): CommandDef | null;\n /** Every command's id for the active document, in the order they were added. The same array until one changes. */\n listCommandIds(): readonly CommandId[];\n\n // ── what a button shows ──\n /** A command as a button shows it, or `null` for an unknown id. The same object while nothing about it changed. */\n resolveCommand(id: CommandId, documentId?: string): ResolvedCommand | null;\n /** Every command, resolved, in the order they were added. The same array while nothing changed. */\n listCommands(documentId?: string): readonly ResolvedCommand[];\n /** The visible commands whose label or id contains the query, for a command palette. */\n searchCommands(query: string, documentId?: string): readonly ResolvedCommand[];\n /** Every shortcut with its command, for a keyboard help sheet. The same array until the commands change. */\n listShortcuts(): readonly { readonly commandId: CommandId; readonly shortcut: string }[];\n\n // ── running them ──\n /**\n * Run a command; resolves once its `run` has, with `{ status: 'executed' }` and\n * `onExecuted`, or `{ status: 'rejected', reason }` for a command that is unknown, hidden or\n * disabled (a command turned off is hidden). A `run` that throws fires `onExecutionFailed` and rejects with its `PluginError`;\n * the signal rejects `operation-cancelled`.\n */\n execute(id: CommandId, options?: ExecuteOptions): Promise<ExecuteResult>;\n /** Whether a command can run now: it exists, and is enabled and visible. */\n canExecute(id: CommandId, documentId?: string): boolean;\n /**\n * Why a command won't run whatever the moment: it's turned off, or not allowed for its\n * document. `null` when it may run (or only can't right now), and for an unknown id.\n */\n getRefusal(id: CommandId, documentId?: string): CommandRefusal | null;\n\n // ── turning commands off ──\n /** The categories turned off. */\n getDisabledCategories(): readonly string[];\n /** Whether a category is turned off: it, or a category it's under (`annotations` for `annotations.highlight`). */\n isCategoryDisabled(category: string): boolean;\n /** Turn a category off, with every category under it: the `disabledCategories` setting gains it. */\n disableCategory(category: string): void;\n /** Turn a category on again. */\n enableCategory(category: string): void;\n /** Replace the categories that are off. */\n setDisabledCategories(categories: readonly string[]): void;\n /** The commands turned off one by one. */\n getDisabledCommands(): readonly CommandId[];\n /** Whether a command is turned off: by its id, or through one of its categories. */\n isCommandDisabled(id: CommandId): boolean;\n /** Turn one command off: the `disabledCommands` setting gains it. */\n disableCommand(id: CommandId): void;\n /** Turn a command on again; it stays off while one of its categories is. */\n enableCommand(id: CommandId): void;\n /** Replace the commands that are off one by one. */\n setDisabledCommands(ids: readonly CommandId[]): void;\n\n // ── events ──\n /** A command ran. */\n readonly onExecuted: EventHook<CommandExecutedEvent>;\n /** A command's `run` threw; `execute` rejects with the same error. */\n readonly onExecutionFailed: EventHook<CommandExecutionFailedEvent>;\n}\n"],"mappings":";;;;;AAMA,MAAa,iBAAA,GAAA,eAAA,sBAAA,CAA0D,YAAY,EACjF,MAAM,6EACR,CAAC;;;;;;;AC0KD,MAAa,yBACX,MACA,UACY;CACZ,IAAI,SAAS,OAAO,OAAO;CAC3B,IAAI,CAAC,QAAQ,CAAC,OAAO,OAAO;CAC5B,OACE,KAAK,OAAO,MAAM,MAClB,KAAK,UAAU,MAAM,SACrB,KAAK,SAAS,MAAM,QACpB,KAAK,YAAY,YAAY,MAAM,YAAY,WAC/C,KAAK,YAAY,cAAc,MAAM,YAAY,aACjD,KAAK,SAAS,MAAM,QACpB,KAAK,YAAY,MAAM,WACvB,KAAK,WAAW,MAAM,UACtB,KAAK,YAAY,MAAM,WACvB,KAAK,mBAAmB,MAAM,kBAC9B,KAAK,UAAU,WAAW,MAAM,UAAU,UAC1C,KAAK,UAAU,OAAO,UAAU,UAAU,aAAa,MAAM,UAAU,MAAM;AAEjF;;;;;AAMA,MAAa,uBAAuB,QAAoC;CACtE;CACA,OAAO;CACP,WAAW,CAAC;CACZ,SAAS;CACT,QAAQ;CACR,SAAS;CACT,YAAY,CAAC;AACf;;AAGA,MAAa,yBAAyB,IAAe,UACnD,eAAe,GAAG,IAAA,GAAA,kBAAA,WAAA,CAAc,IAAI,KAAK,EAAE;;;;;;AAe7C,SAAgB,eACd,SACA,SACA,SACc;CACd,MAAM,CAAC,SAAS,QAAQ;CACxB,OAAO;EACL,GAAG;EACH,WAAW,QAAQ,QAAQ,EAAE;EAC7B,UAAU,UAAU,KAAA,IAAY,QAAA,GAAA,kBAAA,eAAA,CAAsB,OAAO,EAAE,OAAO,QAAQ,MAAM,CAAC;CACvF;AACF;;AA2BA,MAAa,oBAAsC;CACjD,UAAU,CAAC;CACX,oBAAoB,CAAC;CACrB,kBAAkB,CAAC;CACnB,YAAY;AACd"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { createCapabilityToken } from "@embedpdf/core";
|
|
2
|
+
import { didYouMean, formatShortcut } from "@embedpdf/core-ui";
|
|
3
|
+
//#region src/token.ts
|
|
4
|
+
/** The package token, created once here; `contract.ts` re-exports it and
|
|
5
|
+
* `host-contract.ts` widens it to the host capability. */
|
|
6
|
+
const CommandsToken = createCapabilityToken("commands", { hint: `add commandsPlugin() from '@embedpdf/plugin-commands' to your plugins list` });
|
|
7
|
+
//#endregion
|
|
8
|
+
//#region src/contract.ts
|
|
9
|
+
/**
|
|
10
|
+
* Whether two resolved commands show the same, for readers that compare what a command looks
|
|
11
|
+
* like rather than which object holds it (a group of commands, or one command for two documents).
|
|
12
|
+
*/
|
|
13
|
+
const resolvedCommandsEqual = (left, right) => {
|
|
14
|
+
if (left === right) return true;
|
|
15
|
+
if (!left || !right) return false;
|
|
16
|
+
return left.id === right.id && left.label === right.label && left.icon === right.icon && left.iconAccent?.primary === right.iconAccent?.primary && left.iconAccent?.secondary === right.iconAccent?.secondary && left.menu === right.menu && left.enabled === right.enabled && left.active === right.active && left.visible === right.visible && left.disabledReason === right.disabledReason && left.shortcuts.length === right.shortcuts.length && left.shortcuts.every((shortcut, index) => shortcut === right.shortcuts[index]);
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* What a component or a toolbar draws for a command id no plugin registered: labelled with its
|
|
20
|
+
* id, neither enabled nor visible, the way a turned-off command is.
|
|
21
|
+
*/
|
|
22
|
+
const unregisteredCommand = (id) => ({
|
|
23
|
+
id,
|
|
24
|
+
label: id,
|
|
25
|
+
shortcuts: [],
|
|
26
|
+
enabled: false,
|
|
27
|
+
active: false,
|
|
28
|
+
visible: false,
|
|
29
|
+
categories: []
|
|
30
|
+
});
|
|
31
|
+
/** What a component that asks for an id no plugin registered hears, in development. */
|
|
32
|
+
const unknownCommandWarning = (id, known) => `no command "${id}"${didYouMean(id, known)}: it shows as neither visible nor enabled`;
|
|
33
|
+
/**
|
|
34
|
+
* A resolved command, bound for a button: `run` executes it through `execute`, and `shortcut` is
|
|
35
|
+
* its first shortcut formatted for the platform. Which platform is the caller's to know
|
|
36
|
+
* (`isMacPlatform()` in `@embedpdf/web`).
|
|
37
|
+
*/
|
|
38
|
+
function boundCommandOf(command, execute, options) {
|
|
39
|
+
const [first] = command.shortcuts;
|
|
40
|
+
return {
|
|
41
|
+
...command,
|
|
42
|
+
run: () => execute(command.id),
|
|
43
|
+
shortcut: first === void 0 ? null : formatShortcut(first, { isMac: options.isMac })
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/** What the commands settings are when the app registers none. */
|
|
47
|
+
const COMMANDS_DEFAULTS = {
|
|
48
|
+
commands: [],
|
|
49
|
+
disabledCategories: [],
|
|
50
|
+
disabledCommands: [],
|
|
51
|
+
notAllowed: "hide"
|
|
52
|
+
};
|
|
53
|
+
//#endregion
|
|
54
|
+
export { unregisteredCommand as a, unknownCommandWarning as i, boundCommandOf as n, CommandsToken as o, resolvedCommandsEqual as r, COMMANDS_DEFAULTS as t };
|
|
55
|
+
|
|
56
|
+
//# sourceMappingURL=contract-Cj5BTtO7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contract-Cj5BTtO7.js","names":[],"sources":["../src/token.ts","../src/contract.ts"],"sourcesContent":["/** The package token, created once here; `contract.ts` re-exports it and\n * `host-contract.ts` widens it to the host capability. */\nimport { createCapabilityToken } from '@embedpdf/core';\n\nimport type { CommandsCapability } from './contract';\n\nexport const CommandsToken = createCapabilityToken<CommandsCapability>('commands', {\n hint: `add commandsPlugin() from '@embedpdf/plugin-commands' to your plugins list`,\n});\n","/**\n * @embedpdf/plugin-commands/contract — the commands that toolbars, menus,\n * shortcuts and a command palette all show and run.\n *\n * A command's state is read from live state: `resolveCommand` asks the other\n * capabilities when it's called, so every reader follows the kernel's one\n * change stream, with no events. Definitions hold functions, so they live in\n * the settings and the plugin's registry, never in state.\n */\nimport type {\n CapabilityToken,\n DeepPartial,\n EventHook,\n OperationOptions,\n Permission,\n PluginErrorInfo,\n SettingsApi,\n Unsubscribe,\n} from '@embedpdf/core';\nimport { didYouMean, formatShortcut } from '@embedpdf/core-ui';\n\nexport { CommandsToken } from './token';\n\nexport type CommandId = string;\n\n/**\n * What a command's derivations and `run` see: capabilities resolved for the command's document\n * (the one named, else the document in scope, else the active one).\n */\nexport interface CommandContext {\n /** The command's document, or `null` when none is open. */\n readonly documentId: string | null;\n /** What the caller passed: `execute(id, { args })`. */\n readonly args?: unknown;\n /** Fires when the caller cancels `execute()`: pass it on to the calls `run` makes. */\n readonly signal?: AbortSignal;\n /** A capability, for the command's document when the plugin is document-scoped. Throws when it isn't available. */\n get<T>(token: CapabilityToken<T>): T;\n /** Like `get`, but `null` when the capability isn't available (no plugin, no document). */\n tryGet<T>(token: CapabilityToken<T>): T | null;\n}\n\n/**\n * Up to two colors that go with a command's icon, such as a tool's current color: data a\n * renderer may use (tint the icon, show a swatch), like `icon` itself.\n */\nexport interface IconAccent {\n /** The mark: a stroke, the markup or the text color. */\n readonly primary?: string;\n /** The fill, when there is one. */\n readonly secondary?: string;\n}\n\n/** One command, as you define it. */\nexport interface CommandDef {\n /** A unique name, by convention `area:action`: `'zoom:in'`, `'review:approve'`. */\n readonly id: string;\n /** What the user sees. With `labelKey` too, it's what shows when no language has the key. */\n readonly label?: string;\n /**\n * A translation key for the label, read through the i18n plugin. Without the plugin, or a\n * string for the key, the command shows `label`, else the key.\n */\n readonly labelKey?: string;\n /** Your icon's name; your buttons turn it into an icon. */\n readonly icon?: string;\n /** Colors for the icon, read from live state like `active`. */\n readonly iconAccent?: (context: CommandContext) => IconAccent | null;\n /** A key such as `'Mod+K'` (`Mod` is Cmd on a Mac, Ctrl elsewhere), or a list of them. */\n readonly shortcut?: string | readonly string[];\n /**\n * Whether its shortcut also runs while the cursor is in a text field where the shortcuts\n * listen (a search box, a comment), as the viewer's Find does. Default false: a key typed in\n * a field is the field's.\n */\n readonly shortcutInTextFields?: boolean;\n /**\n * The features it belongs to, so turning one off turns it off: `['annotations.highlight']`.\n * Turning off a feature turns off every feature under it, on whole dotted parts: `annotations`\n * covers `annotations.highlight`, not `annotationsExtra`.\n */\n readonly categories?: readonly string[];\n /**\n * The scope permissions it needs, such as `'doc.annotate.modify'`, checked against its\n * document. Without them it's hidden, or shown disabled with its reason under the\n * `notAllowed: 'disable'` setting. With no document open there is nothing to check.\n */\n readonly requires?: readonly Permission[];\n /**\n * Whether the session may run it, from the plugins' `can*` checks\n * (`documents.canPrint()`), for a command whose permission is a plugin's to know. When it\n * says no, the command isn't allowed, as with `requires`. Asked only while a document is\n * open; one that throws allows it.\n */\n readonly allowed?: (context: CommandContext) => boolean;\n /**\n * The translation key of the sentence that says why `allowed` refused it, with `{label}` for\n * its label: `'commands.notAllowed.doc-print'`. Without it, or a string for it,\n * `commands.notAllowed.default`.\n */\n readonly notAllowedKey?: string;\n\n // ── what the command opens ───────────────────────────────────────────────\n // A command that opens a panel, menu or dialog says so instead of opening\n // it in `run`: it then needs no `run`, it shows as active while the surface\n // is open, and a button can show that it opens a menu.\n /** Opens and closes a menu of yours, by its id. */\n readonly menu?: string;\n /**\n * Opens and closes a panel, closing the others with the same `exclusive` tag. With `focus`,\n * opening it asks for the cursor (the shell's `open(id, { focus: true })`).\n */\n readonly panel?:\n | string\n | { readonly id: string; readonly exclusive?: string; readonly focus?: boolean };\n /** Opens and closes a dialog; one dialog is open at a time. */\n readonly modal?: string;\n\n // ── read from live state, again whenever anything changes ────────────────\n /** When it can run. Default: always. */\n readonly enabled?: (context: CommandContext) => boolean;\n /** When it shows as pressed, such as the current tool. */\n readonly active?: (context: CommandContext) => boolean;\n /** When it shows at all. Default: always. */\n readonly visible?: (context: CommandContext) => boolean;\n\n /** What it does; `execute()` resolves once it has. Not needed for a `menu`, `panel` or `modal`. */\n readonly run?: (context: CommandContext) => void | Promise<unknown>;\n}\n\n/**\n * A command for each of a set of names, made from one definition, such as `tool:<id>` for every\n * tool a document has. Its commands resolve and run like any other, and `listCommands()` lists\n * one per name. A command defined with the same id wins over the family's.\n */\nexport interface CommandFamily {\n /** Where the commands' ids start: `'tool:'` makes `tool:highlight`. */\n readonly prefix: string;\n /** The names the command's document has, in order. Return the same array while nothing changed. */\n readonly names: (context: CommandContext) => readonly string[];\n /** The command for one name. A family's commands have no shortcuts. */\n readonly command: (name: string) => Omit<CommandDef, 'id' | 'shortcut'>;\n}\n\n/** A command as a button shows it: everything read for its document. */\nexport interface ResolvedCommand {\n readonly id: string;\n readonly label: string;\n readonly icon?: string;\n readonly iconAccent?: IconAccent;\n readonly shortcuts: readonly string[];\n readonly menu?: string;\n readonly enabled: boolean;\n readonly active: boolean;\n readonly visible: boolean;\n readonly categories: readonly string[];\n /**\n * Why it's disabled, as a sentence for its tooltip: set when the scope doesn't allow it and\n * the `notAllowed` setting is `'disable'`.\n */\n readonly disabledReason?: string;\n}\n\n/**\n * Why a command won't run whatever the moment: it's turned off in this viewer\n * (`disabledCategories`, `disabledCommands`), or the scope doesn't allow it (`requires`).\n * A command that only can't run right now (`enabled`, `visible`) has no refusal.\n */\nexport interface CommandRefusal {\n readonly reason: 'turned-off' | 'not-allowed';\n /** A sentence for the user, translated through the i18n plugin when it's there. */\n readonly message: string;\n}\n\n/**\n * Whether two resolved commands show the same, for readers that compare what a command looks\n * like rather than which object holds it (a group of commands, or one command for two documents).\n */\nexport const resolvedCommandsEqual = (\n left: ResolvedCommand | null,\n right: ResolvedCommand | null,\n): boolean => {\n if (left === right) return true;\n if (!left || !right) return false;\n return (\n left.id === right.id &&\n left.label === right.label &&\n left.icon === right.icon &&\n left.iconAccent?.primary === right.iconAccent?.primary &&\n left.iconAccent?.secondary === right.iconAccent?.secondary &&\n left.menu === right.menu &&\n left.enabled === right.enabled &&\n left.active === right.active &&\n left.visible === right.visible &&\n left.disabledReason === right.disabledReason &&\n left.shortcuts.length === right.shortcuts.length &&\n left.shortcuts.every((shortcut, index) => shortcut === right.shortcuts[index])\n );\n};\n\n/**\n * What a component or a toolbar draws for a command id no plugin registered: labelled with its\n * id, neither enabled nor visible, the way a turned-off command is.\n */\nexport const unregisteredCommand = (id: CommandId): ResolvedCommand => ({\n id,\n label: id,\n shortcuts: [],\n enabled: false,\n active: false,\n visible: false,\n categories: [],\n});\n\n/** What a component that asks for an id no plugin registered hears, in development. */\nexport const unknownCommandWarning = (id: CommandId, known: Iterable<CommandId>): string =>\n `no command \"${id}\"${didYouMean(id, known)}: it shows as neither visible nor enabled`;\n\n/** A command with everything a button needs: what it shows, `run`, and its shortcut for a tooltip. */\nexport interface BoundCommand extends ResolvedCommand {\n /** Run the command for the document it was read for. */\n readonly run: () => Promise<ExecuteResult>;\n /** Its first shortcut, formatted for the platform (`'⌘K'` on a Mac, `'Ctrl+K'` elsewhere), or `null`. */\n readonly shortcut: string | null;\n}\n\n/**\n * A resolved command, bound for a button: `run` executes it through `execute`, and `shortcut` is\n * its first shortcut formatted for the platform. Which platform is the caller's to know\n * (`isMacPlatform()` in `@embedpdf/web`).\n */\nexport function boundCommandOf(\n command: ResolvedCommand,\n execute: (id: CommandId) => Promise<ExecuteResult>,\n options: { readonly isMac: boolean },\n): BoundCommand {\n const [first] = command.shortcuts;\n return {\n ...command,\n run: () => execute(command.id),\n shortcut: first === undefined ? null : formatShortcut(first, { isMac: options.isMac }),\n };\n}\n\n/**\n * The commands plugin's settings. `commandsPlugin(config)` registers them over\n * {@link COMMANDS_DEFAULTS}, and `updateSettings()` changes them while the app runs.\n */\nexport interface CommandsSettings {\n /** The commands your viewer has. A later definition with an id that's taken replaces the earlier one. */\n readonly commands: readonly (CommandDef | CommandFamily)[];\n /**\n * Categories turned off, with every category under them: their commands are hidden and\n * refused wherever they appear.\n */\n readonly disabledCategories: readonly string[];\n /** Commands turned off one by one, by id: hidden and refused wherever they appear. */\n readonly disabledCommands: readonly CommandId[];\n /**\n * What a command the scope doesn't allow does: `'hide'` leaves it out, `'disable'` shows it\n * disabled, with the reason in its `disabledReason`.\n */\n readonly notAllowed: NotAllowedMode;\n}\n\n/** How a command shows when the scope doesn't allow it: hidden, or disabled with its reason. */\nexport type NotAllowedMode = 'hide' | 'disable';\n\n/** What the commands settings are when the app registers none. */\nexport const COMMANDS_DEFAULTS: CommandsSettings = {\n commands: [],\n disabledCategories: [],\n disabledCommands: [],\n notAllowed: 'hide',\n};\n\n/** What `commandsPlugin(config)` takes: any of the settings, merged over the defaults. */\nexport type CommandsConfig = DeepPartial<CommandsSettings>;\n\nexport interface RegisterCommandOptions {\n /** Replace a command with the same id; without it, a taken id throws `conflict`. */\n replace?: boolean;\n}\n\nexport interface ExecuteOptions extends OperationOptions {\n /** The document to run it for; the document in scope, else the active one, when left out. */\n documentId?: string;\n /** Passed to the command's `run` and derivations as `args`. */\n args?: unknown;\n}\n\n/** How `execute()` went: it ran, or it was refused before running, and why. */\nexport type ExecuteResult =\n | { readonly status: 'executed' }\n | { readonly status: 'rejected'; readonly reason: 'not-found' | 'disabled' | 'hidden' };\n\n// ── events ──\nexport interface CommandExecutedEvent {\n readonly commandId: CommandId;\n readonly documentId: string | null;\n readonly args: unknown;\n}\nexport interface CommandExecutionFailedEvent {\n readonly commandId: CommandId;\n readonly documentId: string | null;\n readonly error: PluginErrorInfo;\n}\n\n/**\n * The commands. A call that leaves out the document is for the document in scope when the\n * capability was resolved for one (`ctx.forDocument`, a `<DocumentScope>`), and for the active\n * document otherwise.\n */\nexport interface CommandsCapability extends SettingsApi<CommandsSettings> {\n // ── the commands ──\n /**\n * Add a command while the app runs, and get a function that removes it. A taken id throws\n * `conflict` unless `replace`.\n */\n registerCommand(definition: CommandDef, options?: RegisterCommandOptions): Unsubscribe;\n /** `registerCommand` for several definitions; the function removes all of them. */\n registerCommands(\n definitions: readonly CommandDef[],\n options?: RegisterCommandOptions,\n ): Unsubscribe;\n /** Whether a command has this id; with a family, every id that starts with its prefix does. */\n hasCommand(id: CommandId): boolean;\n /** A command as you defined it, or `null`. */\n getCommand(id: CommandId): CommandDef | null;\n /** Every command's id for the active document, in the order they were added. The same array until one changes. */\n listCommandIds(): readonly CommandId[];\n\n // ── what a button shows ──\n /** A command as a button shows it, or `null` for an unknown id. The same object while nothing about it changed. */\n resolveCommand(id: CommandId, documentId?: string): ResolvedCommand | null;\n /** Every command, resolved, in the order they were added. The same array while nothing changed. */\n listCommands(documentId?: string): readonly ResolvedCommand[];\n /** The visible commands whose label or id contains the query, for a command palette. */\n searchCommands(query: string, documentId?: string): readonly ResolvedCommand[];\n /** Every shortcut with its command, for a keyboard help sheet. The same array until the commands change. */\n listShortcuts(): readonly { readonly commandId: CommandId; readonly shortcut: string }[];\n\n // ── running them ──\n /**\n * Run a command; resolves once its `run` has, with `{ status: 'executed' }` and\n * `onExecuted`, or `{ status: 'rejected', reason }` for a command that is unknown, hidden or\n * disabled (a command turned off is hidden). A `run` that throws fires `onExecutionFailed` and rejects with its `PluginError`;\n * the signal rejects `operation-cancelled`.\n */\n execute(id: CommandId, options?: ExecuteOptions): Promise<ExecuteResult>;\n /** Whether a command can run now: it exists, and is enabled and visible. */\n canExecute(id: CommandId, documentId?: string): boolean;\n /**\n * Why a command won't run whatever the moment: it's turned off, or not allowed for its\n * document. `null` when it may run (or only can't right now), and for an unknown id.\n */\n getRefusal(id: CommandId, documentId?: string): CommandRefusal | null;\n\n // ── turning commands off ──\n /** The categories turned off. */\n getDisabledCategories(): readonly string[];\n /** Whether a category is turned off: it, or a category it's under (`annotations` for `annotations.highlight`). */\n isCategoryDisabled(category: string): boolean;\n /** Turn a category off, with every category under it: the `disabledCategories` setting gains it. */\n disableCategory(category: string): void;\n /** Turn a category on again. */\n enableCategory(category: string): void;\n /** Replace the categories that are off. */\n setDisabledCategories(categories: readonly string[]): void;\n /** The commands turned off one by one. */\n getDisabledCommands(): readonly CommandId[];\n /** Whether a command is turned off: by its id, or through one of its categories. */\n isCommandDisabled(id: CommandId): boolean;\n /** Turn one command off: the `disabledCommands` setting gains it. */\n disableCommand(id: CommandId): void;\n /** Turn a command on again; it stays off while one of its categories is. */\n enableCommand(id: CommandId): void;\n /** Replace the commands that are off one by one. */\n setDisabledCommands(ids: readonly CommandId[]): void;\n\n // ── events ──\n /** A command ran. */\n readonly onExecuted: EventHook<CommandExecutedEvent>;\n /** A command's `run` threw; `execute` rejects with the same error. */\n readonly onExecutionFailed: EventHook<CommandExecutionFailedEvent>;\n}\n"],"mappings":";;;;;AAMA,MAAa,gBAAgB,sBAA0C,YAAY,EACjF,MAAM,6EACR,CAAC;;;;;;;AC0KD,MAAa,yBACX,MACA,UACY;CACZ,IAAI,SAAS,OAAO,OAAO;CAC3B,IAAI,CAAC,QAAQ,CAAC,OAAO,OAAO;CAC5B,OACE,KAAK,OAAO,MAAM,MAClB,KAAK,UAAU,MAAM,SACrB,KAAK,SAAS,MAAM,QACpB,KAAK,YAAY,YAAY,MAAM,YAAY,WAC/C,KAAK,YAAY,cAAc,MAAM,YAAY,aACjD,KAAK,SAAS,MAAM,QACpB,KAAK,YAAY,MAAM,WACvB,KAAK,WAAW,MAAM,UACtB,KAAK,YAAY,MAAM,WACvB,KAAK,mBAAmB,MAAM,kBAC9B,KAAK,UAAU,WAAW,MAAM,UAAU,UAC1C,KAAK,UAAU,OAAO,UAAU,UAAU,aAAa,MAAM,UAAU,MAAM;AAEjF;;;;;AAMA,MAAa,uBAAuB,QAAoC;CACtE;CACA,OAAO;CACP,WAAW,CAAC;CACZ,SAAS;CACT,QAAQ;CACR,SAAS;CACT,YAAY,CAAC;AACf;;AAGA,MAAa,yBAAyB,IAAe,UACnD,eAAe,GAAG,GAAG,WAAW,IAAI,KAAK,EAAE;;;;;;AAe7C,SAAgB,eACd,SACA,SACA,SACc;CACd,MAAM,CAAC,SAAS,QAAQ;CACxB,OAAO;EACL,GAAG;EACH,WAAW,QAAQ,QAAQ,EAAE;EAC7B,UAAU,UAAU,KAAA,IAAY,OAAO,eAAe,OAAO,EAAE,OAAO,QAAQ,MAAM,CAAC;CACvF;AACF;;AA2BA,MAAa,oBAAsC;CACjD,UAAU,CAAC;CACX,oBAAoB,CAAC;CACrB,kBAAkB,CAAC;CACnB,YAAY;AACd"}
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
import { CapabilityToken, DeepPartial, EventHook, OperationOptions, Permission, PluginErrorInfo, SettingsApi, Unsubscribe } from "@embedpdf/core";
|
|
2
|
+
//#region src/token.d.ts
|
|
3
|
+
declare const CommandsToken: import("@embedpdf/core").CapabilityToken<CommandsCapability>;
|
|
4
|
+
//#endregion
|
|
5
|
+
//#region src/contract.d.ts
|
|
6
|
+
type CommandId = string;
|
|
7
|
+
/**
|
|
8
|
+
* What a command's derivations and `run` see: capabilities resolved for the command's document
|
|
9
|
+
* (the one named, else the document in scope, else the active one).
|
|
10
|
+
*/
|
|
11
|
+
interface CommandContext {
|
|
12
|
+
/** The command's document, or `null` when none is open. */
|
|
13
|
+
readonly documentId: string | null;
|
|
14
|
+
/** What the caller passed: `execute(id, { args })`. */
|
|
15
|
+
readonly args?: unknown;
|
|
16
|
+
/** Fires when the caller cancels `execute()`: pass it on to the calls `run` makes. */
|
|
17
|
+
readonly signal?: AbortSignal;
|
|
18
|
+
/** A capability, for the command's document when the plugin is document-scoped. Throws when it isn't available. */
|
|
19
|
+
get<T>(token: CapabilityToken<T>): T;
|
|
20
|
+
/** Like `get`, but `null` when the capability isn't available (no plugin, no document). */
|
|
21
|
+
tryGet<T>(token: CapabilityToken<T>): T | null;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Up to two colors that go with a command's icon, such as a tool's current color: data a
|
|
25
|
+
* renderer may use (tint the icon, show a swatch), like `icon` itself.
|
|
26
|
+
*/
|
|
27
|
+
interface IconAccent {
|
|
28
|
+
/** The mark: a stroke, the markup or the text color. */
|
|
29
|
+
readonly primary?: string;
|
|
30
|
+
/** The fill, when there is one. */
|
|
31
|
+
readonly secondary?: string;
|
|
32
|
+
}
|
|
33
|
+
/** One command, as you define it. */
|
|
34
|
+
interface CommandDef {
|
|
35
|
+
/** A unique name, by convention `area:action`: `'zoom:in'`, `'review:approve'`. */
|
|
36
|
+
readonly id: string;
|
|
37
|
+
/** What the user sees. With `labelKey` too, it's what shows when no language has the key. */
|
|
38
|
+
readonly label?: string;
|
|
39
|
+
/**
|
|
40
|
+
* A translation key for the label, read through the i18n plugin. Without the plugin, or a
|
|
41
|
+
* string for the key, the command shows `label`, else the key.
|
|
42
|
+
*/
|
|
43
|
+
readonly labelKey?: string;
|
|
44
|
+
/** Your icon's name; your buttons turn it into an icon. */
|
|
45
|
+
readonly icon?: string;
|
|
46
|
+
/** Colors for the icon, read from live state like `active`. */
|
|
47
|
+
readonly iconAccent?: (context: CommandContext) => IconAccent | null;
|
|
48
|
+
/** A key such as `'Mod+K'` (`Mod` is Cmd on a Mac, Ctrl elsewhere), or a list of them. */
|
|
49
|
+
readonly shortcut?: string | readonly string[];
|
|
50
|
+
/**
|
|
51
|
+
* Whether its shortcut also runs while the cursor is in a text field where the shortcuts
|
|
52
|
+
* listen (a search box, a comment), as the viewer's Find does. Default false: a key typed in
|
|
53
|
+
* a field is the field's.
|
|
54
|
+
*/
|
|
55
|
+
readonly shortcutInTextFields?: boolean;
|
|
56
|
+
/**
|
|
57
|
+
* The features it belongs to, so turning one off turns it off: `['annotations.highlight']`.
|
|
58
|
+
* Turning off a feature turns off every feature under it, on whole dotted parts: `annotations`
|
|
59
|
+
* covers `annotations.highlight`, not `annotationsExtra`.
|
|
60
|
+
*/
|
|
61
|
+
readonly categories?: readonly string[];
|
|
62
|
+
/**
|
|
63
|
+
* The scope permissions it needs, such as `'doc.annotate.modify'`, checked against its
|
|
64
|
+
* document. Without them it's hidden, or shown disabled with its reason under the
|
|
65
|
+
* `notAllowed: 'disable'` setting. With no document open there is nothing to check.
|
|
66
|
+
*/
|
|
67
|
+
readonly requires?: readonly Permission[];
|
|
68
|
+
/**
|
|
69
|
+
* Whether the session may run it, from the plugins' `can*` checks
|
|
70
|
+
* (`documents.canPrint()`), for a command whose permission is a plugin's to know. When it
|
|
71
|
+
* says no, the command isn't allowed, as with `requires`. Asked only while a document is
|
|
72
|
+
* open; one that throws allows it.
|
|
73
|
+
*/
|
|
74
|
+
readonly allowed?: (context: CommandContext) => boolean;
|
|
75
|
+
/**
|
|
76
|
+
* The translation key of the sentence that says why `allowed` refused it, with `{label}` for
|
|
77
|
+
* its label: `'commands.notAllowed.doc-print'`. Without it, or a string for it,
|
|
78
|
+
* `commands.notAllowed.default`.
|
|
79
|
+
*/
|
|
80
|
+
readonly notAllowedKey?: string;
|
|
81
|
+
/** Opens and closes a menu of yours, by its id. */
|
|
82
|
+
readonly menu?: string;
|
|
83
|
+
/**
|
|
84
|
+
* Opens and closes a panel, closing the others with the same `exclusive` tag. With `focus`,
|
|
85
|
+
* opening it asks for the cursor (the shell's `open(id, { focus: true })`).
|
|
86
|
+
*/
|
|
87
|
+
readonly panel?: string | {
|
|
88
|
+
readonly id: string;
|
|
89
|
+
readonly exclusive?: string;
|
|
90
|
+
readonly focus?: boolean;
|
|
91
|
+
};
|
|
92
|
+
/** Opens and closes a dialog; one dialog is open at a time. */
|
|
93
|
+
readonly modal?: string;
|
|
94
|
+
/** When it can run. Default: always. */
|
|
95
|
+
readonly enabled?: (context: CommandContext) => boolean;
|
|
96
|
+
/** When it shows as pressed, such as the current tool. */
|
|
97
|
+
readonly active?: (context: CommandContext) => boolean;
|
|
98
|
+
/** When it shows at all. Default: always. */
|
|
99
|
+
readonly visible?: (context: CommandContext) => boolean;
|
|
100
|
+
/** What it does; `execute()` resolves once it has. Not needed for a `menu`, `panel` or `modal`. */
|
|
101
|
+
readonly run?: (context: CommandContext) => void | Promise<unknown>;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* A command for each of a set of names, made from one definition, such as `tool:<id>` for every
|
|
105
|
+
* tool a document has. Its commands resolve and run like any other, and `listCommands()` lists
|
|
106
|
+
* one per name. A command defined with the same id wins over the family's.
|
|
107
|
+
*/
|
|
108
|
+
interface CommandFamily {
|
|
109
|
+
/** Where the commands' ids start: `'tool:'` makes `tool:highlight`. */
|
|
110
|
+
readonly prefix: string;
|
|
111
|
+
/** The names the command's document has, in order. Return the same array while nothing changed. */
|
|
112
|
+
readonly names: (context: CommandContext) => readonly string[];
|
|
113
|
+
/** The command for one name. A family's commands have no shortcuts. */
|
|
114
|
+
readonly command: (name: string) => Omit<CommandDef, 'id' | 'shortcut'>;
|
|
115
|
+
}
|
|
116
|
+
/** A command as a button shows it: everything read for its document. */
|
|
117
|
+
interface ResolvedCommand {
|
|
118
|
+
readonly id: string;
|
|
119
|
+
readonly label: string;
|
|
120
|
+
readonly icon?: string;
|
|
121
|
+
readonly iconAccent?: IconAccent;
|
|
122
|
+
readonly shortcuts: readonly string[];
|
|
123
|
+
readonly menu?: string;
|
|
124
|
+
readonly enabled: boolean;
|
|
125
|
+
readonly active: boolean;
|
|
126
|
+
readonly visible: boolean;
|
|
127
|
+
readonly categories: readonly string[];
|
|
128
|
+
/**
|
|
129
|
+
* Why it's disabled, as a sentence for its tooltip: set when the scope doesn't allow it and
|
|
130
|
+
* the `notAllowed` setting is `'disable'`.
|
|
131
|
+
*/
|
|
132
|
+
readonly disabledReason?: string;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Why a command won't run whatever the moment: it's turned off in this viewer
|
|
136
|
+
* (`disabledCategories`, `disabledCommands`), or the scope doesn't allow it (`requires`).
|
|
137
|
+
* A command that only can't run right now (`enabled`, `visible`) has no refusal.
|
|
138
|
+
*/
|
|
139
|
+
interface CommandRefusal {
|
|
140
|
+
readonly reason: 'turned-off' | 'not-allowed';
|
|
141
|
+
/** A sentence for the user, translated through the i18n plugin when it's there. */
|
|
142
|
+
readonly message: string;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Whether two resolved commands show the same, for readers that compare what a command looks
|
|
146
|
+
* like rather than which object holds it (a group of commands, or one command for two documents).
|
|
147
|
+
*/
|
|
148
|
+
declare const resolvedCommandsEqual: (left: ResolvedCommand | null, right: ResolvedCommand | null) => boolean;
|
|
149
|
+
/**
|
|
150
|
+
* What a component or a toolbar draws for a command id no plugin registered: labelled with its
|
|
151
|
+
* id, neither enabled nor visible, the way a turned-off command is.
|
|
152
|
+
*/
|
|
153
|
+
declare const unregisteredCommand: (id: CommandId) => ResolvedCommand;
|
|
154
|
+
/** What a component that asks for an id no plugin registered hears, in development. */
|
|
155
|
+
declare const unknownCommandWarning: (id: CommandId, known: Iterable<CommandId>) => string;
|
|
156
|
+
/** A command with everything a button needs: what it shows, `run`, and its shortcut for a tooltip. */
|
|
157
|
+
interface BoundCommand extends ResolvedCommand {
|
|
158
|
+
/** Run the command for the document it was read for. */
|
|
159
|
+
readonly run: () => Promise<ExecuteResult>;
|
|
160
|
+
/** Its first shortcut, formatted for the platform (`'⌘K'` on a Mac, `'Ctrl+K'` elsewhere), or `null`. */
|
|
161
|
+
readonly shortcut: string | null;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* A resolved command, bound for a button: `run` executes it through `execute`, and `shortcut` is
|
|
165
|
+
* its first shortcut formatted for the platform. Which platform is the caller's to know
|
|
166
|
+
* (`isMacPlatform()` in `@embedpdf/web`).
|
|
167
|
+
*/
|
|
168
|
+
declare function boundCommandOf(command: ResolvedCommand, execute: (id: CommandId) => Promise<ExecuteResult>, options: {
|
|
169
|
+
readonly isMac: boolean;
|
|
170
|
+
}): BoundCommand;
|
|
171
|
+
/**
|
|
172
|
+
* The commands plugin's settings. `commandsPlugin(config)` registers them over
|
|
173
|
+
* {@link COMMANDS_DEFAULTS}, and `updateSettings()` changes them while the app runs.
|
|
174
|
+
*/
|
|
175
|
+
interface CommandsSettings {
|
|
176
|
+
/** The commands your viewer has. A later definition with an id that's taken replaces the earlier one. */
|
|
177
|
+
readonly commands: readonly (CommandDef | CommandFamily)[];
|
|
178
|
+
/**
|
|
179
|
+
* Categories turned off, with every category under them: their commands are hidden and
|
|
180
|
+
* refused wherever they appear.
|
|
181
|
+
*/
|
|
182
|
+
readonly disabledCategories: readonly string[];
|
|
183
|
+
/** Commands turned off one by one, by id: hidden and refused wherever they appear. */
|
|
184
|
+
readonly disabledCommands: readonly CommandId[];
|
|
185
|
+
/**
|
|
186
|
+
* What a command the scope doesn't allow does: `'hide'` leaves it out, `'disable'` shows it
|
|
187
|
+
* disabled, with the reason in its `disabledReason`.
|
|
188
|
+
*/
|
|
189
|
+
readonly notAllowed: NotAllowedMode;
|
|
190
|
+
}
|
|
191
|
+
/** How a command shows when the scope doesn't allow it: hidden, or disabled with its reason. */
|
|
192
|
+
type NotAllowedMode = 'hide' | 'disable';
|
|
193
|
+
/** What the commands settings are when the app registers none. */
|
|
194
|
+
declare const COMMANDS_DEFAULTS: CommandsSettings;
|
|
195
|
+
/** What `commandsPlugin(config)` takes: any of the settings, merged over the defaults. */
|
|
196
|
+
type CommandsConfig = DeepPartial<CommandsSettings>;
|
|
197
|
+
interface RegisterCommandOptions {
|
|
198
|
+
/** Replace a command with the same id; without it, a taken id throws `conflict`. */
|
|
199
|
+
replace?: boolean;
|
|
200
|
+
}
|
|
201
|
+
interface ExecuteOptions extends OperationOptions {
|
|
202
|
+
/** The document to run it for; the document in scope, else the active one, when left out. */
|
|
203
|
+
documentId?: string;
|
|
204
|
+
/** Passed to the command's `run` and derivations as `args`. */
|
|
205
|
+
args?: unknown;
|
|
206
|
+
}
|
|
207
|
+
/** How `execute()` went: it ran, or it was refused before running, and why. */
|
|
208
|
+
type ExecuteResult = {
|
|
209
|
+
readonly status: 'executed';
|
|
210
|
+
} | {
|
|
211
|
+
readonly status: 'rejected';
|
|
212
|
+
readonly reason: 'not-found' | 'disabled' | 'hidden';
|
|
213
|
+
};
|
|
214
|
+
interface CommandExecutedEvent {
|
|
215
|
+
readonly commandId: CommandId;
|
|
216
|
+
readonly documentId: string | null;
|
|
217
|
+
readonly args: unknown;
|
|
218
|
+
}
|
|
219
|
+
interface CommandExecutionFailedEvent {
|
|
220
|
+
readonly commandId: CommandId;
|
|
221
|
+
readonly documentId: string | null;
|
|
222
|
+
readonly error: PluginErrorInfo;
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* The commands. A call that leaves out the document is for the document in scope when the
|
|
226
|
+
* capability was resolved for one (`ctx.forDocument`, a `<DocumentScope>`), and for the active
|
|
227
|
+
* document otherwise.
|
|
228
|
+
*/
|
|
229
|
+
interface CommandsCapability extends SettingsApi<CommandsSettings> {
|
|
230
|
+
/**
|
|
231
|
+
* Add a command while the app runs, and get a function that removes it. A taken id throws
|
|
232
|
+
* `conflict` unless `replace`.
|
|
233
|
+
*/
|
|
234
|
+
registerCommand(definition: CommandDef, options?: RegisterCommandOptions): Unsubscribe;
|
|
235
|
+
/** `registerCommand` for several definitions; the function removes all of them. */
|
|
236
|
+
registerCommands(definitions: readonly CommandDef[], options?: RegisterCommandOptions): Unsubscribe;
|
|
237
|
+
/** Whether a command has this id; with a family, every id that starts with its prefix does. */
|
|
238
|
+
hasCommand(id: CommandId): boolean;
|
|
239
|
+
/** A command as you defined it, or `null`. */
|
|
240
|
+
getCommand(id: CommandId): CommandDef | null;
|
|
241
|
+
/** Every command's id for the active document, in the order they were added. The same array until one changes. */
|
|
242
|
+
listCommandIds(): readonly CommandId[];
|
|
243
|
+
/** A command as a button shows it, or `null` for an unknown id. The same object while nothing about it changed. */
|
|
244
|
+
resolveCommand(id: CommandId, documentId?: string): ResolvedCommand | null;
|
|
245
|
+
/** Every command, resolved, in the order they were added. The same array while nothing changed. */
|
|
246
|
+
listCommands(documentId?: string): readonly ResolvedCommand[];
|
|
247
|
+
/** The visible commands whose label or id contains the query, for a command palette. */
|
|
248
|
+
searchCommands(query: string, documentId?: string): readonly ResolvedCommand[];
|
|
249
|
+
/** Every shortcut with its command, for a keyboard help sheet. The same array until the commands change. */
|
|
250
|
+
listShortcuts(): readonly {
|
|
251
|
+
readonly commandId: CommandId;
|
|
252
|
+
readonly shortcut: string;
|
|
253
|
+
}[];
|
|
254
|
+
/**
|
|
255
|
+
* Run a command; resolves once its `run` has, with `{ status: 'executed' }` and
|
|
256
|
+
* `onExecuted`, or `{ status: 'rejected', reason }` for a command that is unknown, hidden or
|
|
257
|
+
* disabled (a command turned off is hidden). A `run` that throws fires `onExecutionFailed` and rejects with its `PluginError`;
|
|
258
|
+
* the signal rejects `operation-cancelled`.
|
|
259
|
+
*/
|
|
260
|
+
execute(id: CommandId, options?: ExecuteOptions): Promise<ExecuteResult>;
|
|
261
|
+
/** Whether a command can run now: it exists, and is enabled and visible. */
|
|
262
|
+
canExecute(id: CommandId, documentId?: string): boolean;
|
|
263
|
+
/**
|
|
264
|
+
* Why a command won't run whatever the moment: it's turned off, or not allowed for its
|
|
265
|
+
* document. `null` when it may run (or only can't right now), and for an unknown id.
|
|
266
|
+
*/
|
|
267
|
+
getRefusal(id: CommandId, documentId?: string): CommandRefusal | null;
|
|
268
|
+
/** The categories turned off. */
|
|
269
|
+
getDisabledCategories(): readonly string[];
|
|
270
|
+
/** Whether a category is turned off: it, or a category it's under (`annotations` for `annotations.highlight`). */
|
|
271
|
+
isCategoryDisabled(category: string): boolean;
|
|
272
|
+
/** Turn a category off, with every category under it: the `disabledCategories` setting gains it. */
|
|
273
|
+
disableCategory(category: string): void;
|
|
274
|
+
/** Turn a category on again. */
|
|
275
|
+
enableCategory(category: string): void;
|
|
276
|
+
/** Replace the categories that are off. */
|
|
277
|
+
setDisabledCategories(categories: readonly string[]): void;
|
|
278
|
+
/** The commands turned off one by one. */
|
|
279
|
+
getDisabledCommands(): readonly CommandId[];
|
|
280
|
+
/** Whether a command is turned off: by its id, or through one of its categories. */
|
|
281
|
+
isCommandDisabled(id: CommandId): boolean;
|
|
282
|
+
/** Turn one command off: the `disabledCommands` setting gains it. */
|
|
283
|
+
disableCommand(id: CommandId): void;
|
|
284
|
+
/** Turn a command on again; it stays off while one of its categories is. */
|
|
285
|
+
enableCommand(id: CommandId): void;
|
|
286
|
+
/** Replace the commands that are off one by one. */
|
|
287
|
+
setDisabledCommands(ids: readonly CommandId[]): void;
|
|
288
|
+
/** A command ran. */
|
|
289
|
+
readonly onExecuted: EventHook<CommandExecutedEvent>;
|
|
290
|
+
/** A command's `run` threw; `execute` rejects with the same error. */
|
|
291
|
+
readonly onExecutionFailed: EventHook<CommandExecutionFailedEvent>;
|
|
292
|
+
}
|
|
293
|
+
//#endregion
|
|
294
|
+
export { CommandsToken as C, unregisteredCommand as S, RegisterCommandOptions as _, CommandExecutedEvent as a, resolvedCommandsEqual as b, CommandId as c, CommandsConfig as d, CommandsSettings as f, NotAllowedMode as g, IconAccent as h, CommandDef as i, CommandRefusal as l, ExecuteResult as m, COMMANDS_DEFAULTS as n, CommandExecutionFailedEvent as o, ExecuteOptions as p, CommandContext as r, CommandFamily as s, BoundCommand as t, CommandsCapability as u, ResolvedCommand as v, unknownCommandWarning as x, boundCommandOf as y };
|
|
295
|
+
//# sourceMappingURL=contract-DAV5VR3P.d.cts.map
|