@embedpdf/plugin-commands 2.3.0 → 2.4.0

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.cjs CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@embedpdf/core"),t="commands",s={id:t,name:"Commands Plugin",version:"1.0.0",provides:["commands"],requires:[],optional:["i18n","ui"],defaultConfig:{commands:{}}},i="COMMANDS/SET_DISABLED_CATEGORIES",o=e=>({type:i,payload:e}),a=class extends e.BasePlugin{constructor(t,s,i){var a;super(t,s),this.commands=new Map,this.i18n=null,this.shortcutMap=new Map,this.commandExecuted$=e.createEmitter(),this.commandStateChanged$=e.createEmitter(),this.shortcutExecuted$=e.createEmitter(),this.categoryChanged$=e.createBehaviorEmitter(),this.previousStates=new Map;const r=s.getPlugin("i18n");this.i18n=(null==r?void 0:r.provides())??null,(null==(a=i.disabledCategories)?void 0:a.length)&&this.dispatch(o(i.disabledCategories)),Object.values(i.commands).forEach(e=>{this.registerCommand(e)}),this.registry.getStore().subscribe((e,t)=>{this.onGlobalStoreChange(t)})}onDocumentClosed(e){this.previousStates.delete(e),this.logger.debug("CommandsPlugin","DocumentClosed",`Cleaned up command state cache for document: ${e}`)}async initialize(){this.logger.info("CommandsPlugin","Initialize","Commands plugin initialized")}async destroy(){this.commandExecuted$.clear(),this.commandStateChanged$.clear(),this.shortcutExecuted$.clear(),this.categoryChanged$.clear(),this.commands.clear(),this.shortcutMap.clear(),this.previousStates.clear(),super.destroy()}disableCategoryImpl(e){const t=new Set(this.state.disabledCategories);t.has(e)||(t.add(e),this.dispatch(o(Array.from(t))),this.categoryChanged$.emit({disabledCategories:Array.from(t)}))}enableCategoryImpl(e){const t=new Set(this.state.disabledCategories);t.has(e)&&(t.delete(e),this.dispatch(o(Array.from(t))),this.categoryChanged$.emit({disabledCategories:Array.from(t)}))}toggleCategoryImpl(e){this.state.disabledCategories.includes(e)?this.enableCategoryImpl(e):this.disableCategoryImpl(e)}setDisabledCategoriesImpl(e){this.dispatch(o(e)),this.categoryChanged$.emit({disabledCategories:e})}isCommandCategoryDisabled(e){var t;return!!(null==(t=e.categories)?void 0:t.length)&&e.categories.some(e=>this.state.disabledCategories.includes(e))}buildCapability(){return{resolve:(e,t)=>this.resolve(e,t),execute:(e,t,s="ui")=>this.execute(e,t,s),getAllCommands:e=>this.getAllCommands(e),getCommandsByCategory:(e,t)=>this.getCommandsByCategory(e,t),getCommandByShortcut:e=>this.getCommandByShortcut(e),getAllShortcuts:()=>new Map(this.shortcutMap),forDocument:e=>this.createCommandScope(e),registerCommand:e=>this.registerCommand(e),unregisterCommand:e=>this.unregisterCommand(e),disableCategory:e=>this.disableCategoryImpl(e),enableCategory:e=>this.enableCategoryImpl(e),toggleCategory:e=>this.toggleCategoryImpl(e),setDisabledCategories:e=>this.setDisabledCategoriesImpl(e),getDisabledCategories:()=>this.state.disabledCategories,isCategoryDisabled:e=>this.state.disabledCategories.includes(e),onCommandExecuted:this.commandExecuted$.on,onCommandStateChanged:this.commandStateChanged$.on,onShortcutExecuted:this.shortcutExecuted$.on,onCategoryChanged:this.categoryChanged$.on}}createCommandScope(e){return{resolve:t=>this.resolve(t,e),execute:(t,s="ui")=>this.execute(t,e,s),getAllCommands:()=>this.getAllCommands(e),getCommandsByCategory:t=>this.getCommandsByCategory(t,e),onCommandStateChanged:t=>this.commandStateChanged$.on(s=>{if(s.documentId===e){const{documentId:e,...i}=s;t(i)}})}}resolve(e,t){const s=t??this.getActiveDocumentId(),i=this.commands.get(e);if(!i)throw new Error(`Command not found: ${e}`);const o=this.registry.getStore().getState(),a=this.resolveLabel(i,o,s),r=i.shortcuts?Array.isArray(i.shortcuts)?i.shortcuts:[i.shortcuts]:void 0,n=this.resolveDynamic(i.disabled,o,s)??!1,d=this.isCommandCategoryDisabled(i),m=n||d;return{id:i.id,label:a,icon:this.resolveDynamic(i.icon,o,s),iconProps:this.resolveDynamic(i.iconProps,o,s),active:this.resolveDynamic(i.active,o,s)??!1,disabled:m,visible:this.resolveDynamic(i.visible,o,s)??!0,shortcuts:r,shortcutLabel:i.shortcutLabel,categories:i.categories,description:i.description,execute:()=>i.action({registry:this.registry,state:o,documentId:s})}}resolveLabel(e,t,s){const i=this.resolveDynamic(e.labelKey,t,s);if(i&&this.i18n){const o=this.resolveDynamic(e.labelParams,t,s);return this.i18n.t(i,{params:o,documentId:s})}return e.label?e.label:e.id}resolveDynamic(e,t,s){if(void 0!==e)return"function"==typeof e?e({registry:this.registry,state:t,documentId:s}):e}execute(e,t,s="ui"){const i=t??this.getActiveDocumentId(),o=this.resolve(e,i);o.disabled?this.logger.warn("CommandsPlugin","ExecutionBlocked",`Command '${e}' is disabled for document '${i}'`):o.visible?(o.execute(),this.commandExecuted$.emit({commandId:e,documentId:i,source:s}),this.logger.debug("CommandsPlugin","CommandExecuted",`Command '${e}' executed for document '${i}' (source: ${s})`)):this.logger.warn("CommandsPlugin","ExecutionBlocked",`Command '${e}' is not visible for document '${i}'`)}registerCommand(e){if(this.commands.has(e.id)&&this.logger.warn("CommandsPlugin","CommandOverwrite",`Command '${e.id}' already exists and will be overwritten`),this.commands.set(e.id,e),e.shortcuts){(Array.isArray(e.shortcuts)?e.shortcuts:[e.shortcuts]).forEach(t=>{const s=this.normalizeShortcut(t);this.shortcutMap.set(s,e.id)})}this.logger.debug("CommandsPlugin","CommandRegistered",`Command '${e.id}' registered`)}unregisterCommand(e){const t=this.commands.get(e);if(t){if(t.shortcuts){(Array.isArray(t.shortcuts)?t.shortcuts:[t.shortcuts]).forEach(e=>{const t=this.normalizeShortcut(e);this.shortcutMap.delete(t)})}this.commands.delete(e),this.logger.debug("CommandsPlugin","CommandUnregistered",`Command '${e}' unregistered`)}}getCommandByShortcut(e){const t=this.normalizeShortcut(e),s=this.shortcutMap.get(t);return s?this.commands.get(s)??null:null}normalizeShortcut(e){return e.toLowerCase().split("+").sort().join("+")}getAllCommands(e){const t=e??this.getActiveDocumentId();return Array.from(this.commands.keys()).map(e=>this.resolve(e,t))}getCommandsByCategory(e,t){const s=t??this.getActiveDocumentId();return Array.from(this.commands.values()).filter(t=>{var s;return null==(s=t.categories)?void 0:s.includes(e)}).map(e=>this.resolve(e.id,s))}onGlobalStoreChange(e){Object.keys(e.core.documents).forEach(t=>{this.detectCommandChanges(t,e)})}detectCommandChanges(t,s){const i=s.core.documents[t];if(!i||"loaded"!==i.status)return;const o=this.previousStates.get(t)??new Map;this.commands.forEach((s,i)=>{const a=this.resolve(i,t),r=o.get(i);if(!r)return void o.set(i,a);const n={};r.active!==a.active&&(n.active=a.active),r.disabled!==a.disabled&&(n.disabled=a.disabled),r.visible!==a.visible&&(n.visible=a.visible),r.label!==a.label&&(n.label=a.label),r.icon!==a.icon&&(n.icon=a.icon),e.arePropsEqual(r.iconProps,a.iconProps)||(n.iconProps=a.iconProps),Object.keys(n).length>0&&(o.set(i,a),this.commandStateChanged$.emit({commandId:i,documentId:t,changes:n}))}),this.previousStates.set(t,o)}};a.id="commands";let r=a;const n={disabledCategories:[]},d={manifest:s,create:(e,s)=>new r(t,e,s),reducer:(e=n,t)=>t.type===i?{...e,disabledCategories:t.payload}:e,initialState:n};exports.COMMANDS_PLUGIN_ID=t,exports.CommandsPlugin=r,exports.CommandsPluginPackage=d,exports.manifest=s;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@embedpdf/core"),t="commands",s={id:t,name:"Commands Plugin",version:"1.0.0",provides:["commands"],requires:[],optional:["i18n","ui"],defaultConfig:{commands:{}}},o="COMMANDS/SET_DISABLED_CATEGORIES",i=e=>({type:o,payload:e}),a=class extends e.BasePlugin{constructor(t,s,o){var a;super(t,s),this.commands=new Map,this.i18n=null,this.shortcutMap=new Map,this.commandExecuted$=e.createEmitter(),this.commandStateChanged$=e.createEmitter(),this.shortcutExecuted$=e.createEmitter(),this.categoryChanged$=e.createBehaviorEmitter(),this.previousStates=new Map;const r=s.getPlugin("i18n");this.i18n=(null==r?void 0:r.provides())??null,(null==(a=o.disabledCategories)?void 0:a.length)&&this.dispatch(i(o.disabledCategories)),Object.values(o.commands).forEach(e=>{this.registerCommand(e)}),this.registry.getStore().subscribe((e,t)=>{this.onGlobalStoreChange(t)})}onDocumentClosed(e){this.previousStates.delete(e),this.logger.debug("CommandsPlugin","DocumentClosed",`Cleaned up command state cache for document: ${e}`)}async initialize(){this.logger.info("CommandsPlugin","Initialize","Commands plugin initialized")}async destroy(){this.commandExecuted$.clear(),this.commandStateChanged$.clear(),this.shortcutExecuted$.clear(),this.categoryChanged$.clear(),this.commands.clear(),this.shortcutMap.clear(),this.previousStates.clear(),super.destroy()}disableCategoryImpl(e){const t=new Set(this.state.disabledCategories);t.has(e)||(t.add(e),this.dispatch(i(Array.from(t))),this.categoryChanged$.emit({disabledCategories:Array.from(t)}))}enableCategoryImpl(e){const t=new Set(this.state.disabledCategories);t.has(e)&&(t.delete(e),this.dispatch(i(Array.from(t))),this.categoryChanged$.emit({disabledCategories:Array.from(t)}))}toggleCategoryImpl(e){this.state.disabledCategories.includes(e)?this.enableCategoryImpl(e):this.disableCategoryImpl(e)}setDisabledCategoriesImpl(e){this.dispatch(i(e)),this.categoryChanged$.emit({disabledCategories:e})}isCommandCategoryDisabled(e){var t;return!!(null==(t=e.categories)?void 0:t.length)&&e.categories.some(e=>this.state.disabledCategories.includes(e))}buildCapability(){return{resolve:(e,t)=>this.resolve(e,t),execute:(e,t,s="ui")=>this.execute(e,t,s),getAllCommands:e=>this.getAllCommands(e),getCommandsByCategory:(e,t)=>this.getCommandsByCategory(e,t),getCommandByShortcut:e=>this.getCommandByShortcut(e),getAllShortcuts:()=>new Map(this.shortcutMap),forDocument:e=>this.createCommandScope(e),registerCommand:e=>this.registerCommand(e),unregisterCommand:e=>this.unregisterCommand(e),disableCategory:e=>this.disableCategoryImpl(e),enableCategory:e=>this.enableCategoryImpl(e),toggleCategory:e=>this.toggleCategoryImpl(e),setDisabledCategories:e=>this.setDisabledCategoriesImpl(e),getDisabledCategories:()=>this.state.disabledCategories,isCategoryDisabled:e=>this.state.disabledCategories.includes(e),onCommandExecuted:this.commandExecuted$.on,onCommandStateChanged:this.commandStateChanged$.on,onShortcutExecuted:this.shortcutExecuted$.on,onCategoryChanged:this.categoryChanged$.on}}createCommandScope(e){return{resolve:t=>this.resolve(t,e),execute:(t,s="ui")=>this.execute(t,e,s),getAllCommands:()=>this.getAllCommands(e),getCommandsByCategory:t=>this.getCommandsByCategory(t,e),onCommandStateChanged:t=>this.commandStateChanged$.on(s=>{if(s.documentId===e){const{documentId:e,...o}=s;t(o)}})}}resolve(e,t){const s=t??this.getActiveDocumentId(),o=this.commands.get(e);if(!o)throw new Error(`Command not found: ${e}`);const i=this.registry.getStore().getState(),a=this.resolveLabel(o,i,s),r=o.shortcuts?Array.isArray(o.shortcuts)?o.shortcuts:[o.shortcuts]:void 0,n=this.resolveDynamic(o.disabled,i,s)??!1,d=this.isCommandCategoryDisabled(o),m=n||d;return{id:o.id,label:a,icon:this.resolveDynamic(o.icon,i,s),iconProps:this.resolveDynamic(o.iconProps,i,s),active:this.resolveDynamic(o.active,i,s)??!1,disabled:m,visible:this.resolveDynamic(o.visible,i,s)??!0,shortcuts:r,shortcutLabel:o.shortcutLabel,categories:o.categories,description:o.description,execute:()=>o.action({registry:this.registry,state:i,documentId:s,logger:this.logger})}}resolveLabel(e,t,s){const o=this.resolveDynamic(e.labelKey,t,s);if(o&&this.i18n){const i=this.resolveDynamic(e.labelParams,t,s);return this.i18n.t(o,{params:i,documentId:s})}return e.label?e.label:e.id}resolveDynamic(e,t,s){if(void 0!==e)return"function"==typeof e?e({registry:this.registry,state:t,documentId:s,logger:this.logger}):e}execute(e,t,s="ui"){const o=t??this.getActiveDocumentId(),i=this.resolve(e,o);i.disabled?this.logger.warn("CommandsPlugin","ExecutionBlocked",`Command '${e}' is disabled for document '${o}'`):i.visible?(i.execute(),this.commandExecuted$.emit({commandId:e,documentId:o,source:s}),this.logger.debug("CommandsPlugin","CommandExecuted",`Command '${e}' executed for document '${o}' (source: ${s})`)):this.logger.warn("CommandsPlugin","ExecutionBlocked",`Command '${e}' is not visible for document '${o}'`)}registerCommand(e){if(this.commands.has(e.id)&&this.logger.warn("CommandsPlugin","CommandOverwrite",`Command '${e.id}' already exists and will be overwritten`),this.commands.set(e.id,e),e.shortcuts){(Array.isArray(e.shortcuts)?e.shortcuts:[e.shortcuts]).forEach(t=>{const s=this.normalizeShortcut(t);this.shortcutMap.set(s,e.id)})}this.logger.debug("CommandsPlugin","CommandRegistered",`Command '${e.id}' registered`)}unregisterCommand(e){const t=this.commands.get(e);if(t){if(t.shortcuts){(Array.isArray(t.shortcuts)?t.shortcuts:[t.shortcuts]).forEach(e=>{const t=this.normalizeShortcut(e);this.shortcutMap.delete(t)})}this.commands.delete(e),this.logger.debug("CommandsPlugin","CommandUnregistered",`Command '${e}' unregistered`)}}getCommandByShortcut(e){const t=this.normalizeShortcut(e),s=this.shortcutMap.get(t);return s?this.commands.get(s)??null:null}normalizeShortcut(e){return e.toLowerCase().split("+").sort().join("+")}getAllCommands(e){const t=e??this.getActiveDocumentId();return Array.from(this.commands.keys()).map(e=>this.resolve(e,t))}getCommandsByCategory(e,t){const s=t??this.getActiveDocumentId();return Array.from(this.commands.values()).filter(t=>{var s;return null==(s=t.categories)?void 0:s.includes(e)}).map(e=>this.resolve(e.id,s))}onGlobalStoreChange(e){Object.keys(e.core.documents).forEach(t=>{this.detectCommandChanges(t,e)})}detectCommandChanges(t,s){const o=s.core.documents[t];if(!o||"loaded"!==o.status)return;const i=this.previousStates.get(t)??new Map;this.commands.forEach((s,o)=>{const a=this.resolve(o,t),r=i.get(o);if(!r)return void i.set(o,a);const n={};r.active!==a.active&&(n.active=a.active),r.disabled!==a.disabled&&(n.disabled=a.disabled),r.visible!==a.visible&&(n.visible=a.visible),r.label!==a.label&&(n.label=a.label),r.icon!==a.icon&&(n.icon=a.icon),e.arePropsEqual(r.iconProps,a.iconProps)||(n.iconProps=a.iconProps),Object.keys(n).length>0&&(i.set(o,a),this.commandStateChanged$.emit({commandId:o,documentId:t,changes:n}))}),this.previousStates.set(t,i)}};a.id="commands";let r=a;const n={disabledCategories:[]},d={manifest:s,create:(e,s)=>new r(t,e,s),reducer:(e=n,t)=>t.type===o?{...e,disabledCategories:t.payload}:e,initialState:n};exports.COMMANDS_PLUGIN_ID=t,exports.CommandsPlugin=r,exports.CommandsPluginPackage=d,exports.manifest=s;
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../src/lib/manifest.ts","../src/lib/actions.ts","../src/lib/commands-plugin.ts","../src/lib/reducer.ts","../src/lib/index.ts"],"sourcesContent":["import { PluginManifest } from '@embedpdf/core';\nimport { CommandsPluginConfig } from './types';\n\nexport const COMMANDS_PLUGIN_ID = 'commands';\n\nexport const manifest: PluginManifest<CommandsPluginConfig> = {\n id: COMMANDS_PLUGIN_ID,\n name: 'Commands Plugin',\n version: '1.0.0',\n provides: ['commands'],\n requires: [],\n optional: ['i18n', 'ui'],\n defaultConfig: {\n commands: {},\n },\n};\n","import { Action } from '@embedpdf/core';\n\nexport const SET_DISABLED_CATEGORIES = 'COMMANDS/SET_DISABLED_CATEGORIES';\n\nexport interface SetDisabledCategoriesAction extends Action {\n type: typeof SET_DISABLED_CATEGORIES;\n payload: string[];\n}\n\nexport type CommandsAction = SetDisabledCategoriesAction;\n\nexport const setDisabledCategories = (categories: string[]): SetDisabledCategoriesAction => ({\n type: SET_DISABLED_CATEGORIES,\n payload: categories,\n});\n","import {\n BasePlugin,\n PluginRegistry,\n StoreState,\n createEmitter,\n createBehaviorEmitter,\n Listener,\n arePropsEqual,\n} from '@embedpdf/core';\nimport { I18nCapability, I18nPlugin } from '@embedpdf/plugin-i18n';\nimport {\n CommandsCapability,\n CommandsPluginConfig,\n CommandsState,\n Command,\n ResolvedCommand,\n CommandExecutedEvent,\n CommandStateChangedEvent,\n ShortcutExecutedEvent,\n CategoryChangedEvent,\n CommandScope,\n Dynamic,\n} from './types';\nimport { CommandsAction, setDisabledCategories } from './actions';\n\nexport class CommandsPlugin extends BasePlugin<\n CommandsPluginConfig,\n CommandsCapability,\n CommandsState,\n CommandsAction\n> {\n static readonly id = 'commands' as const;\n\n private commands = new Map<string, Command>();\n private i18n: I18nCapability | null = null;\n private shortcutMap = new Map<string, string>(); // shortcut -> commandId\n\n private readonly commandExecuted$ = createEmitter<CommandExecutedEvent>();\n private readonly commandStateChanged$ = createEmitter<CommandStateChangedEvent>();\n private readonly shortcutExecuted$ = createEmitter<ShortcutExecutedEvent>();\n private readonly categoryChanged$ = createBehaviorEmitter<CategoryChangedEvent>();\n\n // Cache previous resolved states per document to detect changes\n private previousStates = new Map<string, Map<string, ResolvedCommand>>();\n\n constructor(id: string, registry: PluginRegistry, config: CommandsPluginConfig) {\n super(id, registry);\n\n // Check if i18n plugin is available (optional dependency)\n const i18nPlugin = registry.getPlugin<I18nPlugin>('i18n');\n this.i18n = i18nPlugin?.provides() ?? null;\n\n // Initialize disabled categories from config\n if (config.disabledCategories?.length) {\n this.dispatch(setDisabledCategories(config.disabledCategories));\n }\n\n // Register all commands from config\n Object.values(config.commands).forEach((command) => {\n this.registerCommand(command);\n });\n\n // Subscribe to global store changes\n this.registry.getStore().subscribe((_action, newState) => {\n this.onGlobalStoreChange(newState);\n });\n }\n\n protected override onDocumentClosed(documentId: string): void {\n // Cleanup previous states cache\n this.previousStates.delete(documentId);\n\n this.logger.debug(\n 'CommandsPlugin',\n 'DocumentClosed',\n `Cleaned up command state cache for document: ${documentId}`,\n );\n }\n\n async initialize(): Promise<void> {\n this.logger.info('CommandsPlugin', 'Initialize', 'Commands plugin initialized');\n }\n\n async destroy(): Promise<void> {\n this.commandExecuted$.clear();\n this.commandStateChanged$.clear();\n this.shortcutExecuted$.clear();\n this.categoryChanged$.clear();\n this.commands.clear();\n this.shortcutMap.clear();\n this.previousStates.clear();\n super.destroy();\n }\n\n // ─────────────────────────────────────────────────────────\n // Category Management\n // ─────────────────────────────────────────────────────────\n\n private disableCategoryImpl(category: string): void {\n const current = new Set(this.state.disabledCategories);\n if (!current.has(category)) {\n current.add(category);\n this.dispatch(setDisabledCategories(Array.from(current)));\n this.categoryChanged$.emit({ disabledCategories: Array.from(current) });\n }\n }\n\n private enableCategoryImpl(category: string): void {\n const current = new Set(this.state.disabledCategories);\n if (current.has(category)) {\n current.delete(category);\n this.dispatch(setDisabledCategories(Array.from(current)));\n this.categoryChanged$.emit({ disabledCategories: Array.from(current) });\n }\n }\n\n private toggleCategoryImpl(category: string): void {\n if (this.state.disabledCategories.includes(category)) {\n this.enableCategoryImpl(category);\n } else {\n this.disableCategoryImpl(category);\n }\n }\n\n private setDisabledCategoriesImpl(categories: string[]): void {\n this.dispatch(setDisabledCategories(categories));\n this.categoryChanged$.emit({ disabledCategories: categories });\n }\n\n /**\n * Check if command has any disabled category\n */\n private isCommandCategoryDisabled(command: Command): boolean {\n if (!command.categories?.length) return false;\n return command.categories.some((cat) => this.state.disabledCategories.includes(cat));\n }\n\n // ─────────────────────────────────────────────────────────\n // Capability\n // ─────────────────────────────────────────────────────────\n\n protected buildCapability(): CommandsCapability {\n return {\n resolve: (commandId, documentId) => this.resolve(commandId, documentId),\n execute: (commandId, documentId, source = 'ui') =>\n this.execute(commandId, documentId, source),\n getAllCommands: (documentId) => this.getAllCommands(documentId),\n getCommandsByCategory: (category, documentId) =>\n this.getCommandsByCategory(category, documentId),\n getCommandByShortcut: (shortcut) => this.getCommandByShortcut(shortcut),\n getAllShortcuts: () => new Map(this.shortcutMap),\n forDocument: (documentId) => this.createCommandScope(documentId),\n registerCommand: (command) => this.registerCommand(command),\n unregisterCommand: (commandId) => this.unregisterCommand(commandId),\n\n // Category management\n disableCategory: (category) => this.disableCategoryImpl(category),\n enableCategory: (category) => this.enableCategoryImpl(category),\n toggleCategory: (category) => this.toggleCategoryImpl(category),\n setDisabledCategories: (categories) => this.setDisabledCategoriesImpl(categories),\n getDisabledCategories: () => this.state.disabledCategories,\n isCategoryDisabled: (category) => this.state.disabledCategories.includes(category),\n\n // Events\n onCommandExecuted: this.commandExecuted$.on,\n onCommandStateChanged: this.commandStateChanged$.on,\n onShortcutExecuted: this.shortcutExecuted$.on,\n onCategoryChanged: this.categoryChanged$.on,\n };\n }\n\n // ─────────────────────────────────────────────────────────\n // Document Scoping\n // ─────────────────────────────────────────────────────────\n\n private createCommandScope(documentId: string): CommandScope {\n return {\n resolve: (commandId) => this.resolve(commandId, documentId),\n execute: (commandId, source = 'ui') => this.execute(commandId, documentId, source),\n getAllCommands: () => this.getAllCommands(documentId),\n getCommandsByCategory: (category) => this.getCommandsByCategory(category, documentId),\n onCommandStateChanged: (listener: Listener<Omit<CommandStateChangedEvent, 'documentId'>>) =>\n this.commandStateChanged$.on((event) => {\n if (event.documentId === documentId) {\n const { documentId: _, ...rest } = event;\n listener(rest);\n }\n }),\n };\n }\n\n // ─────────────────────────────────────────────────────────\n // Command Resolution\n // ─────────────────────────────────────────────────────────\n\n private resolve(commandId: string, documentId?: string): ResolvedCommand {\n const resolvedDocId = documentId ?? this.getActiveDocumentId();\n\n const command = this.commands.get(commandId);\n if (!command) {\n throw new Error(`Command not found: ${commandId}`);\n }\n\n const state = this.registry.getStore().getState();\n\n // Resolve label with i18n if available\n const label = this.resolveLabel(command, state, resolvedDocId);\n\n // Resolve shortcuts\n const shortcuts = command.shortcuts\n ? Array.isArray(command.shortcuts)\n ? command.shortcuts\n : [command.shortcuts]\n : undefined;\n\n // Check if disabled via categories OR explicit disabled predicate\n const explicitDisabled = this.resolveDynamic(command.disabled, state, resolvedDocId) ?? false;\n const categoryDisabled = this.isCommandCategoryDisabled(command);\n const isDisabled = explicitDisabled || categoryDisabled;\n\n return {\n id: command.id,\n label,\n icon: this.resolveDynamic(command.icon, state, resolvedDocId),\n iconProps: this.resolveDynamic(command.iconProps, state, resolvedDocId),\n active: this.resolveDynamic(command.active, state, resolvedDocId) ?? false,\n disabled: isDisabled,\n visible: this.resolveDynamic(command.visible, state, resolvedDocId) ?? true,\n shortcuts,\n shortcutLabel: command.shortcutLabel,\n categories: command.categories,\n description: command.description,\n execute: () => command.action({ registry: this.registry, state, documentId: resolvedDocId }),\n };\n }\n\n private resolveLabel(command: Command, state: StoreState<any>, documentId: string): string {\n // Priority: labelKey (with i18n) > label (plain string) > id (fallback)\n const labelKey = this.resolveDynamic(command.labelKey, state, documentId);\n if (labelKey && this.i18n) {\n const params = this.resolveDynamic(command.labelParams, state, documentId);\n return this.i18n.t(labelKey, { params, documentId });\n }\n\n if (command.label) {\n return command.label;\n }\n\n return command.id; // Fallback to ID\n }\n\n private resolveDynamic<T>(\n value: Dynamic<any, T> | undefined,\n state: StoreState<any>,\n documentId: string,\n ): T | undefined {\n if (value === undefined) return undefined;\n\n // Check if it's a function (the dynamic evaluator)\n if (typeof value === 'function') {\n return (\n value as (context: {\n registry: PluginRegistry;\n state: StoreState<any>;\n documentId: string;\n }) => T\n )({\n registry: this.registry,\n state,\n documentId,\n });\n }\n\n // Otherwise it's the static value\n return value as T;\n }\n\n // ─────────────────────────────────────────────────────────\n // Command Execution\n // ─────────────────────────────────────────────────────────\n\n private execute(\n commandId: string,\n documentId?: string,\n source: 'keyboard' | 'ui' | 'api' = 'ui',\n ): void {\n const resolvedDocId = documentId ?? this.getActiveDocumentId();\n const resolved = this.resolve(commandId, resolvedDocId);\n\n if (resolved.disabled) {\n this.logger.warn(\n 'CommandsPlugin',\n 'ExecutionBlocked',\n `Command '${commandId}' is disabled for document '${resolvedDocId}'`,\n );\n return;\n }\n\n if (!resolved.visible) {\n this.logger.warn(\n 'CommandsPlugin',\n 'ExecutionBlocked',\n `Command '${commandId}' is not visible for document '${resolvedDocId}'`,\n );\n return;\n }\n\n resolved.execute();\n\n this.commandExecuted$.emit({\n commandId,\n documentId: resolvedDocId,\n source,\n });\n\n this.logger.debug(\n 'CommandsPlugin',\n 'CommandExecuted',\n `Command '${commandId}' executed for document '${resolvedDocId}' (source: ${source})`,\n );\n }\n\n // ─────────────────────────────────────────────────────────\n // Command Registration\n // ─────────────────────────────────────────────────────────\n\n private registerCommand(command: Command): void {\n if (this.commands.has(command.id)) {\n this.logger.warn(\n 'CommandsPlugin',\n 'CommandOverwrite',\n `Command '${command.id}' already exists and will be overwritten`,\n );\n }\n\n this.commands.set(command.id, command);\n\n // Register shortcuts\n if (command.shortcuts) {\n const shortcuts = Array.isArray(command.shortcuts) ? command.shortcuts : [command.shortcuts];\n\n shortcuts.forEach((shortcut) => {\n const normalized = this.normalizeShortcut(shortcut);\n this.shortcutMap.set(normalized, command.id);\n });\n }\n\n this.logger.debug('CommandsPlugin', 'CommandRegistered', `Command '${command.id}' registered`);\n }\n\n private unregisterCommand(commandId: string): void {\n const command = this.commands.get(commandId);\n if (!command) return;\n\n // Remove shortcuts\n if (command.shortcuts) {\n const shortcuts = Array.isArray(command.shortcuts) ? command.shortcuts : [command.shortcuts];\n\n shortcuts.forEach((shortcut) => {\n const normalized = this.normalizeShortcut(shortcut);\n this.shortcutMap.delete(normalized);\n });\n }\n\n this.commands.delete(commandId);\n this.logger.debug(\n 'CommandsPlugin',\n 'CommandUnregistered',\n `Command '${commandId}' unregistered`,\n );\n }\n\n // ─────────────────────────────────────────────────────────\n // Shortcuts\n // ─────────────────────────────────────────────────────────\n\n private getCommandByShortcut(shortcut: string): Command | null {\n const normalized = this.normalizeShortcut(shortcut);\n const commandId = this.shortcutMap.get(normalized);\n return commandId ? (this.commands.get(commandId) ?? null) : null;\n }\n\n private normalizeShortcut(shortcut: string): string {\n // Normalize: \"Ctrl+Shift+A\" -> \"ctrl+shift+a\"\n return shortcut.toLowerCase().split('+').sort().join('+');\n }\n\n // ─────────────────────────────────────────────────────────\n // Query Methods\n // ─────────────────────────────────────────────────────────\n\n private getAllCommands(documentId?: string): ResolvedCommand[] {\n const resolvedDocId = documentId ?? this.getActiveDocumentId();\n return Array.from(this.commands.keys()).map((id) => this.resolve(id, resolvedDocId));\n }\n\n private getCommandsByCategory(category: string, documentId?: string): ResolvedCommand[] {\n const resolvedDocId = documentId ?? this.getActiveDocumentId();\n return Array.from(this.commands.values())\n .filter((cmd) => cmd.categories?.includes(category))\n .map((cmd) => this.resolve(cmd.id, resolvedDocId));\n }\n\n // ─────────────────────────────────────────────────────────\n // State Change Detection\n // ─────────────────────────────────────────────────────────\n\n private onGlobalStoreChange(newState: StoreState<any>): void {\n // Get all documents from core state\n const documentIds = Object.keys(newState.core.documents);\n\n // Check each document for command state changes\n documentIds.forEach((documentId) => {\n this.detectCommandChanges(documentId, newState);\n });\n }\n\n private detectCommandChanges(documentId: string, newState: StoreState<any>): void {\n // Skip if document isn't fully loaded yet\n const coreDoc = newState.core.documents[documentId];\n if (!coreDoc || coreDoc.status !== 'loaded') return;\n\n const previousCache = this.previousStates.get(documentId) ?? new Map();\n const changedCommandIds: string[] = [];\n\n this.commands.forEach((command, commandId) => {\n const newResolved = this.resolve(commandId, documentId);\n const prevResolved = previousCache.get(commandId);\n\n if (!prevResolved) {\n // First time resolving for this document\n previousCache.set(commandId, newResolved);\n return;\n }\n\n // Check for changes\n const changes: CommandStateChangedEvent['changes'] = {};\n\n if (prevResolved.active !== newResolved.active) {\n changes.active = newResolved.active;\n }\n if (prevResolved.disabled !== newResolved.disabled) {\n changes.disabled = newResolved.disabled;\n }\n if (prevResolved.visible !== newResolved.visible) {\n changes.visible = newResolved.visible;\n }\n if (prevResolved.label !== newResolved.label) {\n changes.label = newResolved.label;\n }\n if (prevResolved.icon !== newResolved.icon) {\n changes.icon = newResolved.icon;\n }\n if (!arePropsEqual(prevResolved.iconProps, newResolved.iconProps)) {\n changes.iconProps = newResolved.iconProps;\n }\n\n if (Object.keys(changes).length > 0) {\n changedCommandIds.push(commandId);\n previousCache.set(commandId, newResolved);\n\n this.commandStateChanged$.emit({\n commandId,\n documentId,\n changes,\n });\n }\n });\n\n this.previousStates.set(documentId, previousCache);\n }\n}\n","import { Reducer } from '@embedpdf/core';\nimport { CommandsState } from './types';\nimport { CommandsAction, SET_DISABLED_CATEGORIES } from './actions';\n\nexport const initialState: CommandsState = {\n disabledCategories: [],\n};\n\nexport const commandsReducer: Reducer<CommandsState, CommandsAction> = (\n state = initialState,\n action,\n) => {\n switch (action.type) {\n case SET_DISABLED_CATEGORIES:\n return {\n ...state,\n disabledCategories: action.payload,\n };\n\n default:\n return state;\n }\n};\n","import { PluginPackage } from '@embedpdf/core';\nimport { manifest, COMMANDS_PLUGIN_ID } from './manifest';\nimport { CommandsPluginConfig, CommandsState } from './types';\nimport { CommandsPlugin } from './commands-plugin';\nimport { CommandsAction } from './actions';\nimport { commandsReducer, initialState } from './reducer';\n\nexport const CommandsPluginPackage: PluginPackage<\n CommandsPlugin,\n CommandsPluginConfig,\n CommandsState,\n CommandsAction\n> = {\n manifest,\n create: (registry, config) => new CommandsPlugin(COMMANDS_PLUGIN_ID, registry, config),\n reducer: commandsReducer,\n initialState,\n};\n\nexport * from './commands-plugin';\nexport * from './types';\nexport * from './manifest';\n"],"names":["COMMANDS_PLUGIN_ID","manifest","id","name","version","provides","requires","optional","defaultConfig","commands","SET_DISABLED_CATEGORIES","setDisabledCategories","categories","type","payload","_CommandsPlugin","BasePlugin","constructor","registry","config","super","this","Map","i18n","shortcutMap","commandExecuted$","createEmitter","commandStateChanged$","shortcutExecuted$","categoryChanged$","createBehaviorEmitter","previousStates","i18nPlugin","getPlugin","_a","disabledCategories","length","dispatch","Object","values","forEach","command","registerCommand","getStore","subscribe","_action","newState","onGlobalStoreChange","onDocumentClosed","documentId","delete","logger","debug","initialize","info","destroy","clear","disableCategoryImpl","category","current","Set","state","has","add","Array","from","emit","enableCategoryImpl","toggleCategoryImpl","includes","setDisabledCategoriesImpl","isCommandCategoryDisabled","some","cat","buildCapability","resolve","commandId","execute","source","getAllCommands","getCommandsByCategory","getCommandByShortcut","shortcut","getAllShortcuts","forDocument","createCommandScope","unregisterCommand","disableCategory","enableCategory","toggleCategory","getDisabledCategories","isCategoryDisabled","onCommandExecuted","on","onCommandStateChanged","onShortcutExecuted","onCategoryChanged","listener","event","_","rest","resolvedDocId","getActiveDocumentId","get","Error","getState","label","resolveLabel","shortcuts","isArray","explicitDisabled","resolveDynamic","disabled","categoryDisabled","isDisabled","icon","iconProps","active","visible","shortcutLabel","description","action","labelKey","params","labelParams","t","value","resolved","warn","set","normalized","normalizeShortcut","toLowerCase","split","sort","join","keys","map","filter","cmd","core","documents","detectCommandChanges","coreDoc","status","previousCache","newResolved","prevResolved","changes","arePropsEqual","CommandsPlugin","initialState","CommandsPluginPackage","create","reducer"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../src/lib/manifest.ts","../src/lib/actions.ts","../src/lib/commands-plugin.ts","../src/lib/reducer.ts","../src/lib/index.ts"],"sourcesContent":["import { PluginManifest } from '@embedpdf/core';\nimport { CommandsPluginConfig } from './types';\n\nexport const COMMANDS_PLUGIN_ID = 'commands';\n\nexport const manifest: PluginManifest<CommandsPluginConfig> = {\n id: COMMANDS_PLUGIN_ID,\n name: 'Commands Plugin',\n version: '1.0.0',\n provides: ['commands'],\n requires: [],\n optional: ['i18n', 'ui'],\n defaultConfig: {\n commands: {},\n },\n};\n","import { Action } from '@embedpdf/core';\n\nexport const SET_DISABLED_CATEGORIES = 'COMMANDS/SET_DISABLED_CATEGORIES';\n\nexport interface SetDisabledCategoriesAction extends Action {\n type: typeof SET_DISABLED_CATEGORIES;\n payload: string[];\n}\n\nexport type CommandsAction = SetDisabledCategoriesAction;\n\nexport const setDisabledCategories = (categories: string[]): SetDisabledCategoriesAction => ({\n type: SET_DISABLED_CATEGORIES,\n payload: categories,\n});\n","import {\n BasePlugin,\n PluginRegistry,\n StoreState,\n createEmitter,\n createBehaviorEmitter,\n Listener,\n arePropsEqual,\n} from '@embedpdf/core';\nimport { Logger } from '@embedpdf/models';\nimport { I18nCapability, I18nPlugin } from '@embedpdf/plugin-i18n';\nimport {\n CommandsCapability,\n CommandsPluginConfig,\n CommandsState,\n Command,\n ResolvedCommand,\n CommandExecutedEvent,\n CommandStateChangedEvent,\n ShortcutExecutedEvent,\n CategoryChangedEvent,\n CommandScope,\n Dynamic,\n} from './types';\nimport { CommandsAction, setDisabledCategories } from './actions';\n\nexport class CommandsPlugin extends BasePlugin<\n CommandsPluginConfig,\n CommandsCapability,\n CommandsState,\n CommandsAction\n> {\n static readonly id = 'commands' as const;\n\n private commands = new Map<string, Command>();\n private i18n: I18nCapability | null = null;\n private shortcutMap = new Map<string, string>(); // shortcut -> commandId\n\n private readonly commandExecuted$ = createEmitter<CommandExecutedEvent>();\n private readonly commandStateChanged$ = createEmitter<CommandStateChangedEvent>();\n private readonly shortcutExecuted$ = createEmitter<ShortcutExecutedEvent>();\n private readonly categoryChanged$ = createBehaviorEmitter<CategoryChangedEvent>();\n\n // Cache previous resolved states per document to detect changes\n private previousStates = new Map<string, Map<string, ResolvedCommand>>();\n\n constructor(id: string, registry: PluginRegistry, config: CommandsPluginConfig) {\n super(id, registry);\n\n // Check if i18n plugin is available (optional dependency)\n const i18nPlugin = registry.getPlugin<I18nPlugin>('i18n');\n this.i18n = i18nPlugin?.provides() ?? null;\n\n // Initialize disabled categories from config\n if (config.disabledCategories?.length) {\n this.dispatch(setDisabledCategories(config.disabledCategories));\n }\n\n // Register all commands from config\n Object.values(config.commands).forEach((command) => {\n this.registerCommand(command);\n });\n\n // Subscribe to global store changes\n this.registry.getStore().subscribe((_action, newState) => {\n this.onGlobalStoreChange(newState);\n });\n }\n\n protected override onDocumentClosed(documentId: string): void {\n // Cleanup previous states cache\n this.previousStates.delete(documentId);\n\n this.logger.debug(\n 'CommandsPlugin',\n 'DocumentClosed',\n `Cleaned up command state cache for document: ${documentId}`,\n );\n }\n\n async initialize(): Promise<void> {\n this.logger.info('CommandsPlugin', 'Initialize', 'Commands plugin initialized');\n }\n\n async destroy(): Promise<void> {\n this.commandExecuted$.clear();\n this.commandStateChanged$.clear();\n this.shortcutExecuted$.clear();\n this.categoryChanged$.clear();\n this.commands.clear();\n this.shortcutMap.clear();\n this.previousStates.clear();\n super.destroy();\n }\n\n // ─────────────────────────────────────────────────────────\n // Category Management\n // ─────────────────────────────────────────────────────────\n\n private disableCategoryImpl(category: string): void {\n const current = new Set(this.state.disabledCategories);\n if (!current.has(category)) {\n current.add(category);\n this.dispatch(setDisabledCategories(Array.from(current)));\n this.categoryChanged$.emit({ disabledCategories: Array.from(current) });\n }\n }\n\n private enableCategoryImpl(category: string): void {\n const current = new Set(this.state.disabledCategories);\n if (current.has(category)) {\n current.delete(category);\n this.dispatch(setDisabledCategories(Array.from(current)));\n this.categoryChanged$.emit({ disabledCategories: Array.from(current) });\n }\n }\n\n private toggleCategoryImpl(category: string): void {\n if (this.state.disabledCategories.includes(category)) {\n this.enableCategoryImpl(category);\n } else {\n this.disableCategoryImpl(category);\n }\n }\n\n private setDisabledCategoriesImpl(categories: string[]): void {\n this.dispatch(setDisabledCategories(categories));\n this.categoryChanged$.emit({ disabledCategories: categories });\n }\n\n /**\n * Check if command has any disabled category\n */\n private isCommandCategoryDisabled(command: Command): boolean {\n if (!command.categories?.length) return false;\n return command.categories.some((cat) => this.state.disabledCategories.includes(cat));\n }\n\n // ─────────────────────────────────────────────────────────\n // Capability\n // ─────────────────────────────────────────────────────────\n\n protected buildCapability(): CommandsCapability {\n return {\n resolve: (commandId, documentId) => this.resolve(commandId, documentId),\n execute: (commandId, documentId, source = 'ui') =>\n this.execute(commandId, documentId, source),\n getAllCommands: (documentId) => this.getAllCommands(documentId),\n getCommandsByCategory: (category, documentId) =>\n this.getCommandsByCategory(category, documentId),\n getCommandByShortcut: (shortcut) => this.getCommandByShortcut(shortcut),\n getAllShortcuts: () => new Map(this.shortcutMap),\n forDocument: (documentId) => this.createCommandScope(documentId),\n registerCommand: (command) => this.registerCommand(command),\n unregisterCommand: (commandId) => this.unregisterCommand(commandId),\n\n // Category management\n disableCategory: (category) => this.disableCategoryImpl(category),\n enableCategory: (category) => this.enableCategoryImpl(category),\n toggleCategory: (category) => this.toggleCategoryImpl(category),\n setDisabledCategories: (categories) => this.setDisabledCategoriesImpl(categories),\n getDisabledCategories: () => this.state.disabledCategories,\n isCategoryDisabled: (category) => this.state.disabledCategories.includes(category),\n\n // Events\n onCommandExecuted: this.commandExecuted$.on,\n onCommandStateChanged: this.commandStateChanged$.on,\n onShortcutExecuted: this.shortcutExecuted$.on,\n onCategoryChanged: this.categoryChanged$.on,\n };\n }\n\n // ─────────────────────────────────────────────────────────\n // Document Scoping\n // ─────────────────────────────────────────────────────────\n\n private createCommandScope(documentId: string): CommandScope {\n return {\n resolve: (commandId) => this.resolve(commandId, documentId),\n execute: (commandId, source = 'ui') => this.execute(commandId, documentId, source),\n getAllCommands: () => this.getAllCommands(documentId),\n getCommandsByCategory: (category) => this.getCommandsByCategory(category, documentId),\n onCommandStateChanged: (listener: Listener<Omit<CommandStateChangedEvent, 'documentId'>>) =>\n this.commandStateChanged$.on((event) => {\n if (event.documentId === documentId) {\n const { documentId: _, ...rest } = event;\n listener(rest);\n }\n }),\n };\n }\n\n // ─────────────────────────────────────────────────────────\n // Command Resolution\n // ─────────────────────────────────────────────────────────\n\n private resolve(commandId: string, documentId?: string): ResolvedCommand {\n const resolvedDocId = documentId ?? this.getActiveDocumentId();\n\n const command = this.commands.get(commandId);\n if (!command) {\n throw new Error(`Command not found: ${commandId}`);\n }\n\n const state = this.registry.getStore().getState();\n\n // Resolve label with i18n if available\n const label = this.resolveLabel(command, state, resolvedDocId);\n\n // Resolve shortcuts\n const shortcuts = command.shortcuts\n ? Array.isArray(command.shortcuts)\n ? command.shortcuts\n : [command.shortcuts]\n : undefined;\n\n // Check if disabled via categories OR explicit disabled predicate\n const explicitDisabled = this.resolveDynamic(command.disabled, state, resolvedDocId) ?? false;\n const categoryDisabled = this.isCommandCategoryDisabled(command);\n const isDisabled = explicitDisabled || categoryDisabled;\n\n return {\n id: command.id,\n label,\n icon: this.resolveDynamic(command.icon, state, resolvedDocId),\n iconProps: this.resolveDynamic(command.iconProps, state, resolvedDocId),\n active: this.resolveDynamic(command.active, state, resolvedDocId) ?? false,\n disabled: isDisabled,\n visible: this.resolveDynamic(command.visible, state, resolvedDocId) ?? true,\n shortcuts,\n shortcutLabel: command.shortcutLabel,\n categories: command.categories,\n description: command.description,\n execute: () =>\n command.action({\n registry: this.registry,\n state,\n documentId: resolvedDocId,\n logger: this.logger,\n }),\n };\n }\n\n private resolveLabel(command: Command, state: StoreState<any>, documentId: string): string {\n // Priority: labelKey (with i18n) > label (plain string) > id (fallback)\n const labelKey = this.resolveDynamic(command.labelKey, state, documentId);\n if (labelKey && this.i18n) {\n const params = this.resolveDynamic(command.labelParams, state, documentId);\n return this.i18n.t(labelKey, { params, documentId });\n }\n\n if (command.label) {\n return command.label;\n }\n\n return command.id; // Fallback to ID\n }\n\n private resolveDynamic<T>(\n value: Dynamic<any, T> | undefined,\n state: StoreState<any>,\n documentId: string,\n ): T | undefined {\n if (value === undefined) return undefined;\n\n // Check if it's a function (the dynamic evaluator)\n if (typeof value === 'function') {\n return (\n value as (context: {\n registry: PluginRegistry;\n state: StoreState<any>;\n documentId: string;\n logger: Logger;\n }) => T\n )({\n registry: this.registry,\n state,\n documentId,\n logger: this.logger,\n });\n }\n\n // Otherwise it's the static value\n return value as T;\n }\n\n // ─────────────────────────────────────────────────────────\n // Command Execution\n // ─────────────────────────────────────────────────────────\n\n private execute(\n commandId: string,\n documentId?: string,\n source: 'keyboard' | 'ui' | 'api' = 'ui',\n ): void {\n const resolvedDocId = documentId ?? this.getActiveDocumentId();\n const resolved = this.resolve(commandId, resolvedDocId);\n\n if (resolved.disabled) {\n this.logger.warn(\n 'CommandsPlugin',\n 'ExecutionBlocked',\n `Command '${commandId}' is disabled for document '${resolvedDocId}'`,\n );\n return;\n }\n\n if (!resolved.visible) {\n this.logger.warn(\n 'CommandsPlugin',\n 'ExecutionBlocked',\n `Command '${commandId}' is not visible for document '${resolvedDocId}'`,\n );\n return;\n }\n\n resolved.execute();\n\n this.commandExecuted$.emit({\n commandId,\n documentId: resolvedDocId,\n source,\n });\n\n this.logger.debug(\n 'CommandsPlugin',\n 'CommandExecuted',\n `Command '${commandId}' executed for document '${resolvedDocId}' (source: ${source})`,\n );\n }\n\n // ─────────────────────────────────────────────────────────\n // Command Registration\n // ─────────────────────────────────────────────────────────\n\n private registerCommand(command: Command): void {\n if (this.commands.has(command.id)) {\n this.logger.warn(\n 'CommandsPlugin',\n 'CommandOverwrite',\n `Command '${command.id}' already exists and will be overwritten`,\n );\n }\n\n this.commands.set(command.id, command);\n\n // Register shortcuts\n if (command.shortcuts) {\n const shortcuts = Array.isArray(command.shortcuts) ? command.shortcuts : [command.shortcuts];\n\n shortcuts.forEach((shortcut) => {\n const normalized = this.normalizeShortcut(shortcut);\n this.shortcutMap.set(normalized, command.id);\n });\n }\n\n this.logger.debug('CommandsPlugin', 'CommandRegistered', `Command '${command.id}' registered`);\n }\n\n private unregisterCommand(commandId: string): void {\n const command = this.commands.get(commandId);\n if (!command) return;\n\n // Remove shortcuts\n if (command.shortcuts) {\n const shortcuts = Array.isArray(command.shortcuts) ? command.shortcuts : [command.shortcuts];\n\n shortcuts.forEach((shortcut) => {\n const normalized = this.normalizeShortcut(shortcut);\n this.shortcutMap.delete(normalized);\n });\n }\n\n this.commands.delete(commandId);\n this.logger.debug(\n 'CommandsPlugin',\n 'CommandUnregistered',\n `Command '${commandId}' unregistered`,\n );\n }\n\n // ─────────────────────────────────────────────────────────\n // Shortcuts\n // ─────────────────────────────────────────────────────────\n\n private getCommandByShortcut(shortcut: string): Command | null {\n const normalized = this.normalizeShortcut(shortcut);\n const commandId = this.shortcutMap.get(normalized);\n return commandId ? (this.commands.get(commandId) ?? null) : null;\n }\n\n private normalizeShortcut(shortcut: string): string {\n // Normalize: \"Ctrl+Shift+A\" -> \"ctrl+shift+a\"\n return shortcut.toLowerCase().split('+').sort().join('+');\n }\n\n // ─────────────────────────────────────────────────────────\n // Query Methods\n // ─────────────────────────────────────────────────────────\n\n private getAllCommands(documentId?: string): ResolvedCommand[] {\n const resolvedDocId = documentId ?? this.getActiveDocumentId();\n return Array.from(this.commands.keys()).map((id) => this.resolve(id, resolvedDocId));\n }\n\n private getCommandsByCategory(category: string, documentId?: string): ResolvedCommand[] {\n const resolvedDocId = documentId ?? this.getActiveDocumentId();\n return Array.from(this.commands.values())\n .filter((cmd) => cmd.categories?.includes(category))\n .map((cmd) => this.resolve(cmd.id, resolvedDocId));\n }\n\n // ─────────────────────────────────────────────────────────\n // State Change Detection\n // ─────────────────────────────────────────────────────────\n\n private onGlobalStoreChange(newState: StoreState<any>): void {\n // Get all documents from core state\n const documentIds = Object.keys(newState.core.documents);\n\n // Check each document for command state changes\n documentIds.forEach((documentId) => {\n this.detectCommandChanges(documentId, newState);\n });\n }\n\n private detectCommandChanges(documentId: string, newState: StoreState<any>): void {\n // Skip if document isn't fully loaded yet\n const coreDoc = newState.core.documents[documentId];\n if (!coreDoc || coreDoc.status !== 'loaded') return;\n\n const previousCache = this.previousStates.get(documentId) ?? new Map();\n const changedCommandIds: string[] = [];\n\n this.commands.forEach((command, commandId) => {\n const newResolved = this.resolve(commandId, documentId);\n const prevResolved = previousCache.get(commandId);\n\n if (!prevResolved) {\n // First time resolving for this document\n previousCache.set(commandId, newResolved);\n return;\n }\n\n // Check for changes\n const changes: CommandStateChangedEvent['changes'] = {};\n\n if (prevResolved.active !== newResolved.active) {\n changes.active = newResolved.active;\n }\n if (prevResolved.disabled !== newResolved.disabled) {\n changes.disabled = newResolved.disabled;\n }\n if (prevResolved.visible !== newResolved.visible) {\n changes.visible = newResolved.visible;\n }\n if (prevResolved.label !== newResolved.label) {\n changes.label = newResolved.label;\n }\n if (prevResolved.icon !== newResolved.icon) {\n changes.icon = newResolved.icon;\n }\n if (!arePropsEqual(prevResolved.iconProps, newResolved.iconProps)) {\n changes.iconProps = newResolved.iconProps;\n }\n\n if (Object.keys(changes).length > 0) {\n changedCommandIds.push(commandId);\n previousCache.set(commandId, newResolved);\n\n this.commandStateChanged$.emit({\n commandId,\n documentId,\n changes,\n });\n }\n });\n\n this.previousStates.set(documentId, previousCache);\n }\n}\n","import { Reducer } from '@embedpdf/core';\nimport { CommandsState } from './types';\nimport { CommandsAction, SET_DISABLED_CATEGORIES } from './actions';\n\nexport const initialState: CommandsState = {\n disabledCategories: [],\n};\n\nexport const commandsReducer: Reducer<CommandsState, CommandsAction> = (\n state = initialState,\n action,\n) => {\n switch (action.type) {\n case SET_DISABLED_CATEGORIES:\n return {\n ...state,\n disabledCategories: action.payload,\n };\n\n default:\n return state;\n }\n};\n","import { PluginPackage } from '@embedpdf/core';\nimport { manifest, COMMANDS_PLUGIN_ID } from './manifest';\nimport { CommandsPluginConfig, CommandsState } from './types';\nimport { CommandsPlugin } from './commands-plugin';\nimport { CommandsAction } from './actions';\nimport { commandsReducer, initialState } from './reducer';\n\nexport const CommandsPluginPackage: PluginPackage<\n CommandsPlugin,\n CommandsPluginConfig,\n CommandsState,\n CommandsAction\n> = {\n manifest,\n create: (registry, config) => new CommandsPlugin(COMMANDS_PLUGIN_ID, registry, config),\n reducer: commandsReducer,\n initialState,\n};\n\nexport * from './commands-plugin';\nexport * from './types';\nexport * from './manifest';\n"],"names":["COMMANDS_PLUGIN_ID","manifest","id","name","version","provides","requires","optional","defaultConfig","commands","SET_DISABLED_CATEGORIES","setDisabledCategories","categories","type","payload","_CommandsPlugin","BasePlugin","constructor","registry","config","super","this","Map","i18n","shortcutMap","commandExecuted$","createEmitter","commandStateChanged$","shortcutExecuted$","categoryChanged$","createBehaviorEmitter","previousStates","i18nPlugin","getPlugin","_a","disabledCategories","length","dispatch","Object","values","forEach","command","registerCommand","getStore","subscribe","_action","newState","onGlobalStoreChange","onDocumentClosed","documentId","delete","logger","debug","initialize","info","destroy","clear","disableCategoryImpl","category","current","Set","state","has","add","Array","from","emit","enableCategoryImpl","toggleCategoryImpl","includes","setDisabledCategoriesImpl","isCommandCategoryDisabled","some","cat","buildCapability","resolve","commandId","execute","source","getAllCommands","getCommandsByCategory","getCommandByShortcut","shortcut","getAllShortcuts","forDocument","createCommandScope","unregisterCommand","disableCategory","enableCategory","toggleCategory","getDisabledCategories","isCategoryDisabled","onCommandExecuted","on","onCommandStateChanged","onShortcutExecuted","onCategoryChanged","listener","event","_","rest","resolvedDocId","getActiveDocumentId","get","Error","getState","label","resolveLabel","shortcuts","isArray","explicitDisabled","resolveDynamic","disabled","categoryDisabled","isDisabled","icon","iconProps","active","visible","shortcutLabel","description","action","labelKey","params","labelParams","t","value","resolved","warn","set","normalized","normalizeShortcut","toLowerCase","split","sort","join","keys","map","filter","cmd","core","documents","detectCommandChanges","coreDoc","status","previousCache","newResolved","prevResolved","changes","arePropsEqual","CommandsPlugin","initialState","CommandsPluginPackage","create","reducer"],"mappings":"kHAGaA,EAAqB,WAErBC,EAAiD,CAC5DC,GAAIF,EACJG,KAAM,kBACNC,QAAS,QACTC,SAAU,CAAC,YACXC,SAAU,GACVC,SAAU,CAAC,OAAQ,MACnBC,cAAe,CACbC,SAAU,CAAA,ICXDC,EAA0B,mCAS1BC,EAAyBC,IAAA,CACpCC,KAAMH,EACNI,QAASF,ICaEG,EAAN,cAA6BC,EAAAA,WAoBlC,WAAAC,CAAYf,EAAYgB,EAA0BC,SAChDC,MAAMlB,EAAIgB,GAbZG,KAAQZ,aAAea,IACvBD,KAAQE,KAA8B,KACtCF,KAAQG,gBAAkBF,IAE1BD,KAAiBI,iBAAmBC,kBACpCL,KAAiBM,qBAAuBD,kBACxCL,KAAiBO,kBAAoBF,kBACrCL,KAAiBQ,iBAAmBC,0BAGpCT,KAAQU,mBAAqBT,IAM3B,MAAMU,EAAad,EAASe,UAAsB,QAClDZ,KAAKE,YAAOS,WAAY3B,aAAc,MAGlC,OAAA6B,EAAAf,EAAOgB,yBAAP,EAAAD,EAA2BE,SAC7Bf,KAAKgB,SAAS1B,EAAsBQ,EAAOgB,qBAI7CG,OAAOC,OAAOpB,EAAOV,UAAU+B,QAASC,IACtCpB,KAAKqB,gBAAgBD,KAIvBpB,KAAKH,SAASyB,WAAWC,UAAU,CAACC,EAASC,KAC3CzB,KAAK0B,oBAAoBD,IAE7B,CAEmB,gBAAAE,CAAiBC,GAElC5B,KAAKU,eAAemB,OAAOD,GAE3B5B,KAAK8B,OAAOC,MACV,iBACA,iBACA,gDAAgDH,IAEpD,CAEA,gBAAMI,GACJhC,KAAK8B,OAAOG,KAAK,iBAAkB,aAAc,8BACnD,CAEA,aAAMC,GACJlC,KAAKI,iBAAiB+B,QACtBnC,KAAKM,qBAAqB6B,QAC1BnC,KAAKO,kBAAkB4B,QACvBnC,KAAKQ,iBAAiB2B,QACtBnC,KAAKZ,SAAS+C,QACdnC,KAAKG,YAAYgC,QACjBnC,KAAKU,eAAeyB,QACpBpC,MAAMmC,SACR,CAMQ,mBAAAE,CAAoBC,GAC1B,MAAMC,EAAU,IAAIC,IAAIvC,KAAKwC,MAAM1B,oBAC9BwB,EAAQG,IAAIJ,KACfC,EAAQI,IAAIL,GACZrC,KAAKgB,SAAS1B,EAAsBqD,MAAMC,KAAKN,KAC/CtC,KAAKQ,iBAAiBqC,KAAK,CAAE/B,mBAAoB6B,MAAMC,KAAKN,KAEhE,CAEQ,kBAAAQ,CAAmBT,GACzB,MAAMC,EAAU,IAAIC,IAAIvC,KAAKwC,MAAM1B,oBAC/BwB,EAAQG,IAAIJ,KACdC,EAAQT,OAAOQ,GACfrC,KAAKgB,SAAS1B,EAAsBqD,MAAMC,KAAKN,KAC/CtC,KAAKQ,iBAAiBqC,KAAK,CAAE/B,mBAAoB6B,MAAMC,KAAKN,KAEhE,CAEQ,kBAAAS,CAAmBV,GACrBrC,KAAKwC,MAAM1B,mBAAmBkC,SAASX,GACzCrC,KAAK8C,mBAAmBT,GAExBrC,KAAKoC,oBAAoBC,EAE7B,CAEQ,yBAAAY,CAA0B1D,GAChCS,KAAKgB,SAAS1B,EAAsBC,IACpCS,KAAKQ,iBAAiBqC,KAAK,CAAE/B,mBAAoBvB,GACnD,CAKQ,yBAAA2D,CAA0B9B,SAChC,SAAK,OAAAP,EAAAO,EAAQ7B,iBAAR,EAAAsB,EAAoBE,SAClBK,EAAQ7B,WAAW4D,KAAMC,GAAQpD,KAAKwC,MAAM1B,mBAAmBkC,SAASI,GACjF,CAMU,eAAAC,GACR,MAAO,CACLC,QAAS,CAACC,EAAW3B,IAAe5B,KAAKsD,QAAQC,EAAW3B,GAC5D4B,QAAS,CAACD,EAAW3B,EAAY6B,EAAS,OACxCzD,KAAKwD,QAAQD,EAAW3B,EAAY6B,GACtCC,eAAiB9B,GAAe5B,KAAK0D,eAAe9B,GACpD+B,sBAAuB,CAACtB,EAAUT,IAChC5B,KAAK2D,sBAAsBtB,EAAUT,GACvCgC,qBAAuBC,GAAa7D,KAAK4D,qBAAqBC,GAC9DC,gBAAiB,IAAM,IAAI7D,IAAID,KAAKG,aACpC4D,YAAcnC,GAAe5B,KAAKgE,mBAAmBpC,GACrDP,gBAAkBD,GAAYpB,KAAKqB,gBAAgBD,GACnD6C,kBAAoBV,GAAcvD,KAAKiE,kBAAkBV,GAGzDW,gBAAkB7B,GAAarC,KAAKoC,oBAAoBC,GACxD8B,eAAiB9B,GAAarC,KAAK8C,mBAAmBT,GACtD+B,eAAiB/B,GAAarC,KAAK+C,mBAAmBV,GACtD/C,sBAAwBC,GAAeS,KAAKiD,0BAA0B1D,GACtE8E,sBAAuB,IAAMrE,KAAKwC,MAAM1B,mBACxCwD,mBAAqBjC,GAAarC,KAAKwC,MAAM1B,mBAAmBkC,SAASX,GAGzEkC,kBAAmBvE,KAAKI,iBAAiBoE,GACzCC,sBAAuBzE,KAAKM,qBAAqBkE,GACjDE,mBAAoB1E,KAAKO,kBAAkBiE,GAC3CG,kBAAmB3E,KAAKQ,iBAAiBgE,GAE7C,CAMQ,kBAAAR,CAAmBpC,GACzB,MAAO,CACL0B,QAAUC,GAAcvD,KAAKsD,QAAQC,EAAW3B,GAChD4B,QAAS,CAACD,EAAWE,EAAS,OAASzD,KAAKwD,QAAQD,EAAW3B,EAAY6B,GAC3EC,eAAgB,IAAM1D,KAAK0D,eAAe9B,GAC1C+B,sBAAwBtB,GAAarC,KAAK2D,sBAAsBtB,EAAUT,GAC1E6C,sBAAwBG,GACtB5E,KAAKM,qBAAqBkE,GAAIK,IAC5B,GAAIA,EAAMjD,aAAeA,EAAY,CACnC,MAAQA,WAAYkD,KAAMC,GAASF,EACnCD,EAASG,EACX,IAGR,CAMQ,OAAAzB,CAAQC,EAAmB3B,GACjC,MAAMoD,EAAgBpD,GAAc5B,KAAKiF,sBAEnC7D,EAAUpB,KAAKZ,SAAS8F,IAAI3B,GAClC,IAAKnC,EACH,MAAM,IAAI+D,MAAM,sBAAsB5B,KAGxC,MAAMf,EAAQxC,KAAKH,SAASyB,WAAW8D,WAGjCC,EAAQrF,KAAKsF,aAAalE,EAASoB,EAAOwC,GAG1CO,EAAYnE,EAAQmE,UACtB5C,MAAM6C,QAAQpE,EAAQmE,WACpBnE,EAAQmE,UACR,CAACnE,EAAQmE,gBACX,EAGEE,EAAmBzF,KAAK0F,eAAetE,EAAQuE,SAAUnD,EAAOwC,KAAkB,EAClFY,EAAmB5F,KAAKkD,0BAA0B9B,GAClDyE,EAAaJ,GAAoBG,EAEvC,MAAO,CACL/G,GAAIuC,EAAQvC,GACZwG,QACAS,KAAM9F,KAAK0F,eAAetE,EAAQ0E,KAAMtD,EAAOwC,GAC/Ce,UAAW/F,KAAK0F,eAAetE,EAAQ2E,UAAWvD,EAAOwC,GACzDgB,OAAQhG,KAAK0F,eAAetE,EAAQ4E,OAAQxD,EAAOwC,KAAkB,EACrEW,SAAUE,EACVI,QAASjG,KAAK0F,eAAetE,EAAQ6E,QAASzD,EAAOwC,KAAkB,EACvEO,YACAW,cAAe9E,EAAQ8E,cACvB3G,WAAY6B,EAAQ7B,WACpB4G,YAAa/E,EAAQ+E,YACrB3C,QAAS,IACPpC,EAAQgF,OAAO,CACbvG,SAAUG,KAAKH,SACf2C,QACAZ,WAAYoD,EACZlD,OAAQ9B,KAAK8B,SAGrB,CAEQ,YAAAwD,CAAalE,EAAkBoB,EAAwBZ,GAE7D,MAAMyE,EAAWrG,KAAK0F,eAAetE,EAAQiF,SAAU7D,EAAOZ,GAC9D,GAAIyE,GAAYrG,KAAKE,KAAM,CACzB,MAAMoG,EAAStG,KAAK0F,eAAetE,EAAQmF,YAAa/D,EAAOZ,GAC/D,OAAO5B,KAAKE,KAAKsG,EAAEH,EAAU,CAAEC,SAAQ1E,cACzC,CAEA,OAAIR,EAAQiE,MACHjE,EAAQiE,MAGVjE,EAAQvC,EACjB,CAEQ,cAAA6G,CACNe,EACAjE,EACAZ,GAEA,YAAI6E,EAGJ,MAAqB,mBAAVA,EAEPA,EAMA,CACA5G,SAAUG,KAAKH,SACf2C,QACAZ,aACAE,OAAQ9B,KAAK8B,SAKV2E,CACT,CAMQ,OAAAjD,CACND,EACA3B,EACA6B,EAAoC,MAEpC,MAAMuB,EAAgBpD,GAAc5B,KAAKiF,sBACnCyB,EAAW1G,KAAKsD,QAAQC,EAAWyB,GAErC0B,EAASf,SACX3F,KAAK8B,OAAO6E,KACV,iBACA,mBACA,YAAYpD,gCAAwCyB,MAKnD0B,EAAST,SASdS,EAASlD,UAETxD,KAAKI,iBAAiByC,KAAK,CACzBU,YACA3B,WAAYoD,EACZvB,WAGFzD,KAAK8B,OAAOC,MACV,iBACA,kBACA,YAAYwB,6BAAqCyB,eAA2BvB,OAnB5EzD,KAAK8B,OAAO6E,KACV,iBACA,mBACA,YAAYpD,mCAA2CyB,KAkB7D,CAMQ,eAAA3D,CAAgBD,GAYtB,GAXIpB,KAAKZ,SAASqD,IAAIrB,EAAQvC,KAC5BmB,KAAK8B,OAAO6E,KACV,iBACA,mBACA,YAAYvF,EAAQvC,8CAIxBmB,KAAKZ,SAASwH,IAAIxF,EAAQvC,GAAIuC,GAG1BA,EAAQmE,UAAW,EACH5C,MAAM6C,QAAQpE,EAAQmE,WAAanE,EAAQmE,UAAY,CAACnE,EAAQmE,YAExEpE,QAAS0C,IACjB,MAAMgD,EAAa7G,KAAK8G,kBAAkBjD,GAC1C7D,KAAKG,YAAYyG,IAAIC,EAAYzF,EAAQvC,KAE7C,CAEAmB,KAAK8B,OAAOC,MAAM,iBAAkB,oBAAqB,YAAYX,EAAQvC,iBAC/E,CAEQ,iBAAAoF,CAAkBV,GACxB,MAAMnC,EAAUpB,KAAKZ,SAAS8F,IAAI3B,GAClC,GAAKnC,EAAL,CAGA,GAAIA,EAAQmE,UAAW,EACH5C,MAAM6C,QAAQpE,EAAQmE,WAAanE,EAAQmE,UAAY,CAACnE,EAAQmE,YAExEpE,QAAS0C,IACjB,MAAMgD,EAAa7G,KAAK8G,kBAAkBjD,GAC1C7D,KAAKG,YAAY0B,OAAOgF,IAE5B,CAEA7G,KAAKZ,SAASyC,OAAO0B,GACrBvD,KAAK8B,OAAOC,MACV,iBACA,sBACA,YAAYwB,kBAhBA,CAkBhB,CAMQ,oBAAAK,CAAqBC,GAC3B,MAAMgD,EAAa7G,KAAK8G,kBAAkBjD,GACpCN,EAAYvD,KAAKG,YAAY+E,IAAI2B,GACvC,OAAOtD,EAAavD,KAAKZ,SAAS8F,IAAI3B,IAAc,KAAQ,IAC9D,CAEQ,iBAAAuD,CAAkBjD,GAExB,OAAOA,EAASkD,cAAcC,MAAM,KAAKC,OAAOC,KAAK,IACvD,CAMQ,cAAAxD,CAAe9B,GACrB,MAAMoD,EAAgBpD,GAAc5B,KAAKiF,sBACzC,OAAOtC,MAAMC,KAAK5C,KAAKZ,SAAS+H,QAAQC,IAAKvI,GAAOmB,KAAKsD,QAAQzE,EAAImG,GACvE,CAEQ,qBAAArB,CAAsBtB,EAAkBT,GAC9C,MAAMoD,EAAgBpD,GAAc5B,KAAKiF,sBACzC,OAAOtC,MAAMC,KAAK5C,KAAKZ,SAAS8B,UAC7BmG,OAAQC,UAAQ,OAAA,OAAAzG,EAAAyG,EAAI/H,qBAAYyD,SAASX,KACzC+E,IAAKE,GAAQtH,KAAKsD,QAAQgE,EAAIzI,GAAImG,GACvC,CAMQ,mBAAAtD,CAAoBD,GAENR,OAAOkG,KAAK1F,EAAS8F,KAAKC,WAGlCrG,QAASS,IACnB5B,KAAKyH,qBAAqB7F,EAAYH,IAE1C,CAEQ,oBAAAgG,CAAqB7F,EAAoBH,GAE/C,MAAMiG,EAAUjG,EAAS8F,KAAKC,UAAU5F,GACxC,IAAK8F,GAA8B,WAAnBA,EAAQC,OAAqB,OAE7C,MAAMC,EAAgB5H,KAAKU,eAAewE,IAAItD,QAAmB3B,IAGjED,KAAKZ,SAAS+B,QAAQ,CAACC,EAASmC,KAC9B,MAAMsE,EAAc7H,KAAKsD,QAAQC,EAAW3B,GACtCkG,EAAeF,EAAc1C,IAAI3B,GAEvC,IAAKuE,EAGH,YADAF,EAAchB,IAAIrD,EAAWsE,GAK/B,MAAME,EAA+C,CAAA,EAEjDD,EAAa9B,SAAW6B,EAAY7B,SACtC+B,EAAQ/B,OAAS6B,EAAY7B,QAE3B8B,EAAanC,WAAakC,EAAYlC,WACxCoC,EAAQpC,SAAWkC,EAAYlC,UAE7BmC,EAAa7B,UAAY4B,EAAY5B,UACvC8B,EAAQ9B,QAAU4B,EAAY5B,SAE5B6B,EAAazC,QAAUwC,EAAYxC,QACrC0C,EAAQ1C,MAAQwC,EAAYxC,OAE1ByC,EAAahC,OAAS+B,EAAY/B,OACpCiC,EAAQjC,KAAO+B,EAAY/B,MAExBkC,EAAAA,cAAcF,EAAa/B,UAAW8B,EAAY9B,aACrDgC,EAAQhC,UAAY8B,EAAY9B,WAG9B9E,OAAOkG,KAAKY,GAAShH,OAAS,IAEhC6G,EAAchB,IAAIrD,EAAWsE,GAE7B7H,KAAKM,qBAAqBuC,KAAK,CAC7BU,YACA3B,aACAmG,eAKN/H,KAAKU,eAAekG,IAAIhF,EAAYgG,EACtC,GA/bAlI,EAAgBb,GAAK,WANhB,IAAMoJ,EAANvI,ECtBA,MAAMwI,EAA8B,CACzCpH,mBAAoB,ICETqH,EAKT,CACFvJ,WACAwJ,OAAQ,CAACvI,EAAUC,IAAW,IAAImI,EAAetJ,EAAoBkB,EAAUC,GAC/EuI,QDPqE,CACrE7F,EAAQ0F,EACR9B,IAEQA,EAAO5G,OACRH,EACI,IACFmD,EACH1B,mBAAoBsF,EAAO3G,SAItB+C,ECJX0F"}
package/dist/index.js CHANGED
@@ -171,7 +171,12 @@ const _CommandsPlugin = class _CommandsPlugin extends BasePlugin {
171
171
  shortcutLabel: command.shortcutLabel,
172
172
  categories: command.categories,
173
173
  description: command.description,
174
- execute: () => command.action({ registry: this.registry, state, documentId: resolvedDocId })
174
+ execute: () => command.action({
175
+ registry: this.registry,
176
+ state,
177
+ documentId: resolvedDocId,
178
+ logger: this.logger
179
+ })
175
180
  };
176
181
  }
177
182
  resolveLabel(command, state, documentId) {
@@ -191,7 +196,8 @@ const _CommandsPlugin = class _CommandsPlugin extends BasePlugin {
191
196
  return value({
192
197
  registry: this.registry,
193
198
  state,
194
- documentId
199
+ documentId,
200
+ logger: this.logger
195
201
  });
196
202
  }
197
203
  return value;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/lib/manifest.ts","../src/lib/actions.ts","../src/lib/commands-plugin.ts","../src/lib/reducer.ts","../src/lib/index.ts"],"sourcesContent":["import { PluginManifest } from '@embedpdf/core';\nimport { CommandsPluginConfig } from './types';\n\nexport const COMMANDS_PLUGIN_ID = 'commands';\n\nexport const manifest: PluginManifest<CommandsPluginConfig> = {\n id: COMMANDS_PLUGIN_ID,\n name: 'Commands Plugin',\n version: '1.0.0',\n provides: ['commands'],\n requires: [],\n optional: ['i18n', 'ui'],\n defaultConfig: {\n commands: {},\n },\n};\n","import { Action } from '@embedpdf/core';\n\nexport const SET_DISABLED_CATEGORIES = 'COMMANDS/SET_DISABLED_CATEGORIES';\n\nexport interface SetDisabledCategoriesAction extends Action {\n type: typeof SET_DISABLED_CATEGORIES;\n payload: string[];\n}\n\nexport type CommandsAction = SetDisabledCategoriesAction;\n\nexport const setDisabledCategories = (categories: string[]): SetDisabledCategoriesAction => ({\n type: SET_DISABLED_CATEGORIES,\n payload: categories,\n});\n","import {\n BasePlugin,\n PluginRegistry,\n StoreState,\n createEmitter,\n createBehaviorEmitter,\n Listener,\n arePropsEqual,\n} from '@embedpdf/core';\nimport { I18nCapability, I18nPlugin } from '@embedpdf/plugin-i18n';\nimport {\n CommandsCapability,\n CommandsPluginConfig,\n CommandsState,\n Command,\n ResolvedCommand,\n CommandExecutedEvent,\n CommandStateChangedEvent,\n ShortcutExecutedEvent,\n CategoryChangedEvent,\n CommandScope,\n Dynamic,\n} from './types';\nimport { CommandsAction, setDisabledCategories } from './actions';\n\nexport class CommandsPlugin extends BasePlugin<\n CommandsPluginConfig,\n CommandsCapability,\n CommandsState,\n CommandsAction\n> {\n static readonly id = 'commands' as const;\n\n private commands = new Map<string, Command>();\n private i18n: I18nCapability | null = null;\n private shortcutMap = new Map<string, string>(); // shortcut -> commandId\n\n private readonly commandExecuted$ = createEmitter<CommandExecutedEvent>();\n private readonly commandStateChanged$ = createEmitter<CommandStateChangedEvent>();\n private readonly shortcutExecuted$ = createEmitter<ShortcutExecutedEvent>();\n private readonly categoryChanged$ = createBehaviorEmitter<CategoryChangedEvent>();\n\n // Cache previous resolved states per document to detect changes\n private previousStates = new Map<string, Map<string, ResolvedCommand>>();\n\n constructor(id: string, registry: PluginRegistry, config: CommandsPluginConfig) {\n super(id, registry);\n\n // Check if i18n plugin is available (optional dependency)\n const i18nPlugin = registry.getPlugin<I18nPlugin>('i18n');\n this.i18n = i18nPlugin?.provides() ?? null;\n\n // Initialize disabled categories from config\n if (config.disabledCategories?.length) {\n this.dispatch(setDisabledCategories(config.disabledCategories));\n }\n\n // Register all commands from config\n Object.values(config.commands).forEach((command) => {\n this.registerCommand(command);\n });\n\n // Subscribe to global store changes\n this.registry.getStore().subscribe((_action, newState) => {\n this.onGlobalStoreChange(newState);\n });\n }\n\n protected override onDocumentClosed(documentId: string): void {\n // Cleanup previous states cache\n this.previousStates.delete(documentId);\n\n this.logger.debug(\n 'CommandsPlugin',\n 'DocumentClosed',\n `Cleaned up command state cache for document: ${documentId}`,\n );\n }\n\n async initialize(): Promise<void> {\n this.logger.info('CommandsPlugin', 'Initialize', 'Commands plugin initialized');\n }\n\n async destroy(): Promise<void> {\n this.commandExecuted$.clear();\n this.commandStateChanged$.clear();\n this.shortcutExecuted$.clear();\n this.categoryChanged$.clear();\n this.commands.clear();\n this.shortcutMap.clear();\n this.previousStates.clear();\n super.destroy();\n }\n\n // ─────────────────────────────────────────────────────────\n // Category Management\n // ─────────────────────────────────────────────────────────\n\n private disableCategoryImpl(category: string): void {\n const current = new Set(this.state.disabledCategories);\n if (!current.has(category)) {\n current.add(category);\n this.dispatch(setDisabledCategories(Array.from(current)));\n this.categoryChanged$.emit({ disabledCategories: Array.from(current) });\n }\n }\n\n private enableCategoryImpl(category: string): void {\n const current = new Set(this.state.disabledCategories);\n if (current.has(category)) {\n current.delete(category);\n this.dispatch(setDisabledCategories(Array.from(current)));\n this.categoryChanged$.emit({ disabledCategories: Array.from(current) });\n }\n }\n\n private toggleCategoryImpl(category: string): void {\n if (this.state.disabledCategories.includes(category)) {\n this.enableCategoryImpl(category);\n } else {\n this.disableCategoryImpl(category);\n }\n }\n\n private setDisabledCategoriesImpl(categories: string[]): void {\n this.dispatch(setDisabledCategories(categories));\n this.categoryChanged$.emit({ disabledCategories: categories });\n }\n\n /**\n * Check if command has any disabled category\n */\n private isCommandCategoryDisabled(command: Command): boolean {\n if (!command.categories?.length) return false;\n return command.categories.some((cat) => this.state.disabledCategories.includes(cat));\n }\n\n // ─────────────────────────────────────────────────────────\n // Capability\n // ─────────────────────────────────────────────────────────\n\n protected buildCapability(): CommandsCapability {\n return {\n resolve: (commandId, documentId) => this.resolve(commandId, documentId),\n execute: (commandId, documentId, source = 'ui') =>\n this.execute(commandId, documentId, source),\n getAllCommands: (documentId) => this.getAllCommands(documentId),\n getCommandsByCategory: (category, documentId) =>\n this.getCommandsByCategory(category, documentId),\n getCommandByShortcut: (shortcut) => this.getCommandByShortcut(shortcut),\n getAllShortcuts: () => new Map(this.shortcutMap),\n forDocument: (documentId) => this.createCommandScope(documentId),\n registerCommand: (command) => this.registerCommand(command),\n unregisterCommand: (commandId) => this.unregisterCommand(commandId),\n\n // Category management\n disableCategory: (category) => this.disableCategoryImpl(category),\n enableCategory: (category) => this.enableCategoryImpl(category),\n toggleCategory: (category) => this.toggleCategoryImpl(category),\n setDisabledCategories: (categories) => this.setDisabledCategoriesImpl(categories),\n getDisabledCategories: () => this.state.disabledCategories,\n isCategoryDisabled: (category) => this.state.disabledCategories.includes(category),\n\n // Events\n onCommandExecuted: this.commandExecuted$.on,\n onCommandStateChanged: this.commandStateChanged$.on,\n onShortcutExecuted: this.shortcutExecuted$.on,\n onCategoryChanged: this.categoryChanged$.on,\n };\n }\n\n // ─────────────────────────────────────────────────────────\n // Document Scoping\n // ─────────────────────────────────────────────────────────\n\n private createCommandScope(documentId: string): CommandScope {\n return {\n resolve: (commandId) => this.resolve(commandId, documentId),\n execute: (commandId, source = 'ui') => this.execute(commandId, documentId, source),\n getAllCommands: () => this.getAllCommands(documentId),\n getCommandsByCategory: (category) => this.getCommandsByCategory(category, documentId),\n onCommandStateChanged: (listener: Listener<Omit<CommandStateChangedEvent, 'documentId'>>) =>\n this.commandStateChanged$.on((event) => {\n if (event.documentId === documentId) {\n const { documentId: _, ...rest } = event;\n listener(rest);\n }\n }),\n };\n }\n\n // ─────────────────────────────────────────────────────────\n // Command Resolution\n // ─────────────────────────────────────────────────────────\n\n private resolve(commandId: string, documentId?: string): ResolvedCommand {\n const resolvedDocId = documentId ?? this.getActiveDocumentId();\n\n const command = this.commands.get(commandId);\n if (!command) {\n throw new Error(`Command not found: ${commandId}`);\n }\n\n const state = this.registry.getStore().getState();\n\n // Resolve label with i18n if available\n const label = this.resolveLabel(command, state, resolvedDocId);\n\n // Resolve shortcuts\n const shortcuts = command.shortcuts\n ? Array.isArray(command.shortcuts)\n ? command.shortcuts\n : [command.shortcuts]\n : undefined;\n\n // Check if disabled via categories OR explicit disabled predicate\n const explicitDisabled = this.resolveDynamic(command.disabled, state, resolvedDocId) ?? false;\n const categoryDisabled = this.isCommandCategoryDisabled(command);\n const isDisabled = explicitDisabled || categoryDisabled;\n\n return {\n id: command.id,\n label,\n icon: this.resolveDynamic(command.icon, state, resolvedDocId),\n iconProps: this.resolveDynamic(command.iconProps, state, resolvedDocId),\n active: this.resolveDynamic(command.active, state, resolvedDocId) ?? false,\n disabled: isDisabled,\n visible: this.resolveDynamic(command.visible, state, resolvedDocId) ?? true,\n shortcuts,\n shortcutLabel: command.shortcutLabel,\n categories: command.categories,\n description: command.description,\n execute: () => command.action({ registry: this.registry, state, documentId: resolvedDocId }),\n };\n }\n\n private resolveLabel(command: Command, state: StoreState<any>, documentId: string): string {\n // Priority: labelKey (with i18n) > label (plain string) > id (fallback)\n const labelKey = this.resolveDynamic(command.labelKey, state, documentId);\n if (labelKey && this.i18n) {\n const params = this.resolveDynamic(command.labelParams, state, documentId);\n return this.i18n.t(labelKey, { params, documentId });\n }\n\n if (command.label) {\n return command.label;\n }\n\n return command.id; // Fallback to ID\n }\n\n private resolveDynamic<T>(\n value: Dynamic<any, T> | undefined,\n state: StoreState<any>,\n documentId: string,\n ): T | undefined {\n if (value === undefined) return undefined;\n\n // Check if it's a function (the dynamic evaluator)\n if (typeof value === 'function') {\n return (\n value as (context: {\n registry: PluginRegistry;\n state: StoreState<any>;\n documentId: string;\n }) => T\n )({\n registry: this.registry,\n state,\n documentId,\n });\n }\n\n // Otherwise it's the static value\n return value as T;\n }\n\n // ─────────────────────────────────────────────────────────\n // Command Execution\n // ─────────────────────────────────────────────────────────\n\n private execute(\n commandId: string,\n documentId?: string,\n source: 'keyboard' | 'ui' | 'api' = 'ui',\n ): void {\n const resolvedDocId = documentId ?? this.getActiveDocumentId();\n const resolved = this.resolve(commandId, resolvedDocId);\n\n if (resolved.disabled) {\n this.logger.warn(\n 'CommandsPlugin',\n 'ExecutionBlocked',\n `Command '${commandId}' is disabled for document '${resolvedDocId}'`,\n );\n return;\n }\n\n if (!resolved.visible) {\n this.logger.warn(\n 'CommandsPlugin',\n 'ExecutionBlocked',\n `Command '${commandId}' is not visible for document '${resolvedDocId}'`,\n );\n return;\n }\n\n resolved.execute();\n\n this.commandExecuted$.emit({\n commandId,\n documentId: resolvedDocId,\n source,\n });\n\n this.logger.debug(\n 'CommandsPlugin',\n 'CommandExecuted',\n `Command '${commandId}' executed for document '${resolvedDocId}' (source: ${source})`,\n );\n }\n\n // ─────────────────────────────────────────────────────────\n // Command Registration\n // ─────────────────────────────────────────────────────────\n\n private registerCommand(command: Command): void {\n if (this.commands.has(command.id)) {\n this.logger.warn(\n 'CommandsPlugin',\n 'CommandOverwrite',\n `Command '${command.id}' already exists and will be overwritten`,\n );\n }\n\n this.commands.set(command.id, command);\n\n // Register shortcuts\n if (command.shortcuts) {\n const shortcuts = Array.isArray(command.shortcuts) ? command.shortcuts : [command.shortcuts];\n\n shortcuts.forEach((shortcut) => {\n const normalized = this.normalizeShortcut(shortcut);\n this.shortcutMap.set(normalized, command.id);\n });\n }\n\n this.logger.debug('CommandsPlugin', 'CommandRegistered', `Command '${command.id}' registered`);\n }\n\n private unregisterCommand(commandId: string): void {\n const command = this.commands.get(commandId);\n if (!command) return;\n\n // Remove shortcuts\n if (command.shortcuts) {\n const shortcuts = Array.isArray(command.shortcuts) ? command.shortcuts : [command.shortcuts];\n\n shortcuts.forEach((shortcut) => {\n const normalized = this.normalizeShortcut(shortcut);\n this.shortcutMap.delete(normalized);\n });\n }\n\n this.commands.delete(commandId);\n this.logger.debug(\n 'CommandsPlugin',\n 'CommandUnregistered',\n `Command '${commandId}' unregistered`,\n );\n }\n\n // ─────────────────────────────────────────────────────────\n // Shortcuts\n // ─────────────────────────────────────────────────────────\n\n private getCommandByShortcut(shortcut: string): Command | null {\n const normalized = this.normalizeShortcut(shortcut);\n const commandId = this.shortcutMap.get(normalized);\n return commandId ? (this.commands.get(commandId) ?? null) : null;\n }\n\n private normalizeShortcut(shortcut: string): string {\n // Normalize: \"Ctrl+Shift+A\" -> \"ctrl+shift+a\"\n return shortcut.toLowerCase().split('+').sort().join('+');\n }\n\n // ─────────────────────────────────────────────────────────\n // Query Methods\n // ─────────────────────────────────────────────────────────\n\n private getAllCommands(documentId?: string): ResolvedCommand[] {\n const resolvedDocId = documentId ?? this.getActiveDocumentId();\n return Array.from(this.commands.keys()).map((id) => this.resolve(id, resolvedDocId));\n }\n\n private getCommandsByCategory(category: string, documentId?: string): ResolvedCommand[] {\n const resolvedDocId = documentId ?? this.getActiveDocumentId();\n return Array.from(this.commands.values())\n .filter((cmd) => cmd.categories?.includes(category))\n .map((cmd) => this.resolve(cmd.id, resolvedDocId));\n }\n\n // ─────────────────────────────────────────────────────────\n // State Change Detection\n // ─────────────────────────────────────────────────────────\n\n private onGlobalStoreChange(newState: StoreState<any>): void {\n // Get all documents from core state\n const documentIds = Object.keys(newState.core.documents);\n\n // Check each document for command state changes\n documentIds.forEach((documentId) => {\n this.detectCommandChanges(documentId, newState);\n });\n }\n\n private detectCommandChanges(documentId: string, newState: StoreState<any>): void {\n // Skip if document isn't fully loaded yet\n const coreDoc = newState.core.documents[documentId];\n if (!coreDoc || coreDoc.status !== 'loaded') return;\n\n const previousCache = this.previousStates.get(documentId) ?? new Map();\n const changedCommandIds: string[] = [];\n\n this.commands.forEach((command, commandId) => {\n const newResolved = this.resolve(commandId, documentId);\n const prevResolved = previousCache.get(commandId);\n\n if (!prevResolved) {\n // First time resolving for this document\n previousCache.set(commandId, newResolved);\n return;\n }\n\n // Check for changes\n const changes: CommandStateChangedEvent['changes'] = {};\n\n if (prevResolved.active !== newResolved.active) {\n changes.active = newResolved.active;\n }\n if (prevResolved.disabled !== newResolved.disabled) {\n changes.disabled = newResolved.disabled;\n }\n if (prevResolved.visible !== newResolved.visible) {\n changes.visible = newResolved.visible;\n }\n if (prevResolved.label !== newResolved.label) {\n changes.label = newResolved.label;\n }\n if (prevResolved.icon !== newResolved.icon) {\n changes.icon = newResolved.icon;\n }\n if (!arePropsEqual(prevResolved.iconProps, newResolved.iconProps)) {\n changes.iconProps = newResolved.iconProps;\n }\n\n if (Object.keys(changes).length > 0) {\n changedCommandIds.push(commandId);\n previousCache.set(commandId, newResolved);\n\n this.commandStateChanged$.emit({\n commandId,\n documentId,\n changes,\n });\n }\n });\n\n this.previousStates.set(documentId, previousCache);\n }\n}\n","import { Reducer } from '@embedpdf/core';\nimport { CommandsState } from './types';\nimport { CommandsAction, SET_DISABLED_CATEGORIES } from './actions';\n\nexport const initialState: CommandsState = {\n disabledCategories: [],\n};\n\nexport const commandsReducer: Reducer<CommandsState, CommandsAction> = (\n state = initialState,\n action,\n) => {\n switch (action.type) {\n case SET_DISABLED_CATEGORIES:\n return {\n ...state,\n disabledCategories: action.payload,\n };\n\n default:\n return state;\n }\n};\n","import { PluginPackage } from '@embedpdf/core';\nimport { manifest, COMMANDS_PLUGIN_ID } from './manifest';\nimport { CommandsPluginConfig, CommandsState } from './types';\nimport { CommandsPlugin } from './commands-plugin';\nimport { CommandsAction } from './actions';\nimport { commandsReducer, initialState } from './reducer';\n\nexport const CommandsPluginPackage: PluginPackage<\n CommandsPlugin,\n CommandsPluginConfig,\n CommandsState,\n CommandsAction\n> = {\n manifest,\n create: (registry, config) => new CommandsPlugin(COMMANDS_PLUGIN_ID, registry, config),\n reducer: commandsReducer,\n initialState,\n};\n\nexport * from './commands-plugin';\nexport * from './types';\nexport * from './manifest';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/lib/manifest.ts","../src/lib/actions.ts","../src/lib/commands-plugin.ts","../src/lib/reducer.ts","../src/lib/index.ts"],"sourcesContent":["import { PluginManifest } from '@embedpdf/core';\nimport { CommandsPluginConfig } from './types';\n\nexport const COMMANDS_PLUGIN_ID = 'commands';\n\nexport const manifest: PluginManifest<CommandsPluginConfig> = {\n id: COMMANDS_PLUGIN_ID,\n name: 'Commands Plugin',\n version: '1.0.0',\n provides: ['commands'],\n requires: [],\n optional: ['i18n', 'ui'],\n defaultConfig: {\n commands: {},\n },\n};\n","import { Action } from '@embedpdf/core';\n\nexport const SET_DISABLED_CATEGORIES = 'COMMANDS/SET_DISABLED_CATEGORIES';\n\nexport interface SetDisabledCategoriesAction extends Action {\n type: typeof SET_DISABLED_CATEGORIES;\n payload: string[];\n}\n\nexport type CommandsAction = SetDisabledCategoriesAction;\n\nexport const setDisabledCategories = (categories: string[]): SetDisabledCategoriesAction => ({\n type: SET_DISABLED_CATEGORIES,\n payload: categories,\n});\n","import {\n BasePlugin,\n PluginRegistry,\n StoreState,\n createEmitter,\n createBehaviorEmitter,\n Listener,\n arePropsEqual,\n} from '@embedpdf/core';\nimport { Logger } from '@embedpdf/models';\nimport { I18nCapability, I18nPlugin } from '@embedpdf/plugin-i18n';\nimport {\n CommandsCapability,\n CommandsPluginConfig,\n CommandsState,\n Command,\n ResolvedCommand,\n CommandExecutedEvent,\n CommandStateChangedEvent,\n ShortcutExecutedEvent,\n CategoryChangedEvent,\n CommandScope,\n Dynamic,\n} from './types';\nimport { CommandsAction, setDisabledCategories } from './actions';\n\nexport class CommandsPlugin extends BasePlugin<\n CommandsPluginConfig,\n CommandsCapability,\n CommandsState,\n CommandsAction\n> {\n static readonly id = 'commands' as const;\n\n private commands = new Map<string, Command>();\n private i18n: I18nCapability | null = null;\n private shortcutMap = new Map<string, string>(); // shortcut -> commandId\n\n private readonly commandExecuted$ = createEmitter<CommandExecutedEvent>();\n private readonly commandStateChanged$ = createEmitter<CommandStateChangedEvent>();\n private readonly shortcutExecuted$ = createEmitter<ShortcutExecutedEvent>();\n private readonly categoryChanged$ = createBehaviorEmitter<CategoryChangedEvent>();\n\n // Cache previous resolved states per document to detect changes\n private previousStates = new Map<string, Map<string, ResolvedCommand>>();\n\n constructor(id: string, registry: PluginRegistry, config: CommandsPluginConfig) {\n super(id, registry);\n\n // Check if i18n plugin is available (optional dependency)\n const i18nPlugin = registry.getPlugin<I18nPlugin>('i18n');\n this.i18n = i18nPlugin?.provides() ?? null;\n\n // Initialize disabled categories from config\n if (config.disabledCategories?.length) {\n this.dispatch(setDisabledCategories(config.disabledCategories));\n }\n\n // Register all commands from config\n Object.values(config.commands).forEach((command) => {\n this.registerCommand(command);\n });\n\n // Subscribe to global store changes\n this.registry.getStore().subscribe((_action, newState) => {\n this.onGlobalStoreChange(newState);\n });\n }\n\n protected override onDocumentClosed(documentId: string): void {\n // Cleanup previous states cache\n this.previousStates.delete(documentId);\n\n this.logger.debug(\n 'CommandsPlugin',\n 'DocumentClosed',\n `Cleaned up command state cache for document: ${documentId}`,\n );\n }\n\n async initialize(): Promise<void> {\n this.logger.info('CommandsPlugin', 'Initialize', 'Commands plugin initialized');\n }\n\n async destroy(): Promise<void> {\n this.commandExecuted$.clear();\n this.commandStateChanged$.clear();\n this.shortcutExecuted$.clear();\n this.categoryChanged$.clear();\n this.commands.clear();\n this.shortcutMap.clear();\n this.previousStates.clear();\n super.destroy();\n }\n\n // ─────────────────────────────────────────────────────────\n // Category Management\n // ─────────────────────────────────────────────────────────\n\n private disableCategoryImpl(category: string): void {\n const current = new Set(this.state.disabledCategories);\n if (!current.has(category)) {\n current.add(category);\n this.dispatch(setDisabledCategories(Array.from(current)));\n this.categoryChanged$.emit({ disabledCategories: Array.from(current) });\n }\n }\n\n private enableCategoryImpl(category: string): void {\n const current = new Set(this.state.disabledCategories);\n if (current.has(category)) {\n current.delete(category);\n this.dispatch(setDisabledCategories(Array.from(current)));\n this.categoryChanged$.emit({ disabledCategories: Array.from(current) });\n }\n }\n\n private toggleCategoryImpl(category: string): void {\n if (this.state.disabledCategories.includes(category)) {\n this.enableCategoryImpl(category);\n } else {\n this.disableCategoryImpl(category);\n }\n }\n\n private setDisabledCategoriesImpl(categories: string[]): void {\n this.dispatch(setDisabledCategories(categories));\n this.categoryChanged$.emit({ disabledCategories: categories });\n }\n\n /**\n * Check if command has any disabled category\n */\n private isCommandCategoryDisabled(command: Command): boolean {\n if (!command.categories?.length) return false;\n return command.categories.some((cat) => this.state.disabledCategories.includes(cat));\n }\n\n // ─────────────────────────────────────────────────────────\n // Capability\n // ─────────────────────────────────────────────────────────\n\n protected buildCapability(): CommandsCapability {\n return {\n resolve: (commandId, documentId) => this.resolve(commandId, documentId),\n execute: (commandId, documentId, source = 'ui') =>\n this.execute(commandId, documentId, source),\n getAllCommands: (documentId) => this.getAllCommands(documentId),\n getCommandsByCategory: (category, documentId) =>\n this.getCommandsByCategory(category, documentId),\n getCommandByShortcut: (shortcut) => this.getCommandByShortcut(shortcut),\n getAllShortcuts: () => new Map(this.shortcutMap),\n forDocument: (documentId) => this.createCommandScope(documentId),\n registerCommand: (command) => this.registerCommand(command),\n unregisterCommand: (commandId) => this.unregisterCommand(commandId),\n\n // Category management\n disableCategory: (category) => this.disableCategoryImpl(category),\n enableCategory: (category) => this.enableCategoryImpl(category),\n toggleCategory: (category) => this.toggleCategoryImpl(category),\n setDisabledCategories: (categories) => this.setDisabledCategoriesImpl(categories),\n getDisabledCategories: () => this.state.disabledCategories,\n isCategoryDisabled: (category) => this.state.disabledCategories.includes(category),\n\n // Events\n onCommandExecuted: this.commandExecuted$.on,\n onCommandStateChanged: this.commandStateChanged$.on,\n onShortcutExecuted: this.shortcutExecuted$.on,\n onCategoryChanged: this.categoryChanged$.on,\n };\n }\n\n // ─────────────────────────────────────────────────────────\n // Document Scoping\n // ─────────────────────────────────────────────────────────\n\n private createCommandScope(documentId: string): CommandScope {\n return {\n resolve: (commandId) => this.resolve(commandId, documentId),\n execute: (commandId, source = 'ui') => this.execute(commandId, documentId, source),\n getAllCommands: () => this.getAllCommands(documentId),\n getCommandsByCategory: (category) => this.getCommandsByCategory(category, documentId),\n onCommandStateChanged: (listener: Listener<Omit<CommandStateChangedEvent, 'documentId'>>) =>\n this.commandStateChanged$.on((event) => {\n if (event.documentId === documentId) {\n const { documentId: _, ...rest } = event;\n listener(rest);\n }\n }),\n };\n }\n\n // ─────────────────────────────────────────────────────────\n // Command Resolution\n // ─────────────────────────────────────────────────────────\n\n private resolve(commandId: string, documentId?: string): ResolvedCommand {\n const resolvedDocId = documentId ?? this.getActiveDocumentId();\n\n const command = this.commands.get(commandId);\n if (!command) {\n throw new Error(`Command not found: ${commandId}`);\n }\n\n const state = this.registry.getStore().getState();\n\n // Resolve label with i18n if available\n const label = this.resolveLabel(command, state, resolvedDocId);\n\n // Resolve shortcuts\n const shortcuts = command.shortcuts\n ? Array.isArray(command.shortcuts)\n ? command.shortcuts\n : [command.shortcuts]\n : undefined;\n\n // Check if disabled via categories OR explicit disabled predicate\n const explicitDisabled = this.resolveDynamic(command.disabled, state, resolvedDocId) ?? false;\n const categoryDisabled = this.isCommandCategoryDisabled(command);\n const isDisabled = explicitDisabled || categoryDisabled;\n\n return {\n id: command.id,\n label,\n icon: this.resolveDynamic(command.icon, state, resolvedDocId),\n iconProps: this.resolveDynamic(command.iconProps, state, resolvedDocId),\n active: this.resolveDynamic(command.active, state, resolvedDocId) ?? false,\n disabled: isDisabled,\n visible: this.resolveDynamic(command.visible, state, resolvedDocId) ?? true,\n shortcuts,\n shortcutLabel: command.shortcutLabel,\n categories: command.categories,\n description: command.description,\n execute: () =>\n command.action({\n registry: this.registry,\n state,\n documentId: resolvedDocId,\n logger: this.logger,\n }),\n };\n }\n\n private resolveLabel(command: Command, state: StoreState<any>, documentId: string): string {\n // Priority: labelKey (with i18n) > label (plain string) > id (fallback)\n const labelKey = this.resolveDynamic(command.labelKey, state, documentId);\n if (labelKey && this.i18n) {\n const params = this.resolveDynamic(command.labelParams, state, documentId);\n return this.i18n.t(labelKey, { params, documentId });\n }\n\n if (command.label) {\n return command.label;\n }\n\n return command.id; // Fallback to ID\n }\n\n private resolveDynamic<T>(\n value: Dynamic<any, T> | undefined,\n state: StoreState<any>,\n documentId: string,\n ): T | undefined {\n if (value === undefined) return undefined;\n\n // Check if it's a function (the dynamic evaluator)\n if (typeof value === 'function') {\n return (\n value as (context: {\n registry: PluginRegistry;\n state: StoreState<any>;\n documentId: string;\n logger: Logger;\n }) => T\n )({\n registry: this.registry,\n state,\n documentId,\n logger: this.logger,\n });\n }\n\n // Otherwise it's the static value\n return value as T;\n }\n\n // ─────────────────────────────────────────────────────────\n // Command Execution\n // ─────────────────────────────────────────────────────────\n\n private execute(\n commandId: string,\n documentId?: string,\n source: 'keyboard' | 'ui' | 'api' = 'ui',\n ): void {\n const resolvedDocId = documentId ?? this.getActiveDocumentId();\n const resolved = this.resolve(commandId, resolvedDocId);\n\n if (resolved.disabled) {\n this.logger.warn(\n 'CommandsPlugin',\n 'ExecutionBlocked',\n `Command '${commandId}' is disabled for document '${resolvedDocId}'`,\n );\n return;\n }\n\n if (!resolved.visible) {\n this.logger.warn(\n 'CommandsPlugin',\n 'ExecutionBlocked',\n `Command '${commandId}' is not visible for document '${resolvedDocId}'`,\n );\n return;\n }\n\n resolved.execute();\n\n this.commandExecuted$.emit({\n commandId,\n documentId: resolvedDocId,\n source,\n });\n\n this.logger.debug(\n 'CommandsPlugin',\n 'CommandExecuted',\n `Command '${commandId}' executed for document '${resolvedDocId}' (source: ${source})`,\n );\n }\n\n // ─────────────────────────────────────────────────────────\n // Command Registration\n // ─────────────────────────────────────────────────────────\n\n private registerCommand(command: Command): void {\n if (this.commands.has(command.id)) {\n this.logger.warn(\n 'CommandsPlugin',\n 'CommandOverwrite',\n `Command '${command.id}' already exists and will be overwritten`,\n );\n }\n\n this.commands.set(command.id, command);\n\n // Register shortcuts\n if (command.shortcuts) {\n const shortcuts = Array.isArray(command.shortcuts) ? command.shortcuts : [command.shortcuts];\n\n shortcuts.forEach((shortcut) => {\n const normalized = this.normalizeShortcut(shortcut);\n this.shortcutMap.set(normalized, command.id);\n });\n }\n\n this.logger.debug('CommandsPlugin', 'CommandRegistered', `Command '${command.id}' registered`);\n }\n\n private unregisterCommand(commandId: string): void {\n const command = this.commands.get(commandId);\n if (!command) return;\n\n // Remove shortcuts\n if (command.shortcuts) {\n const shortcuts = Array.isArray(command.shortcuts) ? command.shortcuts : [command.shortcuts];\n\n shortcuts.forEach((shortcut) => {\n const normalized = this.normalizeShortcut(shortcut);\n this.shortcutMap.delete(normalized);\n });\n }\n\n this.commands.delete(commandId);\n this.logger.debug(\n 'CommandsPlugin',\n 'CommandUnregistered',\n `Command '${commandId}' unregistered`,\n );\n }\n\n // ─────────────────────────────────────────────────────────\n // Shortcuts\n // ─────────────────────────────────────────────────────────\n\n private getCommandByShortcut(shortcut: string): Command | null {\n const normalized = this.normalizeShortcut(shortcut);\n const commandId = this.shortcutMap.get(normalized);\n return commandId ? (this.commands.get(commandId) ?? null) : null;\n }\n\n private normalizeShortcut(shortcut: string): string {\n // Normalize: \"Ctrl+Shift+A\" -> \"ctrl+shift+a\"\n return shortcut.toLowerCase().split('+').sort().join('+');\n }\n\n // ─────────────────────────────────────────────────────────\n // Query Methods\n // ─────────────────────────────────────────────────────────\n\n private getAllCommands(documentId?: string): ResolvedCommand[] {\n const resolvedDocId = documentId ?? this.getActiveDocumentId();\n return Array.from(this.commands.keys()).map((id) => this.resolve(id, resolvedDocId));\n }\n\n private getCommandsByCategory(category: string, documentId?: string): ResolvedCommand[] {\n const resolvedDocId = documentId ?? this.getActiveDocumentId();\n return Array.from(this.commands.values())\n .filter((cmd) => cmd.categories?.includes(category))\n .map((cmd) => this.resolve(cmd.id, resolvedDocId));\n }\n\n // ─────────────────────────────────────────────────────────\n // State Change Detection\n // ─────────────────────────────────────────────────────────\n\n private onGlobalStoreChange(newState: StoreState<any>): void {\n // Get all documents from core state\n const documentIds = Object.keys(newState.core.documents);\n\n // Check each document for command state changes\n documentIds.forEach((documentId) => {\n this.detectCommandChanges(documentId, newState);\n });\n }\n\n private detectCommandChanges(documentId: string, newState: StoreState<any>): void {\n // Skip if document isn't fully loaded yet\n const coreDoc = newState.core.documents[documentId];\n if (!coreDoc || coreDoc.status !== 'loaded') return;\n\n const previousCache = this.previousStates.get(documentId) ?? new Map();\n const changedCommandIds: string[] = [];\n\n this.commands.forEach((command, commandId) => {\n const newResolved = this.resolve(commandId, documentId);\n const prevResolved = previousCache.get(commandId);\n\n if (!prevResolved) {\n // First time resolving for this document\n previousCache.set(commandId, newResolved);\n return;\n }\n\n // Check for changes\n const changes: CommandStateChangedEvent['changes'] = {};\n\n if (prevResolved.active !== newResolved.active) {\n changes.active = newResolved.active;\n }\n if (prevResolved.disabled !== newResolved.disabled) {\n changes.disabled = newResolved.disabled;\n }\n if (prevResolved.visible !== newResolved.visible) {\n changes.visible = newResolved.visible;\n }\n if (prevResolved.label !== newResolved.label) {\n changes.label = newResolved.label;\n }\n if (prevResolved.icon !== newResolved.icon) {\n changes.icon = newResolved.icon;\n }\n if (!arePropsEqual(prevResolved.iconProps, newResolved.iconProps)) {\n changes.iconProps = newResolved.iconProps;\n }\n\n if (Object.keys(changes).length > 0) {\n changedCommandIds.push(commandId);\n previousCache.set(commandId, newResolved);\n\n this.commandStateChanged$.emit({\n commandId,\n documentId,\n changes,\n });\n }\n });\n\n this.previousStates.set(documentId, previousCache);\n }\n}\n","import { Reducer } from '@embedpdf/core';\nimport { CommandsState } from './types';\nimport { CommandsAction, SET_DISABLED_CATEGORIES } from './actions';\n\nexport const initialState: CommandsState = {\n disabledCategories: [],\n};\n\nexport const commandsReducer: Reducer<CommandsState, CommandsAction> = (\n state = initialState,\n action,\n) => {\n switch (action.type) {\n case SET_DISABLED_CATEGORIES:\n return {\n ...state,\n disabledCategories: action.payload,\n };\n\n default:\n return state;\n }\n};\n","import { PluginPackage } from '@embedpdf/core';\nimport { manifest, COMMANDS_PLUGIN_ID } from './manifest';\nimport { CommandsPluginConfig, CommandsState } from './types';\nimport { CommandsPlugin } from './commands-plugin';\nimport { CommandsAction } from './actions';\nimport { commandsReducer, initialState } from './reducer';\n\nexport const CommandsPluginPackage: PluginPackage<\n CommandsPlugin,\n CommandsPluginConfig,\n CommandsState,\n CommandsAction\n> = {\n manifest,\n create: (registry, config) => new CommandsPlugin(COMMANDS_PLUGIN_ID, registry, config),\n reducer: commandsReducer,\n initialState,\n};\n\nexport * from './commands-plugin';\nexport * from './types';\nexport * from './manifest';\n"],"names":[],"mappings":"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"}
@@ -1,9 +1,11 @@
1
1
  import { BasePluginConfig, CoreState, EventHook, PluginRegistry } from '@embedpdf/core';
2
+ import { Logger } from '@embedpdf/models';
2
3
  import { TranslationKey } from '@embedpdf/plugin-i18n';
3
4
  export type Dynamic<TStore, T> = T | ((context: {
4
5
  registry: PluginRegistry;
5
6
  state: TStore;
6
7
  documentId: string;
8
+ logger: Logger;
7
9
  }) => T);
8
10
  export interface IconProps {
9
11
  primaryColor?: string;
@@ -22,6 +24,7 @@ export interface Command<TStore = any> {
22
24
  registry: PluginRegistry;
23
25
  state: TStore;
24
26
  documentId: string;
27
+ logger: Logger;
25
28
  }) => void;
26
29
  active?: Dynamic<TStore, boolean>;
27
30
  disabled?: Dynamic<TStore, boolean>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@embedpdf/plugin-commands",
3
- "version": "2.3.0",
3
+ "version": "2.4.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "main": "./dist/index.cjs",
@@ -35,14 +35,14 @@
35
35
  }
36
36
  },
37
37
  "dependencies": {
38
- "@embedpdf/models": "2.3.0"
38
+ "@embedpdf/models": "2.4.0"
39
39
  },
40
40
  "devDependencies": {
41
41
  "@types/react": "^18.2.0",
42
42
  "typescript": "^5.0.0",
43
43
  "@embedpdf/build": "1.1.0",
44
- "@embedpdf/plugin-i18n": "2.3.0",
45
- "@embedpdf/core": "2.3.0"
44
+ "@embedpdf/plugin-i18n": "2.4.0",
45
+ "@embedpdf/core": "2.4.0"
46
46
  },
47
47
  "peerDependencies": {
48
48
  "react": ">=16.8.0",
@@ -50,7 +50,7 @@
50
50
  "preact": "^10.26.4",
51
51
  "vue": ">=3.2.0",
52
52
  "svelte": ">=5 <6",
53
- "@embedpdf/core": "2.3.0"
53
+ "@embedpdf/core": "2.4.0"
54
54
  },
55
55
  "files": [
56
56
  "dist",