@embedpdf/plugin-ui 1.0.18 → 1.0.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +28 -7
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("@embedpdf/core");class e{constructor(t,e){this.children=[],this.updateCallbacks=[],this.hadUpdateBeforeListeners=!1,this.componentConfig=t;const n=t.props||{};if("function"==typeof n){const e=n(t.initialState);this.props={...e,id:t.id}}else this.props={...n,id:t.id};this.type=t.type,this.registry=e}addChild(t,e,n=0,i){this.children.push({id:t,component:e,priority:n,className:i}),this.sortChildren()}sortChildren(){this.children.sort(((t,e)=>t.priority-e.priority))}removeChild(t){this.children=this.children.filter((e=>e.component!==t))}clearChildren(){this.children=[]}get getRenderType(){return this.componentConfig.render||this.type}getRenderer(){return this.registry[this.getRenderType]}getChildren(){return this.children}getChildContext(t){const e=this.componentConfig.getChildContext;return"function"==typeof e?{...t,...e(this.props)}:e&&"object"==typeof e?{...t,...e}:t}update(t){const{id:e,...n}=t;this.props={...this.props,...n},0===this.updateCallbacks.length&&(this.hadUpdateBeforeListeners=!0),this.notifyUpdate()}onUpdate(t){return this.updateCallbacks.push(t),this.hadUpdateBeforeListeners}offUpdate(t){this.updateCallbacks=this.updateCallbacks.filter((e=>e!==t))}notifyUpdate(){this.updateCallbacks.forEach((t=>t()))}}const n="UI_INIT_COMPONENTS",i="UI_SET_HEADER_VISIBLE",o="UI_TOGGLE_PANEL",s="UI_SHOW_COMMAND_MENU",r="UI_HIDE_COMMAND_MENU",a="UI_UPDATE_COMPONENT_STATE",l=t=>({type:r,payload:t}),c={panel:{},header:{},groupedItems:{},divider:{},iconButton:{},tabButton:{},selectButton:{},custom:{},floating:{},commandMenu:{}};function d(){const t=new Map;return{emit(e,n){const i=t.get(e);i&&i.forEach((t=>t(n)))},on(e,n){t.has(e)||t.set(e,new Set);return t.get(e).add(n),()=>this.off(e,n)},off(e,n){const i=t.get(e);i&&(i.delete(n),0===i.size&&t.delete(e))}}}function p(t,e){const n=t=>"function"==typeof t?t(e):t;return"group"===t.type?{...t,label:n(t.label)??""}:{...t,icon:n(t.icon)??"",iconProps:n(t.iconProps)??{},label:n(t.label)??"",visible:n(t.visible)??!0,active:n(t.active)??!1,disabled:n(t.disabled)??!1}}const u=class t{constructor(t={},e){this.registry={},this.shortcutMap={},this.eventController=d(),this.pluginRegistry=e,this.registerItems(t),this.setupKeyboardListeners()}get state(){return this.pluginRegistry.getStore().getState()}registerItem(t){this.registry[t.id]&&console.warn(`Menu item with ID ${t.id} already exists and will be overwritten`),this.registry[t.id]=t,"shortcut"in t&&t.shortcut&&(this.shortcutMap[this.normalizeShortcut(t.shortcut)]=t.id)}registerItems(t){Object.values(t).forEach((t=>{this.registerItem(t)}))}resolve(t){return p(this.registry[t],this.state)}getMenuItem(t){const e=this.resolve(t);if(e)return{item:e,isGroup:"group"===e.type,isMenu:"menu"===e.type,isAction:"action"===e.type}}getAction(t){const e=this.getMenuItem(t);if(e&&e.isAction)return e.item}getMenuOrAction(t){const e=this.getMenuItem(t);if(e)return e.item}getAllItems(){return{...this.registry}}getItemsByIds(t){return t.map((t=>this.resolve(t))).filter((t=>void 0!==t))}getChildItems(t,e={}){var n;const i=this.resolve(t);if(!i||!("children"in i)||!(null==(n=i.children)?void 0:n.length))return[];const o=this.getItemsByIds(i.children);if(!e.flatten)return o;const s=[];for(const r of o)if("group"===r.type)s.push(r);else if("menu"===r.type){const t=this.getChildItems(r.id,{flatten:!0});s.push(...t)}else s.push(r);return s}executeCommand(e,n={}){var i;const o=this.getMenuItem(e);if(!o)return void console.warn(`Menu item '${e}' not found`);if("group"===o.item.type)return void console.warn(`Cannot execute group '${e}'`);const{item:s}=o;s.disabled?console.warn(`Menu item '${e}' is disabled`):o.isAction?(s.action(this.pluginRegistry,this.state),this.eventController.emit(t.EVENTS.COMMAND_EXECUTED,{command:s,source:n.source||"api"})):"children"in s&&(null==(i=s.children)?void 0:i.length)&&this.handleSubmenu(s,n)}executeShortcut(e){const n=this.normalizeShortcut(e),i=this.shortcutMap[n];return!!i&&(this.executeCommand(i,{source:"shortcut"}),this.eventController.emit(t.EVENTS.SHORTCUT_EXECUTED,{shortcut:n,itemId:i}),!0)}on(t,e){return this.eventController.on(t,e)}off(t,e){this.eventController.off(t,e)}handleSubmenu(e,n){this.eventController.emit(t.EVENTS.MENU_REQUESTED,{menuId:e.id,triggerElement:n.triggerElement,position:n.position,flatten:n.flatten||!1})}setupKeyboardListeners(){if("undefined"==typeof window)return;document.addEventListener("keydown",(t=>{const e=t.target;if("INPUT"===e.tagName||"TEXTAREA"===e.tagName||e.isContentEditable)return;const n=this.buildShortcutString(t);n&&this.executeShortcut(n)&&t.preventDefault()}))}buildShortcutString(t){const e=[];t.ctrlKey&&e.push("Ctrl"),t.shiftKey&&e.push("Shift"),t.altKey&&e.push("Alt"),t.metaKey&&e.push("Meta");const n=t.key;if(!["Control","Shift","Alt","Meta"].includes(n)){const t=1===n.length?n.toUpperCase():n;return[...e,t].join("+")}return null}normalizeShortcut(t){return t.split("+").map((t=>t.trim())).join("+")}capabilities(){return{registerItem:this.registerItem.bind(this),registerItems:this.registerItems.bind(this),executeCommand:this.executeCommand.bind(this),getAction:this.getAction.bind(this),getMenuOrAction:this.getMenuOrAction.bind(this),getChildItems:this.getChildItems.bind(this),getItemsByIds:this.getItemsByIds.bind(this),getAllItems:this.getAllItems.bind(this)}}};u.EVENTS={COMMAND_EXECUTED:"menu:command_executed",MENU_REQUESTED:"menu:requested",SHORTCUT_EXECUTED:"menu:shortcut_executed"};let h=u;const m=class extends t.BasePlugin{constructor(t,e,n){super(t,e),this.componentRenderers={},this.components={},this.mapStateCallbacks={},this.globalStoreSubscription=()=>{},this.config=n,this.menuManager=new h(n.menuItems||{},this.registry),this.setupCommandEventHandlers(),this.globalStoreSubscription=this.registry.getStore().subscribe(((t,e)=>{this.onGlobalStoreChange(e)}))}async initialize(){this.buildComponents(),this.linkGroupedItems(),this.setInitialStateUIComponents()}setupCommandEventHandlers(){this.menuManager.on(h.EVENTS.MENU_REQUESTED,(t=>{var e;const{menuId:n,triggerElement:i,position:o,flatten:r}=t;if((null==(e=this.state.commandMenu.commandMenu)?void 0:e.activeCommand)===n)return this.dispatch(l({id:"commandMenu"}));this.dispatch({type:s,payload:{id:"commandMenu",commandId:n,triggerElement:i,position:o,flatten:r}})})),this.menuManager.on(h.EVENTS.COMMAND_EXECUTED,(t=>{console.log("Command executed:",t.command.id,"source:",t.source)}))}addComponent(t,n){this.components[t]&&console.warn(`Component with ID ${t} already exists and will be overwritten`);const i=new e(n,this.componentRenderers);return this.components[t]=i,"function"==typeof n.mapStateToProps&&(this.mapStateCallbacks[t]=n.mapStateToProps),i}buildComponents(){Object.entries(this.config.components).forEach((([t,e])=>{this.addComponent(t,e)}))}linkGroupedItems(){Object.values(this.components).forEach((t=>{var e;if(f(t)){const n=t.componentConfig;null==(e=n.slots)||e.forEach((e=>{const i=this.components[e.componentId];i?t.addChild(e.componentId,i,e.priority,e.className):console.warn(`Child component ${e.componentId} not found for GroupedItems ${n.id}`)}))}}))}setInitialStateUIComponents(){const t=c;Object.entries(this.config.components).forEach((([e,n])=>{n.initialState?t[n.type][e]=n.initialState:t[n.type][e]={}})),this.dispatch({type:n,payload:t})}onGlobalStoreChange(e){for(const[n,i]of Object.entries(this.components)){const o=this.mapStateCallbacks[n];if(!o)continue;const{id:s,...r}=i.props,a=o(e,r),l={...r,...a};t.arePropsEqual(r,l)||i.update(a)}}addSlot(t,e,n,i){const o=this.components[t];if(!o)return void console.error(`Parent component ${t} not found`);if(!f(o))return void console.error(`Parent component ${t} does not support slots`);const s=this.components[e];if(!s)return void console.error(`Child component ${e} not found`);const r=o.getChildren();let a=n;if(void 0===a){a=(r.length>0?Math.max(...r.map((t=>t.priority))):0)+10}o.addChild(e,s,a,i)}buildCapability(){return{registerComponentRenderer:(t,e)=>{this.componentRenderers[t]=e},getComponent:t=>this.components[t],registerComponent:this.addComponent.bind(this),getCommandMenu:()=>Object.values(this.components).find((t=>function(t){return"commandMenu"===t.type}(t))),hideCommandMenu:()=>this.debouncedDispatch(l({id:"commandMenu"}),100),getFloatingComponents:t=>Object.values(this.components).filter((t=>b(t))).filter((e=>!t||e.props.scrollerPosition===t)),getHeadersByPlacement:t=>Object.values(this.components).filter((t=>y(t))).filter((e=>e.props.placement===t)),getPanelsByLocation:t=>Object.values(this.components).filter((t=>C(t))).filter((e=>e.props.location===t)),addSlot:this.addSlot.bind(this),togglePanel:t=>{this.dispatch((t=>({type:o,payload:t}))(t))},setHeaderVisible:t=>{this.dispatch((t=>({type:i,payload:t}))(t))},updateComponentState:t=>{this.dispatch((t=>({type:a,payload:t}))(t))},...this.menuManager.capabilities()}}async destroy(){this.globalStoreSubscription(),this.components={},this.componentRenderers={},this.mapStateCallbacks={}}};m.id="ui";let g=m;function f(t){return function(t){return"groupedItems"===t.type}(t)||y(t)||C(t)||b(t)||function(t){return"custom"===t.type}(t)}function y(t){return"header"===t.type}function C(t){return"panel"===t.type}function b(t){return"floating"===t.type}const E="ui",I={id:E,name:"UI Plugin",version:"1.0.0",provides:["ui"],requires:[],optional:[],defaultConfig:{enabled:!0,components:{}}};const v={manifest:I,create:(t,e,n)=>new g(E,t,n),reducer:(t=c,e)=>{switch(e.type){case n:return{...t,...e.payload};case o:{const n=t.panel[e.payload.id]||{},{open:i,visibleChild:o}=e.payload,s=n.visibleChild;let r=n.open,a=n.visibleChild;return o===s?r=void 0!==i?i:!n.open:(a=o,r=!0),{...t,panel:{...t.panel,[e.payload.id]:{...n,open:r,visibleChild:a}}}}case i:return{...t,header:{...t.header,[e.payload.id]:{...t.header[e.payload.id],visible:e.payload.visible,visibleChild:e.payload.visibleChild}}};case s:return{...t,commandMenu:{...t.commandMenu,[e.payload.id]:{activeCommand:e.payload.commandId,triggerElement:e.payload.triggerElement,position:e.payload.position,open:!0,flatten:e.payload.flatten}}};case r:return{...t,commandMenu:{...t.commandMenu,[e.payload.id]:{...t.commandMenu[e.payload.id],open:!1,activeCommand:null,triggerElement:void 0,position:void 0,flatten:!1}}};case a:{const{componentType:n,componentId:i,patch:o}=e.payload;if(!t[n]||!t[n][i])return t;const s=t[n][i],r=Object.fromEntries(Object.entries(o).filter((([t])=>t in s)));return 0===Object.keys(r).length?t:{...t,[n]:{...t[n],[i]:{...s,...r}}}}default:return t}},initialState:c};exports.UIComponent=e,exports.UIPlugin=g,exports.UIPluginPackage=v,exports.UI_PLUGIN_ID=E,exports.createEventController=d,exports.defineComponent=function(){return t=>t},exports.getIconProps=function(t,e){const n=p(t,e);return"group"===n.type?{}:n.iconProps??{}},exports.hasActive=function(t){return"active"in t},exports.isActive=function(t,e){const n=p(t,e);return"group"!==n.type&&!!n.active},exports.isDisabled=function(t,e){const n=p(t,e);return"group"!==n.type&&!!n.disabled},exports.isVisible=function(t,e){const n=p(t,e);return"group"!==n.type&&!!n.visible},exports.manifest=I,exports.resolveMenuItem=p;
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("@embedpdf/core");class e{constructor(t,e){this.children=[],this.updateCallbacks=[],this.hadUpdateBeforeListeners=!1,this.componentConfig=t;const n=t.props||{};if("function"==typeof n){const e=n(t.initialState);this.props={...e,id:t.id}}else this.props={...n,id:t.id};this.type=t.type,this.registry=e}addChild(t,e,n=0,i){this.children.push({id:t,component:e,priority:n,className:i}),this.sortChildren()}sortChildren(){this.children.sort(((t,e)=>t.priority-e.priority))}removeChild(t){this.children=this.children.filter((e=>e.component!==t))}clearChildren(){this.children=[]}get getRenderType(){return this.componentConfig.render||this.type}getRenderer(){return this.registry[this.getRenderType]}getChildren(){return this.children}getChildContext(t){const e=this.componentConfig.getChildContext;return"function"==typeof e?{...t,...e(this.props)}:e&&"object"==typeof e?{...t,...e}:t}update(t){const{id:e,...n}=t;this.props={...this.props,...n},0===this.updateCallbacks.length&&(this.hadUpdateBeforeListeners=!0),this.notifyUpdate()}onUpdate(t){return this.updateCallbacks.push(t),this.hadUpdateBeforeListeners}offUpdate(t){this.updateCallbacks=this.updateCallbacks.filter((e=>e!==t))}notifyUpdate(){this.updateCallbacks.forEach((t=>t()))}}const n="UI_INIT_COMPONENTS",i="UI_SET_HEADER_VISIBLE",o="UI_TOGGLE_PANEL",s="UI_SHOW_COMMAND_MENU",r="UI_HIDE_COMMAND_MENU",a="UI_UPDATE_COMPONENT_STATE",l=t=>({type:r,payload:t}),d={panel:{},header:{},groupedItems:{},divider:{},iconButton:{},tabButton:{},selectButton:{},custom:{},floating:{},commandMenu:{}};function c(){const t=new Map;return{emit(e,n){const i=t.get(e);i&&i.forEach((t=>t(n)))},on(e,n){t.has(e)||t.set(e,new Set);return t.get(e).add(n),()=>this.off(e,n)},off(e,n){const i=t.get(e);i&&(i.delete(n),0===i.size&&t.delete(e))}}}function p(t,e){const n=t=>"function"==typeof t?t(e):t;return"group"===t.type?{...t,label:n(t.label)??""}:{...t,icon:n(t.icon)??"",iconProps:n(t.iconProps)??{},label:n(t.label)??"",visible:n(t.visible)??!0,active:n(t.active)??!1,disabled:n(t.disabled)??!1}}const u=class t{constructor(t={},e){this.registry={},this.shortcutMap={},this.eventController=c(),this.pluginRegistry=e,this.registerItems(t),this.setupKeyboardListeners()}get state(){return this.pluginRegistry.getStore().getState()}registerItem(t){this.registry[t.id]&&console.warn(`Menu item with ID ${t.id} already exists and will be overwritten`),this.registry[t.id]=t,"shortcut"in t&&t.shortcut&&(this.shortcutMap[this.normalizeShortcut(t.shortcut)]=t.id)}registerItems(t){Object.values(t).forEach((t=>{this.registerItem(t)}))}resolve(t){return p(this.registry[t],this.state)}getMenuItem(t){const e=this.resolve(t);if(e)return{item:e,isGroup:"group"===e.type,isMenu:"menu"===e.type,isAction:"action"===e.type}}getAction(t){const e=this.getMenuItem(t);if(e&&e.isAction)return e.item}getMenuOrAction(t){const e=this.getMenuItem(t);if(e)return e.item}getAllItems(){return{...this.registry}}getItemsByIds(t){return t.map((t=>this.resolve(t))).filter((t=>void 0!==t))}getChildItems(t,e={}){var n;const i=this.resolve(t);if(!i||!("children"in i)||!(null==(n=i.children)?void 0:n.length))return[];const o=this.getItemsByIds(i.children);if(!e.flatten)return o;const s=[];for(const r of o)if("group"===r.type)s.push(r);else if("menu"===r.type){const t=this.getChildItems(r.id,{flatten:!0});s.push(...t)}else s.push(r);return s}executeCommand(e,n={}){var i;const o=this.getMenuItem(e);if(!o)return void console.warn(`Menu item '${e}' not found`);if("group"===o.item.type)return void console.warn(`Cannot execute group '${e}'`);const{item:s}=o;s.disabled?console.warn(`Menu item '${e}' is disabled`):o.isAction?(s.action(this.pluginRegistry,this.state),this.eventController.emit(t.EVENTS.COMMAND_EXECUTED,{command:s,source:n.source||"api"})):"children"in s&&(null==(i=s.children)?void 0:i.length)&&this.handleSubmenu(s,n)}executeShortcut(e){const n=this.normalizeShortcut(e),i=this.shortcutMap[n];return!!i&&(this.executeCommand(i,{source:"shortcut"}),this.eventController.emit(t.EVENTS.SHORTCUT_EXECUTED,{shortcut:n,itemId:i}),!0)}on(t,e){return this.eventController.on(t,e)}off(t,e){this.eventController.off(t,e)}handleSubmenu(e,n){this.eventController.emit(t.EVENTS.MENU_REQUESTED,{menuId:e.id,triggerElement:n.triggerElement,position:n.position,flatten:n.flatten||!1})}setupKeyboardListeners(){if("undefined"==typeof window)return;document.addEventListener("keydown",(t=>{const e=t.target;if("INPUT"===e.tagName||"TEXTAREA"===e.tagName||e.isContentEditable)return;const n=this.buildShortcutString(t);n&&this.executeShortcut(n)&&t.preventDefault()}))}buildShortcutString(t){const e=[];t.ctrlKey&&e.push("Ctrl"),t.shiftKey&&e.push("Shift"),t.altKey&&e.push("Alt"),t.metaKey&&e.push("Meta");const n=t.key;if(!["Control","Shift","Alt","Meta"].includes(n)){const t=1===n.length?n.toUpperCase():n;return[...e,t].join("+")}return null}normalizeShortcut(t){return t.split("+").map((t=>t.trim())).join("+")}capabilities(){return{registerItem:this.registerItem.bind(this),registerItems:this.registerItems.bind(this),executeCommand:this.executeCommand.bind(this),getAction:this.getAction.bind(this),getMenuOrAction:this.getMenuOrAction.bind(this),getChildItems:this.getChildItems.bind(this),getItemsByIds:this.getItemsByIds.bind(this),getAllItems:this.getAllItems.bind(this)}}};u.EVENTS={COMMAND_EXECUTED:"menu:command_executed",MENU_REQUESTED:"menu:requested",SHORTCUT_EXECUTED:"menu:shortcut_executed"};let h=u;const m=class extends t.BasePlugin{constructor(t,e,n){super(t,e),this.componentRenderers={},this.components={},this.mapStateCallbacks={},this.globalStoreSubscription=()=>{},this.config=n,this.menuManager=new h(n.menuItems||{},this.registry),this.setupCommandEventHandlers(),this.globalStoreSubscription=this.registry.getStore().subscribe(((t,e)=>{this.onGlobalStoreChange(e)}))}async initialize(){this.buildComponents(),this.linkGroupedItems(),this.setInitialStateUIComponents()}setupCommandEventHandlers(){this.menuManager.on(h.EVENTS.MENU_REQUESTED,(t=>{var e;const{menuId:n,triggerElement:i,position:o,flatten:r}=t;if((null==(e=this.state.commandMenu.commandMenu)?void 0:e.activeCommand)===n)return this.dispatch(l({id:"commandMenu"}));this.dispatch({type:s,payload:{id:"commandMenu",commandId:n,triggerElement:i,position:o,flatten:r}})})),this.menuManager.on(h.EVENTS.COMMAND_EXECUTED,(t=>{this.logger.debug("UIPlugin","CommandExecuted",`Command executed: ${t.command.id}`,{commandId:t.command.id,source:t.source})}))}addComponent(t,n){this.components[t]&&this.logger.warn("UIPlugin","ComponentAlreadyExists",`Component with ID ${t} already exists and will be overwritten`);const i=new e(n,this.componentRenderers);return this.components[t]=i,"function"==typeof n.mapStateToProps&&(this.mapStateCallbacks[t]=n.mapStateToProps),i}buildComponents(){Object.entries(this.config.components).forEach((([t,e])=>{this.addComponent(t,e)}))}linkGroupedItems(){Object.values(this.components).forEach((t=>{var e;if(f(t)){const n=t.componentConfig;null==(e=n.slots)||e.forEach((e=>{const i=this.components[e.componentId];i?t.addChild(e.componentId,i,e.priority,e.className):this.logger.warn("UIPlugin","ChildComponentNotFound",`Child component ${e.componentId} not found for GroupedItems ${n.id}`)}))}}))}setInitialStateUIComponents(){const t=d;Object.entries(this.config.components).forEach((([e,n])=>{n.initialState?t[n.type][e]=n.initialState:t[n.type][e]={}})),this.dispatch({type:n,payload:t})}onGlobalStoreChange(e){for(const[n,i]of Object.entries(this.components)){const o=this.mapStateCallbacks[n];if(!o)continue;const{id:s,...r}=i.props,a=o(e,r),l={...r,...a};t.arePropsEqual(r,l)||i.update(a)}}addSlot(t,e,n,i){const o=this.components[t];if(!o)return void this.logger.error("UIPlugin","ParentComponentNotFound",`Parent component ${t} not found`);if(!f(o))return void this.logger.error("UIPlugin","ParentComponentDoesNotSupportSlots",`Parent component ${t} does not support slots`);const s=this.components[e];if(!s)return void this.logger.error("UIPlugin","ChildComponentNotFound",`Child component ${e} not found`);const r=o.getChildren();let a=n;if(void 0===a){a=(r.length>0?Math.max(...r.map((t=>t.priority))):0)+10}o.addChild(e,s,a,i)}buildCapability(){return{registerComponentRenderer:(t,e)=>{this.componentRenderers[t]=e},getComponent:t=>this.components[t],registerComponent:this.addComponent.bind(this),getCommandMenu:()=>Object.values(this.components).find((t=>function(t){return"commandMenu"===t.type}(t))),hideCommandMenu:()=>this.debouncedDispatch(l({id:"commandMenu"}),100),getFloatingComponents:t=>Object.values(this.components).filter((t=>b(t))).filter((e=>!t||e.props.scrollerPosition===t)),getHeadersByPlacement:t=>Object.values(this.components).filter((t=>C(t))).filter((e=>e.props.placement===t)),getPanelsByLocation:t=>Object.values(this.components).filter((t=>y(t))).filter((e=>e.props.location===t)),addSlot:this.addSlot.bind(this),togglePanel:t=>{this.dispatch((t=>({type:o,payload:t}))(t))},setHeaderVisible:t=>{this.dispatch((t=>({type:i,payload:t}))(t))},updateComponentState:t=>{this.dispatch((t=>({type:a,payload:t}))(t))},...this.menuManager.capabilities()}}async destroy(){this.globalStoreSubscription(),this.components={},this.componentRenderers={},this.mapStateCallbacks={}}};m.id="ui";let g=m;function f(t){return function(t){return"groupedItems"===t.type}(t)||C(t)||y(t)||b(t)||function(t){return"custom"===t.type}(t)}function C(t){return"header"===t.type}function y(t){return"panel"===t.type}function b(t){return"floating"===t.type}const E="ui",I={id:E,name:"UI Plugin",version:"1.0.0",provides:["ui"],requires:[],optional:[],defaultConfig:{enabled:!0,components:{}}};const v={manifest:I,create:(t,e)=>new g(E,t,e),reducer:(t=d,e)=>{switch(e.type){case n:return{...t,...e.payload};case o:{const n=t.panel[e.payload.id]||{},{open:i,visibleChild:o}=e.payload,s=n.visibleChild;let r=n.open,a=n.visibleChild;return o===s?r=void 0!==i?i:!n.open:(a=o,r=!0),{...t,panel:{...t.panel,[e.payload.id]:{...n,open:r,visibleChild:a}}}}case i:return{...t,header:{...t.header,[e.payload.id]:{...t.header[e.payload.id],visible:e.payload.visible,visibleChild:e.payload.visibleChild}}};case s:return{...t,commandMenu:{...t.commandMenu,[e.payload.id]:{activeCommand:e.payload.commandId,triggerElement:e.payload.triggerElement,position:e.payload.position,open:!0,flatten:e.payload.flatten}}};case r:return{...t,commandMenu:{...t.commandMenu,[e.payload.id]:{...t.commandMenu[e.payload.id],open:!1,activeCommand:null,triggerElement:void 0,position:void 0,flatten:!1}}};case a:{const{componentType:n,componentId:i,patch:o}=e.payload;if(!t[n]||!t[n][i])return t;const s=t[n][i],r=Object.fromEntries(Object.entries(o).filter((([t])=>t in s)));return 0===Object.keys(r).length?t:{...t,[n]:{...t[n],[i]:{...s,...r}}}}default:return t}},initialState:d};exports.UIComponent=e,exports.UIPlugin=g,exports.UIPluginPackage=v,exports.UI_PLUGIN_ID=E,exports.createEventController=c,exports.defineComponent=function(){return t=>t},exports.getIconProps=function(t,e){const n=p(t,e);return"group"===n.type?{}:n.iconProps??{}},exports.hasActive=function(t){return"active"in t},exports.isActive=function(t,e){const n=p(t,e);return"group"!==n.type&&!!n.active},exports.isDisabled=function(t,e){const n=p(t,e);return"group"!==n.type&&!!n.disabled},exports.isVisible=function(t,e){const n=p(t,e);return"group"!==n.type&&!!n.visible},exports.manifest=I,exports.resolveMenuItem=p;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","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/ui-plugin.ts","../src/lib/manifest.ts","../src/lib/index.ts","../src/lib/menu/types.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 iconProps: dyn(item.iconProps) ?? {},\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\nexport function getIconProps<TStore>(item: MenuItem<TStore>, state: TStore): any {\n const resolved = resolveMenuItem(item, state);\n if (resolved.type === 'group') {\n return {};\n }\n return resolved.iconProps ?? {};\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 { 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';\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\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 // 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.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 { 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 './menu/utils';\n","import { PluginRegistry } from '@embedpdf/core';\n\nexport type Dynamic<TStore, T> = T | ((state: TStore) => T);\n\nexport type IconProps = {\n primaryColor?: string;\n secondaryColor?: string;\n className?: string;\n title?: string;\n};\n\nexport interface MenuItemBase<TStore = any> {\n icon?: Dynamic<TStore, string>;\n iconProps?: Dynamic<TStore, IconProps>;\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 iconProps?: IconProps;\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"],"names":["UIComponent","constructor","componentConfig","registry","this","children","updateCallbacks","hadUpdateBeforeListeners","props","initialProps","initialState","id","type","addChild","child","priority","className","push","component","sortChildren","sort","a","b","removeChild","filter","c","clearChildren","getRenderType","render","getRenderer","getChildren","getChildContext","context","childContextProp","update","newProps","otherProps","length","notifyUpdate","onUpdate","callback","offUpdate","cb","forEach","UI_INIT_COMPONENTS","UI_SET_HEADER_VISIBLE","UI_TOGGLE_PANEL","UI_SHOW_COMMAND_MENU","UI_HIDE_COMMAND_MENU","UI_UPDATE_COMPONENT_STATE","uiHideCommandMenu","payload","panel","header","groupedItems","divider","iconButton","tabButton","selectButton","custom","floating","commandMenu","createEventController","eventMap","Map","emit","eventType","data","callbacks","get","on","has","set","Set","add","off","delete","size","resolveMenuItem","item","state","dyn","v","label","icon","iconProps","visible","active","disabled","_MenuManager","items","pluginRegistry","shortcutMap","eventController","registerItems","setupKeyboardListeners","getStore","getState","registerItem","console","warn","shortcut","normalizeShortcut","Object","values","resolve","getMenuItem","isGroup","isMenu","isAction","getAction","resolved","getMenuOrAction","getAllItems","getItemsByIds","ids","map","getChildItems","menuId","options","_a","flatten","flattened","menuChildren","executeCommand","action","EVENTS","COMMAND_EXECUTED","command","source","handleSubmenu","executeShortcut","normalizedShortcut","itemId","SHORTCUT_EXECUTED","menuItem","MENU_REQUESTED","triggerElement","position","window","document","addEventListener","event","target","tagName","isContentEditable","buildShortcutString","preventDefault","modifiers","ctrlKey","shiftKey","altKey","metaKey","key","includes","displayKey","toUpperCase","join","split","part","trim","capabilities","bind","MenuManager","_UIPlugin","BasePlugin","config","super","componentRenderers","components","mapStateCallbacks","globalStoreSubscription","menuManager","menuItems","setupCommandEventHandlers","subscribe","_action","newState","onGlobalStoreChange","initialize","buildComponents","linkGroupedItems","setInitialStateUIComponents","activeCommand","dispatch","commandId","log","addComponent","mapStateToProps","entries","isItemWithSlots","slots","slot","componentId","defaultState","definition","uiComponent","mapFn","_id","ownProps","partial","merged","arePropsEqual","addSlot","parentId","slotId","parentComponent","error","childComponent","parentChildren","slotPriority","Math","max","buildCapability","registerComponentRenderer","renderer","getComponent","registerComponent","getCommandMenu","find","isCommandMenuComponent","hideCommandMenu","debouncedDispatch","getFloatingComponents","scrollerPosition","isFloatingComponent","getHeadersByPlacement","placement","isHeaderComponent","getPanelsByLocation","location","isPanelComponent","togglePanel","uiTogglePanel","setHeaderVisible","uiSetHeaderVisible","updateComponentState","uiUpdateComponentState","destroy","UIPlugin","isGroupedItemsComponent","isCustomComponent","UI_PLUGIN_ID","manifest","name","version","provides","requires","optional","defaultConfig","enabled","UIPluginPackage","create","_engine","reducer","prevPanel","open","nextOpen","visibleChild","nextVisibleChild","prevVisibleChild","componentType","patch","current","filteredPatch","fromEntries","k","keys"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","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/ui-plugin.ts","../src/lib/manifest.ts","../src/lib/index.ts","../src/lib/menu/types.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 iconProps: dyn(item.iconProps) ?? {},\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\nexport function getIconProps<TStore>(item: MenuItem<TStore>, state: TStore): any {\n const resolved = resolveMenuItem(item, state);\n if (resolved.type === 'group') {\n return {};\n }\n return resolved.iconProps ?? {};\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 { 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';\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\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 // 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 this.logger.debug('UIPlugin', 'CommandExecuted', `Command executed: ${data.command.id}`, {\n commandId: data.command.id,\n source: data.source,\n });\n });\n }\n\n private addComponent(id: string, componentConfig: UIComponentType<any>) {\n if (this.components[id]) {\n this.logger.warn(\n 'UIPlugin',\n 'ComponentAlreadyExists',\n `Component with ID ${id} already exists and will be overwritten`,\n );\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 this.logger.warn(\n 'UIPlugin',\n 'ChildComponentNotFound',\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 this.logger.error(\n 'UIPlugin',\n 'ParentComponentNotFound',\n `Parent component ${parentId} not found`,\n );\n return;\n }\n\n // 2. Check if parent has slots (is a container type)\n if (!isItemWithSlots(parentComponent)) {\n this.logger.error(\n 'UIPlugin',\n 'ParentComponentDoesNotSupportSlots',\n `Parent component ${parentId} does not support slots`,\n );\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 this.logger.error(\n 'UIPlugin',\n 'ChildComponentNotFound',\n `Child component ${slotId} not found`,\n );\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.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 { 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, 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 './menu/utils';\n","import { PluginRegistry } from '@embedpdf/core';\n\nexport type Dynamic<TStore, T> = T | ((state: TStore) => T);\n\nexport type IconProps = {\n primaryColor?: string;\n secondaryColor?: string;\n className?: string;\n title?: string;\n};\n\nexport interface MenuItemBase<TStore = any> {\n icon?: Dynamic<TStore, string>;\n iconProps?: Dynamic<TStore, IconProps>;\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 iconProps?: IconProps;\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"],"names":["UIComponent","constructor","componentConfig","registry","this","children","updateCallbacks","hadUpdateBeforeListeners","props","initialProps","initialState","id","type","addChild","child","priority","className","push","component","sortChildren","sort","a","b","removeChild","filter","c","clearChildren","getRenderType","render","getRenderer","getChildren","getChildContext","context","childContextProp","update","newProps","otherProps","length","notifyUpdate","onUpdate","callback","offUpdate","cb","forEach","UI_INIT_COMPONENTS","UI_SET_HEADER_VISIBLE","UI_TOGGLE_PANEL","UI_SHOW_COMMAND_MENU","UI_HIDE_COMMAND_MENU","UI_UPDATE_COMPONENT_STATE","uiHideCommandMenu","payload","panel","header","groupedItems","divider","iconButton","tabButton","selectButton","custom","floating","commandMenu","createEventController","eventMap","Map","emit","eventType","data","callbacks","get","on","has","set","Set","add","off","delete","size","resolveMenuItem","item","state","dyn","v","label","icon","iconProps","visible","active","disabled","_MenuManager","items","pluginRegistry","shortcutMap","eventController","registerItems","setupKeyboardListeners","getStore","getState","registerItem","console","warn","shortcut","normalizeShortcut","Object","values","resolve","getMenuItem","isGroup","isMenu","isAction","getAction","resolved","getMenuOrAction","getAllItems","getItemsByIds","ids","map","getChildItems","menuId","options","_a","flatten","flattened","menuChildren","executeCommand","action","EVENTS","COMMAND_EXECUTED","command","source","handleSubmenu","executeShortcut","normalizedShortcut","itemId","SHORTCUT_EXECUTED","menuItem","MENU_REQUESTED","triggerElement","position","window","document","addEventListener","event","target","tagName","isContentEditable","buildShortcutString","preventDefault","modifiers","ctrlKey","shiftKey","altKey","metaKey","key","includes","displayKey","toUpperCase","join","split","part","trim","capabilities","bind","MenuManager","_UIPlugin","BasePlugin","config","super","componentRenderers","components","mapStateCallbacks","globalStoreSubscription","menuManager","menuItems","setupCommandEventHandlers","subscribe","_action","newState","onGlobalStoreChange","initialize","buildComponents","linkGroupedItems","setInitialStateUIComponents","activeCommand","dispatch","commandId","logger","debug","addComponent","mapStateToProps","entries","isItemWithSlots","slots","slot","componentId","defaultState","definition","uiComponent","mapFn","_id","ownProps","partial","merged","arePropsEqual","addSlot","parentId","slotId","parentComponent","error","childComponent","parentChildren","slotPriority","Math","max","buildCapability","registerComponentRenderer","renderer","getComponent","registerComponent","getCommandMenu","find","isCommandMenuComponent","hideCommandMenu","debouncedDispatch","getFloatingComponents","scrollerPosition","isFloatingComponent","getHeadersByPlacement","placement","isHeaderComponent","getPanelsByLocation","location","isPanelComponent","togglePanel","uiTogglePanel","setHeaderVisible","uiSetHeaderVisible","updateComponentState","uiUpdateComponentState","destroy","UIPlugin","isGroupedItemsComponent","isCustomComponent","UI_PLUGIN_ID","manifest","name","version","provides","requires","optional","defaultConfig","enabled","UIPluginPackage","create","reducer","prevPanel","open","nextOpen","visibleChild","nextVisibleChild","prevVisibleChild","componentType","patch","current","filteredPatch","fromEntries","k","keys"],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -561,12 +561,19 @@ const _UIPlugin = class _UIPlugin extends BasePlugin {
|
|
|
561
561
|
);
|
|
562
562
|
});
|
|
563
563
|
this.menuManager.on(MenuManager.EVENTS.COMMAND_EXECUTED, (data) => {
|
|
564
|
-
|
|
564
|
+
this.logger.debug("UIPlugin", "CommandExecuted", `Command executed: ${data.command.id}`, {
|
|
565
|
+
commandId: data.command.id,
|
|
566
|
+
source: data.source
|
|
567
|
+
});
|
|
565
568
|
});
|
|
566
569
|
}
|
|
567
570
|
addComponent(id, componentConfig) {
|
|
568
571
|
if (this.components[id]) {
|
|
569
|
-
|
|
572
|
+
this.logger.warn(
|
|
573
|
+
"UIPlugin",
|
|
574
|
+
"ComponentAlreadyExists",
|
|
575
|
+
`Component with ID ${id} already exists and will be overwritten`
|
|
576
|
+
);
|
|
570
577
|
}
|
|
571
578
|
const component = new UIComponent(componentConfig, this.componentRenderers);
|
|
572
579
|
this.components[id] = component;
|
|
@@ -590,7 +597,9 @@ const _UIPlugin = class _UIPlugin extends BasePlugin {
|
|
|
590
597
|
if (child) {
|
|
591
598
|
component.addChild(slot.componentId, child, slot.priority, slot.className);
|
|
592
599
|
} else {
|
|
593
|
-
|
|
600
|
+
this.logger.warn(
|
|
601
|
+
"UIPlugin",
|
|
602
|
+
"ChildComponentNotFound",
|
|
594
603
|
`Child component ${slot.componentId} not found for GroupedItems ${props.id}`
|
|
595
604
|
);
|
|
596
605
|
}
|
|
@@ -624,16 +633,28 @@ const _UIPlugin = class _UIPlugin extends BasePlugin {
|
|
|
624
633
|
addSlot(parentId, slotId, priority, className) {
|
|
625
634
|
const parentComponent = this.components[parentId];
|
|
626
635
|
if (!parentComponent) {
|
|
627
|
-
|
|
636
|
+
this.logger.error(
|
|
637
|
+
"UIPlugin",
|
|
638
|
+
"ParentComponentNotFound",
|
|
639
|
+
`Parent component ${parentId} not found`
|
|
640
|
+
);
|
|
628
641
|
return;
|
|
629
642
|
}
|
|
630
643
|
if (!isItemWithSlots(parentComponent)) {
|
|
631
|
-
|
|
644
|
+
this.logger.error(
|
|
645
|
+
"UIPlugin",
|
|
646
|
+
"ParentComponentDoesNotSupportSlots",
|
|
647
|
+
`Parent component ${parentId} does not support slots`
|
|
648
|
+
);
|
|
632
649
|
return;
|
|
633
650
|
}
|
|
634
651
|
const childComponent = this.components[slotId];
|
|
635
652
|
if (!childComponent) {
|
|
636
|
-
|
|
653
|
+
this.logger.error(
|
|
654
|
+
"UIPlugin",
|
|
655
|
+
"ChildComponentNotFound",
|
|
656
|
+
`Child component ${slotId} not found`
|
|
657
|
+
);
|
|
637
658
|
return;
|
|
638
659
|
}
|
|
639
660
|
const parentChildren = parentComponent.getChildren();
|
|
@@ -721,7 +742,7 @@ function hasActive(command) {
|
|
|
721
742
|
}
|
|
722
743
|
const UIPluginPackage = {
|
|
723
744
|
manifest,
|
|
724
|
-
create: (registry,
|
|
745
|
+
create: (registry, config) => new UIPlugin(UI_PLUGIN_ID, registry, config),
|
|
725
746
|
reducer: uiReducer,
|
|
726
747
|
initialState
|
|
727
748
|
};
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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/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 iconProps: dyn(item.iconProps) ?? {},\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\nexport function getIconProps<TStore>(item: MenuItem<TStore>, state: TStore): any {\n const resolved = resolveMenuItem(item, state);\n if (resolved.type === 'group') {\n return {};\n }\n return resolved.iconProps ?? {};\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 { 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';\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\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 // 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.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 type IconProps = {\n primaryColor?: string;\n secondaryColor?: string;\n className?: string;\n title?: string;\n};\n\nexport interface MenuItemBase<TStore = any> {\n icon?: Dynamic<TStore, string>;\n iconProps?: Dynamic<TStore, IconProps>;\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 iconProps?: IconProps;\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 './menu/utils';\n"],"names":[],"mappings":"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"}
|
|
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/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 iconProps: dyn(item.iconProps) ?? {},\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\nexport function getIconProps<TStore>(item: MenuItem<TStore>, state: TStore): any {\n const resolved = resolveMenuItem(item, state);\n if (resolved.type === 'group') {\n return {};\n }\n return resolved.iconProps ?? {};\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 { 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';\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\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 // 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 this.logger.debug('UIPlugin', 'CommandExecuted', `Command executed: ${data.command.id}`, {\n commandId: data.command.id,\n source: data.source,\n });\n });\n }\n\n private addComponent(id: string, componentConfig: UIComponentType<any>) {\n if (this.components[id]) {\n this.logger.warn(\n 'UIPlugin',\n 'ComponentAlreadyExists',\n `Component with ID ${id} already exists and will be overwritten`,\n );\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 this.logger.warn(\n 'UIPlugin',\n 'ChildComponentNotFound',\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 this.logger.error(\n 'UIPlugin',\n 'ParentComponentNotFound',\n `Parent component ${parentId} not found`,\n );\n return;\n }\n\n // 2. Check if parent has slots (is a container type)\n if (!isItemWithSlots(parentComponent)) {\n this.logger.error(\n 'UIPlugin',\n 'ParentComponentDoesNotSupportSlots',\n `Parent component ${parentId} does not support slots`,\n );\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 this.logger.error(\n 'UIPlugin',\n 'ChildComponentNotFound',\n `Child component ${slotId} not found`,\n );\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.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 type IconProps = {\n primaryColor?: string;\n secondaryColor?: string;\n className?: string;\n title?: string;\n};\n\nexport interface MenuItemBase<TStore = any> {\n icon?: Dynamic<TStore, string>;\n iconProps?: Dynamic<TStore, IconProps>;\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 iconProps?: IconProps;\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, 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 './menu/utils';\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@embedpdf/plugin-ui",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.19",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.cjs",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -23,19 +23,19 @@
|
|
|
23
23
|
}
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@embedpdf/models": "1.0.
|
|
26
|
+
"@embedpdf/models": "1.0.19"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@types/react": "^18.2.0",
|
|
30
30
|
"typescript": "^5.0.0",
|
|
31
|
-
"@embedpdf/
|
|
32
|
-
"@embedpdf/
|
|
31
|
+
"@embedpdf/build": "1.0.0",
|
|
32
|
+
"@embedpdf/core": "1.0.19"
|
|
33
33
|
},
|
|
34
34
|
"peerDependencies": {
|
|
35
35
|
"react": ">=16.8.0",
|
|
36
36
|
"react-dom": ">=16.8.0",
|
|
37
37
|
"preact": "^10.26.4",
|
|
38
|
-
"@embedpdf/core": "1.0.
|
|
38
|
+
"@embedpdf/core": "1.0.19"
|
|
39
39
|
},
|
|
40
40
|
"files": [
|
|
41
41
|
"dist",
|