@embedpdf/plugin-ui 1.0.11 → 1.0.12

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.
Files changed (50) hide show
  1. package/dist/index.cjs +2 -883
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.d.ts +1 -495
  4. package/dist/index.js +37 -56
  5. package/dist/index.js.map +1 -1
  6. package/dist/lib/actions.d.ts +88 -0
  7. package/dist/lib/icons/icon-manager.d.ts +47 -0
  8. package/dist/lib/icons/types.d.ts +36 -0
  9. package/dist/lib/index.d.ts +13 -0
  10. package/dist/lib/manifest.d.ts +4 -0
  11. package/dist/lib/menu/menu-manager.d.ts +98 -0
  12. package/dist/lib/menu/types.d.ts +83 -0
  13. package/dist/lib/menu/utils.d.ts +5 -0
  14. package/dist/lib/reducer.d.ts +5 -0
  15. package/dist/lib/types.d.ts +204 -0
  16. package/dist/lib/ui-component.d.ts +30 -0
  17. package/dist/lib/ui-plugin.d.ts +24 -0
  18. package/dist/lib/utils.d.ts +33 -0
  19. package/dist/preact/adapter.d.ts +5 -0
  20. package/dist/preact/core.d.ts +1 -0
  21. package/dist/preact/index.cjs +2 -130
  22. package/dist/preact/index.cjs.map +1 -1
  23. package/dist/preact/index.d.ts +1 -70
  24. package/dist/preact/index.js +19 -26
  25. package/dist/preact/index.js.map +1 -1
  26. package/dist/react/adapter.d.ts +2 -0
  27. package/dist/react/core.d.ts +1 -0
  28. package/dist/react/index.cjs +2 -2
  29. package/dist/react/index.cjs.map +1 -1
  30. package/dist/react/index.d.ts +1 -2
  31. package/dist/react/index.js +92 -1
  32. package/dist/react/index.js.map +1 -1
  33. package/dist/shared-preact/components/component-wrapper.d.ts +5 -0
  34. package/dist/shared-preact/components/index.d.ts +1 -0
  35. package/dist/shared-preact/components/plugin-ui-provider.d.ts +37 -0
  36. package/dist/shared-preact/hooks/index.d.ts +2 -0
  37. package/dist/shared-preact/hooks/use-icon.d.ts +15 -0
  38. package/dist/shared-preact/hooks/use-ui.d.ts +11 -0
  39. package/dist/shared-preact/index.d.ts +2 -0
  40. package/dist/shared-react/components/component-wrapper.d.ts +5 -0
  41. package/dist/shared-react/components/index.d.ts +1 -0
  42. package/dist/shared-react/components/plugin-ui-provider.d.ts +37 -0
  43. package/dist/shared-react/hooks/index.d.ts +2 -0
  44. package/dist/shared-react/hooks/use-icon.d.ts +15 -0
  45. package/dist/shared-react/hooks/use-ui.d.ts +11 -0
  46. package/dist/shared-react/index.d.ts +2 -0
  47. package/package.json +14 -11
  48. package/dist/index.d.cts +0 -495
  49. package/dist/preact/index.d.cts +0 -70
  50. package/dist/react/index.d.cts +0 -2
package/dist/index.js CHANGED
@@ -1,8 +1,5 @@
1
- // src/lib/ui-plugin.ts
2
1
  import { BasePlugin, arePropsEqual } from "@embedpdf/core";
3
-
4
- // src/lib/ui-component.ts
5
- var UIComponent = class {
2
+ class UIComponent {
6
3
  constructor(componentConfig, registry) {
7
4
  this.children = [];
8
5
  this.updateCallbacks = [];
@@ -70,42 +67,38 @@ var UIComponent = class {
70
67
  notifyUpdate() {
71
68
  this.updateCallbacks.forEach((cb) => cb());
72
69
  }
73
- };
74
-
75
- // src/lib/actions.ts
76
- var UI_INIT_COMPONENTS = "UI_INIT_COMPONENTS";
77
- var UI_SET_HEADER_VISIBLE = "UI_SET_HEADER_VISIBLE";
78
- var UI_TOGGLE_PANEL = "UI_TOGGLE_PANEL";
79
- var UI_SHOW_COMMAND_MENU = "UI_SHOW_COMMAND_MENU";
80
- var UI_HIDE_COMMAND_MENU = "UI_HIDE_COMMAND_MENU";
81
- var UI_UPDATE_COMPONENT_STATE = "UI_UPDATE_COMPONENT_STATE";
82
- var uiInitComponents = (state) => ({
70
+ }
71
+ const UI_INIT_COMPONENTS = "UI_INIT_COMPONENTS";
72
+ const UI_SET_HEADER_VISIBLE = "UI_SET_HEADER_VISIBLE";
73
+ const UI_TOGGLE_PANEL = "UI_TOGGLE_PANEL";
74
+ const UI_SHOW_COMMAND_MENU = "UI_SHOW_COMMAND_MENU";
75
+ const UI_HIDE_COMMAND_MENU = "UI_HIDE_COMMAND_MENU";
76
+ const UI_UPDATE_COMPONENT_STATE = "UI_UPDATE_COMPONENT_STATE";
77
+ const uiInitComponents = (state) => ({
83
78
  type: UI_INIT_COMPONENTS,
84
79
  payload: state
85
80
  });
86
- var uiTogglePanel = (payload) => ({
81
+ const uiTogglePanel = (payload) => ({
87
82
  type: UI_TOGGLE_PANEL,
88
83
  payload
89
84
  });
90
- var uiSetHeaderVisible = (payload) => ({
85
+ const uiSetHeaderVisible = (payload) => ({
91
86
  type: UI_SET_HEADER_VISIBLE,
92
87
  payload
93
88
  });
94
- var uiShowCommandMenu = (payload) => ({
89
+ const uiShowCommandMenu = (payload) => ({
95
90
  type: UI_SHOW_COMMAND_MENU,
96
91
  payload
97
92
  });
98
- var uiHideCommandMenu = (payload) => ({
93
+ const uiHideCommandMenu = (payload) => ({
99
94
  type: UI_HIDE_COMMAND_MENU,
100
95
  payload
101
96
  });
102
- var uiUpdateComponentState = (payload) => ({
97
+ const uiUpdateComponentState = (payload) => ({
103
98
  type: UI_UPDATE_COMPONENT_STATE,
104
99
  payload
105
100
  });
106
-
107
- // src/lib/reducer.ts
108
- var initialState = {
101
+ const initialState = {
109
102
  panel: {},
110
103
  header: {},
111
104
  groupedItems: {},
@@ -117,7 +110,7 @@ var initialState = {
117
110
  floating: {},
118
111
  commandMenu: {}
119
112
  };
120
- var uiReducer = (state = initialState, action) => {
113
+ const uiReducer = (state = initialState, action) => {
121
114
  switch (action.type) {
122
115
  case UI_INIT_COMPONENTS:
123
116
  return {
@@ -210,8 +203,6 @@ var uiReducer = (state = initialState, action) => {
210
203
  return state;
211
204
  }
212
205
  };
213
-
214
- // src/lib/utils.ts
215
206
  function defineComponent() {
216
207
  return (c) => c;
217
208
  }
@@ -243,8 +234,6 @@ function createEventController() {
243
234
  }
244
235
  };
245
236
  }
246
-
247
- // src/lib/menu/utils.ts
248
237
  function resolveMenuItem(item, state) {
249
238
  const dyn = (v) => typeof v === "function" ? v(state) : v;
250
239
  if (item.type === "group") {
@@ -283,13 +272,10 @@ function isDisabled(item, state) {
283
272
  }
284
273
  return resolved.disabled ? true : false;
285
274
  }
286
-
287
- // src/lib/menu/menu-manager.ts
288
- var _MenuManager = class _MenuManager {
275
+ const _MenuManager = class _MenuManager {
289
276
  constructor(items = {}, pluginRegistry) {
290
277
  this.registry = {};
291
278
  this.shortcutMap = {};
292
- // maps shortcut to menu item id
293
279
  this.eventController = createEventController();
294
280
  this.pluginRegistry = pluginRegistry;
295
281
  this.registerItems(items);
@@ -374,8 +360,9 @@ var _MenuManager = class _MenuManager {
374
360
  * If flatten is true, it will recursively include submenu children but not groups
375
361
  */
376
362
  getChildItems(menuId, options = {}) {
363
+ var _a;
377
364
  const item = this.resolve(menuId);
378
- if (!item || !("children" in item) || !item.children?.length) {
365
+ if (!item || !("children" in item) || !((_a = item.children) == null ? void 0 : _a.length)) {
379
366
  return [];
380
367
  }
381
368
  const children = this.getItemsByIds(item.children);
@@ -399,6 +386,7 @@ var _MenuManager = class _MenuManager {
399
386
  * Execute a command by ID
400
387
  */
401
388
  executeCommand(id, options = {}) {
389
+ var _a;
402
390
  const resolved = this.getMenuItem(id);
403
391
  if (!resolved) {
404
392
  console.warn(`Menu item '${id}' not found`);
@@ -419,7 +407,7 @@ var _MenuManager = class _MenuManager {
419
407
  command: item,
420
408
  source: options.source || "api"
421
409
  });
422
- } else if ("children" in item && item.children?.length) {
410
+ } else if ("children" in item && ((_a = item.children) == null ? void 0 : _a.length)) {
423
411
  this.handleSubmenu(item, options);
424
412
  }
425
413
  }
@@ -518,16 +506,13 @@ var _MenuManager = class _MenuManager {
518
506
  };
519
507
  }
520
508
  };
521
- // Event types
522
509
  _MenuManager.EVENTS = {
523
510
  COMMAND_EXECUTED: "menu:command_executed",
524
511
  MENU_REQUESTED: "menu:requested",
525
512
  SHORTCUT_EXECUTED: "menu:shortcut_executed"
526
513
  };
527
- var MenuManager = _MenuManager;
528
-
529
- // src/lib/icons/icon-manager.ts
530
- var IconManager = class {
514
+ let MenuManager = _MenuManager;
515
+ class IconManager {
531
516
  constructor(icons) {
532
517
  this.icons = {};
533
518
  this.registerIcons(icons);
@@ -581,13 +566,14 @@ var IconManager = class {
581
566
  * If the identifier is an icon ID, the registered SVG is returned
582
567
  */
583
568
  getSvgString(identifier) {
569
+ var _a;
584
570
  if (this.isSvgString(identifier)) {
585
571
  return identifier;
586
572
  }
587
573
  if (this.isSvgDataUri(identifier)) {
588
574
  return this.dataUriToSvgString(identifier);
589
575
  }
590
- return this.getIcon(identifier)?.svg;
576
+ return (_a = this.getIcon(identifier)) == null ? void 0 : _a.svg;
591
577
  }
592
578
  /**
593
579
  * Utility method to parse a data URI
@@ -616,10 +602,8 @@ var IconManager = class {
616
602
  svgStringToDataUri: this.svgStringToDataUri.bind(this)
617
603
  };
618
604
  }
619
- };
620
-
621
- // src/lib/ui-plugin.ts
622
- var UIPlugin = class extends BasePlugin {
605
+ }
606
+ const _UIPlugin = class _UIPlugin extends BasePlugin {
623
607
  constructor(id, registry, config) {
624
608
  super(id, registry);
625
609
  this.componentRenderers = {};
@@ -643,8 +627,9 @@ var UIPlugin = class extends BasePlugin {
643
627
  // Set up handlers for command events
644
628
  setupCommandEventHandlers() {
645
629
  this.menuManager.on(MenuManager.EVENTS.MENU_REQUESTED, (data) => {
630
+ var _a;
646
631
  const { menuId, triggerElement, position, flatten } = data;
647
- const isOpen = this.state.commandMenu.commandMenu?.activeCommand === menuId;
632
+ const isOpen = ((_a = this.state.commandMenu.commandMenu) == null ? void 0 : _a.activeCommand) === menuId;
648
633
  if (isOpen) {
649
634
  return this.dispatch(uiHideCommandMenu({ id: "commandMenu" }));
650
635
  }
@@ -680,9 +665,10 @@ var UIPlugin = class extends BasePlugin {
680
665
  }
681
666
  linkGroupedItems() {
682
667
  Object.values(this.components).forEach((component) => {
668
+ var _a;
683
669
  if (isItemWithSlots(component)) {
684
670
  const props = component.componentConfig;
685
- props.slots?.forEach((slot) => {
671
+ (_a = props.slots) == null ? void 0 : _a.forEach((slot) => {
686
672
  const child = this.components[slot.componentId];
687
673
  if (child) {
688
674
  component.addChild(slot.componentId, child, slot.priority, slot.className);
@@ -778,7 +764,8 @@ var UIPlugin = class extends BasePlugin {
778
764
  this.mapStateCallbacks = {};
779
765
  }
780
766
  };
781
- UIPlugin.id = "ui";
767
+ _UIPlugin.id = "ui";
768
+ let UIPlugin = _UIPlugin;
782
769
  function isItemWithSlots(component) {
783
770
  return isGroupedItemsComponent(component) || isHeaderComponent(component) || isPanelComponent(component) || isFloatingComponent(component) || isCustomComponent(component);
784
771
  }
@@ -800,10 +787,8 @@ function isCommandMenuComponent(component) {
800
787
  function isCustomComponent(component) {
801
788
  return component.type === "custom";
802
789
  }
803
-
804
- // src/lib/manifest.ts
805
- var UI_PLUGIN_ID = "ui";
806
- var manifest = {
790
+ const UI_PLUGIN_ID = "ui";
791
+ const manifest = {
807
792
  id: UI_PLUGIN_ID,
808
793
  name: "UI Plugin",
809
794
  version: "1.0.0",
@@ -815,14 +800,10 @@ var manifest = {
815
800
  components: {}
816
801
  }
817
802
  };
818
-
819
- // src/lib/menu/types.ts
820
803
  function hasActive(command) {
821
804
  return "active" in command;
822
805
  }
823
-
824
- // src/lib/index.ts
825
- var UIPluginPackage = {
806
+ const UIPluginPackage = {
826
807
  manifest,
827
808
  create: (registry, _engine, config) => new UIPlugin(UI_PLUGIN_ID, registry, config),
828
809
  reducer: uiReducer,
@@ -842,4 +823,4 @@ export {
842
823
  manifest,
843
824
  resolveMenuItem
844
825
  };
845
- //# sourceMappingURL=index.js.map
826
+ //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/ui-plugin.ts","../src/lib/ui-component.ts","../src/lib/actions.ts","../src/lib/reducer.ts","../src/lib/utils.ts","../src/lib/menu/utils.ts","../src/lib/menu/menu-manager.ts","../src/lib/icons/icon-manager.ts","../src/lib/manifest.ts","../src/lib/menu/types.ts","../src/lib/index.ts"],"sourcesContent":["import { BasePlugin, CoreState, PluginRegistry, StoreState, arePropsEqual } from '@embedpdf/core';\nimport {\n childrenFunctionOptions,\n CommandMenuComponent,\n CustomComponent,\n FloatingComponent,\n GroupedItemsComponent,\n HeaderComponent,\n PanelComponent,\n UICapability,\n UIComponentType,\n UIPluginConfig,\n UIPluginState,\n} from './types';\nimport { UIComponent } from './ui-component';\nimport { initialState } from './reducer';\nimport {\n uiInitComponents,\n UIPluginAction,\n uiSetHeaderVisible,\n uiShowCommandMenu,\n uiTogglePanel,\n uiHideCommandMenu,\n TogglePanelPayload,\n SetHeaderVisiblePayload,\n uiUpdateComponentState,\n UpdateComponentStatePayload,\n} from './actions';\nimport { MenuManager } from './menu/menu-manager';\nimport { IconManager } from './icons/icon-manager';\n\nexport class UIPlugin extends BasePlugin<\n UIPluginConfig,\n UICapability,\n UIPluginState,\n UIPluginAction\n> {\n static readonly id = 'ui' as const;\n private componentRenderers: Record<\n string,\n (\n props: any,\n children: (options?: childrenFunctionOptions) => any[],\n context?: Record<string, any>,\n ) => any\n > = {};\n private components: Record<string, UIComponent<UIComponentType<any>>> = {};\n private config: UIPluginConfig;\n private mapStateCallbacks: {\n [componentId: string]: (storeState: any, ownProps: any) => any;\n } = {};\n private globalStoreSubscription: () => void = () => {};\n private menuManager: MenuManager; // Add this\n private iconManager: IconManager;\n\n constructor(id: string, registry: PluginRegistry, config: UIPluginConfig) {\n super(id, registry);\n this.config = config;\n\n // Initialize command center\n this.menuManager = new MenuManager(config.menuItems || {}, this.registry);\n\n // Initialize icon registry\n this.iconManager = new IconManager(config.icons || []);\n\n // Subscribe to command events\n this.setupCommandEventHandlers();\n\n // Subscribe exactly once to the global store\n this.globalStoreSubscription = this.registry.getStore().subscribe((_action, newState) => {\n this.onGlobalStoreChange(newState);\n });\n }\n\n async initialize(): Promise<void> {\n // Step 1: Build all individual components\n this.buildComponents();\n\n // Step 2: Link children for grouped items\n this.linkGroupedItems();\n\n // Step 3: Set initial state for UI components\n this.setInitialStateUIComponents();\n }\n\n // Set up handlers for command events\n private setupCommandEventHandlers(): void {\n // Handle command menu requests\n this.menuManager.on(MenuManager.EVENTS.MENU_REQUESTED, (data) => {\n const { menuId, triggerElement, position, flatten } = data;\n\n const isOpen = this.state.commandMenu.commandMenu?.activeCommand === menuId;\n if (isOpen) {\n return this.dispatch(uiHideCommandMenu({ id: 'commandMenu' }));\n }\n\n this.dispatch(\n uiShowCommandMenu({\n id: 'commandMenu',\n commandId: menuId,\n triggerElement,\n position,\n flatten,\n }),\n );\n });\n\n // Optional: Track command execution for analytics or other purposes\n this.menuManager.on(MenuManager.EVENTS.COMMAND_EXECUTED, (data) => {\n console.log('Command executed:', data.command.id, 'source:', data.source);\n });\n }\n\n private addComponent(id: string, componentConfig: UIComponentType<any>) {\n if (this.components[id]) {\n console.warn(`Component with ID ${id} already exists and will be overwritten`);\n }\n // Step 1: Build the UIComponent\n const component = new UIComponent(componentConfig, this.componentRenderers);\n this.components[id] = component;\n\n // Step 2: Store mapStateToProps if present\n if (typeof componentConfig.mapStateToProps === 'function') {\n this.mapStateCallbacks[id] = componentConfig.mapStateToProps;\n }\n\n return component;\n }\n\n private buildComponents() {\n Object.entries(this.config.components).forEach(([id, componentConfig]) => {\n this.addComponent(id, componentConfig);\n });\n }\n\n private linkGroupedItems() {\n Object.values(this.components).forEach((component) => {\n if (isItemWithSlots(component)) {\n const props = component.componentConfig;\n props.slots?.forEach((slot) => {\n const child = this.components[slot.componentId];\n if (child) {\n component.addChild(slot.componentId, child, slot.priority, slot.className);\n } else {\n console.warn(\n `Child component ${slot.componentId} not found for GroupedItems ${props.id}`,\n );\n }\n });\n }\n });\n }\n\n private setInitialStateUIComponents() {\n const defaultState: UIPluginState = initialState;\n\n Object.entries(this.config.components).forEach(([componentId, definition]) => {\n if (definition.initialState) {\n // store the initialState object, e.g. { open: false } or { active: true }\n defaultState[definition.type][componentId] = definition.initialState;\n } else {\n defaultState[definition.type][componentId] = {};\n }\n });\n\n this.dispatch(uiInitComponents(defaultState));\n }\n\n private onGlobalStoreChange(state: StoreState<CoreState>) {\n for (const [id, uiComponent] of Object.entries(this.components)) {\n const mapFn = this.mapStateCallbacks[id];\n if (!mapFn) continue; // no mapping\n\n // ownProps is the UIComponent's current props\n const { id: _id, ...ownProps } = uiComponent.props;\n\n const partial = mapFn(state, ownProps);\n // If partial is non-empty or changes from old, do update\n const merged = { ...ownProps, ...partial };\n\n if (!arePropsEqual(ownProps, merged)) {\n uiComponent.update(partial);\n }\n }\n }\n\n private addSlot(parentId: string, slotId: string, priority?: number, className?: string) {\n // 1. Get the parent component\n const parentComponent = this.components[parentId];\n\n if (!parentComponent) {\n console.error(`Parent component ${parentId} not found`);\n return;\n }\n\n // 2. Check if parent has slots (is a container type)\n if (!isItemWithSlots(parentComponent)) {\n console.error(`Parent component ${parentId} does not support slots`);\n return;\n }\n\n // 3. Get the component to add to the slot\n const childComponent = this.components[slotId];\n\n if (!childComponent) {\n console.error(`Child component ${slotId} not found`);\n return;\n }\n\n const parentChildren = parentComponent.getChildren();\n\n // 4. Determine priority for the new slot\n let slotPriority = priority;\n\n if (slotPriority === undefined) {\n // If no priority is specified, add it at the end with a reasonable gap\n const maxPriority =\n parentChildren.length > 0 ? Math.max(...parentChildren.map((child) => child.priority)) : 0;\n slotPriority = maxPriority + 10; // Add a gap of 10\n }\n\n // 6. Add the child to the parent component with the appropriate priority\n // The UIComponent will handle sorting and avoid duplicates\n parentComponent.addChild(slotId, childComponent, slotPriority, className);\n }\n\n protected buildCapability(): UICapability {\n return {\n registerComponentRenderer: (\n type: string,\n renderer: (\n props: any,\n children: (options?: childrenFunctionOptions) => any[],\n context?: Record<string, any>,\n ) => any,\n ) => {\n this.componentRenderers[type] = renderer;\n },\n getComponent: <T>(id: string): T | undefined => {\n return this.components[id] as T | undefined;\n },\n registerComponent: this.addComponent.bind(this),\n getCommandMenu: () =>\n Object.values(this.components).find((component) => isCommandMenuComponent(component)),\n hideCommandMenu: () => this.debouncedDispatch(uiHideCommandMenu({ id: 'commandMenu' }), 100),\n getFloatingComponents: (scrollerPosition?: 'inside' | 'outside') =>\n Object.values(this.components)\n .filter((component) => isFloatingComponent(component))\n .filter(\n (component) =>\n !scrollerPosition || component.props.scrollerPosition === scrollerPosition,\n ),\n getHeadersByPlacement: (placement: 'top' | 'bottom' | 'left' | 'right') =>\n Object.values(this.components)\n .filter((component) => isHeaderComponent(component))\n .filter((component) => component.props.placement === placement),\n getPanelsByLocation: (location: 'left' | 'right') =>\n Object.values(this.components)\n .filter((component) => isPanelComponent(component))\n .filter((component) => component.props.location === location),\n addSlot: this.addSlot.bind(this),\n togglePanel: (payload: TogglePanelPayload) => {\n this.dispatch(uiTogglePanel(payload));\n },\n setHeaderVisible: (payload: SetHeaderVisiblePayload) => {\n this.dispatch(uiSetHeaderVisible(payload));\n },\n updateComponentState: (payload: UpdateComponentStatePayload) => {\n this.dispatch(uiUpdateComponentState(payload));\n },\n ...this.iconManager.capabilities(),\n ...this.menuManager.capabilities(),\n };\n }\n\n async destroy(): Promise<void> {\n this.globalStoreSubscription();\n this.components = {};\n this.componentRenderers = {};\n this.mapStateCallbacks = {};\n }\n}\n\nfunction isItemWithSlots(\n component: UIComponent<UIComponentType<any>>,\n): component is\n | UIComponent<GroupedItemsComponent>\n | UIComponent<HeaderComponent>\n | UIComponent<PanelComponent>\n | UIComponent<FloatingComponent>\n | UIComponent<CustomComponent> {\n return (\n isGroupedItemsComponent(component) ||\n isHeaderComponent(component) ||\n isPanelComponent(component) ||\n isFloatingComponent(component) ||\n isCustomComponent(component)\n );\n}\n\n// Type guard function\nfunction isGroupedItemsComponent(\n component: UIComponent<UIComponentType>,\n): component is UIComponent<GroupedItemsComponent> {\n return component.type === 'groupedItems';\n}\n\nfunction isHeaderComponent(\n component: UIComponent<UIComponentType>,\n): component is UIComponent<HeaderComponent> {\n return component.type === 'header';\n}\n\nfunction isPanelComponent(\n component: UIComponent<UIComponentType>,\n): component is UIComponent<PanelComponent> {\n return component.type === 'panel';\n}\n\nfunction isFloatingComponent(\n component: UIComponent<UIComponentType>,\n): component is UIComponent<FloatingComponent> {\n return component.type === 'floating';\n}\n\nfunction isCommandMenuComponent(\n component: UIComponent<UIComponentType>,\n): component is UIComponent<CommandMenuComponent> {\n return component.type === 'commandMenu';\n}\n\nfunction isCustomComponent(\n component: UIComponent<UIComponentType>,\n): component is UIComponent<CustomComponent> {\n return component.type === 'custom';\n}\n","import { BaseUIComponent, childrenFunctionOptions } from './types';\n\nexport class UIComponent<T extends BaseUIComponent<any, any, any>> {\n public componentConfig: T;\n public props: T['id'] extends string\n ? T extends BaseUIComponent<infer P, any, any>\n ? P & { id: string }\n : any\n : any;\n public type: string;\n private children: Array<{\n id: string;\n component: UIComponent<any>;\n priority: number;\n className?: string;\n }> = [];\n private registry: Record<\n string,\n (\n props: any,\n children: (options?: childrenFunctionOptions) => any[],\n context?: Record<string, any>,\n ) => any\n >;\n private updateCallbacks: (() => void)[] = [];\n private hadUpdateBeforeListeners = false;\n\n constructor(\n componentConfig: T,\n registry: Record<\n string,\n (\n props: any,\n children: (options?: childrenFunctionOptions) => any[],\n context?: Record<string, any>,\n ) => any\n >,\n ) {\n this.componentConfig = componentConfig;\n\n const props = componentConfig.props || {};\n\n if (typeof props === 'function') {\n const initialProps = props(componentConfig.initialState);\n this.props = { ...initialProps, id: componentConfig.id };\n } else {\n this.props = { ...props, id: componentConfig.id };\n }\n\n this.type = componentConfig.type;\n this.registry = registry;\n }\n\n addChild(id: string, child: UIComponent<any>, priority: number = 0, className?: string) {\n this.children.push({ id, component: child, priority, className });\n // Sort children by priority\n this.sortChildren();\n }\n\n // Helper to sort children by priority\n private sortChildren() {\n this.children.sort((a, b) => a.priority - b.priority);\n }\n\n removeChild(child: UIComponent<any>) {\n this.children = this.children.filter((c) => c.component !== child);\n }\n\n clearChildren() {\n this.children = [];\n }\n\n get getRenderType() {\n return this.componentConfig.render || this.type;\n }\n\n public getRenderer() {\n return this.registry[this.getRenderType];\n }\n\n public getChildren() {\n return this.children;\n }\n\n // Optionally, a component can provide a function to extend the context for its children.\n // For instance, a header could supply a \"direction\" based on its position.\n public getChildContext(context: Record<string, any>): Record<string, any> {\n const childContextProp = this.componentConfig.getChildContext;\n if (typeof childContextProp === 'function') {\n // Handle function case (existing behavior)\n return { ...context, ...childContextProp(this.props) };\n } else if (childContextProp && typeof childContextProp === 'object') {\n // Handle object case\n return { ...context, ...childContextProp };\n }\n return context;\n }\n\n update(newProps: Partial<T extends BaseUIComponent<infer P, any, any> ? P : any>) {\n const { id, ...otherProps } = newProps;\n this.props = { ...this.props, ...otherProps };\n if (this.updateCallbacks.length === 0) {\n this.hadUpdateBeforeListeners = true;\n }\n this.notifyUpdate();\n }\n\n onUpdate(callback: () => void) {\n this.updateCallbacks.push(callback);\n return this.hadUpdateBeforeListeners;\n }\n\n offUpdate(callback: () => void) {\n this.updateCallbacks = this.updateCallbacks.filter((cb) => cb !== callback);\n }\n\n protected notifyUpdate() {\n this.updateCallbacks.forEach((cb) => cb());\n }\n}\n","import { Action } from '@embedpdf/core';\nimport { UIPluginState } from './types';\n\nexport const UI_INIT_COMPONENTS = 'UI_INIT_COMPONENTS';\nexport const UI_INIT_FLYOUT = 'UI_INIT_FLYOUT';\nexport const UI_TOGGLE_FLYOUT = 'UI_TOGGLE_FLYOUT';\nexport const UI_SET_HEADER_VISIBLE = 'UI_SET_HEADER_VISIBLE';\nexport const UI_TOGGLE_PANEL = 'UI_TOGGLE_PANEL';\nexport const UI_SHOW_COMMAND_MENU = 'UI_SHOW_COMMAND_MENU';\nexport const UI_HIDE_COMMAND_MENU = 'UI_HIDE_COMMAND_MENU';\nexport const UI_UPDATE_COMMAND_MENU = 'UI_UPDATE_COMMAND_MENU';\nexport const UI_UPDATE_COMPONENT_STATE = 'UI_UPDATE_COMPONENT_STATE';\n\nexport interface InitFlyoutPayload {\n id: string;\n triggerElement: HTMLElement;\n}\n\nexport interface ToggleFlyoutPayload {\n id: string;\n open?: boolean;\n}\n\nexport interface SetHeaderVisiblePayload {\n id: string;\n visible: boolean;\n visibleChild?: string;\n}\n\nexport interface TogglePanelPayload {\n id: string;\n open?: boolean;\n visibleChild: string;\n}\n\nexport interface ShowCommandMenuPayload {\n id: string;\n commandId: string;\n triggerElement?: HTMLElement;\n position?: 'top' | 'bottom' | 'left' | 'right';\n flatten?: boolean;\n}\n\nexport interface UpdateComponentStatePayload<T = any> {\n /** one of the top-level keys inside UIPluginState, e.g. \"panel\" | \"custom\" … */\n componentType: keyof UIPluginState;\n /** same id you used when registering the component */\n componentId: string;\n /** partial patch – only keys existing in the current state will be applied */\n patch: Partial<T>;\n}\n\nexport interface HideCommandMenuPayload {\n id: string;\n}\n\nexport interface UiInitComponentsAction extends Action {\n type: typeof UI_INIT_COMPONENTS;\n payload: UIPluginState;\n}\n\nexport interface UiInitFlyoutAction extends Action {\n type: typeof UI_INIT_FLYOUT;\n payload: InitFlyoutPayload;\n}\n\nexport interface UiToggleFlyoutAction extends Action {\n type: typeof UI_TOGGLE_FLYOUT;\n payload: ToggleFlyoutPayload;\n}\n\nexport interface UiSetHeaderVisibleAction extends Action {\n type: typeof UI_SET_HEADER_VISIBLE;\n payload: SetHeaderVisiblePayload;\n}\n\nexport interface UiTogglePanelAction extends Action {\n type: typeof UI_TOGGLE_PANEL;\n payload: TogglePanelPayload;\n}\n\nexport interface UiShowCommandMenuAction extends Action {\n type: typeof UI_SHOW_COMMAND_MENU;\n payload: ShowCommandMenuPayload;\n}\n\nexport interface UiHideCommandMenuAction extends Action {\n type: typeof UI_HIDE_COMMAND_MENU;\n payload: HideCommandMenuPayload;\n}\n\nexport interface UiUpdateComponentStateAction extends Action {\n type: typeof UI_UPDATE_COMPONENT_STATE;\n payload: UpdateComponentStatePayload;\n}\n\nexport type UIPluginAction =\n | UiInitComponentsAction\n | UiInitFlyoutAction\n | UiToggleFlyoutAction\n | UiSetHeaderVisibleAction\n | UiTogglePanelAction\n | UiShowCommandMenuAction\n | UiHideCommandMenuAction\n | UiUpdateComponentStateAction;\n\nexport const uiInitComponents = (state: UIPluginState): UiInitComponentsAction => ({\n type: UI_INIT_COMPONENTS,\n payload: state,\n});\n\nexport const uiInitFlyout = (payload: InitFlyoutPayload): UiInitFlyoutAction => ({\n type: UI_INIT_FLYOUT,\n payload,\n});\n\nexport const uiToggleFlyout = (payload: ToggleFlyoutPayload): UiToggleFlyoutAction => ({\n type: UI_TOGGLE_FLYOUT,\n payload,\n});\n\nexport const uiTogglePanel = (payload: TogglePanelPayload): UiTogglePanelAction => ({\n type: UI_TOGGLE_PANEL,\n payload,\n});\n\nexport const uiSetHeaderVisible = (payload: SetHeaderVisiblePayload): UiSetHeaderVisibleAction => ({\n type: UI_SET_HEADER_VISIBLE,\n payload,\n});\n\nexport const uiShowCommandMenu = (payload: ShowCommandMenuPayload): UiShowCommandMenuAction => ({\n type: UI_SHOW_COMMAND_MENU,\n payload,\n});\n\nexport const uiHideCommandMenu = (payload: HideCommandMenuPayload): UiHideCommandMenuAction => ({\n type: UI_HIDE_COMMAND_MENU,\n payload,\n});\n\nexport const uiUpdateComponentState = <T>(\n payload: UpdateComponentStatePayload<T>,\n): UiUpdateComponentStateAction => ({\n type: UI_UPDATE_COMPONENT_STATE,\n payload,\n});\n","import { Reducer } from '@embedpdf/core';\nimport { UIPluginState } from './types';\nimport {\n UI_HIDE_COMMAND_MENU,\n UI_INIT_COMPONENTS,\n UI_SET_HEADER_VISIBLE,\n UI_SHOW_COMMAND_MENU,\n UI_TOGGLE_PANEL,\n UI_UPDATE_COMPONENT_STATE,\n UIPluginAction,\n} from './actions';\n\nexport const initialState: UIPluginState = {\n panel: {},\n header: {},\n groupedItems: {},\n divider: {},\n iconButton: {},\n tabButton: {},\n selectButton: {},\n custom: {},\n floating: {},\n commandMenu: {},\n};\n\nexport const uiReducer: Reducer<UIPluginState, UIPluginAction> = (state = initialState, action) => {\n switch (action.type) {\n case UI_INIT_COMPONENTS:\n return {\n ...state,\n ...action.payload,\n };\n case UI_TOGGLE_PANEL: {\n const prevPanel = state.panel[action.payload.id] || {};\n const { open: nextOpen, visibleChild: nextVisibleChild } = action.payload;\n const prevVisibleChild = prevPanel.visibleChild;\n\n let open = prevPanel.open;\n let visibleChild = prevPanel.visibleChild;\n\n if (nextVisibleChild === prevVisibleChild) {\n // Toggle open if visibleChild is the same\n open = nextOpen !== undefined ? nextOpen : !prevPanel.open;\n } else {\n // Only change visibleChild, keep open as is\n visibleChild = nextVisibleChild;\n open = true;\n }\n\n return {\n ...state,\n panel: {\n ...state.panel,\n [action.payload.id]: {\n ...prevPanel,\n open,\n visibleChild,\n },\n },\n };\n }\n case UI_SET_HEADER_VISIBLE:\n return {\n ...state,\n header: {\n ...state.header,\n [action.payload.id]: {\n ...state.header[action.payload.id],\n visible: action.payload.visible,\n visibleChild: action.payload.visibleChild,\n },\n },\n };\n case UI_SHOW_COMMAND_MENU:\n return {\n ...state,\n commandMenu: {\n ...state.commandMenu,\n [action.payload.id]: {\n activeCommand: action.payload.commandId,\n triggerElement: action.payload.triggerElement,\n position: action.payload.position,\n open: true,\n flatten: action.payload.flatten,\n },\n },\n };\n case UI_HIDE_COMMAND_MENU:\n return {\n ...state,\n commandMenu: {\n ...state.commandMenu,\n [action.payload.id]: {\n ...state.commandMenu[action.payload.id],\n open: false,\n activeCommand: null,\n triggerElement: undefined,\n position: undefined,\n flatten: false,\n },\n },\n };\n case UI_UPDATE_COMPONENT_STATE: {\n const { componentType, componentId, patch } = action.payload;\n\n // if the slice or the component is unknown → ignore\n if (!state[componentType] || !state[componentType][componentId]) return state;\n\n const current = state[componentType][componentId] as Record<string, any>;\n\n // keep only keys that already exist\n const filteredPatch = Object.fromEntries(Object.entries(patch).filter(([k]) => k in current));\n\n // no allowed keys? -> no-op\n if (Object.keys(filteredPatch).length === 0) return state;\n\n return {\n ...state,\n [componentType]: {\n ...state[componentType],\n [componentId]: {\n ...current,\n ...filteredPatch,\n },\n },\n };\n }\n default:\n return state;\n }\n};\n","import type { CustomComponent } from './types';\n\nexport function defineComponent<TInit, TProps, TStore = any>() {\n return <\n C extends CustomComponent<TStore> & {\n initialState: TInit;\n props: (init: TInit) => TProps;\n mapStateToProps: (storeState: TStore, ownProps: TProps) => TProps;\n },\n >(\n c: C,\n ) => c;\n}\n\n/**\n * Type definition for event callbacks\n */\nexport type EventCallback = (data: any) => void;\n\n/**\n * Interface for the event controller\n */\nexport interface EventController {\n /**\n * Emit an event of the specified type with the given data\n */\n emit(eventType: string, data: any): void;\n\n /**\n * Subscribe to events of the specified type\n * Returns a function that can be called to unsubscribe\n */\n on(eventType: string, callback: EventCallback): () => void;\n\n /**\n * Unsubscribe a specific callback from events of the specified type\n */\n off(eventType: string, callback: EventCallback): void;\n}\n\n/**\n * Creates an event controller that manages event subscriptions and dispatching\n * This is a lightweight pub/sub implementation for typed events\n */\nexport function createEventController(): EventController {\n // Map of event types to sets of callbacks\n const eventMap = new Map<string, Set<EventCallback>>();\n\n return {\n emit(eventType: string, data: any): void {\n const callbacks = eventMap.get(eventType);\n if (callbacks) {\n // Call each callback with the event data\n callbacks.forEach((callback) => callback(data));\n }\n },\n\n on(eventType: string, callback: EventCallback): () => void {\n // Create a set for this event type if it doesn't exist\n if (!eventMap.has(eventType)) {\n eventMap.set(eventType, new Set());\n }\n\n // Add the callback to the set\n const callbacks = eventMap.get(eventType)!;\n callbacks.add(callback);\n\n // Return a function that removes this specific callback\n return () => this.off(eventType, callback);\n },\n\n off(eventType: string, callback: EventCallback): void {\n const callbacks = eventMap.get(eventType);\n if (callbacks) {\n // Remove the callback from the set\n callbacks.delete(callback);\n\n // Clean up empty sets\n if (callbacks.size === 0) {\n eventMap.delete(eventType);\n }\n }\n },\n };\n}\n","import { MenuItem, Dynamic, ResolvedMenuItem } from './types';\n\nexport function resolveMenuItem<TStore>(\n item: MenuItem<TStore>,\n state: TStore,\n): ResolvedMenuItem<TStore> {\n const dyn = <T>(v: Dynamic<TStore, T> | undefined): T | undefined =>\n typeof v === 'function' ? (v as any)(state) : v;\n\n if (item.type === 'group') {\n return {\n ...item,\n label: dyn(item.label) ?? '',\n };\n }\n\n // spread keeps unknown keys (e.g. children) intact\n return {\n ...item,\n icon: dyn(item.icon) ?? '',\n label: dyn(item.label) ?? '',\n visible: dyn(item.visible) ?? true,\n active: dyn(item.active) ?? false,\n disabled: dyn(item.disabled) ?? false,\n };\n}\n\nexport function isActive<TStore>(item: MenuItem<TStore>, state: TStore): boolean {\n const resolved = resolveMenuItem(item, state);\n\n if (resolved.type === 'group') {\n return false;\n }\n\n return resolved.active ? true : false;\n}\n\nexport function isVisible<TStore>(item: MenuItem<TStore>, state: TStore): boolean {\n const resolved = resolveMenuItem(item, state);\n\n if (resolved.type === 'group') {\n return false;\n }\n\n return resolved.visible ? true : false;\n}\n\nexport function isDisabled<TStore>(item: MenuItem<TStore>, state: TStore): boolean {\n const resolved = resolveMenuItem(item, state);\n\n if (resolved.type === 'group') {\n return false;\n }\n\n return resolved.disabled ? true : false;\n}\n","import { PluginRegistry } from '@embedpdf/core';\nimport {\n MenuItem,\n Action,\n ExecuteOptions,\n ResolvedMenuItem,\n MenuRegistry,\n Menu,\n MenuManagerCapabilities,\n ResolvedMenuItemResult,\n ResolvedMenu,\n ResolvedAction,\n} from './types';\nimport { EventCallback, createEventController } from '../utils';\nimport { resolveMenuItem } from './utils';\n\n/**\n * MenuManager manages a registry of menu items and handles their execution.\n * It also manages keyboard shortcuts and implements responsive behavior.\n */\nexport class MenuManager {\n private registry: MenuRegistry = {};\n private shortcutMap: Record<string, string> = {}; // maps shortcut to menu item id\n private eventController = createEventController();\n private pluginRegistry: PluginRegistry;\n\n // Event types\n static readonly EVENTS = {\n COMMAND_EXECUTED: 'menu:command_executed',\n MENU_REQUESTED: 'menu:requested',\n SHORTCUT_EXECUTED: 'menu:shortcut_executed',\n };\n\n constructor(items: MenuRegistry = {}, pluginRegistry: PluginRegistry) {\n this.pluginRegistry = pluginRegistry;\n this.registerItems(items);\n this.setupKeyboardListeners();\n }\n\n /**\n * Get the current state of the plugin registry\n */\n private get state() {\n return this.pluginRegistry.getStore().getState();\n }\n\n /**\n * Register a single menu item\n */\n registerItem(item: MenuItem): void {\n if (this.registry[item.id]) {\n console.warn(`Menu item with ID ${item.id} already exists and will be overwritten`);\n }\n\n this.registry[item.id] = item;\n\n if ('shortcut' in item && item.shortcut) {\n this.shortcutMap[this.normalizeShortcut(item.shortcut)] = item.id;\n }\n }\n\n /**\n * Register multiple menu items at once\n */\n registerItems(items: MenuRegistry): void {\n Object.values(items).forEach((item) => {\n this.registerItem(item);\n });\n }\n\n /**\n * Resolve a menu item by ID\n */\n public resolve(id: string): ResolvedMenuItem {\n const raw = this.registry[id];\n return resolveMenuItem(raw, this.state);\n }\n\n /**\n * Get a menu item by ID with type information\n */\n getMenuItem(id: string): ResolvedMenuItemResult | undefined {\n const item = this.resolve(id);\n if (!item) return undefined;\n\n return {\n item,\n isGroup: item.type === 'group',\n isMenu: item.type === 'menu',\n isAction: item.type === 'action',\n };\n }\n\n /**\n * Get a action by ID (only returns Action type items)\n */\n getAction(id: string): ResolvedAction | undefined {\n const resolved = this.getMenuItem(id);\n if (!resolved || !resolved.isAction) return undefined;\n return resolved.item as ResolvedAction;\n }\n\n /**\n * Get menu or action by ID\n */\n getMenuOrAction(id: string): ResolvedMenu | ResolvedAction | undefined {\n const resolved = this.getMenuItem(id);\n if (!resolved) return undefined;\n return resolved.item as ResolvedMenu | ResolvedAction;\n }\n\n /**\n * Get all registered menu items\n */\n getAllItems(): MenuRegistry {\n return { ...this.registry };\n }\n\n /**\n * Get menu items by their IDs\n */\n getItemsByIds(ids: string[]): MenuItem[] {\n return ids.map((id) => this.resolve(id)).filter((item) => item !== undefined) as MenuItem[];\n }\n\n /**\n * Get child items for a given menu ID\n * If flatten is true, it will recursively include submenu children but not groups\n */\n getChildItems(menuId: string, options: { flatten?: boolean } = {}): MenuItem[] {\n const item = this.resolve(menuId);\n if (!item || !('children' in item) || !item.children?.length) {\n return [];\n }\n\n // Get all immediate children\n const children = this.getItemsByIds(item.children);\n\n // If flatten is false or not specified, return immediate children\n if (!options.flatten) {\n return children;\n }\n\n // If flatten is true, recursively include menu children\n const flattened: MenuItem[] = [];\n\n for (const child of children) {\n if (child.type === 'group') {\n // For groups, add the group itself but don't flatten its children\n flattened.push(child);\n } else if (child.type === 'menu') {\n // For menus, recursively flatten their children\n const menuChildren = this.getChildItems(child.id, { flatten: true });\n flattened.push(...menuChildren);\n } else {\n // For commands, add them directly\n flattened.push(child);\n }\n }\n\n return flattened;\n }\n\n /**\n * Execute a command by ID\n */\n executeCommand(id: string, options: ExecuteOptions = {}): void {\n const resolved = this.getMenuItem(id);\n if (!resolved) {\n console.warn(`Menu item '${id}' not found`);\n return;\n }\n if (resolved.item.type === 'group') {\n console.warn(`Cannot execute group '${id}'`);\n return;\n }\n\n const { item } = resolved;\n\n if (item.disabled) {\n console.warn(`Menu item '${id}' is disabled`);\n return;\n }\n\n if (resolved.isAction) {\n // Execute the command's action\n (item as Action).action(this.pluginRegistry, this.state);\n this.eventController.emit(MenuManager.EVENTS.COMMAND_EXECUTED, {\n command: item,\n source: options.source || 'api',\n });\n } else if ('children' in item && item.children?.length) {\n // Handle submenu\n this.handleSubmenu(item, options);\n }\n }\n\n /**\n * Execute a command from a keyboard shortcut\n */\n executeShortcut(shortcut: string): boolean {\n const normalizedShortcut = this.normalizeShortcut(shortcut);\n const itemId = this.shortcutMap[normalizedShortcut];\n\n if (itemId) {\n this.executeCommand(itemId, { source: 'shortcut' });\n this.eventController.emit(MenuManager.EVENTS.SHORTCUT_EXECUTED, {\n shortcut: normalizedShortcut,\n itemId,\n });\n return true;\n }\n return false;\n }\n\n /**\n * Subscribe to menu events\n */\n on(eventType: string, callback: EventCallback): () => void {\n return this.eventController.on(eventType, callback);\n }\n\n /**\n * Remove an event subscription\n */\n off(eventType: string, callback: EventCallback): void {\n this.eventController.off(eventType, callback);\n }\n\n /**\n * Handle a menu item that has children (showing a submenu)\n */\n private handleSubmenu(menuItem: MenuItem, options: ExecuteOptions): void {\n this.eventController.emit(MenuManager.EVENTS.MENU_REQUESTED, {\n menuId: menuItem.id,\n triggerElement: options.triggerElement,\n position: options.position,\n flatten: options.flatten || false,\n });\n }\n\n /**\n * Set up keyboard listeners for shortcuts\n */\n private setupKeyboardListeners(): void {\n if (typeof window === 'undefined') return;\n\n const handleKeyDown = (event: KeyboardEvent) => {\n // Don't handle shortcuts if the event target is an input, textarea, or has contentEditable\n const target = event.target as HTMLElement;\n if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.isContentEditable) {\n return;\n }\n\n const shortcut = this.buildShortcutString(event);\n if (shortcut && this.executeShortcut(shortcut)) {\n event.preventDefault();\n }\n };\n\n document.addEventListener('keydown', handleKeyDown);\n }\n\n /**\n * Convert a KeyboardEvent to a shortcut string\n */\n private buildShortcutString(event: KeyboardEvent): string | null {\n const modifiers: string[] = [];\n if (event.ctrlKey) modifiers.push('Ctrl');\n if (event.shiftKey) modifiers.push('Shift');\n if (event.altKey) modifiers.push('Alt');\n if (event.metaKey) modifiers.push('Meta');\n\n // Only add non-modifier keys\n const key = event.key;\n const isModifier = ['Control', 'Shift', 'Alt', 'Meta'].includes(key);\n if (!isModifier) {\n // Handle special case for uppercase letters\n const displayKey = key.length === 1 ? key.toUpperCase() : key;\n return [...modifiers, displayKey].join('+');\n }\n\n return null;\n }\n\n /**\n * Normalize a shortcut string for consistent comparison\n */\n private normalizeShortcut(shortcut: string): string {\n return shortcut\n .split('+')\n .map((part) => part.trim())\n .join('+');\n }\n\n /**\n * Get capabilities for the MenuManager\n */\n capabilities(): MenuManagerCapabilities {\n return {\n registerItem: this.registerItem.bind(this),\n registerItems: this.registerItems.bind(this),\n executeCommand: this.executeCommand.bind(this),\n getAction: this.getAction.bind(this),\n getMenuOrAction: this.getMenuOrAction.bind(this),\n getChildItems: this.getChildItems.bind(this),\n getItemsByIds: this.getItemsByIds.bind(this),\n getAllItems: this.getAllItems.bind(this),\n };\n }\n}\n","import { Icon, IconCapabilities, IconIdentifier, IconRegistry } from './types';\n\n/**\n * Registry for managing icons throughout the application\n */\nexport class IconManager {\n private icons: IconRegistry = {};\n\n constructor(icons: Icon[] | IconRegistry) {\n this.registerIcons(icons);\n }\n\n /**\n * Register a single icon\n */\n public registerIcon(icon: Icon): void {\n if (this.icons[icon.id]) {\n console.warn(`Icon with ID ${icon.id} already exists and will be overwritten`);\n }\n this.icons[icon.id] = icon;\n }\n\n /**\n * Register multiple icons at once\n */\n public registerIcons(icons: Icon[] | IconRegistry): void {\n if (Array.isArray(icons)) {\n icons.forEach((icon) => this.registerIcon(icon));\n } else {\n Object.entries(icons).forEach(([id, icon]) => this.registerIcon(icon));\n }\n }\n\n /**\n * Get all registered icons\n */\n public getAllIcons(): IconRegistry {\n return { ...this.icons };\n }\n\n /**\n * Get an icon by its ID\n */\n public getIcon(id: string): Icon | undefined {\n return this.icons[id];\n }\n\n /**\n * Check if an identifier is an SVG string\n */\n public isSvgString(identifier: IconIdentifier): boolean {\n return identifier.trim().startsWith('<svg') && identifier.includes('</svg>');\n }\n\n /**\n * Check if a string is an SVG data URI\n */\n public isSvgDataUri(value: string): boolean {\n return value.startsWith('data:image/svg+xml;base64,');\n }\n\n /**\n * Get the SVG string for an icon identifier\n * If the identifier is a raw SVG string, it is returned as is\n * If the identifier is an icon ID, the registered SVG is returned\n */\n public getSvgString(identifier: IconIdentifier): string | undefined {\n if (this.isSvgString(identifier)) {\n return identifier;\n }\n if (this.isSvgDataUri(identifier)) {\n return this.dataUriToSvgString(identifier);\n }\n return this.getIcon(identifier)?.svg;\n }\n\n /**\n * Utility method to parse a data URI\n */\n public dataUriToSvgString(dataUri: string): string {\n const base64 = dataUri.substring('data:image/svg+xml;base64,'.length);\n return atob(base64);\n }\n\n /**\n * Convert an SVG string to a data URI\n */\n public svgStringToDataUri(svgString: string): string {\n const base64 = btoa(svgString);\n return `data:image/svg+xml;base64,${base64}`;\n }\n\n capabilities(): IconCapabilities {\n return {\n registerIcon: this.registerIcon.bind(this),\n registerIcons: this.registerIcons.bind(this),\n getIcon: this.getIcon.bind(this),\n getAllIcons: this.getAllIcons.bind(this),\n getSvgString: this.getSvgString.bind(this),\n isSvgString: this.isSvgString.bind(this),\n isSvgDataUri: this.isSvgDataUri.bind(this),\n dataUriToSvgString: this.dataUriToSvgString.bind(this),\n svgStringToDataUri: this.svgStringToDataUri.bind(this),\n };\n }\n}\n","import { PluginManifest } from '@embedpdf/core';\nimport { UIPluginConfig } from './types';\n\nexport const UI_PLUGIN_ID = 'ui';\n\nexport const manifest: PluginManifest<UIPluginConfig> = {\n id: UI_PLUGIN_ID,\n name: 'UI Plugin',\n version: '1.0.0',\n provides: ['ui'],\n requires: [],\n optional: [],\n defaultConfig: {\n enabled: true,\n components: {},\n },\n};\n","import { PluginRegistry } from '@embedpdf/core';\n\nexport type Dynamic<TStore, T> = T | ((state: TStore) => T);\n\nexport interface MenuItemBase<TStore = any> {\n icon?: Dynamic<TStore, string>;\n label: Dynamic<TStore, string>;\n active?: Dynamic<TStore, boolean>; // whether command is currently active\n disabled?: Dynamic<TStore, boolean>; // whether command is currently disabled\n shortcut?: string; // \"Ctrl+Plus\"\n shortcutLabel?: string; // \"Ctrl+Plus\"\n visible?: Dynamic<TStore, boolean>; // whether command should be visible\n dividerBefore?: boolean; // whether to add a divider before the command\n}\n\nexport interface Action<TStore = any> extends MenuItemBase<TStore> {\n id: string; // \"zoomIn\"\n type: 'action'; // i18n key or literal\n action: (registry: PluginRegistry, state: TStore) => void; // executed onClick // whether to add a divider before the command\n}\n\nexport interface Group<TStore = any> {\n id: string;\n type: 'group';\n label: Dynamic<TStore, string>;\n children: string[];\n}\n\nexport interface Menu<TStore = any> extends MenuItemBase<TStore> {\n id: string;\n type: 'menu';\n children: string[];\n}\n\nexport type MenuItem<TStore = any> = Action<TStore> | Group | Menu<TStore>;\n\nexport type MenuRegistry = Record<string, MenuItem>;\n\n// Options for executing an action\nexport interface ExecuteOptions {\n source?: 'click' | 'shortcut' | 'api';\n triggerElement?: HTMLElement;\n flatten?: boolean;\n position?: 'top' | 'bottom' | 'left' | 'right';\n}\n\nexport function hasActive<TStore>(command: MenuItem<TStore>): command is Action<TStore> {\n return 'active' in command;\n}\n\nexport interface MenuManagerCapabilities {\n registerItem: (commandItem: MenuItem) => void;\n registerItems: (commands: MenuRegistry) => void;\n executeCommand: (id: string, options?: ExecuteOptions) => void;\n getAction: (id: string) => ResolvedAction | undefined;\n getMenuOrAction: (id: string) => ResolvedMenu | ResolvedAction | undefined;\n getChildItems: (commandId: string, options?: { flatten?: boolean }) => ResolvedMenuItem[];\n getItemsByIds: (ids: string[]) => ResolvedMenuItem[];\n getAllItems: () => MenuRegistry;\n}\n\n// Add these new resolved types after the existing interfaces\nexport type Resolved<TStore, T> = T extends Dynamic<TStore, infer U> ? U : T;\n\nexport interface ResolvedMenuItemBase<TStore = any> {\n icon?: string;\n label: string;\n active?: boolean;\n disabled?: boolean;\n shortcut?: string;\n shortcutLabel?: string;\n visible?: boolean;\n dividerBefore?: boolean;\n}\n\nexport interface ResolvedAction<TStore = any> extends ResolvedMenuItemBase<TStore> {\n id: string;\n type: 'action';\n action: (registry: PluginRegistry, state: TStore) => void;\n}\n\nexport interface ResolvedGroup<TStore = any> {\n id: string;\n type: 'group';\n label: string;\n children: string[];\n}\n\nexport interface ResolvedMenu<TStore = any> extends ResolvedMenuItemBase<TStore> {\n id: string;\n type: 'menu';\n children: string[];\n}\n\nexport type ResolvedMenuItem<TStore = any> =\n | ResolvedAction<TStore>\n | ResolvedGroup<TStore>\n | ResolvedMenu<TStore>;\n\n// Result of menu item resolution\nexport interface ResolvedMenuItemResult<TStore = any> {\n item: ResolvedMenuItem<TStore>;\n isGroup: boolean;\n isMenu: boolean;\n isAction: boolean;\n}\n","import { PluginPackage } from '@embedpdf/core';\nimport { UIPlugin } from './ui-plugin';\nimport { manifest, UI_PLUGIN_ID } from './manifest';\nimport { UIPluginConfig, UIPluginState } from './types';\nimport { uiReducer, initialState } from './reducer';\nimport { UIPluginAction } from './actions';\n\nexport const UIPluginPackage: PluginPackage<\n UIPlugin,\n UIPluginConfig,\n UIPluginState,\n UIPluginAction\n> = {\n manifest,\n create: (registry, _engine, config) => new UIPlugin(UI_PLUGIN_ID, registry, config!),\n reducer: uiReducer,\n initialState,\n};\n\nexport * from './manifest';\nexport * from './ui-plugin';\nexport * from './types';\nexport * from './ui-component';\nexport * from './utils';\nexport * from './menu/types';\nexport * from './icons/types';\nexport * from './menu/utils';\n"],"mappings":"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","names":[]}
1
+ {"version":3,"file":"index.js","sources":["../src/lib/ui-component.ts","../src/lib/actions.ts","../src/lib/reducer.ts","../src/lib/utils.ts","../src/lib/menu/utils.ts","../src/lib/menu/menu-manager.ts","../src/lib/icons/icon-manager.ts","../src/lib/ui-plugin.ts","../src/lib/manifest.ts","../src/lib/menu/types.ts","../src/lib/index.ts"],"sourcesContent":["import { BaseUIComponent, childrenFunctionOptions } from './types';\n\nexport class UIComponent<T extends BaseUIComponent<any, any, any>> {\n public componentConfig: T;\n public props: T['id'] extends string\n ? T extends BaseUIComponent<infer P, any, any>\n ? P & { id: string }\n : any\n : any;\n public type: string;\n private children: Array<{\n id: string;\n component: UIComponent<any>;\n priority: number;\n className?: string;\n }> = [];\n private registry: Record<\n string,\n (\n props: any,\n children: (options?: childrenFunctionOptions) => any[],\n context?: Record<string, any>,\n ) => any\n >;\n private updateCallbacks: (() => void)[] = [];\n private hadUpdateBeforeListeners = false;\n\n constructor(\n componentConfig: T,\n registry: Record<\n string,\n (\n props: any,\n children: (options?: childrenFunctionOptions) => any[],\n context?: Record<string, any>,\n ) => any\n >,\n ) {\n this.componentConfig = componentConfig;\n\n const props = componentConfig.props || {};\n\n if (typeof props === 'function') {\n const initialProps = props(componentConfig.initialState);\n this.props = { ...initialProps, id: componentConfig.id };\n } else {\n this.props = { ...props, id: componentConfig.id };\n }\n\n this.type = componentConfig.type;\n this.registry = registry;\n }\n\n addChild(id: string, child: UIComponent<any>, priority: number = 0, className?: string) {\n this.children.push({ id, component: child, priority, className });\n // Sort children by priority\n this.sortChildren();\n }\n\n // Helper to sort children by priority\n private sortChildren() {\n this.children.sort((a, b) => a.priority - b.priority);\n }\n\n removeChild(child: UIComponent<any>) {\n this.children = this.children.filter((c) => c.component !== child);\n }\n\n clearChildren() {\n this.children = [];\n }\n\n get getRenderType() {\n return this.componentConfig.render || this.type;\n }\n\n public getRenderer() {\n return this.registry[this.getRenderType];\n }\n\n public getChildren() {\n return this.children;\n }\n\n // Optionally, a component can provide a function to extend the context for its children.\n // For instance, a header could supply a \"direction\" based on its position.\n public getChildContext(context: Record<string, any>): Record<string, any> {\n const childContextProp = this.componentConfig.getChildContext;\n if (typeof childContextProp === 'function') {\n // Handle function case (existing behavior)\n return { ...context, ...childContextProp(this.props) };\n } else if (childContextProp && typeof childContextProp === 'object') {\n // Handle object case\n return { ...context, ...childContextProp };\n }\n return context;\n }\n\n update(newProps: Partial<T extends BaseUIComponent<infer P, any, any> ? P : any>) {\n const { id, ...otherProps } = newProps;\n this.props = { ...this.props, ...otherProps };\n if (this.updateCallbacks.length === 0) {\n this.hadUpdateBeforeListeners = true;\n }\n this.notifyUpdate();\n }\n\n onUpdate(callback: () => void) {\n this.updateCallbacks.push(callback);\n return this.hadUpdateBeforeListeners;\n }\n\n offUpdate(callback: () => void) {\n this.updateCallbacks = this.updateCallbacks.filter((cb) => cb !== callback);\n }\n\n protected notifyUpdate() {\n this.updateCallbacks.forEach((cb) => cb());\n }\n}\n","import { Action } from '@embedpdf/core';\nimport { UIPluginState } from './types';\n\nexport const UI_INIT_COMPONENTS = 'UI_INIT_COMPONENTS';\nexport const UI_INIT_FLYOUT = 'UI_INIT_FLYOUT';\nexport const UI_TOGGLE_FLYOUT = 'UI_TOGGLE_FLYOUT';\nexport const UI_SET_HEADER_VISIBLE = 'UI_SET_HEADER_VISIBLE';\nexport const UI_TOGGLE_PANEL = 'UI_TOGGLE_PANEL';\nexport const UI_SHOW_COMMAND_MENU = 'UI_SHOW_COMMAND_MENU';\nexport const UI_HIDE_COMMAND_MENU = 'UI_HIDE_COMMAND_MENU';\nexport const UI_UPDATE_COMMAND_MENU = 'UI_UPDATE_COMMAND_MENU';\nexport const UI_UPDATE_COMPONENT_STATE = 'UI_UPDATE_COMPONENT_STATE';\n\nexport interface InitFlyoutPayload {\n id: string;\n triggerElement: HTMLElement;\n}\n\nexport interface ToggleFlyoutPayload {\n id: string;\n open?: boolean;\n}\n\nexport interface SetHeaderVisiblePayload {\n id: string;\n visible: boolean;\n visibleChild?: string;\n}\n\nexport interface TogglePanelPayload {\n id: string;\n open?: boolean;\n visibleChild: string;\n}\n\nexport interface ShowCommandMenuPayload {\n id: string;\n commandId: string;\n triggerElement?: HTMLElement;\n position?: 'top' | 'bottom' | 'left' | 'right';\n flatten?: boolean;\n}\n\nexport interface UpdateComponentStatePayload<T = any> {\n /** one of the top-level keys inside UIPluginState, e.g. \"panel\" | \"custom\" … */\n componentType: keyof UIPluginState;\n /** same id you used when registering the component */\n componentId: string;\n /** partial patch – only keys existing in the current state will be applied */\n patch: Partial<T>;\n}\n\nexport interface HideCommandMenuPayload {\n id: string;\n}\n\nexport interface UiInitComponentsAction extends Action {\n type: typeof UI_INIT_COMPONENTS;\n payload: UIPluginState;\n}\n\nexport interface UiInitFlyoutAction extends Action {\n type: typeof UI_INIT_FLYOUT;\n payload: InitFlyoutPayload;\n}\n\nexport interface UiToggleFlyoutAction extends Action {\n type: typeof UI_TOGGLE_FLYOUT;\n payload: ToggleFlyoutPayload;\n}\n\nexport interface UiSetHeaderVisibleAction extends Action {\n type: typeof UI_SET_HEADER_VISIBLE;\n payload: SetHeaderVisiblePayload;\n}\n\nexport interface UiTogglePanelAction extends Action {\n type: typeof UI_TOGGLE_PANEL;\n payload: TogglePanelPayload;\n}\n\nexport interface UiShowCommandMenuAction extends Action {\n type: typeof UI_SHOW_COMMAND_MENU;\n payload: ShowCommandMenuPayload;\n}\n\nexport interface UiHideCommandMenuAction extends Action {\n type: typeof UI_HIDE_COMMAND_MENU;\n payload: HideCommandMenuPayload;\n}\n\nexport interface UiUpdateComponentStateAction extends Action {\n type: typeof UI_UPDATE_COMPONENT_STATE;\n payload: UpdateComponentStatePayload;\n}\n\nexport type UIPluginAction =\n | UiInitComponentsAction\n | UiInitFlyoutAction\n | UiToggleFlyoutAction\n | UiSetHeaderVisibleAction\n | UiTogglePanelAction\n | UiShowCommandMenuAction\n | UiHideCommandMenuAction\n | UiUpdateComponentStateAction;\n\nexport const uiInitComponents = (state: UIPluginState): UiInitComponentsAction => ({\n type: UI_INIT_COMPONENTS,\n payload: state,\n});\n\nexport const uiInitFlyout = (payload: InitFlyoutPayload): UiInitFlyoutAction => ({\n type: UI_INIT_FLYOUT,\n payload,\n});\n\nexport const uiToggleFlyout = (payload: ToggleFlyoutPayload): UiToggleFlyoutAction => ({\n type: UI_TOGGLE_FLYOUT,\n payload,\n});\n\nexport const uiTogglePanel = (payload: TogglePanelPayload): UiTogglePanelAction => ({\n type: UI_TOGGLE_PANEL,\n payload,\n});\n\nexport const uiSetHeaderVisible = (payload: SetHeaderVisiblePayload): UiSetHeaderVisibleAction => ({\n type: UI_SET_HEADER_VISIBLE,\n payload,\n});\n\nexport const uiShowCommandMenu = (payload: ShowCommandMenuPayload): UiShowCommandMenuAction => ({\n type: UI_SHOW_COMMAND_MENU,\n payload,\n});\n\nexport const uiHideCommandMenu = (payload: HideCommandMenuPayload): UiHideCommandMenuAction => ({\n type: UI_HIDE_COMMAND_MENU,\n payload,\n});\n\nexport const uiUpdateComponentState = <T>(\n payload: UpdateComponentStatePayload<T>,\n): UiUpdateComponentStateAction => ({\n type: UI_UPDATE_COMPONENT_STATE,\n payload,\n});\n","import { Reducer } from '@embedpdf/core';\nimport { UIPluginState } from './types';\nimport {\n UI_HIDE_COMMAND_MENU,\n UI_INIT_COMPONENTS,\n UI_SET_HEADER_VISIBLE,\n UI_SHOW_COMMAND_MENU,\n UI_TOGGLE_PANEL,\n UI_UPDATE_COMPONENT_STATE,\n UIPluginAction,\n} from './actions';\n\nexport const initialState: UIPluginState = {\n panel: {},\n header: {},\n groupedItems: {},\n divider: {},\n iconButton: {},\n tabButton: {},\n selectButton: {},\n custom: {},\n floating: {},\n commandMenu: {},\n};\n\nexport const uiReducer: Reducer<UIPluginState, UIPluginAction> = (state = initialState, action) => {\n switch (action.type) {\n case UI_INIT_COMPONENTS:\n return {\n ...state,\n ...action.payload,\n };\n case UI_TOGGLE_PANEL: {\n const prevPanel = state.panel[action.payload.id] || {};\n const { open: nextOpen, visibleChild: nextVisibleChild } = action.payload;\n const prevVisibleChild = prevPanel.visibleChild;\n\n let open = prevPanel.open;\n let visibleChild = prevPanel.visibleChild;\n\n if (nextVisibleChild === prevVisibleChild) {\n // Toggle open if visibleChild is the same\n open = nextOpen !== undefined ? nextOpen : !prevPanel.open;\n } else {\n // Only change visibleChild, keep open as is\n visibleChild = nextVisibleChild;\n open = true;\n }\n\n return {\n ...state,\n panel: {\n ...state.panel,\n [action.payload.id]: {\n ...prevPanel,\n open,\n visibleChild,\n },\n },\n };\n }\n case UI_SET_HEADER_VISIBLE:\n return {\n ...state,\n header: {\n ...state.header,\n [action.payload.id]: {\n ...state.header[action.payload.id],\n visible: action.payload.visible,\n visibleChild: action.payload.visibleChild,\n },\n },\n };\n case UI_SHOW_COMMAND_MENU:\n return {\n ...state,\n commandMenu: {\n ...state.commandMenu,\n [action.payload.id]: {\n activeCommand: action.payload.commandId,\n triggerElement: action.payload.triggerElement,\n position: action.payload.position,\n open: true,\n flatten: action.payload.flatten,\n },\n },\n };\n case UI_HIDE_COMMAND_MENU:\n return {\n ...state,\n commandMenu: {\n ...state.commandMenu,\n [action.payload.id]: {\n ...state.commandMenu[action.payload.id],\n open: false,\n activeCommand: null,\n triggerElement: undefined,\n position: undefined,\n flatten: false,\n },\n },\n };\n case UI_UPDATE_COMPONENT_STATE: {\n const { componentType, componentId, patch } = action.payload;\n\n // if the slice or the component is unknown → ignore\n if (!state[componentType] || !state[componentType][componentId]) return state;\n\n const current = state[componentType][componentId] as Record<string, any>;\n\n // keep only keys that already exist\n const filteredPatch = Object.fromEntries(Object.entries(patch).filter(([k]) => k in current));\n\n // no allowed keys? -> no-op\n if (Object.keys(filteredPatch).length === 0) return state;\n\n return {\n ...state,\n [componentType]: {\n ...state[componentType],\n [componentId]: {\n ...current,\n ...filteredPatch,\n },\n },\n };\n }\n default:\n return state;\n }\n};\n","import type { CustomComponent } from './types';\n\nexport function defineComponent<TInit, TProps, TStore = any>() {\n return <\n C extends CustomComponent<TStore> & {\n initialState: TInit;\n props: (init: TInit) => TProps;\n mapStateToProps: (storeState: TStore, ownProps: TProps) => TProps;\n },\n >(\n c: C,\n ) => c;\n}\n\n/**\n * Type definition for event callbacks\n */\nexport type EventCallback = (data: any) => void;\n\n/**\n * Interface for the event controller\n */\nexport interface EventController {\n /**\n * Emit an event of the specified type with the given data\n */\n emit(eventType: string, data: any): void;\n\n /**\n * Subscribe to events of the specified type\n * Returns a function that can be called to unsubscribe\n */\n on(eventType: string, callback: EventCallback): () => void;\n\n /**\n * Unsubscribe a specific callback from events of the specified type\n */\n off(eventType: string, callback: EventCallback): void;\n}\n\n/**\n * Creates an event controller that manages event subscriptions and dispatching\n * This is a lightweight pub/sub implementation for typed events\n */\nexport function createEventController(): EventController {\n // Map of event types to sets of callbacks\n const eventMap = new Map<string, Set<EventCallback>>();\n\n return {\n emit(eventType: string, data: any): void {\n const callbacks = eventMap.get(eventType);\n if (callbacks) {\n // Call each callback with the event data\n callbacks.forEach((callback) => callback(data));\n }\n },\n\n on(eventType: string, callback: EventCallback): () => void {\n // Create a set for this event type if it doesn't exist\n if (!eventMap.has(eventType)) {\n eventMap.set(eventType, new Set());\n }\n\n // Add the callback to the set\n const callbacks = eventMap.get(eventType)!;\n callbacks.add(callback);\n\n // Return a function that removes this specific callback\n return () => this.off(eventType, callback);\n },\n\n off(eventType: string, callback: EventCallback): void {\n const callbacks = eventMap.get(eventType);\n if (callbacks) {\n // Remove the callback from the set\n callbacks.delete(callback);\n\n // Clean up empty sets\n if (callbacks.size === 0) {\n eventMap.delete(eventType);\n }\n }\n },\n };\n}\n","import { MenuItem, Dynamic, ResolvedMenuItem } from './types';\n\nexport function resolveMenuItem<TStore>(\n item: MenuItem<TStore>,\n state: TStore,\n): ResolvedMenuItem<TStore> {\n const dyn = <T>(v: Dynamic<TStore, T> | undefined): T | undefined =>\n typeof v === 'function' ? (v as any)(state) : v;\n\n if (item.type === 'group') {\n return {\n ...item,\n label: dyn(item.label) ?? '',\n };\n }\n\n // spread keeps unknown keys (e.g. children) intact\n return {\n ...item,\n icon: dyn(item.icon) ?? '',\n label: dyn(item.label) ?? '',\n visible: dyn(item.visible) ?? true,\n active: dyn(item.active) ?? false,\n disabled: dyn(item.disabled) ?? false,\n };\n}\n\nexport function isActive<TStore>(item: MenuItem<TStore>, state: TStore): boolean {\n const resolved = resolveMenuItem(item, state);\n\n if (resolved.type === 'group') {\n return false;\n }\n\n return resolved.active ? true : false;\n}\n\nexport function isVisible<TStore>(item: MenuItem<TStore>, state: TStore): boolean {\n const resolved = resolveMenuItem(item, state);\n\n if (resolved.type === 'group') {\n return false;\n }\n\n return resolved.visible ? true : false;\n}\n\nexport function isDisabled<TStore>(item: MenuItem<TStore>, state: TStore): boolean {\n const resolved = resolveMenuItem(item, state);\n\n if (resolved.type === 'group') {\n return false;\n }\n\n return resolved.disabled ? true : false;\n}\n","import { PluginRegistry } from '@embedpdf/core';\nimport {\n MenuItem,\n Action,\n ExecuteOptions,\n ResolvedMenuItem,\n MenuRegistry,\n Menu,\n MenuManagerCapabilities,\n ResolvedMenuItemResult,\n ResolvedMenu,\n ResolvedAction,\n} from './types';\nimport { EventCallback, createEventController } from '../utils';\nimport { resolveMenuItem } from './utils';\n\n/**\n * MenuManager manages a registry of menu items and handles their execution.\n * It also manages keyboard shortcuts and implements responsive behavior.\n */\nexport class MenuManager {\n private registry: MenuRegistry = {};\n private shortcutMap: Record<string, string> = {}; // maps shortcut to menu item id\n private eventController = createEventController();\n private pluginRegistry: PluginRegistry;\n\n // Event types\n static readonly EVENTS = {\n COMMAND_EXECUTED: 'menu:command_executed',\n MENU_REQUESTED: 'menu:requested',\n SHORTCUT_EXECUTED: 'menu:shortcut_executed',\n };\n\n constructor(items: MenuRegistry = {}, pluginRegistry: PluginRegistry) {\n this.pluginRegistry = pluginRegistry;\n this.registerItems(items);\n this.setupKeyboardListeners();\n }\n\n /**\n * Get the current state of the plugin registry\n */\n private get state() {\n return this.pluginRegistry.getStore().getState();\n }\n\n /**\n * Register a single menu item\n */\n registerItem(item: MenuItem): void {\n if (this.registry[item.id]) {\n console.warn(`Menu item with ID ${item.id} already exists and will be overwritten`);\n }\n\n this.registry[item.id] = item;\n\n if ('shortcut' in item && item.shortcut) {\n this.shortcutMap[this.normalizeShortcut(item.shortcut)] = item.id;\n }\n }\n\n /**\n * Register multiple menu items at once\n */\n registerItems(items: MenuRegistry): void {\n Object.values(items).forEach((item) => {\n this.registerItem(item);\n });\n }\n\n /**\n * Resolve a menu item by ID\n */\n public resolve(id: string): ResolvedMenuItem {\n const raw = this.registry[id];\n return resolveMenuItem(raw, this.state);\n }\n\n /**\n * Get a menu item by ID with type information\n */\n getMenuItem(id: string): ResolvedMenuItemResult | undefined {\n const item = this.resolve(id);\n if (!item) return undefined;\n\n return {\n item,\n isGroup: item.type === 'group',\n isMenu: item.type === 'menu',\n isAction: item.type === 'action',\n };\n }\n\n /**\n * Get a action by ID (only returns Action type items)\n */\n getAction(id: string): ResolvedAction | undefined {\n const resolved = this.getMenuItem(id);\n if (!resolved || !resolved.isAction) return undefined;\n return resolved.item as ResolvedAction;\n }\n\n /**\n * Get menu or action by ID\n */\n getMenuOrAction(id: string): ResolvedMenu | ResolvedAction | undefined {\n const resolved = this.getMenuItem(id);\n if (!resolved) return undefined;\n return resolved.item as ResolvedMenu | ResolvedAction;\n }\n\n /**\n * Get all registered menu items\n */\n getAllItems(): MenuRegistry {\n return { ...this.registry };\n }\n\n /**\n * Get menu items by their IDs\n */\n getItemsByIds(ids: string[]): ResolvedMenuItem[] {\n return ids.map((id) => this.resolve(id)).filter((item) => item !== undefined);\n }\n\n /**\n * Get child items for a given menu ID\n * If flatten is true, it will recursively include submenu children but not groups\n */\n getChildItems(menuId: string, options: { flatten?: boolean } = {}): ResolvedMenuItem[] {\n const item = this.resolve(menuId);\n if (!item || !('children' in item) || !item.children?.length) {\n return [];\n }\n\n // Get all immediate children\n const children = this.getItemsByIds(item.children);\n\n // If flatten is false or not specified, return immediate children\n if (!options.flatten) {\n return children;\n }\n\n // If flatten is true, recursively include menu children\n const flattened: ResolvedMenuItem[] = [];\n\n for (const child of children) {\n if (child.type === 'group') {\n // For groups, add the group itself but don't flatten its children\n flattened.push(child);\n } else if (child.type === 'menu') {\n // For menus, recursively flatten their children\n const menuChildren = this.getChildItems(child.id, { flatten: true });\n flattened.push(...menuChildren);\n } else {\n // For commands, add them directly\n flattened.push(child);\n }\n }\n\n return flattened;\n }\n\n /**\n * Execute a command by ID\n */\n executeCommand(id: string, options: ExecuteOptions = {}): void {\n const resolved = this.getMenuItem(id);\n if (!resolved) {\n console.warn(`Menu item '${id}' not found`);\n return;\n }\n if (resolved.item.type === 'group') {\n console.warn(`Cannot execute group '${id}'`);\n return;\n }\n\n const { item } = resolved;\n\n if (item.disabled) {\n console.warn(`Menu item '${id}' is disabled`);\n return;\n }\n\n if (resolved.isAction) {\n // Execute the command's action\n (item as Action).action(this.pluginRegistry, this.state);\n this.eventController.emit(MenuManager.EVENTS.COMMAND_EXECUTED, {\n command: item,\n source: options.source || 'api',\n });\n } else if ('children' in item && item.children?.length) {\n // Handle submenu\n this.handleSubmenu(item, options);\n }\n }\n\n /**\n * Execute a command from a keyboard shortcut\n */\n executeShortcut(shortcut: string): boolean {\n const normalizedShortcut = this.normalizeShortcut(shortcut);\n const itemId = this.shortcutMap[normalizedShortcut];\n\n if (itemId) {\n this.executeCommand(itemId, { source: 'shortcut' });\n this.eventController.emit(MenuManager.EVENTS.SHORTCUT_EXECUTED, {\n shortcut: normalizedShortcut,\n itemId,\n });\n return true;\n }\n return false;\n }\n\n /**\n * Subscribe to menu events\n */\n on(eventType: string, callback: EventCallback): () => void {\n return this.eventController.on(eventType, callback);\n }\n\n /**\n * Remove an event subscription\n */\n off(eventType: string, callback: EventCallback): void {\n this.eventController.off(eventType, callback);\n }\n\n /**\n * Handle a menu item that has children (showing a submenu)\n */\n private handleSubmenu(menuItem: MenuItem, options: ExecuteOptions): void {\n this.eventController.emit(MenuManager.EVENTS.MENU_REQUESTED, {\n menuId: menuItem.id,\n triggerElement: options.triggerElement,\n position: options.position,\n flatten: options.flatten || false,\n });\n }\n\n /**\n * Set up keyboard listeners for shortcuts\n */\n private setupKeyboardListeners(): void {\n if (typeof window === 'undefined') return;\n\n const handleKeyDown = (event: KeyboardEvent) => {\n // Don't handle shortcuts if the event target is an input, textarea, or has contentEditable\n const target = event.target as HTMLElement;\n if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.isContentEditable) {\n return;\n }\n\n const shortcut = this.buildShortcutString(event);\n if (shortcut && this.executeShortcut(shortcut)) {\n event.preventDefault();\n }\n };\n\n document.addEventListener('keydown', handleKeyDown);\n }\n\n /**\n * Convert a KeyboardEvent to a shortcut string\n */\n private buildShortcutString(event: KeyboardEvent): string | null {\n const modifiers: string[] = [];\n if (event.ctrlKey) modifiers.push('Ctrl');\n if (event.shiftKey) modifiers.push('Shift');\n if (event.altKey) modifiers.push('Alt');\n if (event.metaKey) modifiers.push('Meta');\n\n // Only add non-modifier keys\n const key = event.key;\n const isModifier = ['Control', 'Shift', 'Alt', 'Meta'].includes(key);\n if (!isModifier) {\n // Handle special case for uppercase letters\n const displayKey = key.length === 1 ? key.toUpperCase() : key;\n return [...modifiers, displayKey].join('+');\n }\n\n return null;\n }\n\n /**\n * Normalize a shortcut string for consistent comparison\n */\n private normalizeShortcut(shortcut: string): string {\n return shortcut\n .split('+')\n .map((part) => part.trim())\n .join('+');\n }\n\n /**\n * Get capabilities for the MenuManager\n */\n capabilities(): MenuManagerCapabilities {\n return {\n registerItem: this.registerItem.bind(this),\n registerItems: this.registerItems.bind(this),\n executeCommand: this.executeCommand.bind(this),\n getAction: this.getAction.bind(this),\n getMenuOrAction: this.getMenuOrAction.bind(this),\n getChildItems: this.getChildItems.bind(this),\n getItemsByIds: this.getItemsByIds.bind(this),\n getAllItems: this.getAllItems.bind(this),\n };\n }\n}\n","import { Icon, IconCapabilities, IconIdentifier, IconRegistry } from './types';\n\n/**\n * Registry for managing icons throughout the application\n */\nexport class IconManager {\n private icons: IconRegistry = {};\n\n constructor(icons: Icon[] | IconRegistry) {\n this.registerIcons(icons);\n }\n\n /**\n * Register a single icon\n */\n public registerIcon(icon: Icon): void {\n if (this.icons[icon.id]) {\n console.warn(`Icon with ID ${icon.id} already exists and will be overwritten`);\n }\n this.icons[icon.id] = icon;\n }\n\n /**\n * Register multiple icons at once\n */\n public registerIcons(icons: Icon[] | IconRegistry): void {\n if (Array.isArray(icons)) {\n icons.forEach((icon) => this.registerIcon(icon));\n } else {\n Object.entries(icons).forEach(([id, icon]) => this.registerIcon(icon));\n }\n }\n\n /**\n * Get all registered icons\n */\n public getAllIcons(): IconRegistry {\n return { ...this.icons };\n }\n\n /**\n * Get an icon by its ID\n */\n public getIcon(id: string): Icon | undefined {\n return this.icons[id];\n }\n\n /**\n * Check if an identifier is an SVG string\n */\n public isSvgString(identifier: IconIdentifier): boolean {\n return identifier.trim().startsWith('<svg') && identifier.includes('</svg>');\n }\n\n /**\n * Check if a string is an SVG data URI\n */\n public isSvgDataUri(value: string): boolean {\n return value.startsWith('data:image/svg+xml;base64,');\n }\n\n /**\n * Get the SVG string for an icon identifier\n * If the identifier is a raw SVG string, it is returned as is\n * If the identifier is an icon ID, the registered SVG is returned\n */\n public getSvgString(identifier: IconIdentifier): string | undefined {\n if (this.isSvgString(identifier)) {\n return identifier;\n }\n if (this.isSvgDataUri(identifier)) {\n return this.dataUriToSvgString(identifier);\n }\n return this.getIcon(identifier)?.svg;\n }\n\n /**\n * Utility method to parse a data URI\n */\n public dataUriToSvgString(dataUri: string): string {\n const base64 = dataUri.substring('data:image/svg+xml;base64,'.length);\n return atob(base64);\n }\n\n /**\n * Convert an SVG string to a data URI\n */\n public svgStringToDataUri(svgString: string): string {\n const base64 = btoa(svgString);\n return `data:image/svg+xml;base64,${base64}`;\n }\n\n capabilities(): IconCapabilities {\n return {\n registerIcon: this.registerIcon.bind(this),\n registerIcons: this.registerIcons.bind(this),\n getIcon: this.getIcon.bind(this),\n getAllIcons: this.getAllIcons.bind(this),\n getSvgString: this.getSvgString.bind(this),\n isSvgString: this.isSvgString.bind(this),\n isSvgDataUri: this.isSvgDataUri.bind(this),\n dataUriToSvgString: this.dataUriToSvgString.bind(this),\n svgStringToDataUri: this.svgStringToDataUri.bind(this),\n };\n }\n}\n","import { BasePlugin, CoreState, PluginRegistry, StoreState, arePropsEqual } from '@embedpdf/core';\nimport {\n childrenFunctionOptions,\n CommandMenuComponent,\n CustomComponent,\n FloatingComponent,\n GroupedItemsComponent,\n HeaderComponent,\n PanelComponent,\n UICapability,\n UIComponentType,\n UIPluginConfig,\n UIPluginState,\n} from './types';\nimport { UIComponent } from './ui-component';\nimport { initialState } from './reducer';\nimport {\n uiInitComponents,\n UIPluginAction,\n uiSetHeaderVisible,\n uiShowCommandMenu,\n uiTogglePanel,\n uiHideCommandMenu,\n TogglePanelPayload,\n SetHeaderVisiblePayload,\n uiUpdateComponentState,\n UpdateComponentStatePayload,\n} from './actions';\nimport { MenuManager } from './menu/menu-manager';\nimport { IconManager } from './icons/icon-manager';\n\nexport class UIPlugin extends BasePlugin<\n UIPluginConfig,\n UICapability,\n UIPluginState,\n UIPluginAction\n> {\n static readonly id = 'ui' as const;\n private componentRenderers: Record<\n string,\n (\n props: any,\n children: (options?: childrenFunctionOptions) => any[],\n context?: Record<string, any>,\n ) => any\n > = {};\n private components: Record<string, UIComponent<UIComponentType<any>>> = {};\n private config: UIPluginConfig;\n private mapStateCallbacks: {\n [componentId: string]: (storeState: any, ownProps: any) => any;\n } = {};\n private globalStoreSubscription: () => void = () => {};\n private menuManager: MenuManager; // Add this\n private iconManager: IconManager;\n\n constructor(id: string, registry: PluginRegistry, config: UIPluginConfig) {\n super(id, registry);\n this.config = config;\n\n // Initialize command center\n this.menuManager = new MenuManager(config.menuItems || {}, this.registry);\n\n // Initialize icon registry\n this.iconManager = new IconManager(config.icons || []);\n\n // Subscribe to command events\n this.setupCommandEventHandlers();\n\n // Subscribe exactly once to the global store\n this.globalStoreSubscription = this.registry.getStore().subscribe((_action, newState) => {\n this.onGlobalStoreChange(newState);\n });\n }\n\n async initialize(): Promise<void> {\n // Step 1: Build all individual components\n this.buildComponents();\n\n // Step 2: Link children for grouped items\n this.linkGroupedItems();\n\n // Step 3: Set initial state for UI components\n this.setInitialStateUIComponents();\n }\n\n // Set up handlers for command events\n private setupCommandEventHandlers(): void {\n // Handle command menu requests\n this.menuManager.on(MenuManager.EVENTS.MENU_REQUESTED, (data) => {\n const { menuId, triggerElement, position, flatten } = data;\n\n const isOpen = this.state.commandMenu.commandMenu?.activeCommand === menuId;\n if (isOpen) {\n return this.dispatch(uiHideCommandMenu({ id: 'commandMenu' }));\n }\n\n this.dispatch(\n uiShowCommandMenu({\n id: 'commandMenu',\n commandId: menuId,\n triggerElement,\n position,\n flatten,\n }),\n );\n });\n\n // Optional: Track command execution for analytics or other purposes\n this.menuManager.on(MenuManager.EVENTS.COMMAND_EXECUTED, (data) => {\n console.log('Command executed:', data.command.id, 'source:', data.source);\n });\n }\n\n private addComponent(id: string, componentConfig: UIComponentType<any>) {\n if (this.components[id]) {\n console.warn(`Component with ID ${id} already exists and will be overwritten`);\n }\n // Step 1: Build the UIComponent\n const component = new UIComponent(componentConfig, this.componentRenderers);\n this.components[id] = component;\n\n // Step 2: Store mapStateToProps if present\n if (typeof componentConfig.mapStateToProps === 'function') {\n this.mapStateCallbacks[id] = componentConfig.mapStateToProps;\n }\n\n return component;\n }\n\n private buildComponents() {\n Object.entries(this.config.components).forEach(([id, componentConfig]) => {\n this.addComponent(id, componentConfig);\n });\n }\n\n private linkGroupedItems() {\n Object.values(this.components).forEach((component) => {\n if (isItemWithSlots(component)) {\n const props = component.componentConfig;\n props.slots?.forEach((slot) => {\n const child = this.components[slot.componentId];\n if (child) {\n component.addChild(slot.componentId, child, slot.priority, slot.className);\n } else {\n console.warn(\n `Child component ${slot.componentId} not found for GroupedItems ${props.id}`,\n );\n }\n });\n }\n });\n }\n\n private setInitialStateUIComponents() {\n const defaultState: UIPluginState = initialState;\n\n Object.entries(this.config.components).forEach(([componentId, definition]) => {\n if (definition.initialState) {\n // store the initialState object, e.g. { open: false } or { active: true }\n defaultState[definition.type][componentId] = definition.initialState;\n } else {\n defaultState[definition.type][componentId] = {};\n }\n });\n\n this.dispatch(uiInitComponents(defaultState));\n }\n\n private onGlobalStoreChange(state: StoreState<CoreState>) {\n for (const [id, uiComponent] of Object.entries(this.components)) {\n const mapFn = this.mapStateCallbacks[id];\n if (!mapFn) continue; // no mapping\n\n // ownProps is the UIComponent's current props\n const { id: _id, ...ownProps } = uiComponent.props;\n\n const partial = mapFn(state, ownProps);\n // If partial is non-empty or changes from old, do update\n const merged = { ...ownProps, ...partial };\n\n if (!arePropsEqual(ownProps, merged)) {\n uiComponent.update(partial);\n }\n }\n }\n\n private addSlot(parentId: string, slotId: string, priority?: number, className?: string) {\n // 1. Get the parent component\n const parentComponent = this.components[parentId];\n\n if (!parentComponent) {\n console.error(`Parent component ${parentId} not found`);\n return;\n }\n\n // 2. Check if parent has slots (is a container type)\n if (!isItemWithSlots(parentComponent)) {\n console.error(`Parent component ${parentId} does not support slots`);\n return;\n }\n\n // 3. Get the component to add to the slot\n const childComponent = this.components[slotId];\n\n if (!childComponent) {\n console.error(`Child component ${slotId} not found`);\n return;\n }\n\n const parentChildren = parentComponent.getChildren();\n\n // 4. Determine priority for the new slot\n let slotPriority = priority;\n\n if (slotPriority === undefined) {\n // If no priority is specified, add it at the end with a reasonable gap\n const maxPriority =\n parentChildren.length > 0 ? Math.max(...parentChildren.map((child) => child.priority)) : 0;\n slotPriority = maxPriority + 10; // Add a gap of 10\n }\n\n // 6. Add the child to the parent component with the appropriate priority\n // The UIComponent will handle sorting and avoid duplicates\n parentComponent.addChild(slotId, childComponent, slotPriority, className);\n }\n\n protected buildCapability(): UICapability {\n return {\n registerComponentRenderer: (\n type: string,\n renderer: (\n props: any,\n children: (options?: childrenFunctionOptions) => any[],\n context?: Record<string, any>,\n ) => any,\n ) => {\n this.componentRenderers[type] = renderer;\n },\n getComponent: <T>(id: string): T | undefined => {\n return this.components[id] as T | undefined;\n },\n registerComponent: this.addComponent.bind(this),\n getCommandMenu: () =>\n Object.values(this.components).find((component) => isCommandMenuComponent(component)),\n hideCommandMenu: () => this.debouncedDispatch(uiHideCommandMenu({ id: 'commandMenu' }), 100),\n getFloatingComponents: (scrollerPosition?: 'inside' | 'outside') =>\n Object.values(this.components)\n .filter((component) => isFloatingComponent(component))\n .filter(\n (component) =>\n !scrollerPosition || component.props.scrollerPosition === scrollerPosition,\n ),\n getHeadersByPlacement: (placement: 'top' | 'bottom' | 'left' | 'right') =>\n Object.values(this.components)\n .filter((component) => isHeaderComponent(component))\n .filter((component) => component.props.placement === placement),\n getPanelsByLocation: (location: 'left' | 'right') =>\n Object.values(this.components)\n .filter((component) => isPanelComponent(component))\n .filter((component) => component.props.location === location),\n addSlot: this.addSlot.bind(this),\n togglePanel: (payload: TogglePanelPayload) => {\n this.dispatch(uiTogglePanel(payload));\n },\n setHeaderVisible: (payload: SetHeaderVisiblePayload) => {\n this.dispatch(uiSetHeaderVisible(payload));\n },\n updateComponentState: (payload: UpdateComponentStatePayload) => {\n this.dispatch(uiUpdateComponentState(payload));\n },\n ...this.iconManager.capabilities(),\n ...this.menuManager.capabilities(),\n };\n }\n\n async destroy(): Promise<void> {\n this.globalStoreSubscription();\n this.components = {};\n this.componentRenderers = {};\n this.mapStateCallbacks = {};\n }\n}\n\nfunction isItemWithSlots(\n component: UIComponent<UIComponentType<any>>,\n): component is\n | UIComponent<GroupedItemsComponent>\n | UIComponent<HeaderComponent>\n | UIComponent<PanelComponent>\n | UIComponent<FloatingComponent>\n | UIComponent<CustomComponent> {\n return (\n isGroupedItemsComponent(component) ||\n isHeaderComponent(component) ||\n isPanelComponent(component) ||\n isFloatingComponent(component) ||\n isCustomComponent(component)\n );\n}\n\n// Type guard function\nfunction isGroupedItemsComponent(\n component: UIComponent<UIComponentType>,\n): component is UIComponent<GroupedItemsComponent> {\n return component.type === 'groupedItems';\n}\n\nfunction isHeaderComponent(\n component: UIComponent<UIComponentType>,\n): component is UIComponent<HeaderComponent> {\n return component.type === 'header';\n}\n\nfunction isPanelComponent(\n component: UIComponent<UIComponentType>,\n): component is UIComponent<PanelComponent> {\n return component.type === 'panel';\n}\n\nfunction isFloatingComponent(\n component: UIComponent<UIComponentType>,\n): component is UIComponent<FloatingComponent> {\n return component.type === 'floating';\n}\n\nfunction isCommandMenuComponent(\n component: UIComponent<UIComponentType>,\n): component is UIComponent<CommandMenuComponent> {\n return component.type === 'commandMenu';\n}\n\nfunction isCustomComponent(\n component: UIComponent<UIComponentType>,\n): component is UIComponent<CustomComponent> {\n return component.type === 'custom';\n}\n","import { PluginManifest } from '@embedpdf/core';\nimport { UIPluginConfig } from './types';\n\nexport const UI_PLUGIN_ID = 'ui';\n\nexport const manifest: PluginManifest<UIPluginConfig> = {\n id: UI_PLUGIN_ID,\n name: 'UI Plugin',\n version: '1.0.0',\n provides: ['ui'],\n requires: [],\n optional: [],\n defaultConfig: {\n enabled: true,\n components: {},\n },\n};\n","import { PluginRegistry } from '@embedpdf/core';\n\nexport type Dynamic<TStore, T> = T | ((state: TStore) => T);\n\nexport interface MenuItemBase<TStore = any> {\n icon?: Dynamic<TStore, string>;\n label: Dynamic<TStore, string>;\n active?: Dynamic<TStore, boolean>; // whether command is currently active\n disabled?: Dynamic<TStore, boolean>; // whether command is currently disabled\n shortcut?: string; // \"Ctrl+Plus\"\n shortcutLabel?: string; // \"Ctrl+Plus\"\n visible?: Dynamic<TStore, boolean>; // whether command should be visible\n dividerBefore?: boolean; // whether to add a divider before the command\n}\n\nexport interface Action<TStore = any> extends MenuItemBase<TStore> {\n id: string; // \"zoomIn\"\n type: 'action'; // i18n key or literal\n action: (registry: PluginRegistry, state: TStore) => void; // executed onClick // whether to add a divider before the command\n}\n\nexport interface Group<TStore = any> {\n id: string;\n type: 'group';\n label: Dynamic<TStore, string>;\n children: string[];\n}\n\nexport interface Menu<TStore = any> extends MenuItemBase<TStore> {\n id: string;\n type: 'menu';\n children: string[];\n}\n\nexport type MenuItem<TStore = any> = Action<TStore> | Group | Menu<TStore>;\n\nexport type MenuRegistry = Record<string, MenuItem>;\n\n// Options for executing an action\nexport interface ExecuteOptions {\n source?: 'click' | 'shortcut' | 'api';\n triggerElement?: HTMLElement;\n flatten?: boolean;\n position?: 'top' | 'bottom' | 'left' | 'right';\n}\n\nexport function hasActive<TStore>(command: MenuItem<TStore>): command is Action<TStore> {\n return 'active' in command;\n}\n\nexport interface MenuManagerCapabilities {\n registerItem: (commandItem: MenuItem) => void;\n registerItems: (commands: MenuRegistry) => void;\n executeCommand: (id: string, options?: ExecuteOptions) => void;\n getAction: (id: string) => ResolvedAction | undefined;\n getMenuOrAction: (id: string) => ResolvedMenu | ResolvedAction | undefined;\n getChildItems: (commandId: string, options?: { flatten?: boolean }) => ResolvedMenuItem[];\n getItemsByIds: (ids: string[]) => ResolvedMenuItem[];\n getAllItems: () => MenuRegistry;\n}\n\n// Add these new resolved types after the existing interfaces\nexport type Resolved<TStore, T> = T extends Dynamic<TStore, infer U> ? U : T;\n\nexport interface ResolvedMenuItemBase<TStore = any> {\n icon?: string;\n label: string;\n active?: boolean;\n disabled?: boolean;\n shortcut?: string;\n shortcutLabel?: string;\n visible?: boolean;\n dividerBefore?: boolean;\n}\n\nexport interface ResolvedAction<TStore = any> extends ResolvedMenuItemBase<TStore> {\n id: string;\n type: 'action';\n action: (registry: PluginRegistry, state: TStore) => void;\n}\n\nexport interface ResolvedGroup<TStore = any> {\n id: string;\n type: 'group';\n label: string;\n children: string[];\n}\n\nexport interface ResolvedMenu<TStore = any> extends ResolvedMenuItemBase<TStore> {\n id: string;\n type: 'menu';\n children: string[];\n}\n\nexport type ResolvedMenuItem<TStore = any> =\n | ResolvedAction<TStore>\n | ResolvedGroup<TStore>\n | ResolvedMenu<TStore>;\n\n// Result of menu item resolution\nexport interface ResolvedMenuItemResult<TStore = any> {\n item: ResolvedMenuItem<TStore>;\n isGroup: boolean;\n isMenu: boolean;\n isAction: boolean;\n}\n","import { PluginPackage } from '@embedpdf/core';\nimport { UIPlugin } from './ui-plugin';\nimport { manifest, UI_PLUGIN_ID } from './manifest';\nimport { UIPluginConfig, UIPluginState } from './types';\nimport { uiReducer, initialState } from './reducer';\nimport { UIPluginAction } from './actions';\n\nexport const UIPluginPackage: PluginPackage<\n UIPlugin,\n UIPluginConfig,\n UIPluginState,\n UIPluginAction\n> = {\n manifest,\n create: (registry, _engine, config) => new UIPlugin(UI_PLUGIN_ID, registry, config!),\n reducer: uiReducer,\n initialState,\n};\n\nexport * from './manifest';\nexport * from './ui-plugin';\nexport * from './types';\nexport * from './ui-component';\nexport * from './utils';\nexport * from './menu/types';\nexport * from './icons/types';\nexport * from './menu/utils';\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,88 @@
1
+ import { Action } from '@embedpdf/core';
2
+ import { UIPluginState } from './types';
3
+ export declare const UI_INIT_COMPONENTS = "UI_INIT_COMPONENTS";
4
+ export declare const UI_INIT_FLYOUT = "UI_INIT_FLYOUT";
5
+ export declare const UI_TOGGLE_FLYOUT = "UI_TOGGLE_FLYOUT";
6
+ export declare const UI_SET_HEADER_VISIBLE = "UI_SET_HEADER_VISIBLE";
7
+ export declare const UI_TOGGLE_PANEL = "UI_TOGGLE_PANEL";
8
+ export declare const UI_SHOW_COMMAND_MENU = "UI_SHOW_COMMAND_MENU";
9
+ export declare const UI_HIDE_COMMAND_MENU = "UI_HIDE_COMMAND_MENU";
10
+ export declare const UI_UPDATE_COMMAND_MENU = "UI_UPDATE_COMMAND_MENU";
11
+ export declare const UI_UPDATE_COMPONENT_STATE = "UI_UPDATE_COMPONENT_STATE";
12
+ export interface InitFlyoutPayload {
13
+ id: string;
14
+ triggerElement: HTMLElement;
15
+ }
16
+ export interface ToggleFlyoutPayload {
17
+ id: string;
18
+ open?: boolean;
19
+ }
20
+ export interface SetHeaderVisiblePayload {
21
+ id: string;
22
+ visible: boolean;
23
+ visibleChild?: string;
24
+ }
25
+ export interface TogglePanelPayload {
26
+ id: string;
27
+ open?: boolean;
28
+ visibleChild: string;
29
+ }
30
+ export interface ShowCommandMenuPayload {
31
+ id: string;
32
+ commandId: string;
33
+ triggerElement?: HTMLElement;
34
+ position?: 'top' | 'bottom' | 'left' | 'right';
35
+ flatten?: boolean;
36
+ }
37
+ export interface UpdateComponentStatePayload<T = any> {
38
+ /** one of the top-level keys inside UIPluginState, e.g. "panel" | "custom" … */
39
+ componentType: keyof UIPluginState;
40
+ /** same id you used when registering the component */
41
+ componentId: string;
42
+ /** partial patch – only keys existing in the current state will be applied */
43
+ patch: Partial<T>;
44
+ }
45
+ export interface HideCommandMenuPayload {
46
+ id: string;
47
+ }
48
+ export interface UiInitComponentsAction extends Action {
49
+ type: typeof UI_INIT_COMPONENTS;
50
+ payload: UIPluginState;
51
+ }
52
+ export interface UiInitFlyoutAction extends Action {
53
+ type: typeof UI_INIT_FLYOUT;
54
+ payload: InitFlyoutPayload;
55
+ }
56
+ export interface UiToggleFlyoutAction extends Action {
57
+ type: typeof UI_TOGGLE_FLYOUT;
58
+ payload: ToggleFlyoutPayload;
59
+ }
60
+ export interface UiSetHeaderVisibleAction extends Action {
61
+ type: typeof UI_SET_HEADER_VISIBLE;
62
+ payload: SetHeaderVisiblePayload;
63
+ }
64
+ export interface UiTogglePanelAction extends Action {
65
+ type: typeof UI_TOGGLE_PANEL;
66
+ payload: TogglePanelPayload;
67
+ }
68
+ export interface UiShowCommandMenuAction extends Action {
69
+ type: typeof UI_SHOW_COMMAND_MENU;
70
+ payload: ShowCommandMenuPayload;
71
+ }
72
+ export interface UiHideCommandMenuAction extends Action {
73
+ type: typeof UI_HIDE_COMMAND_MENU;
74
+ payload: HideCommandMenuPayload;
75
+ }
76
+ export interface UiUpdateComponentStateAction extends Action {
77
+ type: typeof UI_UPDATE_COMPONENT_STATE;
78
+ payload: UpdateComponentStatePayload;
79
+ }
80
+ export type UIPluginAction = UiInitComponentsAction | UiInitFlyoutAction | UiToggleFlyoutAction | UiSetHeaderVisibleAction | UiTogglePanelAction | UiShowCommandMenuAction | UiHideCommandMenuAction | UiUpdateComponentStateAction;
81
+ export declare const uiInitComponents: (state: UIPluginState) => UiInitComponentsAction;
82
+ export declare const uiInitFlyout: (payload: InitFlyoutPayload) => UiInitFlyoutAction;
83
+ export declare const uiToggleFlyout: (payload: ToggleFlyoutPayload) => UiToggleFlyoutAction;
84
+ export declare const uiTogglePanel: (payload: TogglePanelPayload) => UiTogglePanelAction;
85
+ export declare const uiSetHeaderVisible: (payload: SetHeaderVisiblePayload) => UiSetHeaderVisibleAction;
86
+ export declare const uiShowCommandMenu: (payload: ShowCommandMenuPayload) => UiShowCommandMenuAction;
87
+ export declare const uiHideCommandMenu: (payload: HideCommandMenuPayload) => UiHideCommandMenuAction;
88
+ export declare const uiUpdateComponentState: <T>(payload: UpdateComponentStatePayload<T>) => UiUpdateComponentStateAction;