@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/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/capability.ts","../src/reducer.ts","../src/commands.plugin.ts"],"sourcesContent":["import type { CapabilityToken, PluginContext } from '@embedpdf/core';\nimport { I18nToken } from '@embedpdf/plugin-i18n/contract';\nimport { ShellToken } from '@embedpdf/plugin-shell/contract';\nimport { matchShortcut, parseShortcut } from '@embedpdf/core-ui';\nimport type { KeyStroke, ParsedShortcut } from '@embedpdf/core-ui';\nimport type {\n CommandCtx,\n CommandDef,\n CommandsAction,\n CommandsCapability,\n CommandsState,\n IconAccent,\n ResolvedCommand,\n} from './types';\n\n/** A registered command: the definition plus its pre-parsed shortcuts. */\nexport interface RegisteredCommand {\n readonly def: CommandDef;\n readonly shortcuts: readonly string[];\n readonly parsed: readonly ParsedShortcut[];\n}\n\nexport type CommandRegistry = Map<string, RegisteredCommand>;\n\nexport function registerCommand(registry: CommandRegistry, def: CommandDef): void {\n if (registry.has(def.id)) throw new Error(`[commands] duplicate command: ${def.id}`);\n const shortcuts = def.shortcut === undefined ? [] : ([] as string[]).concat(def.shortcut);\n registry.set(def.id, { def, shortcuts, parsed: shortcuts.map(parseShortcut) });\n}\n\nconst panelTarget = (def: CommandDef): { id: string; exclusive?: string } | null =>\n def.panel === undefined ? null : typeof def.panel === 'string' ? { id: def.panel } : def.panel;\n\nexport function createCommandsCapability(\n ctx: PluginContext<CommandsState, CommandsAction>,\n registry: CommandRegistry,\n): CommandsCapability {\n /** Bind capability resolution to the command's target document. The kernel\n * resolves workspace tokens regardless of the document argument, so one\n * code path serves both scopes. */\n const commandCtx = (documentId?: string): CommandCtx => {\n const target = documentId ?? ctx.core().activeId;\n const get = <T>(token: CapabilityToken<T>): T =>\n target ? ctx.forDocument(token, target) : ctx.get(token);\n return {\n documentId: target,\n core: ctx.core,\n get,\n tryGet: <T>(token: CapabilityToken<T>): T | null => {\n try {\n return get(token);\n } catch {\n return null;\n }\n },\n };\n };\n\n /** Derivations run against live state; a derivation that throws (e.g. it\n * needs a document and none is open) falls back to the safe default —\n * the button renders, disabled, exactly like v2's empty state. */\n const derive = (\n fn: ((c: CommandCtx) => boolean) | undefined,\n c: CommandCtx,\n fallback: boolean,\n ): boolean => {\n if (!fn) return fallback;\n try {\n return fn(c);\n } catch {\n return fallback;\n }\n };\n\n /** Same guard as `derive`, for the icon-accent derivation: a throw (no\n * document, provider missing) means \"no accent\" — the icon renders plain. */\n const deriveAccent = (\n fn: ((c: CommandCtx) => IconAccent | null) | undefined,\n c: CommandCtx,\n ): IconAccent | undefined => {\n if (!fn) return undefined;\n try {\n return fn(c) ?? undefined;\n } catch {\n return undefined;\n }\n };\n\n const resolve = (id: string, documentId?: string): ResolvedCommand | null => {\n const entry = registry.get(id);\n if (!entry) return null;\n const { def } = entry;\n const c = commandCtx(documentId);\n\n const disabled = ctx.getState().disabledCategories;\n const categoryHidden = (def.categories ?? []).some((cat) => disabled.includes(cat));\n\n const i18n = c.tryGet(I18nToken);\n const label = i18n ? i18n.t(def.labelKey) : def.labelKey;\n\n // Surface-target commands derive `active` from the surface's open state\n // unless the definition overrides it.\n let active: boolean;\n if (def.active) {\n active = derive(def.active, c, false);\n } else {\n const shell = c.tryGet(ShellToken);\n const panel = panelTarget(def);\n active = shell\n ? def.menu\n ? shell.isMenuOpen(def.menu)\n : panel\n ? shell.isOpen(panel.id)\n : def.modal\n ? shell.isOpen(def.modal)\n : false\n : false;\n }\n\n return {\n id: def.id,\n label,\n icon: def.icon,\n iconAccent: deriveAccent(def.iconAccent, c),\n shortcuts: entry.shortcuts,\n menu: def.menu,\n enabled: derive(def.enabled, c, true) && !categoryHidden,\n active,\n visible: derive(def.visible, c, true) && !categoryHidden,\n categories: def.categories ?? [],\n };\n };\n\n const execute = (id: string, documentId?: string): void => {\n const entry = registry.get(id);\n if (!entry) return;\n const resolved = resolve(id, documentId);\n if (!resolved || !resolved.enabled || !resolved.visible) return;\n const c = commandCtx(documentId);\n\n if (entry.def.run) {\n entry.def.run(c);\n return;\n }\n // Default routing for declarative surface targets.\n const shell = c.tryGet(ShellToken);\n if (!shell) return;\n const panel = panelTarget(entry.def);\n if (entry.def.menu) shell.toggleMenu(entry.def.menu);\n else if (panel) shell.toggle(panel.id, { exclusive: panel.exclusive });\n else if (entry.def.modal) shell.toggle(entry.def.modal, { exclusive: 'modal' });\n };\n\n return {\n register: (def) => registerCommand(registry, def),\n unregister: (id) => void registry.delete(id),\n has: (id) => registry.has(id),\n ids: () => [...registry.keys()],\n\n resolve,\n search: (query, documentId) => {\n const q = query.trim().toLowerCase();\n const hits: ResolvedCommand[] = [];\n for (const id of registry.keys()) {\n const r = resolve(id, documentId);\n if (!r || !r.visible) continue;\n if (q === '' || r.label.toLowerCase().includes(q) || r.id.includes(q)) hits.push(r);\n }\n return hits;\n },\n menuTarget: (id) => {\n const entry = registry.get(id);\n return entry ? { menu: entry.def.menu } : null;\n },\n\n execute,\n matchStroke: (stroke: KeyStroke, opts) => {\n for (const [id, entry] of registry) {\n if (entry.parsed.some((p) => matchShortcut(p, stroke, opts))) return id;\n }\n return null;\n },\n\n disabledCategories: () => ctx.getState().disabledCategories,\n isCategoryDisabled: (category) => ctx.getState().disabledCategories.includes(category),\n disableCategory: (category) => ctx.dispatch({ type: 'COMMANDS/DISABLE_CATEGORY', category }),\n enableCategory: (category) => ctx.dispatch({ type: 'COMMANDS/ENABLE_CATEGORY', category }),\n setDisabledCategories: (categories) =>\n ctx.dispatch({ type: 'COMMANDS/SET_DISABLED_CATEGORIES', categories }),\n };\n}\n","import type { CommandsAction, CommandsState } from './types';\n\nexport const initialCommandsState: CommandsState = {\n disabledCategories: [],\n};\n\nexport function commandsReducer(state: CommandsState, action: CommandsAction): CommandsState {\n switch (action.type) {\n case 'COMMANDS/DISABLE_CATEGORY':\n return state.disabledCategories.includes(action.category)\n ? state\n : { disabledCategories: [...state.disabledCategories, action.category] };\n case 'COMMANDS/ENABLE_CATEGORY':\n return state.disabledCategories.includes(action.category)\n ? { disabledCategories: state.disabledCategories.filter((c) => c !== action.category) }\n : state;\n case 'COMMANDS/SET_DISABLED_CATEGORIES':\n return { disabledCategories: [...action.categories] };\n default:\n return state;\n }\n}\n","import { definePlugin } from '@embedpdf/core';\nimport { createCommandsCapability, registerCommand } from './capability';\nimport type { CommandRegistry } from './capability';\nimport { commandsReducer, initialCommandsState } from './reducer';\nimport { CommandsToken } from './types';\nimport type { CommandsAction, CommandsCapability, CommandsConfig, CommandsState } from './types';\n\n/**\n * The commands plugin: workspace-scoped (one vocabulary for the whole\n * workspace; resolution/execution bind to a target document per call).\n * Definitions live in this closure — never in the store (they hold\n * functions); the store slice holds only `disabledCategories`.\n */\nexport const commandsPlugin = (config?: CommandsConfig) => {\n const registry: CommandRegistry = new Map();\n for (const def of config?.commands ?? []) registerCommand(registry, def);\n\n return definePlugin<CommandsState, CommandsAction, CommandsCapability>({\n id: 'commands',\n scope: 'workspace',\n token: CommandsToken,\n initialState: {\n ...initialCommandsState,\n disabledCategories: [...(config?.disabledCategories ?? [])],\n },\n reduce: commandsReducer,\n capability: (ctx) => createCommandsCapability(ctx, registry),\n });\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["CommandsToken"],"sources":["../src/registry.ts","../src/services/availability.ts","../src/write/turning-off.ts","../src/controller.ts","../src/commands.plugin.ts"],"sourcesContent":["/** A command definition with its shortcuts parsed once, and how the registry tells a family apart. */\nimport { parseShortcut, type ParsedShortcut } from '@embedpdf/core-ui';\n\nimport type { CommandDef, CommandFamily } from './contract';\n\nexport interface RegisteredCommand {\n readonly definition: CommandDef;\n readonly shortcuts: readonly string[];\n readonly parsed: readonly ParsedShortcut[];\n}\n\nexport const registeredCommand = (definition: CommandDef): RegisteredCommand => {\n const shortcuts =\n definition.shortcut === undefined ? [] : ([] as string[]).concat(definition.shortcut);\n return { definition, shortcuts, parsed: shortcuts.map(parseShortcut) };\n};\n\nexport const isCommandFamily = (item: CommandDef | CommandFamily): item is CommandFamily =>\n 'prefix' in item;\n\n/** The commands the settings define, by id (a later id replaces an earlier one), and their families. */\nexport interface ConfiguredCommands {\n readonly commands: ReadonlyMap<string, RegisteredCommand>;\n readonly families: readonly CommandFamily[];\n}\n\nexport function configuredCommands(\n items: readonly (CommandDef | CommandFamily)[],\n): ConfiguredCommands {\n const commands = new Map<string, RegisteredCommand>();\n const families: CommandFamily[] = [];\n for (const item of items) {\n if (isCommandFamily(item)) families.push(item);\n else commands.set(item.id, registeredCommand(item));\n }\n return { commands, families };\n}\n","/**\n * Whether a command is there at all, apart from what it says about the\n * moment (`enabled`, `visible`): turned off in this viewer (its id, or one of\n * its categories), or not allowed for its document (the scope's `requires`, or\n * the plugins' checks in `allowed`), and the sentence that says why, translated\n * when the i18n plugin is there.\n */\nimport type { DocumentHandle, Permission, PluginContext, Settings } from '@embedpdf/core';\nimport { I18nToken } from '@embedpdf/plugin-i18n/contract';\n\nimport type { CommandContext, CommandDef, CommandRefusal, CommandsSettings } from '../contract';\n\n/**\n * Whether a category is off: it, or a category it's under, is in the list. Parts are whole\n * dotted segments, so `annotations` covers `annotations.highlight` and not `annotationsExtra`.\n */\nexport const isCategoryOff = (category: string, disabled: readonly string[]): boolean =>\n disabled.some((off) => category === off || category.startsWith(`${off}.`));\n\n/**\n * The label: a language's string under the command's id, else under its `labelKey` (the current\n * language, then the fallback one), else `label`, else the id. So a string for\n * `'document:download'` relabels that one command, whichever key its label is under.\n */\nexport const labelOf = (definition: CommandDef, context: CommandContext): string => {\n const i18n = context.tryGet(I18nToken);\n if (!i18n) return definition.label ?? definition.labelKey ?? definition.id;\n const fallbackKey = definition.labelKey ? { fallbackKey: definition.labelKey } : {};\n // A command with a key and no label of its own warns once when no language has the key.\n return definition.label === undefined && definition.labelKey\n ? i18n.t(definition.id, fallbackKey)\n : i18n.t(definition.id, { ...fallbackKey, fallback: definition.label ?? definition.id });\n};\n\n/**\n * Whether a document's session holds a permission: what `ctx.allows` answers for a\n * document-scoped plugin, asked here of the command's document, since the commands are one\n * set for the whole workspace.\n */\nconst sessionHolds = (security: DocumentHandle['security'], permission: Permission): boolean =>\n permission === 'annotations:create'\n ? security.allowsAnnotation('create')\n : security.allows(permission);\n\n/** Where a language keeps the sentence for a permission: `commands.notAllowed.doc-text-copy`. */\nconst permissionKeyOf = (permission: Permission): string =>\n `commands.notAllowed.${permission.replace(/[.:]/g, '-')}`;\n\n/** The general sentence's key: `{label} isn't allowed`. */\nconst DEFAULT_NOT_ALLOWED_KEY = 'commands.notAllowed.default';\n\n/** The sentence for a command the session may not run, under `key`, else the general one. */\nexport const notAllowedMessage = (key: string, label: string, context: CommandContext): string => {\n const fallback = `${label} isn't allowed`;\n const i18n = context.tryGet(I18nToken);\n if (!i18n) return fallback;\n const params = { label };\n return i18n.t(key, {\n params,\n fallback: i18n.t(DEFAULT_NOT_ALLOWED_KEY, { params, fallback }),\n });\n};\n\n/** The sentence for a command that's turned off. */\nconst turnedOffMessage = (label: string, context: CommandContext): string => {\n const i18n = context.tryGet(I18nToken);\n return i18n\n ? i18n.t('commands.turnedOff', { params: { label }, fallback: \"{label} isn't available\" })\n : `${label} isn't available`;\n};\n\nexport function createAvailability(\n ctx: PluginContext<void, CommandsSettings>,\n settings: Settings<CommandsSettings>,\n) {\n /** Whether a command is turned off: by its id, or through one of its categories. */\n const isTurnedOff = (definition: CommandDef): boolean => {\n const { disabledCategories, disabledCommands } = settings.get();\n return (\n disabledCommands.includes(definition.id) ||\n (definition.categories ?? []).some((category) => isCategoryOff(category, disabledCategories))\n );\n };\n\n /** Whether a command's `allowed` check says yes; one that throws allows it. */\n const passesCheck = (definition: CommandDef, context: CommandContext): boolean => {\n if (!definition.allowed) return true;\n try {\n return definition.allowed(context);\n } catch {\n return true;\n }\n };\n\n /**\n * Why its document's session may not run a command, as the key of the sentence that says\n * so, or `null` when it may: the first permission `requires` names that the session doesn't\n * hold (`commands.notAllowed.doc-print`), else its `allowed` check saying no (its\n * `notAllowedKey`). With no document open there is no session to ask, and nothing is refused.\n */\n const notAllowedKeyOf = (definition: CommandDef, context: CommandContext): string | null => {\n if (!definition.requires?.length && !definition.allowed) return null;\n const handle = context.documentId === null ? null : ctx.documentHandle(context.documentId);\n if (!handle) return null;\n const missing = definition.requires?.find(\n (permission) => !sessionHolds(handle.security, permission),\n );\n if (missing !== undefined) return permissionKeyOf(missing);\n return passesCheck(definition, context)\n ? null\n : (definition.notAllowedKey ?? DEFAULT_NOT_ALLOWED_KEY);\n };\n\n /** Why a command won't run whatever the moment, or `null` when it may run. */\n const refusalOf = (definition: CommandDef, context: CommandContext): CommandRefusal | null => {\n if (isTurnedOff(definition)) {\n return {\n reason: 'turned-off',\n message: turnedOffMessage(labelOf(definition, context), context),\n };\n }\n const notAllowed = notAllowedKeyOf(definition, context);\n return notAllowed === null\n ? null\n : {\n reason: 'not-allowed',\n message: notAllowedMessage(notAllowed, labelOf(definition, context), context),\n };\n };\n\n return { isTurnedOff, notAllowedKeyOf, refusalOf };\n}\n","/**\n * Turning commands off and on: by category, with every category under it, and\n * one by one. Both lists are settings, so they change live and\n * `resetSettings()` restores what the app registered.\n */\nimport type { Settings } from '@embedpdf/core';\n\nimport type { CommandDef, CommandsCapability, CommandsSettings } from '../contract';\nimport { isCategoryOff } from '../services/availability';\n\ntype OffList = 'disabledCategories' | 'disabledCommands';\n\nexport function createTurningOff(\n settings: Settings<CommandsSettings>,\n definitionOf: (id: string) => CommandDef | null,\n isTurnedOff: (definition: CommandDef) => boolean,\n) {\n const listOf = (list: OffList): readonly string[] => settings.get()[list];\n const replace = (list: OffList, names: readonly string[]): void =>\n settings.api.updateSettings(\n list === 'disabledCategories'\n ? { disabledCategories: [...names] }\n : { disabledCommands: [...names] },\n );\n // Adding a name that's there, or removing one that isn't, changes nothing and fires nothing.\n const add = (list: OffList, name: string): void => {\n const current = listOf(list);\n if (!current.includes(name)) replace(list, [...current, name]);\n };\n const remove = (list: OffList, name: string): void => {\n const current = listOf(list);\n if (current.includes(name))\n replace(\n list,\n current.filter((other) => other !== name),\n );\n };\n\n return {\n getDisabledCategories: () => listOf('disabledCategories'),\n isCategoryDisabled: (category) => isCategoryOff(category, listOf('disabledCategories')),\n disableCategory: (category) => add('disabledCategories', category),\n enableCategory: (category) => remove('disabledCategories', category),\n setDisabledCategories: (categories) => replace('disabledCategories', categories),\n getDisabledCommands: () => listOf('disabledCommands'),\n isCommandDisabled: (id) => {\n const definition = definitionOf(id);\n return definition ? isTurnedOff(definition) : listOf('disabledCommands').includes(id);\n },\n disableCommand: (id) => add('disabledCommands', id),\n enableCommand: (id) => remove('disabledCommands', id),\n setDisabledCommands: (ids) => replace('disabledCommands', ids),\n } satisfies Partial<CommandsCapability>;\n}\n","/**\n * The commands controller: the commands (from the settings, added while the\n * app runs, and from families), resolution for a document (derivations over\n * live state, safe to throw), the one way to run a command, turning commands\n * off (by category and one by one), what the session may run (the scope's\n * `requires`, the plugins' checks in `allowed`), and the host-only keystroke\n * matcher.\n *\n * Definitions hold functions, so the commands added while the app runs are a\n * map outside state; every change to it calls `ctx.notify()` so readers read\n * again.\n */\nimport {\n DocumentsToken,\n isPluginError,\n memo,\n memoByKey,\n PluginError,\n toPluginError,\n toPluginErrorInfo,\n type CapabilityToken,\n type PluginContext,\n type Unsubscribe,\n} from '@embedpdf/core';\nimport { matchShortcut, type KeyStroke } from '@embedpdf/core-ui';\nimport { ShellToken } from '@embedpdf/plugin-shell/contract';\n\nimport type {\n CommandContext,\n CommandDef,\n CommandExecutedEvent,\n CommandExecutionFailedEvent,\n CommandFamily,\n CommandsSettings,\n ExecuteOptions,\n ExecuteResult,\n IconAccent,\n RegisterCommandOptions,\n ResolvedCommand,\n} from './contract';\nimport type { CommandsHostCapability, ShortcutMatch } from './host-contract';\nimport {\n configuredCommands,\n registeredCommand,\n type ConfiguredCommands,\n type RegisteredCommand,\n} from './registry';\nimport { createAvailability, labelOf, notAllowedMessage } from './services/availability';\nimport { createTurningOff } from './write/turning-off';\n\nconst panelTarget = (\n definition: CommandDef,\n): { id: string; exclusive?: string; focus?: boolean } | null =>\n definition.panel === undefined\n ? null\n : typeof definition.panel === 'string'\n ? { id: definition.panel }\n : definition.panel;\n\n/**\n * One command's live derivations for a document, as values a memo can\n * compare: the entry, label, accent colors, the enabled/active/visible flags,\n * and why it's disabled when the scope doesn't allow it.\n */\ntype Derivations = readonly [\n entry: RegisteredCommand | null,\n label: string,\n accentPrimary: string | undefined,\n accentSecondary: string | undefined,\n enabled: boolean,\n active: boolean,\n visible: boolean,\n disabledReason: string | undefined,\n];\n\nconst NOT_REGISTERED: Derivations = [\n null,\n '',\n undefined,\n undefined,\n false,\n false,\n false,\n undefined,\n];\nconst NO_NAMES: readonly string[] = [];\n\nconst accentOf = (primary?: string, secondary?: string): IconAccent | undefined =>\n primary === undefined && secondary === undefined\n ? undefined\n : {\n ...(primary !== undefined ? { primary } : {}),\n ...(secondary !== undefined ? { secondary } : {}),\n };\n\n/** The memo key of a resolution: the command id and the document named, if any. */\nconst resolutionKey = (id: string, documentId: string | undefined): string =>\n JSON.stringify([id, documentId ?? null]);\n\nexport function createCommandsController(ctx: PluginContext<void, CommandsSettings>) {\n const settings = ctx.settings();\n\n /** Commands added while the app runs, in the order they were added. */\n const registered = new Map<string, RegisteredCommand>();\n /** Bumped on every change to `registered`: the input of the reads built from it. */\n let registeredVersion = 0;\n const registeredChanged = (): void => {\n registeredVersion += 1;\n ctx.notify();\n };\n\n /** The commands the settings define, rebuilt when the setting changes. */\n const configured = memo(\n () => [settings.get().commands],\n (items): ConfiguredCommands => configuredCommands(items),\n );\n\n const executed = ctx.events.source<CommandExecutedEvent>();\n const executionFailed = ctx.events.source<CommandExecutionFailedEvent>();\n\n /** Capabilities for the command's document: the one named, else the active one. */\n const commandContext = (\n documentId?: string,\n call: { args?: unknown; signal?: AbortSignal } = {},\n ): CommandContext => {\n const target = documentId ?? ctx.get(DocumentsToken).getActiveId();\n const get = <T>(token: CapabilityToken<T>): T =>\n target ? ctx.forDocument(token, target) : ctx.get(token);\n return {\n documentId: target,\n ...(call.args === undefined ? {} : { args: call.args }),\n ...(call.signal ? { signal: call.signal } : {}),\n get,\n tryGet: <T>(token: CapabilityToken<T>): T | null => {\n try {\n return get(token);\n } catch {\n return null;\n }\n },\n };\n };\n\n /** A family's command for one name, made once so it keeps its identity. */\n const familyCommands = new WeakMap<CommandFamily, Map<string, RegisteredCommand>>();\n const familyCommand = (family: CommandFamily, name: string): RegisteredCommand => {\n let byName = familyCommands.get(family);\n if (!byName) {\n byName = new Map();\n familyCommands.set(family, byName);\n }\n let entry = byName.get(name);\n if (!entry) {\n entry = registeredCommand({ ...family.command(name), id: `${family.prefix}${name}` });\n byName.set(name, entry);\n }\n return entry;\n };\n\n /** The command with this id: one added while the app runs, else the settings', else a family's. */\n const entryOf = (id: string): RegisteredCommand | null => {\n const { commands, families } = configured();\n const entry = registered.get(id) ?? commands.get(id);\n if (entry) return entry;\n const family = families.find(\n (candidate) => id.startsWith(candidate.prefix) && id.length > candidate.prefix.length,\n );\n return family ? familyCommand(family, id.slice(family.prefix.length)) : null;\n };\n\n /** Every command with its own definition (not a family's), each id once. */\n const definedCommands = memo(\n () => [registeredVersion, configured()],\n (_version, { commands }) => {\n const entries = new Map(commands);\n for (const [id, entry] of registered) entries.set(id, entry);\n return [...entries.values()];\n },\n );\n\n // Derivations run against live state; one that throws (it needs a document\n // and none is open, say) falls back to a safe default, so the button renders\n // disabled instead of breaking.\n const derive = (\n derivation: ((context: CommandContext) => boolean) | undefined,\n context: CommandContext,\n fallback: boolean,\n ): boolean => {\n if (!derivation) return fallback;\n try {\n return derivation(context);\n } catch {\n return fallback;\n }\n };\n const deriveAccent = (\n derivation: ((context: CommandContext) => IconAccent | null) | undefined,\n context: CommandContext,\n ): IconAccent | undefined => {\n if (!derivation) return undefined;\n try {\n return derivation(context) ?? undefined;\n } catch {\n return undefined;\n }\n };\n const namesOf = (family: CommandFamily, context: CommandContext): readonly string[] => {\n try {\n return family.names(context);\n } catch {\n return NO_NAMES;\n }\n };\n\n const { isTurnedOff, notAllowedKeyOf, refusalOf } = createAvailability(ctx, settings);\n\n const derivationsOf = (entry: RegisteredCommand, documentId?: string): Derivations => {\n const { definition } = entry;\n const context = commandContext(documentId);\n const label = labelOf(definition, context);\n // Turned off hides it; not allowed hides it, or disables it with the reason.\n const turnedOff = isTurnedOff(definition);\n const notAllowed = turnedOff ? null : notAllowedKeyOf(definition, context);\n const shownWhenNotAllowed = settings.get().notAllowed === 'disable';\n const ruledOut = turnedOff || notAllowed !== null;\n // A command that opens something is active while it's open, unless it says otherwise.\n let active: boolean;\n if (definition.active) {\n active = derive(definition.active, context, false);\n } else {\n const shell = context.tryGet(ShellToken);\n const panel = panelTarget(definition);\n active = shell\n ? definition.menu\n ? shell.isMenuOpen(definition.menu)\n : panel\n ? shell.isOpen(panel.id)\n : definition.modal\n ? shell.isOpen(definition.modal)\n : false\n : false;\n }\n const accent = deriveAccent(definition.iconAccent, context);\n return [\n entry,\n label,\n accent?.primary,\n accent?.secondary,\n !ruledOut && derive(definition.enabled, context, true),\n active,\n !turnedOff &&\n (notAllowed === null || shownWhenNotAllowed) &&\n derive(definition.visible, context, true),\n notAllowed !== null && shownWhenNotAllowed\n ? notAllowedMessage(notAllowed, label, context)\n : undefined,\n ];\n };\n\n /** A resolved command, the same object until one of its derivations or its entry changes. */\n const resolvedByKey = memoByKey(\n (key: string): Derivations => {\n const [id, documentId] = JSON.parse(key) as [string, string | null];\n const entry = entryOf(id);\n return entry ? derivationsOf(entry, documentId ?? undefined) : NOT_REGISTERED;\n },\n (\n _key,\n entry,\n label,\n accentPrimary,\n accentSecondary,\n enabled,\n active,\n visible,\n disabledReason,\n ): ResolvedCommand | null =>\n entry && {\n id: entry.definition.id,\n label,\n icon: entry.definition.icon,\n iconAccent: accentOf(accentPrimary, accentSecondary),\n shortcuts: entry.shortcuts,\n menu: entry.definition.menu,\n enabled,\n active,\n visible,\n categories: entry.definition.categories ?? [],\n ...(disabledReason === undefined ? {} : { disabledReason }),\n },\n );\n const resolveCommand = (id: string, documentId?: string): ResolvedCommand | null =>\n entryOf(id) ? resolvedByKey(resolutionKey(id, documentId)) : null;\n\n /**\n * Every command's id for a document (`''` is the active one): the defined ones in the order\n * they were added, then each family's names that no defined command took.\n */\n const idsByDocument = memoByKey(\n (documentKey: string): readonly unknown[] => {\n const config = configured();\n const context = commandContext(documentKey || undefined);\n return [\n definedCommands(),\n config,\n ...config.families.map((family) => namesOf(family, context)),\n ];\n },\n (_documentKey, ...inputs): readonly string[] => {\n const [defined, { families }, ...names] = inputs as [\n readonly RegisteredCommand[],\n ConfiguredCommands,\n ...(readonly string[])[],\n ];\n const ids = defined.map((entry) => entry.definition.id);\n const taken = new Set(ids);\n families.forEach((family, index) => {\n for (const name of names[index] ?? NO_NAMES) {\n const id = `${family.prefix}${name}`;\n if (taken.has(id)) continue;\n taken.add(id);\n ids.push(id);\n }\n });\n return ids;\n },\n );\n const commandsByDocument = memoByKey(\n (documentKey: string) =>\n idsByDocument(documentKey).map((id) => resolveCommand(id, documentKey || undefined)),\n (_documentKey, ...resolved) =>\n resolved.filter((command): command is ResolvedCommand => command !== null),\n );\n const listCommands = (documentId?: string): readonly ResolvedCommand[] =>\n commandsByDocument(documentId ?? '');\n\n const listShortcuts = memo(\n () => [definedCommands()],\n (entries) =>\n entries.flatMap((entry) =>\n entry.shortcuts.map((shortcut) => ({ commandId: entry.definition.id, shortcut })),\n ),\n );\n\n /** What running a command does: its `run`, or opening what it opens. */\n const runCommand = async (definition: CommandDef, context: CommandContext): Promise<void> => {\n if (definition.run) {\n await definition.run(context);\n return;\n }\n const shell = context.tryGet(ShellToken);\n const panel = panelTarget(definition);\n if (!shell) return;\n if (definition.menu) shell.toggleMenu(definition.menu);\n else if (panel) shell.toggle(panel.id, { exclusive: panel.exclusive, focus: panel.focus });\n else if (definition.modal) shell.toggle(definition.modal, { exclusive: 'modal' });\n };\n\n const execute = async (id: string, options: ExecuteOptions = {}): Promise<ExecuteResult> => {\n const { signal, documentId, args } = options;\n if (signal?.aborted) {\n throw new PluginError('operation-cancelled', 'commands', 'operation cancelled');\n }\n const entry = entryOf(id);\n if (!entry) return { status: 'rejected', reason: 'not-found' };\n const resolved = resolveCommand(id, documentId);\n if (!resolved?.visible) return { status: 'rejected', reason: 'hidden' };\n if (!resolved.enabled) return { status: 'rejected', reason: 'disabled' };\n const context = commandContext(documentId, { args, signal });\n try {\n await ctx.cancellable(signal, runCommand(entry.definition, context));\n } catch (error) {\n // The caller cancelling isn't the command failing.\n if (signal?.aborted && isPluginError(error, 'operation-cancelled')) throw error;\n const failure = toPluginError('commands', error);\n executionFailed.emit({\n commandId: id,\n documentId: context.documentId,\n error: toPluginErrorInfo(failure),\n });\n throw failure;\n }\n executed.emit({ commandId: id, documentId: context.documentId, args });\n return { status: 'executed' };\n };\n\n const registerOne = (definition: CommandDef, options?: RegisterCommandOptions): Unsubscribe => {\n const taken = registered.has(definition.id) || configured().commands.has(definition.id);\n if (taken && !options?.replace) {\n throw new PluginError('conflict', 'commands', `duplicate command '${definition.id}'`);\n }\n const entry = registeredCommand(definition);\n registered.set(definition.id, entry);\n registeredChanged();\n return () => {\n // Own this registration only: a later replacement is not ours to remove.\n if (registered.get(definition.id) !== entry) return;\n registered.delete(definition.id);\n registeredChanged();\n };\n };\n\n const turningOff = createTurningOff(\n settings,\n (id) => entryOf(id)?.definition ?? null,\n isTurnedOff,\n );\n\n const api: CommandsHostCapability = {\n ...settings.api,\n registerCommand: registerOne,\n registerCommands: (definitions, options) => {\n const removers = definitions.map((definition) => registerOne(definition, options));\n return () => removers.forEach((remove) => remove());\n },\n hasCommand: (id) => entryOf(id) !== null,\n getCommand: (id) => entryOf(id)?.definition ?? null,\n listCommandIds: () => idsByDocument(''),\n resolveCommand,\n listCommands,\n searchCommands: (query, documentId) => {\n const needle = query.trim().toLowerCase();\n return listCommands(documentId).filter(\n (command) =>\n command.visible &&\n (needle === '' ||\n command.label.toLowerCase().includes(needle) ||\n command.id.includes(needle)),\n );\n },\n listShortcuts,\n execute,\n canExecute: (id, documentId) => {\n const resolved = resolveCommand(id, documentId);\n return !!resolved && resolved.enabled && resolved.visible;\n },\n getRefusal: (id, documentId) => {\n const entry = entryOf(id);\n return entry ? refusalOf(entry.definition, commandContext(documentId)) : null;\n },\n ...turningOff,\n onExecuted: executed.on,\n onExecutionFailed: executionFailed.on,\n // ── host lens ──\n matchStroke: (stroke: KeyStroke, options) => {\n let refused: ShortcutMatch | null = null;\n for (const entry of definedCommands()) {\n if (options.inTextField && !entry.definition.shortcutInTextFields) continue;\n if (!entry.parsed.some((shortcut) => matchShortcut(shortcut, stroke, options))) continue;\n const context = commandContext();\n const refusal = refusalOf(entry.definition, context);\n if (!refusal) return { commandId: entry.definition.id, refusal: null };\n // A refused command takes its keys only where it would show: Delete with nothing\n // selected stays the page's, even where deleting is turned off.\n if (!derive(entry.definition.visible, context, true)) continue;\n refused ??= { commandId: entry.definition.id, refusal };\n }\n return refused;\n },\n getMenuTarget: (id) => {\n const entry = entryOf(id);\n return entry ? { menu: entry.definition.menu } : null;\n },\n };\n\n return { api };\n}\n","import { definePlugin } from '@embedpdf/core';\nimport { I18nToken } from '@embedpdf/plugin-i18n/contract';\nimport { ShellToken } from '@embedpdf/plugin-shell/contract';\n\nimport { COMMANDS_DEFAULTS, type CommandsConfig } from './contract';\nimport { createCommandsController } from './controller';\nimport { CommandsToken } from './host-contract';\n\n/**\n * The commands: one set for the whole workspace, each resolved and run for a\n * document (the one named, else the document in scope, else the active one).\n * Definitions are settings and app content, never state, since they hold\n * functions. `config` is the settings the app registers, over\n * {@link COMMANDS_DEFAULTS}.\n */\nexport const commandsPlugin = (config?: CommandsConfig) =>\n definePlugin({\n id: 'commands',\n scope: 'workspace',\n token: CommandsToken,\n // Labels come from i18n, and commands that open a panel, menu or dialog\n // go through shell; without them a label is the command's own, and those\n // commands open nothing.\n optional: [I18nToken, ShellToken],\n // Command definitions come from the app and may use any capability.\n resolvesAnyCapability: true,\n settings: { defaults: COMMANDS_DEFAULTS, registered: config },\n create: createCommandsController,\n // Inside a document's scope, a call that leaves out the document is for that one.\n inScope: (commands, documentId) => ({\n ...commands,\n resolveCommand: (id, target = documentId) => commands.resolveCommand(id, target),\n listCommands: (target = documentId) => commands.listCommands(target),\n searchCommands: (query, target = documentId) => commands.searchCommands(query, target),\n execute: (id, options) =>\n commands.execute(id, { ...options, documentId: options?.documentId ?? documentId }),\n canExecute: (id, target = documentId) => commands.canExecute(id, target),\n getRefusal: (id, target = documentId) => commands.getRefusal(id, target),\n }),\n });\n"],"mappings":"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"}
@@ -0,0 +1,243 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ let _embedpdf_core = require("@embedpdf/core");
3
+ let _embedpdf_plugin_actions_contract = require("@embedpdf/plugin-actions/contract");
4
+ let _embedpdf_plugin_annotation_contract = require("@embedpdf/plugin-annotation/contract");
5
+ let _embedpdf_plugin_interaction_contract = require("@embedpdf/plugin-interaction/contract");
6
+ let _embedpdf_plugin_selection_contract = require("@embedpdf/plugin-selection/contract");
7
+ let _embedpdf_plugin_stage_contract = require("@embedpdf/plugin-stage/contract");
8
+ //#region src/standard.ts
9
+ /**
10
+ * @embedpdf/plugin-commands/standard — the commands every viewer has: zoom,
11
+ * pages, view rotation, a command for every tool, copy, delete, download and
12
+ * print, with shortcuts, and labels in EmbedPDF's eight languages (the i18n
13
+ * plugin has the strings). Three of them reach the browser (the clipboard, a
14
+ * file download, the print dialog), which plugins never touch, so each
15
+ * framework's `/commands` builds them with its platform: that is the
16
+ * `standardCommands` an app imports.
17
+ */
18
+ const stageOf = (context) => context.tryGet(_embedpdf_plugin_stage_contract.StageToken);
19
+ const interactionOf = (context) => context.tryGet(_embedpdf_plugin_interaction_contract.InteractionToken);
20
+ /** Enabled while the document has a Stage. */
21
+ const hasStage = (context) => stageOf(context) !== null;
22
+ /** The ids of a tool list, made once per list, which keeps its identity while the tools don't change. */
23
+ const toolIds = /* @__PURE__ */ new WeakMap();
24
+ const idsOf = (tools) => {
25
+ let ids = toolIds.get(tools);
26
+ if (!ids) {
27
+ ids = tools.map((tool) => tool.id);
28
+ toolIds.set(tools, ids);
29
+ }
30
+ return ids;
31
+ };
32
+ /**
33
+ * Whether the user may use a tool: one that draws annotations needs permission to create them.
34
+ * A tool another plugin owns asks nothing here; that plugin refuses its own gesture.
35
+ */
36
+ const mayUseTool = (context, toolId) => {
37
+ const annotation = context.tryGet(_embedpdf_plugin_annotation_contract.AnnotationToken);
38
+ return !annotation?.tools.get(toolId) || annotation.canCreate();
39
+ };
40
+ /** Switching to a tool: active while it's the tool, there only when the document has it. */
41
+ const toolCommand = (toolId) => ({
42
+ labelKey: `commands.tool.${toolId}`,
43
+ label: toolId,
44
+ icon: toolId,
45
+ categories: ["tool"],
46
+ run: (context) => interactionOf(context)?.activateTool(toolId),
47
+ active: (context) => interactionOf(context)?.getActiveToolId() === toolId,
48
+ visible: (context) => interactionOf(context)?.hasTool(toolId) ?? false,
49
+ enabled: (context) => mayUseTool(context, toolId)
50
+ });
51
+ /** `tool:<id>` for every tool the document has. */
52
+ const toolCommands = {
53
+ prefix: "tool:",
54
+ names: (context) => {
55
+ const interaction = interactionOf(context);
56
+ return interaction ? idsOf(interaction.listTools()) : [];
57
+ },
58
+ command: toolCommand
59
+ };
60
+ /** The standard commands, with the browser's part from `platform`. */
61
+ function createStandardCommands(platform) {
62
+ return [
63
+ {
64
+ id: "zoom:in",
65
+ labelKey: "commands.zoom.in",
66
+ label: "Zoom in",
67
+ icon: "zoom-in",
68
+ shortcut: ["Mod+=", "Mod+NumpadAdd"],
69
+ categories: ["zoom"],
70
+ run: (context) => stageOf(context)?.zoomIn(),
71
+ enabled: hasStage
72
+ },
73
+ {
74
+ id: "zoom:out",
75
+ labelKey: "commands.zoom.out",
76
+ label: "Zoom out",
77
+ icon: "zoom-out",
78
+ shortcut: ["Mod+-", "Mod+NumpadSubtract"],
79
+ categories: ["zoom"],
80
+ run: (context) => stageOf(context)?.zoomOut(),
81
+ enabled: hasStage
82
+ },
83
+ {
84
+ id: "zoom:fit-width",
85
+ labelKey: "commands.zoom.fitWidth",
86
+ label: "Fit width",
87
+ icon: "fit-width",
88
+ categories: ["zoom"],
89
+ run: (context) => stageOf(context)?.fitWidth(),
90
+ active: (context) => stageOf(context)?.getZoomMode() === "fit-width",
91
+ enabled: hasStage
92
+ },
93
+ {
94
+ id: "zoom:fit-page",
95
+ labelKey: "commands.zoom.fitPage",
96
+ label: "Fit page",
97
+ icon: "fit-page",
98
+ categories: ["zoom"],
99
+ run: (context) => stageOf(context)?.fitPage(),
100
+ active: (context) => stageOf(context)?.getZoomMode() === "fit-page",
101
+ enabled: hasStage
102
+ },
103
+ {
104
+ id: "page:next",
105
+ labelKey: "commands.page.next",
106
+ label: "Next page",
107
+ icon: "next-page",
108
+ shortcut: "ArrowRight",
109
+ categories: ["page"],
110
+ run: (context) => stageOf(context)?.nextPage(),
111
+ enabled: (context) => stageOf(context)?.canGoNext() ?? false
112
+ },
113
+ {
114
+ id: "page:previous",
115
+ labelKey: "commands.page.previous",
116
+ label: "Previous page",
117
+ icon: "previous-page",
118
+ shortcut: "ArrowLeft",
119
+ categories: ["page"],
120
+ run: (context) => stageOf(context)?.previousPage(),
121
+ enabled: (context) => stageOf(context)?.canGoPrevious() ?? false
122
+ },
123
+ {
124
+ id: "page:first",
125
+ labelKey: "commands.page.first",
126
+ label: "First page",
127
+ icon: "first-page",
128
+ shortcut: "Home",
129
+ categories: ["page"],
130
+ run: (context) => stageOf(context)?.goToFirstPage(),
131
+ enabled: (context) => stageOf(context)?.canGoPrevious() ?? false
132
+ },
133
+ {
134
+ id: "page:last",
135
+ labelKey: "commands.page.last",
136
+ label: "Last page",
137
+ icon: "last-page",
138
+ shortcut: "End",
139
+ categories: ["page"],
140
+ run: (context) => stageOf(context)?.goToLastPage(),
141
+ enabled: (context) => stageOf(context)?.canGoNext() ?? false
142
+ },
143
+ {
144
+ id: "view:rotate-clockwise",
145
+ labelKey: "commands.view.rotateClockwise",
146
+ label: "Rotate clockwise",
147
+ icon: "rotate-clockwise",
148
+ categories: ["view"],
149
+ run: (context) => stageOf(context)?.rotateViewBy(90),
150
+ enabled: hasStage
151
+ },
152
+ {
153
+ id: "view:rotate-counterclockwise",
154
+ labelKey: "commands.view.rotateCounterclockwise",
155
+ label: "Rotate counterclockwise",
156
+ icon: "rotate-counterclockwise",
157
+ categories: ["view"],
158
+ run: (context) => stageOf(context)?.rotateViewBy(-90),
159
+ enabled: hasStage
160
+ },
161
+ {
162
+ ...toolCommand("pointer"),
163
+ id: "tool:pointer",
164
+ shortcut: "V"
165
+ },
166
+ {
167
+ ...toolCommand("pan"),
168
+ id: "tool:pan",
169
+ shortcut: "H"
170
+ },
171
+ toolCommands,
172
+ {
173
+ id: "selection:copy",
174
+ labelKey: "commands.selection.copy",
175
+ label: "Copy",
176
+ icon: "copy",
177
+ shortcut: "Mod+C",
178
+ categories: ["selection"],
179
+ run: (context) => platform.copySelection(context.get(_embedpdf_plugin_selection_contract.SelectionToken)),
180
+ enabled: (context) => {
181
+ const selection = context.tryGet(_embedpdf_plugin_selection_contract.SelectionToken);
182
+ return !!selection && selection.hasSelection() && selection.canCopy();
183
+ }
184
+ },
185
+ {
186
+ id: "annotation:delete",
187
+ labelKey: "commands.annotation.delete",
188
+ label: "Delete",
189
+ icon: "delete",
190
+ shortcut: ["Delete", "Backspace"],
191
+ categories: ["annotation"],
192
+ run: (context) => context.get(_embedpdf_plugin_annotation_contract.AnnotationToken).selection.delete({ signal: context.signal }),
193
+ enabled: (context) => {
194
+ const annotation = context.tryGet(_embedpdf_plugin_annotation_contract.AnnotationToken);
195
+ if (!annotation) return false;
196
+ const selected = annotation.selection.list();
197
+ return selected.length > 0 && selected.every(({ ref }) => annotation.canDelete(ref) && annotation.isEditable(ref));
198
+ }
199
+ },
200
+ {
201
+ id: "document:download",
202
+ labelKey: "commands.document.download",
203
+ label: "Download",
204
+ icon: "download",
205
+ shortcut: "Mod+S",
206
+ categories: ["document"],
207
+ allowed: (context) => context.tryGet(_embedpdf_core.DocumentsToken)?.canDownload() ?? true,
208
+ notAllowedKey: "commands.notAllowed.doc-download",
209
+ run: async (context) => {
210
+ const documents = context.get(_embedpdf_core.DocumentsToken);
211
+ const id = context.documentId ?? void 0;
212
+ const bytes = await documents.download(id, { signal: context.signal });
213
+ platform.saveFile(bytes, fileNameOf(documents.get(id)?.name));
214
+ },
215
+ enabled: (context) => context.documentId !== null
216
+ },
217
+ {
218
+ id: "document:print",
219
+ labelKey: "commands.document.print",
220
+ label: "Print",
221
+ icon: "print",
222
+ shortcut: "Mod+P",
223
+ categories: ["document"],
224
+ allowed: (context) => context.tryGet(_embedpdf_core.DocumentsToken)?.canPrint() ?? true,
225
+ notAllowedKey: "commands.notAllowed.doc-print",
226
+ run: (context) => {
227
+ const actions = context.tryGet(_embedpdf_plugin_actions_contract.ActionsToken);
228
+ if (actions) return actions.runDocumentVerb("print", () => platform.print());
229
+ platform.print();
230
+ },
231
+ enabled: (context) => context.documentId !== null
232
+ }
233
+ ];
234
+ }
235
+ /** The download's file name: the document's name, ending in `.pdf`. */
236
+ function fileNameOf(name) {
237
+ if (!name) return "document.pdf";
238
+ return /\.pdf$/i.test(name) ? name : `${name}.pdf`;
239
+ }
240
+ //#endregion
241
+ exports.createStandardCommands = createStandardCommands;
242
+
243
+ //# sourceMappingURL=standard.cjs.map
@@ -0,0 +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":"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"}
@@ -0,0 +1,17 @@
1
+ import { i as CommandDef, s as CommandFamily } from "./contract-DAV5VR3P.cjs";
2
+ import { SelectionCapability } from "@embedpdf/plugin-selection/contract";
3
+ //#region src/standard.d.ts
4
+ /** What the standard commands need from the browser. */
5
+ interface StandardCommandsPlatform {
6
+ /** Copy the selected text to the clipboard. */
7
+ copySelection(selection: SelectionCapability): Promise<unknown>;
8
+ /** Give the user the bytes as a file download. */
9
+ saveFile(bytes: Uint8Array, fileName: string): void;
10
+ /** Open the print dialog. */
11
+ print(): void;
12
+ }
13
+ /** The standard commands, with the browser's part from `platform`. */
14
+ declare function createStandardCommands(platform: StandardCommandsPlatform): readonly (CommandDef | CommandFamily)[];
15
+ //#endregion
16
+ export { StandardCommandsPlatform, createStandardCommands };
17
+ //# sourceMappingURL=standard.d.cts.map
@@ -0,0 +1,17 @@
1
+ import { i as CommandDef, s as CommandFamily } from "./contract-DAV5VR3P.js";
2
+ import { SelectionCapability } from "@embedpdf/plugin-selection/contract";
3
+ //#region src/standard.d.ts
4
+ /** What the standard commands need from the browser. */
5
+ interface StandardCommandsPlatform {
6
+ /** Copy the selected text to the clipboard. */
7
+ copySelection(selection: SelectionCapability): Promise<unknown>;
8
+ /** Give the user the bytes as a file download. */
9
+ saveFile(bytes: Uint8Array, fileName: string): void;
10
+ /** Open the print dialog. */
11
+ print(): void;
12
+ }
13
+ /** The standard commands, with the browser's part from `platform`. */
14
+ declare function createStandardCommands(platform: StandardCommandsPlatform): readonly (CommandDef | CommandFamily)[];
15
+ //#endregion
16
+ export { StandardCommandsPlatform, createStandardCommands };
17
+ //# sourceMappingURL=standard.d.ts.map