@embedpdf/plugin-ui 1.0.16 → 1.0.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/lib/ui-component.ts","../src/lib/actions.ts","../src/lib/reducer.ts","../src/lib/utils.ts","../src/lib/menu/utils.ts","../src/lib/menu/menu-manager.ts","../src/lib/icons/icon-manager.ts","../src/lib/ui-plugin.ts","../src/lib/manifest.ts","../src/lib/menu/types.ts","../src/lib/index.ts"],"sourcesContent":["import { BaseUIComponent, childrenFunctionOptions } from './types';\n\nexport class UIComponent<T extends BaseUIComponent<any, any, any>> {\n public componentConfig: T;\n public props: T['id'] extends string\n ? T extends BaseUIComponent<infer P, any, any>\n ? P & { id: string }\n : any\n : any;\n public type: string;\n private children: Array<{\n id: string;\n component: UIComponent<any>;\n priority: number;\n className?: string;\n }> = [];\n private registry: Record<\n string,\n (\n props: any,\n children: (options?: childrenFunctionOptions) => any[],\n context?: Record<string, any>,\n ) => any\n >;\n private updateCallbacks: (() => void)[] = [];\n private hadUpdateBeforeListeners = false;\n\n constructor(\n componentConfig: T,\n registry: Record<\n string,\n (\n props: any,\n children: (options?: childrenFunctionOptions) => any[],\n context?: Record<string, any>,\n ) => any\n >,\n ) {\n this.componentConfig = componentConfig;\n\n const props = componentConfig.props || {};\n\n if (typeof props === 'function') {\n const initialProps = props(componentConfig.initialState);\n this.props = { ...initialProps, id: componentConfig.id };\n } else {\n this.props = { ...props, id: componentConfig.id };\n }\n\n this.type = componentConfig.type;\n this.registry = registry;\n }\n\n addChild(id: string, child: UIComponent<any>, priority: number = 0, className?: string) {\n this.children.push({ id, component: child, priority, className });\n // Sort children by priority\n this.sortChildren();\n }\n\n // Helper to sort children by priority\n private sortChildren() {\n this.children.sort((a, b) => a.priority - b.priority);\n }\n\n removeChild(child: UIComponent<any>) {\n this.children = this.children.filter((c) => c.component !== child);\n }\n\n clearChildren() {\n this.children = [];\n }\n\n get getRenderType() {\n return this.componentConfig.render || this.type;\n }\n\n public getRenderer() {\n return this.registry[this.getRenderType];\n }\n\n public getChildren() {\n return this.children;\n }\n\n // Optionally, a component can provide a function to extend the context for its children.\n // For instance, a header could supply a \"direction\" based on its position.\n public getChildContext(context: Record<string, any>): Record<string, any> {\n const childContextProp = this.componentConfig.getChildContext;\n if (typeof childContextProp === 'function') {\n // Handle function case (existing behavior)\n return { ...context, ...childContextProp(this.props) };\n } else if (childContextProp && typeof childContextProp === 'object') {\n // Handle object case\n return { ...context, ...childContextProp };\n }\n return context;\n }\n\n update(newProps: Partial<T extends BaseUIComponent<infer P, any, any> ? P : any>) {\n const { id, ...otherProps } = newProps;\n this.props = { ...this.props, ...otherProps };\n if (this.updateCallbacks.length === 0) {\n this.hadUpdateBeforeListeners = true;\n }\n this.notifyUpdate();\n }\n\n onUpdate(callback: () => void) {\n this.updateCallbacks.push(callback);\n return this.hadUpdateBeforeListeners;\n }\n\n offUpdate(callback: () => void) {\n this.updateCallbacks = this.updateCallbacks.filter((cb) => cb !== callback);\n }\n\n protected notifyUpdate() {\n this.updateCallbacks.forEach((cb) => cb());\n }\n}\n","import { Action } from '@embedpdf/core';\nimport { UIPluginState } from './types';\n\nexport const UI_INIT_COMPONENTS = 'UI_INIT_COMPONENTS';\nexport const UI_INIT_FLYOUT = 'UI_INIT_FLYOUT';\nexport const UI_TOGGLE_FLYOUT = 'UI_TOGGLE_FLYOUT';\nexport const UI_SET_HEADER_VISIBLE = 'UI_SET_HEADER_VISIBLE';\nexport const UI_TOGGLE_PANEL = 'UI_TOGGLE_PANEL';\nexport const UI_SHOW_COMMAND_MENU = 'UI_SHOW_COMMAND_MENU';\nexport const UI_HIDE_COMMAND_MENU = 'UI_HIDE_COMMAND_MENU';\nexport const UI_UPDATE_COMMAND_MENU = 'UI_UPDATE_COMMAND_MENU';\nexport const UI_UPDATE_COMPONENT_STATE = 'UI_UPDATE_COMPONENT_STATE';\n\nexport interface InitFlyoutPayload {\n id: string;\n triggerElement: HTMLElement;\n}\n\nexport interface ToggleFlyoutPayload {\n id: string;\n open?: boolean;\n}\n\nexport interface SetHeaderVisiblePayload {\n id: string;\n visible: boolean;\n visibleChild?: string;\n}\n\nexport interface TogglePanelPayload {\n id: string;\n open?: boolean;\n visibleChild: string;\n}\n\nexport interface ShowCommandMenuPayload {\n id: string;\n commandId: string;\n triggerElement?: HTMLElement;\n position?: 'top' | 'bottom' | 'left' | 'right';\n flatten?: boolean;\n}\n\nexport interface UpdateComponentStatePayload<T = any> {\n /** one of the top-level keys inside UIPluginState, e.g. \"panel\" | \"custom\" … */\n componentType: keyof UIPluginState;\n /** same id you used when registering the component */\n componentId: string;\n /** partial patch – only keys existing in the current state will be applied */\n patch: Partial<T>;\n}\n\nexport interface HideCommandMenuPayload {\n id: string;\n}\n\nexport interface UiInitComponentsAction extends Action {\n type: typeof UI_INIT_COMPONENTS;\n payload: UIPluginState;\n}\n\nexport interface UiInitFlyoutAction extends Action {\n type: typeof UI_INIT_FLYOUT;\n payload: InitFlyoutPayload;\n}\n\nexport interface UiToggleFlyoutAction extends Action {\n type: typeof UI_TOGGLE_FLYOUT;\n payload: ToggleFlyoutPayload;\n}\n\nexport interface UiSetHeaderVisibleAction extends Action {\n type: typeof UI_SET_HEADER_VISIBLE;\n payload: SetHeaderVisiblePayload;\n}\n\nexport interface UiTogglePanelAction extends Action {\n type: typeof UI_TOGGLE_PANEL;\n payload: TogglePanelPayload;\n}\n\nexport interface UiShowCommandMenuAction extends Action {\n type: typeof UI_SHOW_COMMAND_MENU;\n payload: ShowCommandMenuPayload;\n}\n\nexport interface UiHideCommandMenuAction extends Action {\n type: typeof UI_HIDE_COMMAND_MENU;\n payload: HideCommandMenuPayload;\n}\n\nexport interface UiUpdateComponentStateAction extends Action {\n type: typeof UI_UPDATE_COMPONENT_STATE;\n payload: UpdateComponentStatePayload;\n}\n\nexport type UIPluginAction =\n | UiInitComponentsAction\n | UiInitFlyoutAction\n | UiToggleFlyoutAction\n | UiSetHeaderVisibleAction\n | UiTogglePanelAction\n | UiShowCommandMenuAction\n | UiHideCommandMenuAction\n | UiUpdateComponentStateAction;\n\nexport const uiInitComponents = (state: UIPluginState): UiInitComponentsAction => ({\n type: UI_INIT_COMPONENTS,\n payload: state,\n});\n\nexport const uiInitFlyout = (payload: InitFlyoutPayload): UiInitFlyoutAction => ({\n type: UI_INIT_FLYOUT,\n payload,\n});\n\nexport const uiToggleFlyout = (payload: ToggleFlyoutPayload): UiToggleFlyoutAction => ({\n type: UI_TOGGLE_FLYOUT,\n payload,\n});\n\nexport const uiTogglePanel = (payload: TogglePanelPayload): UiTogglePanelAction => ({\n type: UI_TOGGLE_PANEL,\n payload,\n});\n\nexport const uiSetHeaderVisible = (payload: SetHeaderVisiblePayload): UiSetHeaderVisibleAction => ({\n type: UI_SET_HEADER_VISIBLE,\n payload,\n});\n\nexport const uiShowCommandMenu = (payload: ShowCommandMenuPayload): UiShowCommandMenuAction => ({\n type: UI_SHOW_COMMAND_MENU,\n payload,\n});\n\nexport const uiHideCommandMenu = (payload: HideCommandMenuPayload): UiHideCommandMenuAction => ({\n type: UI_HIDE_COMMAND_MENU,\n payload,\n});\n\nexport const uiUpdateComponentState = <T>(\n payload: UpdateComponentStatePayload<T>,\n): UiUpdateComponentStateAction => ({\n type: UI_UPDATE_COMPONENT_STATE,\n payload,\n});\n","import { Reducer } from '@embedpdf/core';\nimport { UIPluginState } from './types';\nimport {\n UI_HIDE_COMMAND_MENU,\n UI_INIT_COMPONENTS,\n UI_SET_HEADER_VISIBLE,\n UI_SHOW_COMMAND_MENU,\n UI_TOGGLE_PANEL,\n UI_UPDATE_COMPONENT_STATE,\n UIPluginAction,\n} from './actions';\n\nexport const initialState: UIPluginState = {\n panel: {},\n header: {},\n groupedItems: {},\n divider: {},\n iconButton: {},\n tabButton: {},\n selectButton: {},\n custom: {},\n floating: {},\n commandMenu: {},\n};\n\nexport const uiReducer: Reducer<UIPluginState, UIPluginAction> = (state = initialState, action) => {\n switch (action.type) {\n case UI_INIT_COMPONENTS:\n return {\n ...state,\n ...action.payload,\n };\n case UI_TOGGLE_PANEL: {\n const prevPanel = state.panel[action.payload.id] || {};\n const { open: nextOpen, visibleChild: nextVisibleChild } = action.payload;\n const prevVisibleChild = prevPanel.visibleChild;\n\n let open = prevPanel.open;\n let visibleChild = prevPanel.visibleChild;\n\n if (nextVisibleChild === prevVisibleChild) {\n // Toggle open if visibleChild is the same\n open = nextOpen !== undefined ? nextOpen : !prevPanel.open;\n } else {\n // Only change visibleChild, keep open as is\n visibleChild = nextVisibleChild;\n open = true;\n }\n\n return {\n ...state,\n panel: {\n ...state.panel,\n [action.payload.id]: {\n ...prevPanel,\n open,\n visibleChild,\n },\n },\n };\n }\n case UI_SET_HEADER_VISIBLE:\n return {\n ...state,\n header: {\n ...state.header,\n [action.payload.id]: {\n ...state.header[action.payload.id],\n visible: action.payload.visible,\n visibleChild: action.payload.visibleChild,\n },\n },\n };\n case UI_SHOW_COMMAND_MENU:\n return {\n ...state,\n commandMenu: {\n ...state.commandMenu,\n [action.payload.id]: {\n activeCommand: action.payload.commandId,\n triggerElement: action.payload.triggerElement,\n position: action.payload.position,\n open: true,\n flatten: action.payload.flatten,\n },\n },\n };\n case UI_HIDE_COMMAND_MENU:\n return {\n ...state,\n commandMenu: {\n ...state.commandMenu,\n [action.payload.id]: {\n ...state.commandMenu[action.payload.id],\n open: false,\n activeCommand: null,\n triggerElement: undefined,\n position: undefined,\n flatten: false,\n },\n },\n };\n case UI_UPDATE_COMPONENT_STATE: {\n const { componentType, componentId, patch } = action.payload;\n\n // if the slice or the component is unknown → ignore\n if (!state[componentType] || !state[componentType][componentId]) return state;\n\n const current = state[componentType][componentId] as Record<string, any>;\n\n // keep only keys that already exist\n const filteredPatch = Object.fromEntries(Object.entries(patch).filter(([k]) => k in current));\n\n // no allowed keys? -> no-op\n if (Object.keys(filteredPatch).length === 0) return state;\n\n return {\n ...state,\n [componentType]: {\n ...state[componentType],\n [componentId]: {\n ...current,\n ...filteredPatch,\n },\n },\n };\n }\n default:\n return state;\n }\n};\n","import type { CustomComponent } from './types';\n\nexport function defineComponent<TInit, TProps, TStore = any>() {\n return <\n C extends CustomComponent<TStore> & {\n initialState: TInit;\n props: (init: TInit) => TProps;\n mapStateToProps: (storeState: TStore, ownProps: TProps) => TProps;\n },\n >(\n c: C,\n ) => c;\n}\n\n/**\n * Type definition for event callbacks\n */\nexport type EventCallback = (data: any) => void;\n\n/**\n * Interface for the event controller\n */\nexport interface EventController {\n /**\n * Emit an event of the specified type with the given data\n */\n emit(eventType: string, data: any): void;\n\n /**\n * Subscribe to events of the specified type\n * Returns a function that can be called to unsubscribe\n */\n on(eventType: string, callback: EventCallback): () => void;\n\n /**\n * Unsubscribe a specific callback from events of the specified type\n */\n off(eventType: string, callback: EventCallback): void;\n}\n\n/**\n * Creates an event controller that manages event subscriptions and dispatching\n * This is a lightweight pub/sub implementation for typed events\n */\nexport function createEventController(): EventController {\n // Map of event types to sets of callbacks\n const eventMap = new Map<string, Set<EventCallback>>();\n\n return {\n emit(eventType: string, data: any): void {\n const callbacks = eventMap.get(eventType);\n if (callbacks) {\n // Call each callback with the event data\n callbacks.forEach((callback) => callback(data));\n }\n },\n\n on(eventType: string, callback: EventCallback): () => void {\n // Create a set for this event type if it doesn't exist\n if (!eventMap.has(eventType)) {\n eventMap.set(eventType, new Set());\n }\n\n // Add the callback to the set\n const callbacks = eventMap.get(eventType)!;\n callbacks.add(callback);\n\n // Return a function that removes this specific callback\n return () => this.off(eventType, callback);\n },\n\n off(eventType: string, callback: EventCallback): void {\n const callbacks = eventMap.get(eventType);\n if (callbacks) {\n // Remove the callback from the set\n callbacks.delete(callback);\n\n // Clean up empty sets\n if (callbacks.size === 0) {\n eventMap.delete(eventType);\n }\n }\n },\n };\n}\n","import { MenuItem, Dynamic, ResolvedMenuItem } from './types';\n\nexport function resolveMenuItem<TStore>(\n item: MenuItem<TStore>,\n state: TStore,\n): ResolvedMenuItem<TStore> {\n const dyn = <T>(v: Dynamic<TStore, T> | undefined): T | undefined =>\n typeof v === 'function' ? (v as any)(state) : v;\n\n if (item.type === 'group') {\n return {\n ...item,\n label: dyn(item.label) ?? '',\n };\n }\n\n // spread keeps unknown keys (e.g. children) intact\n return {\n ...item,\n icon: dyn(item.icon) ?? '',\n label: dyn(item.label) ?? '',\n visible: dyn(item.visible) ?? true,\n active: dyn(item.active) ?? false,\n disabled: dyn(item.disabled) ?? false,\n };\n}\n\nexport function isActive<TStore>(item: MenuItem<TStore>, state: TStore): boolean {\n const resolved = resolveMenuItem(item, state);\n\n if (resolved.type === 'group') {\n return false;\n }\n\n return resolved.active ? true : false;\n}\n\nexport function isVisible<TStore>(item: MenuItem<TStore>, state: TStore): boolean {\n const resolved = resolveMenuItem(item, state);\n\n if (resolved.type === 'group') {\n return false;\n }\n\n return resolved.visible ? true : false;\n}\n\nexport function isDisabled<TStore>(item: MenuItem<TStore>, state: TStore): boolean {\n const resolved = resolveMenuItem(item, state);\n\n if (resolved.type === 'group') {\n return false;\n }\n\n return resolved.disabled ? true : false;\n}\n","import { PluginRegistry } from '@embedpdf/core';\nimport {\n MenuItem,\n Action,\n ExecuteOptions,\n ResolvedMenuItem,\n MenuRegistry,\n Menu,\n MenuManagerCapabilities,\n ResolvedMenuItemResult,\n ResolvedMenu,\n ResolvedAction,\n} from './types';\nimport { EventCallback, createEventController } from '../utils';\nimport { resolveMenuItem } from './utils';\n\n/**\n * MenuManager manages a registry of menu items and handles their execution.\n * It also manages keyboard shortcuts and implements responsive behavior.\n */\nexport class MenuManager {\n private registry: MenuRegistry = {};\n private shortcutMap: Record<string, string> = {}; // maps shortcut to menu item id\n private eventController = createEventController();\n private pluginRegistry: PluginRegistry;\n\n // Event types\n static readonly EVENTS = {\n COMMAND_EXECUTED: 'menu:command_executed',\n MENU_REQUESTED: 'menu:requested',\n SHORTCUT_EXECUTED: 'menu:shortcut_executed',\n };\n\n constructor(items: MenuRegistry = {}, pluginRegistry: PluginRegistry) {\n this.pluginRegistry = pluginRegistry;\n this.registerItems(items);\n this.setupKeyboardListeners();\n }\n\n /**\n * Get the current state of the plugin registry\n */\n private get state() {\n return this.pluginRegistry.getStore().getState();\n }\n\n /**\n * Register a single menu item\n */\n registerItem(item: MenuItem): void {\n if (this.registry[item.id]) {\n console.warn(`Menu item with ID ${item.id} already exists and will be overwritten`);\n }\n\n this.registry[item.id] = item;\n\n if ('shortcut' in item && item.shortcut) {\n this.shortcutMap[this.normalizeShortcut(item.shortcut)] = item.id;\n }\n }\n\n /**\n * Register multiple menu items at once\n */\n registerItems(items: MenuRegistry): void {\n Object.values(items).forEach((item) => {\n this.registerItem(item);\n });\n }\n\n /**\n * Resolve a menu item by ID\n */\n public resolve(id: string): ResolvedMenuItem {\n const raw = this.registry[id];\n return resolveMenuItem(raw, this.state);\n }\n\n /**\n * Get a menu item by ID with type information\n */\n getMenuItem(id: string): ResolvedMenuItemResult | undefined {\n const item = this.resolve(id);\n if (!item) return undefined;\n\n return {\n item,\n isGroup: item.type === 'group',\n isMenu: item.type === 'menu',\n isAction: item.type === 'action',\n };\n }\n\n /**\n * Get a action by ID (only returns Action type items)\n */\n getAction(id: string): ResolvedAction | undefined {\n const resolved = this.getMenuItem(id);\n if (!resolved || !resolved.isAction) return undefined;\n return resolved.item as ResolvedAction;\n }\n\n /**\n * Get menu or action by ID\n */\n getMenuOrAction(id: string): ResolvedMenu | ResolvedAction | undefined {\n const resolved = this.getMenuItem(id);\n if (!resolved) return undefined;\n return resolved.item as ResolvedMenu | ResolvedAction;\n }\n\n /**\n * Get all registered menu items\n */\n getAllItems(): MenuRegistry {\n return { ...this.registry };\n }\n\n /**\n * Get menu items by their IDs\n */\n getItemsByIds(ids: string[]): ResolvedMenuItem[] {\n return ids.map((id) => this.resolve(id)).filter((item) => item !== undefined);\n }\n\n /**\n * Get child items for a given menu ID\n * If flatten is true, it will recursively include submenu children but not groups\n */\n getChildItems(menuId: string, options: { flatten?: boolean } = {}): ResolvedMenuItem[] {\n const item = this.resolve(menuId);\n if (!item || !('children' in item) || !item.children?.length) {\n return [];\n }\n\n // Get all immediate children\n const children = this.getItemsByIds(item.children);\n\n // If flatten is false or not specified, return immediate children\n if (!options.flatten) {\n return children;\n }\n\n // If flatten is true, recursively include menu children\n const flattened: ResolvedMenuItem[] = [];\n\n for (const child of children) {\n if (child.type === 'group') {\n // For groups, add the group itself but don't flatten its children\n flattened.push(child);\n } else if (child.type === 'menu') {\n // For menus, recursively flatten their children\n const menuChildren = this.getChildItems(child.id, { flatten: true });\n flattened.push(...menuChildren);\n } else {\n // For commands, add them directly\n flattened.push(child);\n }\n }\n\n return flattened;\n }\n\n /**\n * Execute a command by ID\n */\n executeCommand(id: string, options: ExecuteOptions = {}): void {\n const resolved = this.getMenuItem(id);\n if (!resolved) {\n console.warn(`Menu item '${id}' not found`);\n return;\n }\n if (resolved.item.type === 'group') {\n console.warn(`Cannot execute group '${id}'`);\n return;\n }\n\n const { item } = resolved;\n\n if (item.disabled) {\n console.warn(`Menu item '${id}' is disabled`);\n return;\n }\n\n if (resolved.isAction) {\n // Execute the command's action\n (item as Action).action(this.pluginRegistry, this.state);\n this.eventController.emit(MenuManager.EVENTS.COMMAND_EXECUTED, {\n command: item,\n source: options.source || 'api',\n });\n } else if ('children' in item && item.children?.length) {\n // Handle submenu\n this.handleSubmenu(item, options);\n }\n }\n\n /**\n * Execute a command from a keyboard shortcut\n */\n executeShortcut(shortcut: string): boolean {\n const normalizedShortcut = this.normalizeShortcut(shortcut);\n const itemId = this.shortcutMap[normalizedShortcut];\n\n if (itemId) {\n this.executeCommand(itemId, { source: 'shortcut' });\n this.eventController.emit(MenuManager.EVENTS.SHORTCUT_EXECUTED, {\n shortcut: normalizedShortcut,\n itemId,\n });\n return true;\n }\n return false;\n }\n\n /**\n * Subscribe to menu events\n */\n on(eventType: string, callback: EventCallback): () => void {\n return this.eventController.on(eventType, callback);\n }\n\n /**\n * Remove an event subscription\n */\n off(eventType: string, callback: EventCallback): void {\n this.eventController.off(eventType, callback);\n }\n\n /**\n * Handle a menu item that has children (showing a submenu)\n */\n private handleSubmenu(menuItem: MenuItem, options: ExecuteOptions): void {\n this.eventController.emit(MenuManager.EVENTS.MENU_REQUESTED, {\n menuId: menuItem.id,\n triggerElement: options.triggerElement,\n position: options.position,\n flatten: options.flatten || false,\n });\n }\n\n /**\n * Set up keyboard listeners for shortcuts\n */\n private setupKeyboardListeners(): void {\n if (typeof window === 'undefined') return;\n\n const handleKeyDown = (event: KeyboardEvent) => {\n // Don't handle shortcuts if the event target is an input, textarea, or has contentEditable\n const target = event.target as HTMLElement;\n if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.isContentEditable) {\n return;\n }\n\n const shortcut = this.buildShortcutString(event);\n if (shortcut && this.executeShortcut(shortcut)) {\n event.preventDefault();\n }\n };\n\n document.addEventListener('keydown', handleKeyDown);\n }\n\n /**\n * Convert a KeyboardEvent to a shortcut string\n */\n private buildShortcutString(event: KeyboardEvent): string | null {\n const modifiers: string[] = [];\n if (event.ctrlKey) modifiers.push('Ctrl');\n if (event.shiftKey) modifiers.push('Shift');\n if (event.altKey) modifiers.push('Alt');\n if (event.metaKey) modifiers.push('Meta');\n\n // Only add non-modifier keys\n const key = event.key;\n const isModifier = ['Control', 'Shift', 'Alt', 'Meta'].includes(key);\n if (!isModifier) {\n // Handle special case for uppercase letters\n const displayKey = key.length === 1 ? key.toUpperCase() : key;\n return [...modifiers, displayKey].join('+');\n }\n\n return null;\n }\n\n /**\n * Normalize a shortcut string for consistent comparison\n */\n private normalizeShortcut(shortcut: string): string {\n return shortcut\n .split('+')\n .map((part) => part.trim())\n .join('+');\n }\n\n /**\n * Get capabilities for the MenuManager\n */\n capabilities(): MenuManagerCapabilities {\n return {\n registerItem: this.registerItem.bind(this),\n registerItems: this.registerItems.bind(this),\n executeCommand: this.executeCommand.bind(this),\n getAction: this.getAction.bind(this),\n getMenuOrAction: this.getMenuOrAction.bind(this),\n getChildItems: this.getChildItems.bind(this),\n getItemsByIds: this.getItemsByIds.bind(this),\n getAllItems: this.getAllItems.bind(this),\n };\n }\n}\n","import { Icon, IconCapabilities, IconIdentifier, IconRegistry } from './types';\n\n/**\n * Registry for managing icons throughout the application\n */\nexport class IconManager {\n private icons: IconRegistry = {};\n\n constructor(icons: Icon[] | IconRegistry) {\n this.registerIcons(icons);\n }\n\n /**\n * Register a single icon\n */\n public registerIcon(icon: Icon): void {\n if (this.icons[icon.id]) {\n console.warn(`Icon with ID ${icon.id} already exists and will be overwritten`);\n }\n this.icons[icon.id] = icon;\n }\n\n /**\n * Register multiple icons at once\n */\n public registerIcons(icons: Icon[] | IconRegistry): void {\n if (Array.isArray(icons)) {\n icons.forEach((icon) => this.registerIcon(icon));\n } else {\n Object.entries(icons).forEach(([id, icon]) => this.registerIcon(icon));\n }\n }\n\n /**\n * Get all registered icons\n */\n public getAllIcons(): IconRegistry {\n return { ...this.icons };\n }\n\n /**\n * Get an icon by its ID\n */\n public getIcon(id: string): Icon | undefined {\n return this.icons[id];\n }\n\n /**\n * Check if an identifier is an SVG string\n */\n public isSvgString(identifier: IconIdentifier): boolean {\n return identifier.trim().startsWith('<svg') && identifier.includes('</svg>');\n }\n\n /**\n * Check if a string is an SVG data URI\n */\n public isSvgDataUri(value: string): boolean {\n return value.startsWith('data:image/svg+xml;base64,');\n }\n\n /**\n * Get the SVG string for an icon identifier\n * If the identifier is a raw SVG string, it is returned as is\n * If the identifier is an icon ID, the registered SVG is returned\n */\n public getSvgString(identifier: IconIdentifier): string | undefined {\n if (this.isSvgString(identifier)) {\n return identifier;\n }\n if (this.isSvgDataUri(identifier)) {\n return this.dataUriToSvgString(identifier);\n }\n return this.getIcon(identifier)?.svg;\n }\n\n /**\n * Utility method to parse a data URI\n */\n public dataUriToSvgString(dataUri: string): string {\n const base64 = dataUri.substring('data:image/svg+xml;base64,'.length);\n return atob(base64);\n }\n\n /**\n * Convert an SVG string to a data URI\n */\n public svgStringToDataUri(svgString: string): string {\n const base64 = btoa(svgString);\n return `data:image/svg+xml;base64,${base64}`;\n }\n\n capabilities(): IconCapabilities {\n return {\n registerIcon: this.registerIcon.bind(this),\n registerIcons: this.registerIcons.bind(this),\n getIcon: this.getIcon.bind(this),\n getAllIcons: this.getAllIcons.bind(this),\n getSvgString: this.getSvgString.bind(this),\n isSvgString: this.isSvgString.bind(this),\n isSvgDataUri: this.isSvgDataUri.bind(this),\n dataUriToSvgString: this.dataUriToSvgString.bind(this),\n svgStringToDataUri: this.svgStringToDataUri.bind(this),\n };\n }\n}\n","import { BasePlugin, CoreState, PluginRegistry, StoreState, arePropsEqual } from '@embedpdf/core';\nimport {\n childrenFunctionOptions,\n CommandMenuComponent,\n CustomComponent,\n FloatingComponent,\n GroupedItemsComponent,\n HeaderComponent,\n PanelComponent,\n UICapability,\n UIComponentType,\n UIPluginConfig,\n UIPluginState,\n} from './types';\nimport { UIComponent } from './ui-component';\nimport { initialState } from './reducer';\nimport {\n uiInitComponents,\n UIPluginAction,\n uiSetHeaderVisible,\n uiShowCommandMenu,\n uiTogglePanel,\n uiHideCommandMenu,\n TogglePanelPayload,\n SetHeaderVisiblePayload,\n uiUpdateComponentState,\n UpdateComponentStatePayload,\n} from './actions';\nimport { MenuManager } from './menu/menu-manager';\nimport { IconManager } from './icons/icon-manager';\n\nexport class UIPlugin extends BasePlugin<\n UIPluginConfig,\n UICapability,\n UIPluginState,\n UIPluginAction\n> {\n static readonly id = 'ui' as const;\n private componentRenderers: Record<\n string,\n (\n props: any,\n children: (options?: childrenFunctionOptions) => any[],\n context?: Record<string, any>,\n ) => any\n > = {};\n private components: Record<string, UIComponent<UIComponentType<any>>> = {};\n private config: UIPluginConfig;\n private mapStateCallbacks: {\n [componentId: string]: (storeState: any, ownProps: any) => any;\n } = {};\n private globalStoreSubscription: () => void = () => {};\n private menuManager: MenuManager; // Add this\n private iconManager: IconManager;\n\n constructor(id: string, registry: PluginRegistry, config: UIPluginConfig) {\n super(id, registry);\n this.config = config;\n\n // Initialize command center\n this.menuManager = new MenuManager(config.menuItems || {}, this.registry);\n\n // Initialize icon registry\n this.iconManager = new IconManager(config.icons || []);\n\n // Subscribe to command events\n this.setupCommandEventHandlers();\n\n // Subscribe exactly once to the global store\n this.globalStoreSubscription = this.registry.getStore().subscribe((_action, newState) => {\n this.onGlobalStoreChange(newState);\n });\n }\n\n async initialize(): Promise<void> {\n // Step 1: Build all individual components\n this.buildComponents();\n\n // Step 2: Link children for grouped items\n this.linkGroupedItems();\n\n // Step 3: Set initial state for UI components\n this.setInitialStateUIComponents();\n }\n\n // Set up handlers for command events\n private setupCommandEventHandlers(): void {\n // Handle command menu requests\n this.menuManager.on(MenuManager.EVENTS.MENU_REQUESTED, (data) => {\n const { menuId, triggerElement, position, flatten } = data;\n\n const isOpen = this.state.commandMenu.commandMenu?.activeCommand === menuId;\n if (isOpen) {\n return this.dispatch(uiHideCommandMenu({ id: 'commandMenu' }));\n }\n\n this.dispatch(\n uiShowCommandMenu({\n id: 'commandMenu',\n commandId: menuId,\n triggerElement,\n position,\n flatten,\n }),\n );\n });\n\n // Optional: Track command execution for analytics or other purposes\n this.menuManager.on(MenuManager.EVENTS.COMMAND_EXECUTED, (data) => {\n console.log('Command executed:', data.command.id, 'source:', data.source);\n });\n }\n\n private addComponent(id: string, componentConfig: UIComponentType<any>) {\n if (this.components[id]) {\n console.warn(`Component with ID ${id} already exists and will be overwritten`);\n }\n // Step 1: Build the UIComponent\n const component = new UIComponent(componentConfig, this.componentRenderers);\n this.components[id] = component;\n\n // Step 2: Store mapStateToProps if present\n if (typeof componentConfig.mapStateToProps === 'function') {\n this.mapStateCallbacks[id] = componentConfig.mapStateToProps;\n }\n\n return component;\n }\n\n private buildComponents() {\n Object.entries(this.config.components).forEach(([id, componentConfig]) => {\n this.addComponent(id, componentConfig);\n });\n }\n\n private linkGroupedItems() {\n Object.values(this.components).forEach((component) => {\n if (isItemWithSlots(component)) {\n const props = component.componentConfig;\n props.slots?.forEach((slot) => {\n const child = this.components[slot.componentId];\n if (child) {\n component.addChild(slot.componentId, child, slot.priority, slot.className);\n } else {\n console.warn(\n `Child component ${slot.componentId} not found for GroupedItems ${props.id}`,\n );\n }\n });\n }\n });\n }\n\n private setInitialStateUIComponents() {\n const defaultState: UIPluginState = initialState;\n\n Object.entries(this.config.components).forEach(([componentId, definition]) => {\n if (definition.initialState) {\n // store the initialState object, e.g. { open: false } or { active: true }\n defaultState[definition.type][componentId] = definition.initialState;\n } else {\n defaultState[definition.type][componentId] = {};\n }\n });\n\n this.dispatch(uiInitComponents(defaultState));\n }\n\n private onGlobalStoreChange(state: StoreState<CoreState>) {\n for (const [id, uiComponent] of Object.entries(this.components)) {\n const mapFn = this.mapStateCallbacks[id];\n if (!mapFn) continue; // no mapping\n\n // ownProps is the UIComponent's current props\n const { id: _id, ...ownProps } = uiComponent.props;\n\n const partial = mapFn(state, ownProps);\n // If partial is non-empty or changes from old, do update\n const merged = { ...ownProps, ...partial };\n\n if (!arePropsEqual(ownProps, merged)) {\n uiComponent.update(partial);\n }\n }\n }\n\n private addSlot(parentId: string, slotId: string, priority?: number, className?: string) {\n // 1. Get the parent component\n const parentComponent = this.components[parentId];\n\n if (!parentComponent) {\n console.error(`Parent component ${parentId} not found`);\n return;\n }\n\n // 2. Check if parent has slots (is a container type)\n if (!isItemWithSlots(parentComponent)) {\n console.error(`Parent component ${parentId} does not support slots`);\n return;\n }\n\n // 3. Get the component to add to the slot\n const childComponent = this.components[slotId];\n\n if (!childComponent) {\n console.error(`Child component ${slotId} not found`);\n return;\n }\n\n const parentChildren = parentComponent.getChildren();\n\n // 4. Determine priority for the new slot\n let slotPriority = priority;\n\n if (slotPriority === undefined) {\n // If no priority is specified, add it at the end with a reasonable gap\n const maxPriority =\n parentChildren.length > 0 ? Math.max(...parentChildren.map((child) => child.priority)) : 0;\n slotPriority = maxPriority + 10; // Add a gap of 10\n }\n\n // 6. Add the child to the parent component with the appropriate priority\n // The UIComponent will handle sorting and avoid duplicates\n parentComponent.addChild(slotId, childComponent, slotPriority, className);\n }\n\n protected buildCapability(): UICapability {\n return {\n registerComponentRenderer: (\n type: string,\n renderer: (\n props: any,\n children: (options?: childrenFunctionOptions) => any[],\n context?: Record<string, any>,\n ) => any,\n ) => {\n this.componentRenderers[type] = renderer;\n },\n getComponent: <T>(id: string): T | undefined => {\n return this.components[id] as T | undefined;\n },\n registerComponent: this.addComponent.bind(this),\n getCommandMenu: () =>\n Object.values(this.components).find((component) => isCommandMenuComponent(component)),\n hideCommandMenu: () => this.debouncedDispatch(uiHideCommandMenu({ id: 'commandMenu' }), 100),\n getFloatingComponents: (scrollerPosition?: 'inside' | 'outside') =>\n Object.values(this.components)\n .filter((component) => isFloatingComponent(component))\n .filter(\n (component) =>\n !scrollerPosition || component.props.scrollerPosition === scrollerPosition,\n ),\n getHeadersByPlacement: (placement: 'top' | 'bottom' | 'left' | 'right') =>\n Object.values(this.components)\n .filter((component) => isHeaderComponent(component))\n .filter((component) => component.props.placement === placement),\n getPanelsByLocation: (location: 'left' | 'right') =>\n Object.values(this.components)\n .filter((component) => isPanelComponent(component))\n .filter((component) => component.props.location === location),\n addSlot: this.addSlot.bind(this),\n togglePanel: (payload: TogglePanelPayload) => {\n this.dispatch(uiTogglePanel(payload));\n },\n setHeaderVisible: (payload: SetHeaderVisiblePayload) => {\n this.dispatch(uiSetHeaderVisible(payload));\n },\n updateComponentState: (payload: UpdateComponentStatePayload) => {\n this.dispatch(uiUpdateComponentState(payload));\n },\n ...this.iconManager.capabilities(),\n ...this.menuManager.capabilities(),\n };\n }\n\n async destroy(): Promise<void> {\n this.globalStoreSubscription();\n this.components = {};\n this.componentRenderers = {};\n this.mapStateCallbacks = {};\n }\n}\n\nfunction isItemWithSlots(\n component: UIComponent<UIComponentType<any>>,\n): component is\n | UIComponent<GroupedItemsComponent>\n | UIComponent<HeaderComponent>\n | UIComponent<PanelComponent>\n | UIComponent<FloatingComponent>\n | UIComponent<CustomComponent> {\n return (\n isGroupedItemsComponent(component) ||\n isHeaderComponent(component) ||\n isPanelComponent(component) ||\n isFloatingComponent(component) ||\n isCustomComponent(component)\n );\n}\n\n// Type guard function\nfunction isGroupedItemsComponent(\n component: UIComponent<UIComponentType>,\n): component is UIComponent<GroupedItemsComponent> {\n return component.type === 'groupedItems';\n}\n\nfunction isHeaderComponent(\n component: UIComponent<UIComponentType>,\n): component is UIComponent<HeaderComponent> {\n return component.type === 'header';\n}\n\nfunction isPanelComponent(\n component: UIComponent<UIComponentType>,\n): component is UIComponent<PanelComponent> {\n return component.type === 'panel';\n}\n\nfunction isFloatingComponent(\n component: UIComponent<UIComponentType>,\n): component is UIComponent<FloatingComponent> {\n return component.type === 'floating';\n}\n\nfunction isCommandMenuComponent(\n component: UIComponent<UIComponentType>,\n): component is UIComponent<CommandMenuComponent> {\n return component.type === 'commandMenu';\n}\n\nfunction isCustomComponent(\n component: UIComponent<UIComponentType>,\n): component is UIComponent<CustomComponent> {\n return component.type === 'custom';\n}\n","import { PluginManifest } from '@embedpdf/core';\nimport { UIPluginConfig } from './types';\n\nexport const UI_PLUGIN_ID = 'ui';\n\nexport const manifest: PluginManifest<UIPluginConfig> = {\n id: UI_PLUGIN_ID,\n name: 'UI Plugin',\n version: '1.0.0',\n provides: ['ui'],\n requires: [],\n optional: [],\n defaultConfig: {\n enabled: true,\n components: {},\n },\n};\n","import { PluginRegistry } from '@embedpdf/core';\n\nexport type Dynamic<TStore, T> = T | ((state: TStore) => T);\n\nexport interface MenuItemBase<TStore = any> {\n icon?: Dynamic<TStore, string>;\n label: Dynamic<TStore, string>;\n active?: Dynamic<TStore, boolean>; // whether command is currently active\n disabled?: Dynamic<TStore, boolean>; // whether command is currently disabled\n shortcut?: string; // \"Ctrl+Plus\"\n shortcutLabel?: string; // \"Ctrl+Plus\"\n visible?: Dynamic<TStore, boolean>; // whether command should be visible\n dividerBefore?: boolean; // whether to add a divider before the command\n}\n\nexport interface Action<TStore = any> extends MenuItemBase<TStore> {\n id: string; // \"zoomIn\"\n type: 'action'; // i18n key or literal\n action: (registry: PluginRegistry, state: TStore) => void; // executed onClick // whether to add a divider before the command\n}\n\nexport interface Group<TStore = any> {\n id: string;\n type: 'group';\n label: Dynamic<TStore, string>;\n children: string[];\n}\n\nexport interface Menu<TStore = any> extends MenuItemBase<TStore> {\n id: string;\n type: 'menu';\n children: string[];\n}\n\nexport type MenuItem<TStore = any> = Action<TStore> | Group | Menu<TStore>;\n\nexport type MenuRegistry = Record<string, MenuItem>;\n\n// Options for executing an action\nexport interface ExecuteOptions {\n source?: 'click' | 'shortcut' | 'api';\n triggerElement?: HTMLElement;\n flatten?: boolean;\n position?: 'top' | 'bottom' | 'left' | 'right';\n}\n\nexport function hasActive<TStore>(command: MenuItem<TStore>): command is Action<TStore> {\n return 'active' in command;\n}\n\nexport interface MenuManagerCapabilities {\n registerItem: (commandItem: MenuItem) => void;\n registerItems: (commands: MenuRegistry) => void;\n executeCommand: (id: string, options?: ExecuteOptions) => void;\n getAction: (id: string) => ResolvedAction | undefined;\n getMenuOrAction: (id: string) => ResolvedMenu | ResolvedAction | undefined;\n getChildItems: (commandId: string, options?: { flatten?: boolean }) => ResolvedMenuItem[];\n getItemsByIds: (ids: string[]) => ResolvedMenuItem[];\n getAllItems: () => MenuRegistry;\n}\n\n// Add these new resolved types after the existing interfaces\nexport type Resolved<TStore, T> = T extends Dynamic<TStore, infer U> ? U : T;\n\nexport interface ResolvedMenuItemBase<TStore = any> {\n icon?: string;\n label: string;\n active?: boolean;\n disabled?: boolean;\n shortcut?: string;\n shortcutLabel?: string;\n visible?: boolean;\n dividerBefore?: boolean;\n}\n\nexport interface ResolvedAction<TStore = any> extends ResolvedMenuItemBase<TStore> {\n id: string;\n type: 'action';\n action: (registry: PluginRegistry, state: TStore) => void;\n}\n\nexport interface ResolvedGroup<TStore = any> {\n id: string;\n type: 'group';\n label: string;\n children: string[];\n}\n\nexport interface ResolvedMenu<TStore = any> extends ResolvedMenuItemBase<TStore> {\n id: string;\n type: 'menu';\n children: string[];\n}\n\nexport type ResolvedMenuItem<TStore = any> =\n | ResolvedAction<TStore>\n | ResolvedGroup<TStore>\n | ResolvedMenu<TStore>;\n\n// Result of menu item resolution\nexport interface ResolvedMenuItemResult<TStore = any> {\n item: ResolvedMenuItem<TStore>;\n isGroup: boolean;\n isMenu: boolean;\n isAction: boolean;\n}\n","import { PluginPackage } from '@embedpdf/core';\nimport { UIPlugin } from './ui-plugin';\nimport { manifest, UI_PLUGIN_ID } from './manifest';\nimport { UIPluginConfig, UIPluginState } from './types';\nimport { uiReducer, initialState } from './reducer';\nimport { UIPluginAction } from './actions';\n\nexport const UIPluginPackage: PluginPackage<\n UIPlugin,\n UIPluginConfig,\n UIPluginState,\n UIPluginAction\n> = {\n manifest,\n create: (registry, _engine, config) => new UIPlugin(UI_PLUGIN_ID, registry, config!),\n reducer: uiReducer,\n initialState,\n};\n\nexport * from './manifest';\nexport * from './ui-plugin';\nexport * from './types';\nexport * from './ui-component';\nexport * from './utils';\nexport * from './menu/types';\nexport * from './icons/types';\nexport * from './menu/utils';\n"],"names":[],"mappings":"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"}
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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"}
@@ -9,5 +9,4 @@ export * from './types';
9
9
  export * from './ui-component';
10
10
  export * from './utils';
11
11
  export * from './menu/types';
12
- export * from './icons/types';
13
12
  export * from './menu/utils';
@@ -1,7 +1,14 @@
1
1
  import { PluginRegistry } from '@embedpdf/core';
2
2
  export type Dynamic<TStore, T> = T | ((state: TStore) => T);
3
+ export type IconProps = {
4
+ primaryColor?: string;
5
+ secondaryColor?: string;
6
+ className?: string;
7
+ title?: string;
8
+ };
3
9
  export interface MenuItemBase<TStore = any> {
4
10
  icon?: Dynamic<TStore, string>;
11
+ iconProps?: Dynamic<TStore, IconProps>;
5
12
  label: Dynamic<TStore, string>;
6
13
  active?: Dynamic<TStore, boolean>;
7
14
  disabled?: Dynamic<TStore, boolean>;
@@ -50,6 +57,7 @@ export interface MenuManagerCapabilities {
50
57
  export type Resolved<TStore, T> = T extends Dynamic<TStore, infer U> ? U : T;
51
58
  export interface ResolvedMenuItemBase<TStore = any> {
52
59
  icon?: string;
60
+ iconProps?: IconProps;
53
61
  label: string;
54
62
  active?: boolean;
55
63
  disabled?: boolean;
@@ -3,3 +3,4 @@ export declare function resolveMenuItem<TStore>(item: MenuItem<TStore>, state: T
3
3
  export declare function isActive<TStore>(item: MenuItem<TStore>, state: TStore): boolean;
4
4
  export declare function isVisible<TStore>(item: MenuItem<TStore>, state: TStore): boolean;
5
5
  export declare function isDisabled<TStore>(item: MenuItem<TStore>, state: TStore): boolean;
6
+ export declare function getIconProps<TStore>(item: MenuItem<TStore>, state: TStore): any;
@@ -1,14 +1,12 @@
1
1
  import { CoreState } from '@embedpdf/core';
2
2
  import { UI_PLUGIN_ID } from './manifest';
3
3
  import { UIComponent } from './ui-component';
4
- import { MenuRegistry, MenuManagerCapabilities } from './menu/types';
5
- import { IconRegistry, IconCapabilities } from './icons/types';
4
+ import { MenuRegistry, MenuManagerCapabilities, IconProps } from './menu/types';
6
5
  import { SetHeaderVisiblePayload, TogglePanelPayload, UpdateComponentStatePayload } from './actions';
7
6
  export interface UIPluginConfig {
8
7
  enabled: boolean;
9
8
  components: Record<string, UIComponentType>;
10
9
  menuItems?: MenuRegistry;
11
- icons?: IconRegistry;
12
10
  }
13
11
  export interface UIPluginState {
14
12
  panel: {
@@ -47,7 +45,7 @@ export interface childrenFunctionOptions {
47
45
  context?: Record<string, any>;
48
46
  filter?: (childId: string) => boolean;
49
47
  }
50
- export type UICapability = IconCapabilities & MenuManagerCapabilities & {
48
+ export type UICapability = MenuManagerCapabilities & {
51
49
  registerComponentRenderer: (type: string, renderer: (props: any, children: (options?: childrenFunctionOptions) => any[], context?: Record<string, any>) => any) => void;
52
50
  getComponent: <T extends BaseUIComponent<any, any, any>>(id: string) => UIComponent<T> | undefined;
53
51
  getCommandMenu: () => UIComponent<CommandMenuComponent> | undefined;
@@ -132,6 +130,7 @@ export interface IconButtonProps {
132
130
  active?: boolean;
133
131
  disabled?: boolean;
134
132
  commandId?: string;
133
+ iconProps?: IconProps;
135
134
  onClick?: () => void;
136
135
  label?: string;
137
136
  img?: string;
@@ -9,7 +9,6 @@ export declare class UIPlugin extends BasePlugin<UIPluginConfig, UICapability, U
9
9
  private mapStateCallbacks;
10
10
  private globalStoreSubscription;
11
11
  private menuManager;
12
- private iconManager;
13
12
  constructor(id: string, registry: PluginRegistry, config: UIPluginConfig);
14
13
  initialize(): Promise<void>;
15
14
  private setupCommandEventHandlers;
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("preact/jsx-runtime"),t=require("@embedpdf/core/preact"),n=require("@embedpdf/plugin-ui");require("preact");const o=require("preact/hooks"),r=()=>t.useCapability(n.UIPlugin.id);function i({component:t,parentContext:n={}}){const[r,s]=o.useState({});o.useEffect((()=>{const e=()=>s({});return t.onUpdate(e)&&s({}),()=>t.offUpdate(e)}),[t]);const l=t.getChildContext(n),g=t.getRenderer();if(!g)throw new Error(`No renderer for type: ${t.getRenderType}`);return g(t.props,(function(n){const o=(null==n?void 0:n.context)?{...l,...n.context}:l;return t.getChildren().filter((({id:e})=>!(null==n?void 0:n.filter)||n.filter(e))).map((({component:t,id:n,className:r})=>r?e.jsx("div",{className:r,children:e.jsx(i,{component:t,parentContext:o},n)}):e.jsx(i,{component:t,parentContext:o},n)))}),l)}exports.PluginUIProvider=function({children:t}){const{provides:n}=r(),o=t=>t.map((t=>e.jsx(i,{component:t},t.props.id)));return t({headers:{top:o((null==n?void 0:n.getHeadersByPlacement("top"))||[]),bottom:o((null==n?void 0:n.getHeadersByPlacement("bottom"))||[]),left:o((null==n?void 0:n.getHeadersByPlacement("left"))||[]),right:o((null==n?void 0:n.getHeadersByPlacement("right"))||[])},panels:{left:o((null==n?void 0:n.getPanelsByLocation("left"))||[]),right:o((null==n?void 0:n.getPanelsByLocation("right"))||[])},floating:{insideScroller:o((null==n?void 0:n.getFloatingComponents("inside"))||[]),outsideScroller:o((null==n?void 0:n.getFloatingComponents("outside"))||[])},commandMenu:(null==n?void 0:n.getCommandMenu())?e.jsx(i,{component:n.getCommandMenu()}):null})},exports.useIcon=function(){const{provides:e}=r();if(!e)throw new Error("useIcon must be used within a UI context");const{registerIcon:t,registerIcons:n,getIcon:o,getAllIcons:i,getSvgString:s,isSvgString:l,isSvgDataUri:g,dataUriToSvgString:a,svgStringToDataUri:c}=e;return{registerIcon:t,registerIcons:n,getIcon:o,getAllIcons:i,getSvgString:s,isSvgString:l,isSvgDataUri:g,dataUriToSvgString:a,svgStringToDataUri:c}},exports.useUICapability=r,exports.useUIPlugin=()=>t.usePlugin(n.UIPlugin.id);
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("preact/jsx-runtime"),t=require("@embedpdf/core/preact"),n=require("@embedpdf/plugin-ui");require("preact");const o=require("preact/hooks"),r=()=>t.useCapability(n.UIPlugin.id);function i({component:t,parentContext:n={}}){const[r,l]=o.useState({});o.useEffect((()=>{const e=()=>l({});return t.onUpdate(e)&&l({}),()=>t.offUpdate(e)}),[t]);const s=t.getChildContext(n),d=t.getRenderer();if(!d)throw new Error(`No renderer for type: ${t.getRenderType}`);return d(t.props,(function(n){const o=(null==n?void 0:n.context)?{...s,...n.context}:s;return t.getChildren().filter((({id:e})=>!(null==n?void 0:n.filter)||n.filter(e))).map((({component:t,id:n,className:r})=>r?e.jsx("div",{className:r,children:e.jsx(i,{component:t,parentContext:o},n)}):e.jsx(i,{component:t,parentContext:o},n)))}),s)}exports.PluginUIProvider=function({children:t}){const{provides:n}=r(),o=t=>t.map((t=>e.jsx(i,{component:t},t.props.id)));return t({headers:{top:o((null==n?void 0:n.getHeadersByPlacement("top"))||[]),bottom:o((null==n?void 0:n.getHeadersByPlacement("bottom"))||[]),left:o((null==n?void 0:n.getHeadersByPlacement("left"))||[]),right:o((null==n?void 0:n.getHeadersByPlacement("right"))||[])},panels:{left:o((null==n?void 0:n.getPanelsByLocation("left"))||[]),right:o((null==n?void 0:n.getPanelsByLocation("right"))||[])},floating:{insideScroller:o((null==n?void 0:n.getFloatingComponents("inside"))||[]),outsideScroller:o((null==n?void 0:n.getFloatingComponents("outside"))||[])},commandMenu:(null==n?void 0:n.getCommandMenu())?e.jsx(i,{component:n.getCommandMenu()}):null})},exports.useUICapability=r,exports.useUIPlugin=()=>t.usePlugin(n.UIPlugin.id);
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../../src/shared/hooks/use-ui.ts","../../src/shared/components/component-wrapper.tsx","../../src/shared/components/plugin-ui-provider.tsx","../../src/shared/hooks/use-icon.ts"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/@framework';\nimport { UIPlugin } from '@embedpdf/plugin-ui';\n\nexport const useUIPlugin = () => usePlugin<UIPlugin>(UIPlugin.id);\nexport const useUICapability = () => useCapability<UIPlugin>(UIPlugin.id);\n","import { useState, useEffect } from '@framework';\nimport { childrenFunctionOptions, UIComponent } from '@embedpdf/plugin-ui';\n\nexport function ComponentWrapper({\n component,\n parentContext = {},\n}: {\n component: UIComponent<any>;\n parentContext?: Record<string, any>;\n}) {\n const [_, forceUpdate] = useState({});\n\n useEffect(() => {\n const updateCallback = () => forceUpdate({});\n // If the component had updated before we attach the listener, force one re-render\n if (component.onUpdate(updateCallback)) {\n forceUpdate({});\n }\n return () => component.offUpdate(updateCallback);\n }, [component]);\n\n // Merge contexts from parent + the UIComponent's own child context\n const childContext = component.getChildContext(parentContext);\n\n // Instead of returning `component.render()`, we do the following:\n\n // 1) Look up the \"renderer function\" for this component type\n const renderer = component.getRenderer(); // We'll define getRenderer() below\n\n if (!renderer) {\n throw new Error(`No renderer for type: ${component.getRenderType}`);\n }\n\n // 2) Build a function that returns child wrappers\n function renderChildrenFn(options?: childrenFunctionOptions) {\n const merged = options?.context ? { ...childContext, ...options.context } : childContext;\n return component\n .getChildren()\n .filter(({ id }) => {\n // If filter function is provided, use it to determine if we should include this child\n return !options?.filter || options.filter(id);\n })\n .map(({ component: child, id, className }) =>\n className ? (\n <div className={className}>\n <ComponentWrapper key={id} component={child} parentContext={merged} />\n </div>\n ) : (\n <ComponentWrapper key={id} component={child} parentContext={merged} />\n ),\n );\n }\n\n // 3) Finally call the renderer with (props, childrenFn, context)\n return renderer(component.props, renderChildrenFn, childContext);\n}\n","import { ReactNode } from '@framework';\nimport { useUICapability } from '../hooks';\nimport { ComponentWrapper } from './component-wrapper';\nimport { UIComponent } from '@embedpdf/plugin-ui';\n\n/**\n * Interface for UI components organized by type/location\n */\nexport interface UIComponentsMap {\n headers: {\n top: ReactNode[];\n bottom: ReactNode[];\n left: ReactNode[];\n right: ReactNode[];\n };\n panels: {\n left: ReactNode[];\n right: ReactNode[];\n };\n floating: {\n insideScroller: ReactNode[];\n outsideScroller: ReactNode[];\n };\n commandMenu: ReactNode | null;\n}\n\n/**\n * Props for the PluginUIProvider\n */\nexport interface PluginUIProviderProps {\n /**\n * Render function that receives UI components\n */\n children: (components: UIComponentsMap) => ReactNode;\n}\n\n/**\n * PluginUIProvider collects all components from the UI plugin system\n * and provides them to a render function without imposing any structure.\n *\n * It uses the render props pattern for maximum flexibility.\n */\nexport function PluginUIProvider({ children }: PluginUIProviderProps) {\n const { provides: uiProvides } = useUICapability();\n\n // Helper function to wrap UIComponents as JSX elements\n const wrapComponents = (components: UIComponent<any>[]): ReactNode[] => {\n return components.map((component) => (\n <ComponentWrapper key={component.props.id} component={component} />\n ));\n };\n\n // Collect and wrap all components from UI plugin\n const componentMap: UIComponentsMap = {\n headers: {\n top: wrapComponents(uiProvides?.getHeadersByPlacement('top') || []),\n bottom: wrapComponents(uiProvides?.getHeadersByPlacement('bottom') || []),\n left: wrapComponents(uiProvides?.getHeadersByPlacement('left') || []),\n right: wrapComponents(uiProvides?.getHeadersByPlacement('right') || []),\n },\n panels: {\n left: wrapComponents(uiProvides?.getPanelsByLocation('left') || []),\n right: wrapComponents(uiProvides?.getPanelsByLocation('right') || []),\n },\n floating: {\n insideScroller: wrapComponents(uiProvides?.getFloatingComponents('inside') || []),\n outsideScroller: wrapComponents(uiProvides?.getFloatingComponents('outside') || []),\n },\n commandMenu: uiProvides?.getCommandMenu() ? (\n <ComponentWrapper component={uiProvides.getCommandMenu()!} />\n ) : null,\n };\n\n // Let the consumer determine the layout structure through the render prop\n return children(componentMap);\n}\n","import { useUICapability } from './use-ui';\nimport { IconIdentifier, Icon as IconType, IconRegistry } from '@embedpdf/plugin-ui';\n\n/**\n * Hook to access icon functionality in React\n */\nexport function useIcon() {\n const { provides: uiProvides } = useUICapability();\n\n if (!uiProvides) {\n throw new Error('useIcon must be used within a UI context');\n }\n\n const {\n registerIcon,\n registerIcons,\n getIcon,\n getAllIcons,\n getSvgString,\n isSvgString,\n isSvgDataUri,\n dataUriToSvgString,\n svgStringToDataUri,\n } = uiProvides;\n\n return {\n registerIcon,\n registerIcons,\n getIcon,\n getAllIcons,\n getSvgString,\n isSvgString,\n isSvgDataUri,\n dataUriToSvgString,\n svgStringToDataUri,\n };\n}\n"],"names":["useUICapability","useCapability","UIPlugin","id","ComponentWrapper","component","parentContext","_","forceUpdate","useState","useEffect","updateCallback","onUpdate","offUpdate","childContext","getChildContext","renderer","getRenderer","Error","getRenderType","props","options","merged","context","getChildren","filter","map","child","className","jsxRuntime","jsx","children","provides","uiProvides","wrapComponents","components","headers","top","getHeadersByPlacement","bottom","left","right","panels","getPanelsByLocation","floating","insideScroller","getFloatingComponents","outsideScroller","commandMenu","getCommandMenu","registerIcon","registerIcons","getIcon","getAllIcons","getSvgString","isSvgString","isSvgDataUri","dataUriToSvgString","svgStringToDataUri","usePlugin"],"mappings":"4OAIaA,EAAkB,IAAMC,gBAAwBC,EAAAA,SAASC,ICD/D,SAASC,GAAiBC,UAC/BA,EAAAC,cACAA,EAAgB,CAAA,IAKhB,MAAOC,EAAGC,GAAeC,EAAAA,SAAS,CAAA,GAElCC,EAAAA,WAAU,KACR,MAAMC,EAAiB,IAAMH,EAAY,IAKlC,OAHHH,EAAUO,SAASD,IACrBH,EAAY,CAAA,GAEP,IAAMH,EAAUQ,UAAUF,EAAc,GAC9C,CAACN,IAGE,MAAAS,EAAeT,EAAUU,gBAAgBT,GAKzCU,EAAWX,EAAUY,cAE3B,IAAKD,EACH,MAAM,IAAIE,MAAM,yBAAyBb,EAAUc,iBAwBrD,OAAOH,EAASX,EAAUe,OApB1B,SAA0BC,GAClB,MAAAC,SAASD,WAASE,SAAU,IAAKT,KAAiBO,EAAQE,SAAYT,EAC5E,OAAOT,EACJmB,cACAC,QAAO,EAAGtB,UAED,MAAAkB,OAAA,EAAAA,EAASI,SAAUJ,EAAQI,OAAOtB,KAE3CuB,KAAI,EAAGrB,UAAWsB,EAAOxB,KAAIyB,eAC5BA,EACEC,EAAAC,IAAC,MAAI,CAAAF,YACHG,SAACD,EAAAA,IAAA1B,EAAA,CAA0BC,UAAWsB,EAAOrB,cAAegB,GAArCnB,KAGxB2B,EAAAA,IAAA1B,EAAA,CAA0BC,UAAWsB,EAAOrB,cAAegB,GAArCnB,IAE3B,GAI+CW,EACrD,0BCbgB,UAAiBiB,SAAEA,IACjC,MAAQC,SAAUC,GAAejC,IAG3BkC,EAAkBC,GACfA,EAAWT,KAAKrB,GACrByB,EAAAA,IAAC1B,GAA0CC,aAApBA,EAAUe,MAAMjB,MA0B3C,OAAO4B,EArB+B,CACpCK,QAAS,CACPC,IAAKH,GAAe,MAAAD,OAAA,EAAAA,EAAYK,sBAAsB,SAAU,IAChEC,OAAQL,GAAe,MAAAD,OAAA,EAAAA,EAAYK,sBAAsB,YAAa,IACtEE,KAAMN,GAAe,MAAAD,OAAA,EAAAA,EAAYK,sBAAsB,UAAW,IAClEG,MAAOP,GAAe,MAAAD,OAAA,EAAAA,EAAYK,sBAAsB,WAAY,KAEtEI,OAAQ,CACNF,KAAMN,GAAe,MAAAD,OAAA,EAAAA,EAAYU,oBAAoB,UAAW,IAChEF,MAAOP,GAAe,MAAAD,OAAA,EAAAA,EAAYU,oBAAoB,WAAY,KAEpEC,SAAU,CACRC,eAAgBX,GAAe,MAAAD,OAAA,EAAAA,EAAYa,sBAAsB,YAAa,IAC9EC,gBAAiBb,GAAe,MAAAD,OAAA,EAAAA,EAAYa,sBAAsB,aAAc,KAElFE,aAAa,MAAAf,OAAA,EAAAA,EAAYgB,kBACvBnB,MAAC1B,GAAiBC,UAAW4B,EAAWgB,mBACtC,MAKR,kBCrEO,WACL,MAAQjB,SAAUC,GAAejC,IAEjC,IAAKiC,EACG,MAAA,IAAIf,MAAM,4CAGZ,MAAAgC,aACJA,EAAAC,cACAA,EAAAC,QACAA,EAAAC,YACAA,EAAAC,aACAA,EAAAC,YACAA,EAAAC,aACAA,EAAAC,mBACAA,EAAAC,mBACAA,GACEzB,EAEG,MAAA,CACLiB,eACAC,gBACAC,UACAC,cACAC,eACAC,cACAC,eACAC,qBACAC,qBAEJ,gDHjC2B,IAAMC,YAAoBzD,EAAAA,SAASC"}
1
+ {"version":3,"file":"index.cjs","sources":["../../src/shared/hooks/use-ui.ts","../../src/shared/components/component-wrapper.tsx","../../src/shared/components/plugin-ui-provider.tsx"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/@framework';\nimport { UIPlugin } from '@embedpdf/plugin-ui';\n\nexport const useUIPlugin = () => usePlugin<UIPlugin>(UIPlugin.id);\nexport const useUICapability = () => useCapability<UIPlugin>(UIPlugin.id);\n","import { useState, useEffect } from '@framework';\nimport { childrenFunctionOptions, UIComponent } from '@embedpdf/plugin-ui';\n\nexport function ComponentWrapper({\n component,\n parentContext = {},\n}: {\n component: UIComponent<any>;\n parentContext?: Record<string, any>;\n}) {\n const [_, forceUpdate] = useState({});\n\n useEffect(() => {\n const updateCallback = () => forceUpdate({});\n // If the component had updated before we attach the listener, force one re-render\n if (component.onUpdate(updateCallback)) {\n forceUpdate({});\n }\n return () => component.offUpdate(updateCallback);\n }, [component]);\n\n // Merge contexts from parent + the UIComponent's own child context\n const childContext = component.getChildContext(parentContext);\n\n // Instead of returning `component.render()`, we do the following:\n\n // 1) Look up the \"renderer function\" for this component type\n const renderer = component.getRenderer(); // We'll define getRenderer() below\n\n if (!renderer) {\n throw new Error(`No renderer for type: ${component.getRenderType}`);\n }\n\n // 2) Build a function that returns child wrappers\n function renderChildrenFn(options?: childrenFunctionOptions) {\n const merged = options?.context ? { ...childContext, ...options.context } : childContext;\n return component\n .getChildren()\n .filter(({ id }) => {\n // If filter function is provided, use it to determine if we should include this child\n return !options?.filter || options.filter(id);\n })\n .map(({ component: child, id, className }) =>\n className ? (\n <div className={className}>\n <ComponentWrapper key={id} component={child} parentContext={merged} />\n </div>\n ) : (\n <ComponentWrapper key={id} component={child} parentContext={merged} />\n ),\n );\n }\n\n // 3) Finally call the renderer with (props, childrenFn, context)\n return renderer(component.props, renderChildrenFn, childContext);\n}\n","import { ReactNode } from '@framework';\nimport { useUICapability } from '../hooks';\nimport { ComponentWrapper } from './component-wrapper';\nimport { UIComponent } from '@embedpdf/plugin-ui';\n\n/**\n * Interface for UI components organized by type/location\n */\nexport interface UIComponentsMap {\n headers: {\n top: ReactNode[];\n bottom: ReactNode[];\n left: ReactNode[];\n right: ReactNode[];\n };\n panels: {\n left: ReactNode[];\n right: ReactNode[];\n };\n floating: {\n insideScroller: ReactNode[];\n outsideScroller: ReactNode[];\n };\n commandMenu: ReactNode | null;\n}\n\n/**\n * Props for the PluginUIProvider\n */\nexport interface PluginUIProviderProps {\n /**\n * Render function that receives UI components\n */\n children: (components: UIComponentsMap) => ReactNode;\n}\n\n/**\n * PluginUIProvider collects all components from the UI plugin system\n * and provides them to a render function without imposing any structure.\n *\n * It uses the render props pattern for maximum flexibility.\n */\nexport function PluginUIProvider({ children }: PluginUIProviderProps) {\n const { provides: uiProvides } = useUICapability();\n\n // Helper function to wrap UIComponents as JSX elements\n const wrapComponents = (components: UIComponent<any>[]): ReactNode[] => {\n return components.map((component) => (\n <ComponentWrapper key={component.props.id} component={component} />\n ));\n };\n\n // Collect and wrap all components from UI plugin\n const componentMap: UIComponentsMap = {\n headers: {\n top: wrapComponents(uiProvides?.getHeadersByPlacement('top') || []),\n bottom: wrapComponents(uiProvides?.getHeadersByPlacement('bottom') || []),\n left: wrapComponents(uiProvides?.getHeadersByPlacement('left') || []),\n right: wrapComponents(uiProvides?.getHeadersByPlacement('right') || []),\n },\n panels: {\n left: wrapComponents(uiProvides?.getPanelsByLocation('left') || []),\n right: wrapComponents(uiProvides?.getPanelsByLocation('right') || []),\n },\n floating: {\n insideScroller: wrapComponents(uiProvides?.getFloatingComponents('inside') || []),\n outsideScroller: wrapComponents(uiProvides?.getFloatingComponents('outside') || []),\n },\n commandMenu: uiProvides?.getCommandMenu() ? (\n <ComponentWrapper component={uiProvides.getCommandMenu()!} />\n ) : null,\n };\n\n // Let the consumer determine the layout structure through the render prop\n return children(componentMap);\n}\n"],"names":["useUICapability","useCapability","UIPlugin","id","ComponentWrapper","component","parentContext","_","forceUpdate","useState","useEffect","updateCallback","onUpdate","offUpdate","childContext","getChildContext","renderer","getRenderer","Error","getRenderType","props","options","merged","context","getChildren","filter","map","child","className","jsxRuntime","jsx","children","provides","uiProvides","wrapComponents","components","headers","top","getHeadersByPlacement","bottom","left","right","panels","getPanelsByLocation","floating","insideScroller","getFloatingComponents","outsideScroller","commandMenu","getCommandMenu","usePlugin"],"mappings":"4OAIaA,EAAkB,IAAMC,gBAAwBC,EAAAA,SAASC,ICD/D,SAASC,GAAiBC,UAC/BA,EAAAC,cACAA,EAAgB,CAAA,IAKhB,MAAOC,EAAGC,GAAeC,EAAAA,SAAS,CAAA,GAElCC,EAAAA,WAAU,KACR,MAAMC,EAAiB,IAAMH,EAAY,IAKlC,OAHHH,EAAUO,SAASD,IACrBH,EAAY,CAAA,GAEP,IAAMH,EAAUQ,UAAUF,EAAc,GAC9C,CAACN,IAGE,MAAAS,EAAeT,EAAUU,gBAAgBT,GAKzCU,EAAWX,EAAUY,cAE3B,IAAKD,EACH,MAAM,IAAIE,MAAM,yBAAyBb,EAAUc,iBAwBrD,OAAOH,EAASX,EAAUe,OApB1B,SAA0BC,GAClB,MAAAC,SAASD,WAASE,SAAU,IAAKT,KAAiBO,EAAQE,SAAYT,EAC5E,OAAOT,EACJmB,cACAC,QAAO,EAAGtB,UAED,MAAAkB,OAAA,EAAAA,EAASI,SAAUJ,EAAQI,OAAOtB,KAE3CuB,KAAI,EAAGrB,UAAWsB,EAAOxB,KAAIyB,eAC5BA,EACEC,EAAAC,IAAC,MAAI,CAAAF,YACHG,SAACD,EAAAA,IAAA1B,EAAA,CAA0BC,UAAWsB,EAAOrB,cAAegB,GAArCnB,KAGxB2B,EAAAA,IAAA1B,EAAA,CAA0BC,UAAWsB,EAAOrB,cAAegB,GAArCnB,IAE3B,GAI+CW,EACrD,0BCbgB,UAAiBiB,SAAEA,IACjC,MAAQC,SAAUC,GAAejC,IAG3BkC,EAAkBC,GACfA,EAAWT,KAAKrB,GACrByB,EAAAA,IAAC1B,GAA0CC,aAApBA,EAAUe,MAAMjB,MA0B3C,OAAO4B,EArB+B,CACpCK,QAAS,CACPC,IAAKH,GAAe,MAAAD,OAAA,EAAAA,EAAYK,sBAAsB,SAAU,IAChEC,OAAQL,GAAe,MAAAD,OAAA,EAAAA,EAAYK,sBAAsB,YAAa,IACtEE,KAAMN,GAAe,MAAAD,OAAA,EAAAA,EAAYK,sBAAsB,UAAW,IAClEG,MAAOP,GAAe,MAAAD,OAAA,EAAAA,EAAYK,sBAAsB,WAAY,KAEtEI,OAAQ,CACNF,KAAMN,GAAe,MAAAD,OAAA,EAAAA,EAAYU,oBAAoB,UAAW,IAChEF,MAAOP,GAAe,MAAAD,OAAA,EAAAA,EAAYU,oBAAoB,WAAY,KAEpEC,SAAU,CACRC,eAAgBX,GAAe,MAAAD,OAAA,EAAAA,EAAYa,sBAAsB,YAAa,IAC9EC,gBAAiBb,GAAe,MAAAD,OAAA,EAAAA,EAAYa,sBAAsB,aAAc,KAElFE,aAAa,MAAAf,OAAA,EAAAA,EAAYgB,kBACvBnB,MAAC1B,GAAiBC,UAAW4B,EAAWgB,mBACtC,MAKR,gDFxE2B,IAAMC,YAAoBhD,EAAAA,SAASC"}
@@ -5,34 +5,6 @@ import "preact";
5
5
  import { useState, useEffect } from "preact/hooks";
6
6
  const useUIPlugin = () => usePlugin(UIPlugin.id);
7
7
  const useUICapability = () => useCapability(UIPlugin.id);
8
- function useIcon() {
9
- const { provides: uiProvides } = useUICapability();
10
- if (!uiProvides) {
11
- throw new Error("useIcon must be used within a UI context");
12
- }
13
- const {
14
- registerIcon,
15
- registerIcons,
16
- getIcon,
17
- getAllIcons,
18
- getSvgString,
19
- isSvgString,
20
- isSvgDataUri,
21
- dataUriToSvgString,
22
- svgStringToDataUri
23
- } = uiProvides;
24
- return {
25
- registerIcon,
26
- registerIcons,
27
- getIcon,
28
- getAllIcons,
29
- getSvgString,
30
- isSvgString,
31
- isSvgDataUri,
32
- dataUriToSvgString,
33
- svgStringToDataUri
34
- };
35
- }
36
8
  function ComponentWrapper({
37
9
  component,
38
10
  parentContext = {}
@@ -86,7 +58,6 @@ function PluginUIProvider({ children }) {
86
58
  }
87
59
  export {
88
60
  PluginUIProvider,
89
- useIcon,
90
61
  useUICapability,
91
62
  useUIPlugin
92
63
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/shared/hooks/use-ui.ts","../../src/shared/hooks/use-icon.ts","../../src/shared/components/component-wrapper.tsx","../../src/shared/components/plugin-ui-provider.tsx"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/@framework';\nimport { UIPlugin } from '@embedpdf/plugin-ui';\n\nexport const useUIPlugin = () => usePlugin<UIPlugin>(UIPlugin.id);\nexport const useUICapability = () => useCapability<UIPlugin>(UIPlugin.id);\n","import { useUICapability } from './use-ui';\nimport { IconIdentifier, Icon as IconType, IconRegistry } from '@embedpdf/plugin-ui';\n\n/**\n * Hook to access icon functionality in React\n */\nexport function useIcon() {\n const { provides: uiProvides } = useUICapability();\n\n if (!uiProvides) {\n throw new Error('useIcon must be used within a UI context');\n }\n\n const {\n registerIcon,\n registerIcons,\n getIcon,\n getAllIcons,\n getSvgString,\n isSvgString,\n isSvgDataUri,\n dataUriToSvgString,\n svgStringToDataUri,\n } = uiProvides;\n\n return {\n registerIcon,\n registerIcons,\n getIcon,\n getAllIcons,\n getSvgString,\n isSvgString,\n isSvgDataUri,\n dataUriToSvgString,\n svgStringToDataUri,\n };\n}\n","import { useState, useEffect } from '@framework';\nimport { childrenFunctionOptions, UIComponent } from '@embedpdf/plugin-ui';\n\nexport function ComponentWrapper({\n component,\n parentContext = {},\n}: {\n component: UIComponent<any>;\n parentContext?: Record<string, any>;\n}) {\n const [_, forceUpdate] = useState({});\n\n useEffect(() => {\n const updateCallback = () => forceUpdate({});\n // If the component had updated before we attach the listener, force one re-render\n if (component.onUpdate(updateCallback)) {\n forceUpdate({});\n }\n return () => component.offUpdate(updateCallback);\n }, [component]);\n\n // Merge contexts from parent + the UIComponent's own child context\n const childContext = component.getChildContext(parentContext);\n\n // Instead of returning `component.render()`, we do the following:\n\n // 1) Look up the \"renderer function\" for this component type\n const renderer = component.getRenderer(); // We'll define getRenderer() below\n\n if (!renderer) {\n throw new Error(`No renderer for type: ${component.getRenderType}`);\n }\n\n // 2) Build a function that returns child wrappers\n function renderChildrenFn(options?: childrenFunctionOptions) {\n const merged = options?.context ? { ...childContext, ...options.context } : childContext;\n return component\n .getChildren()\n .filter(({ id }) => {\n // If filter function is provided, use it to determine if we should include this child\n return !options?.filter || options.filter(id);\n })\n .map(({ component: child, id, className }) =>\n className ? (\n <div className={className}>\n <ComponentWrapper key={id} component={child} parentContext={merged} />\n </div>\n ) : (\n <ComponentWrapper key={id} component={child} parentContext={merged} />\n ),\n );\n }\n\n // 3) Finally call the renderer with (props, childrenFn, context)\n return renderer(component.props, renderChildrenFn, childContext);\n}\n","import { ReactNode } from '@framework';\nimport { useUICapability } from '../hooks';\nimport { ComponentWrapper } from './component-wrapper';\nimport { UIComponent } from '@embedpdf/plugin-ui';\n\n/**\n * Interface for UI components organized by type/location\n */\nexport interface UIComponentsMap {\n headers: {\n top: ReactNode[];\n bottom: ReactNode[];\n left: ReactNode[];\n right: ReactNode[];\n };\n panels: {\n left: ReactNode[];\n right: ReactNode[];\n };\n floating: {\n insideScroller: ReactNode[];\n outsideScroller: ReactNode[];\n };\n commandMenu: ReactNode | null;\n}\n\n/**\n * Props for the PluginUIProvider\n */\nexport interface PluginUIProviderProps {\n /**\n * Render function that receives UI components\n */\n children: (components: UIComponentsMap) => ReactNode;\n}\n\n/**\n * PluginUIProvider collects all components from the UI plugin system\n * and provides them to a render function without imposing any structure.\n *\n * It uses the render props pattern for maximum flexibility.\n */\nexport function PluginUIProvider({ children }: PluginUIProviderProps) {\n const { provides: uiProvides } = useUICapability();\n\n // Helper function to wrap UIComponents as JSX elements\n const wrapComponents = (components: UIComponent<any>[]): ReactNode[] => {\n return components.map((component) => (\n <ComponentWrapper key={component.props.id} component={component} />\n ));\n };\n\n // Collect and wrap all components from UI plugin\n const componentMap: UIComponentsMap = {\n headers: {\n top: wrapComponents(uiProvides?.getHeadersByPlacement('top') || []),\n bottom: wrapComponents(uiProvides?.getHeadersByPlacement('bottom') || []),\n left: wrapComponents(uiProvides?.getHeadersByPlacement('left') || []),\n right: wrapComponents(uiProvides?.getHeadersByPlacement('right') || []),\n },\n panels: {\n left: wrapComponents(uiProvides?.getPanelsByLocation('left') || []),\n right: wrapComponents(uiProvides?.getPanelsByLocation('right') || []),\n },\n floating: {\n insideScroller: wrapComponents(uiProvides?.getFloatingComponents('inside') || []),\n outsideScroller: wrapComponents(uiProvides?.getFloatingComponents('outside') || []),\n },\n commandMenu: uiProvides?.getCommandMenu() ? (\n <ComponentWrapper component={uiProvides.getCommandMenu()!} />\n ) : null,\n };\n\n // Let the consumer determine the layout structure through the render prop\n return children(componentMap);\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../../src/shared/hooks/use-ui.ts","../../src/shared/components/component-wrapper.tsx","../../src/shared/components/plugin-ui-provider.tsx"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/@framework';\nimport { UIPlugin } from '@embedpdf/plugin-ui';\n\nexport const useUIPlugin = () => usePlugin<UIPlugin>(UIPlugin.id);\nexport const useUICapability = () => useCapability<UIPlugin>(UIPlugin.id);\n","import { useState, useEffect } from '@framework';\nimport { childrenFunctionOptions, UIComponent } from '@embedpdf/plugin-ui';\n\nexport function ComponentWrapper({\n component,\n parentContext = {},\n}: {\n component: UIComponent<any>;\n parentContext?: Record<string, any>;\n}) {\n const [_, forceUpdate] = useState({});\n\n useEffect(() => {\n const updateCallback = () => forceUpdate({});\n // If the component had updated before we attach the listener, force one re-render\n if (component.onUpdate(updateCallback)) {\n forceUpdate({});\n }\n return () => component.offUpdate(updateCallback);\n }, [component]);\n\n // Merge contexts from parent + the UIComponent's own child context\n const childContext = component.getChildContext(parentContext);\n\n // Instead of returning `component.render()`, we do the following:\n\n // 1) Look up the \"renderer function\" for this component type\n const renderer = component.getRenderer(); // We'll define getRenderer() below\n\n if (!renderer) {\n throw new Error(`No renderer for type: ${component.getRenderType}`);\n }\n\n // 2) Build a function that returns child wrappers\n function renderChildrenFn(options?: childrenFunctionOptions) {\n const merged = options?.context ? { ...childContext, ...options.context } : childContext;\n return component\n .getChildren()\n .filter(({ id }) => {\n // If filter function is provided, use it to determine if we should include this child\n return !options?.filter || options.filter(id);\n })\n .map(({ component: child, id, className }) =>\n className ? (\n <div className={className}>\n <ComponentWrapper key={id} component={child} parentContext={merged} />\n </div>\n ) : (\n <ComponentWrapper key={id} component={child} parentContext={merged} />\n ),\n );\n }\n\n // 3) Finally call the renderer with (props, childrenFn, context)\n return renderer(component.props, renderChildrenFn, childContext);\n}\n","import { ReactNode } from '@framework';\nimport { useUICapability } from '../hooks';\nimport { ComponentWrapper } from './component-wrapper';\nimport { UIComponent } from '@embedpdf/plugin-ui';\n\n/**\n * Interface for UI components organized by type/location\n */\nexport interface UIComponentsMap {\n headers: {\n top: ReactNode[];\n bottom: ReactNode[];\n left: ReactNode[];\n right: ReactNode[];\n };\n panels: {\n left: ReactNode[];\n right: ReactNode[];\n };\n floating: {\n insideScroller: ReactNode[];\n outsideScroller: ReactNode[];\n };\n commandMenu: ReactNode | null;\n}\n\n/**\n * Props for the PluginUIProvider\n */\nexport interface PluginUIProviderProps {\n /**\n * Render function that receives UI components\n */\n children: (components: UIComponentsMap) => ReactNode;\n}\n\n/**\n * PluginUIProvider collects all components from the UI plugin system\n * and provides them to a render function without imposing any structure.\n *\n * It uses the render props pattern for maximum flexibility.\n */\nexport function PluginUIProvider({ children }: PluginUIProviderProps) {\n const { provides: uiProvides } = useUICapability();\n\n // Helper function to wrap UIComponents as JSX elements\n const wrapComponents = (components: UIComponent<any>[]): ReactNode[] => {\n return components.map((component) => (\n <ComponentWrapper key={component.props.id} component={component} />\n ));\n };\n\n // Collect and wrap all components from UI plugin\n const componentMap: UIComponentsMap = {\n headers: {\n top: wrapComponents(uiProvides?.getHeadersByPlacement('top') || []),\n bottom: wrapComponents(uiProvides?.getHeadersByPlacement('bottom') || []),\n left: wrapComponents(uiProvides?.getHeadersByPlacement('left') || []),\n right: wrapComponents(uiProvides?.getHeadersByPlacement('right') || []),\n },\n panels: {\n left: wrapComponents(uiProvides?.getPanelsByLocation('left') || []),\n right: wrapComponents(uiProvides?.getPanelsByLocation('right') || []),\n },\n floating: {\n insideScroller: wrapComponents(uiProvides?.getFloatingComponents('inside') || []),\n outsideScroller: wrapComponents(uiProvides?.getFloatingComponents('outside') || []),\n },\n commandMenu: uiProvides?.getCommandMenu() ? (\n <ComponentWrapper component={uiProvides.getCommandMenu()!} />\n ) : null,\n };\n\n // Let the consumer determine the layout structure through the render prop\n return children(componentMap);\n}\n"],"names":[],"mappings":";;;;;AAGO,MAAM,cAAc,MAAM,UAAoB,SAAS,EAAE;AACzD,MAAM,kBAAkB,MAAM,cAAwB,SAAS,EAAE;ACDjE,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA,gBAAgB,CAAA;AAClB,GAGG;AACD,QAAM,CAAC,GAAG,WAAW,IAAI,SAAS,CAAA,CAAE;AAEpC,YAAU,MAAM;AACd,UAAM,iBAAiB,MAAM,YAAY,EAAE;AAEvC,QAAA,UAAU,SAAS,cAAc,GAAG;AACtC,kBAAY,CAAA,CAAE;AAAA,IAAA;AAET,WAAA,MAAM,UAAU,UAAU,cAAc;AAAA,EAAA,GAC9C,CAAC,SAAS,CAAC;AAGR,QAAA,eAAe,UAAU,gBAAgB,aAAa;AAKtD,QAAA,WAAW,UAAU,YAAY;AAEvC,MAAI,CAAC,UAAU;AACb,UAAM,IAAI,MAAM,yBAAyB,UAAU,aAAa,EAAE;AAAA,EAAA;AAIpE,WAAS,iBAAiB,SAAmC;AACrD,UAAA,UAAS,mCAAS,WAAU,EAAE,GAAG,cAAc,GAAG,QAAQ,QAAA,IAAY;AAC5E,WAAO,UACJ,YAAY,EACZ,OAAO,CAAC,EAAE,SAAS;AAElB,aAAO,EAAC,mCAAS,WAAU,QAAQ,OAAO,EAAE;AAAA,IAC7C,CAAA,EACA;AAAA,MAAI,CAAC,EAAE,WAAW,OAAO,IAAI,UAAU,MACtC,YACE,oBAAC,OAAI,EAAA,WACH,UAAC,oBAAA,kBAAA,EAA0B,WAAW,OAAO,eAAe,OAArC,GAAA,EAA6C,EACtE,CAAA,IAEC,oBAAA,kBAAA,EAA0B,WAAW,OAAO,eAAe,OAAA,GAArC,EAA6C;AAAA,IAExE;AAAA,EAAA;AAIJ,SAAO,SAAS,UAAU,OAAO,kBAAkB,YAAY;AACjE;ACbgB,SAAA,iBAAiB,EAAE,YAAmC;AACpE,QAAM,EAAE,UAAU,WAAW,IAAI,gBAAgB;AAG3C,QAAA,iBAAiB,CAAC,eAAgD;AAC/D,WAAA,WAAW,IAAI,CAAC,cACrB,oBAAC,oBAA0C,aAApB,UAAU,MAAM,EAA0B,CAClE;AAAA,EACH;AAGA,QAAM,eAAgC;AAAA,IACpC,SAAS;AAAA,MACP,KAAK,gBAAe,yCAAY,sBAAsB,WAAU,CAAA,CAAE;AAAA,MAClE,QAAQ,gBAAe,yCAAY,sBAAsB,cAAa,CAAA,CAAE;AAAA,MACxE,MAAM,gBAAe,yCAAY,sBAAsB,YAAW,CAAA,CAAE;AAAA,MACpE,OAAO,gBAAe,yCAAY,sBAAsB,aAAY,CAAE,CAAA;AAAA,IACxE;AAAA,IACA,QAAQ;AAAA,MACN,MAAM,gBAAe,yCAAY,oBAAoB,YAAW,CAAA,CAAE;AAAA,MAClE,OAAO,gBAAe,yCAAY,oBAAoB,aAAY,CAAE,CAAA;AAAA,IACtE;AAAA,IACA,UAAU;AAAA,MACR,gBAAgB,gBAAe,yCAAY,sBAAsB,cAAa,CAAA,CAAE;AAAA,MAChF,iBAAiB,gBAAe,yCAAY,sBAAsB,eAAc,CAAE,CAAA;AAAA,IACpF;AAAA,IACA,cAAa,yCAAY,oBACvB,oBAAC,oBAAiB,WAAW,WAAW,eAAe,EAAA,CAAI,IACzD;AAAA,EACN;AAGA,SAAO,SAAS,YAAY;AAC9B;"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),t=require("@embedpdf/core/react"),n=require("@embedpdf/plugin-ui"),o=require("react"),r=()=>t.useCapability(n.UIPlugin.id);function i({component:t,parentContext:n={}}){const[r,s]=o.useState({});o.useEffect((()=>{const e=()=>s({});return t.onUpdate(e)&&s({}),()=>t.offUpdate(e)}),[t]);const l=t.getChildContext(n),g=t.getRenderer();if(!g)throw new Error(`No renderer for type: ${t.getRenderType}`);return g(t.props,(function(n){const o=(null==n?void 0:n.context)?{...l,...n.context}:l;return t.getChildren().filter((({id:e})=>!(null==n?void 0:n.filter)||n.filter(e))).map((({component:t,id:n,className:r})=>r?e.jsx("div",{className:r,children:e.jsx(i,{component:t,parentContext:o},n)}):e.jsx(i,{component:t,parentContext:o},n)))}),l)}exports.PluginUIProvider=function({children:t}){const{provides:n}=r(),o=t=>t.map((t=>e.jsx(i,{component:t},t.props.id)));return t({headers:{top:o((null==n?void 0:n.getHeadersByPlacement("top"))||[]),bottom:o((null==n?void 0:n.getHeadersByPlacement("bottom"))||[]),left:o((null==n?void 0:n.getHeadersByPlacement("left"))||[]),right:o((null==n?void 0:n.getHeadersByPlacement("right"))||[])},panels:{left:o((null==n?void 0:n.getPanelsByLocation("left"))||[]),right:o((null==n?void 0:n.getPanelsByLocation("right"))||[])},floating:{insideScroller:o((null==n?void 0:n.getFloatingComponents("inside"))||[]),outsideScroller:o((null==n?void 0:n.getFloatingComponents("outside"))||[])},commandMenu:(null==n?void 0:n.getCommandMenu())?e.jsx(i,{component:n.getCommandMenu()}):null})},exports.useIcon=function(){const{provides:e}=r();if(!e)throw new Error("useIcon must be used within a UI context");const{registerIcon:t,registerIcons:n,getIcon:o,getAllIcons:i,getSvgString:s,isSvgString:l,isSvgDataUri:g,dataUriToSvgString:a,svgStringToDataUri:c}=e;return{registerIcon:t,registerIcons:n,getIcon:o,getAllIcons:i,getSvgString:s,isSvgString:l,isSvgDataUri:g,dataUriToSvgString:a,svgStringToDataUri:c}},exports.useUICapability=r,exports.useUIPlugin=()=>t.usePlugin(n.UIPlugin.id);
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),t=require("@embedpdf/core/react"),n=require("@embedpdf/plugin-ui"),o=require("react"),r=()=>t.useCapability(n.UIPlugin.id);function i({component:t,parentContext:n={}}){const[r,l]=o.useState({});o.useEffect((()=>{const e=()=>l({});return t.onUpdate(e)&&l({}),()=>t.offUpdate(e)}),[t]);const d=t.getChildContext(n),s=t.getRenderer();if(!s)throw new Error(`No renderer for type: ${t.getRenderType}`);return s(t.props,(function(n){const o=(null==n?void 0:n.context)?{...d,...n.context}:d;return t.getChildren().filter((({id:e})=>!(null==n?void 0:n.filter)||n.filter(e))).map((({component:t,id:n,className:r})=>r?e.jsx("div",{className:r,children:e.jsx(i,{component:t,parentContext:o},n)}):e.jsx(i,{component:t,parentContext:o},n)))}),d)}exports.PluginUIProvider=function({children:t}){const{provides:n}=r(),o=t=>t.map((t=>e.jsx(i,{component:t},t.props.id)));return t({headers:{top:o((null==n?void 0:n.getHeadersByPlacement("top"))||[]),bottom:o((null==n?void 0:n.getHeadersByPlacement("bottom"))||[]),left:o((null==n?void 0:n.getHeadersByPlacement("left"))||[]),right:o((null==n?void 0:n.getHeadersByPlacement("right"))||[])},panels:{left:o((null==n?void 0:n.getPanelsByLocation("left"))||[]),right:o((null==n?void 0:n.getPanelsByLocation("right"))||[])},floating:{insideScroller:o((null==n?void 0:n.getFloatingComponents("inside"))||[]),outsideScroller:o((null==n?void 0:n.getFloatingComponents("outside"))||[])},commandMenu:(null==n?void 0:n.getCommandMenu())?e.jsx(i,{component:n.getCommandMenu()}):null})},exports.useUICapability=r,exports.useUIPlugin=()=>t.usePlugin(n.UIPlugin.id);
2
2
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../../src/shared/hooks/use-ui.ts","../../src/shared/components/component-wrapper.tsx","../../src/shared/components/plugin-ui-provider.tsx","../../src/shared/hooks/use-icon.ts"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/@framework';\nimport { UIPlugin } from '@embedpdf/plugin-ui';\n\nexport const useUIPlugin = () => usePlugin<UIPlugin>(UIPlugin.id);\nexport const useUICapability = () => useCapability<UIPlugin>(UIPlugin.id);\n","import { useState, useEffect } from '@framework';\nimport { childrenFunctionOptions, UIComponent } from '@embedpdf/plugin-ui';\n\nexport function ComponentWrapper({\n component,\n parentContext = {},\n}: {\n component: UIComponent<any>;\n parentContext?: Record<string, any>;\n}) {\n const [_, forceUpdate] = useState({});\n\n useEffect(() => {\n const updateCallback = () => forceUpdate({});\n // If the component had updated before we attach the listener, force one re-render\n if (component.onUpdate(updateCallback)) {\n forceUpdate({});\n }\n return () => component.offUpdate(updateCallback);\n }, [component]);\n\n // Merge contexts from parent + the UIComponent's own child context\n const childContext = component.getChildContext(parentContext);\n\n // Instead of returning `component.render()`, we do the following:\n\n // 1) Look up the \"renderer function\" for this component type\n const renderer = component.getRenderer(); // We'll define getRenderer() below\n\n if (!renderer) {\n throw new Error(`No renderer for type: ${component.getRenderType}`);\n }\n\n // 2) Build a function that returns child wrappers\n function renderChildrenFn(options?: childrenFunctionOptions) {\n const merged = options?.context ? { ...childContext, ...options.context } : childContext;\n return component\n .getChildren()\n .filter(({ id }) => {\n // If filter function is provided, use it to determine if we should include this child\n return !options?.filter || options.filter(id);\n })\n .map(({ component: child, id, className }) =>\n className ? (\n <div className={className}>\n <ComponentWrapper key={id} component={child} parentContext={merged} />\n </div>\n ) : (\n <ComponentWrapper key={id} component={child} parentContext={merged} />\n ),\n );\n }\n\n // 3) Finally call the renderer with (props, childrenFn, context)\n return renderer(component.props, renderChildrenFn, childContext);\n}\n","import { ReactNode } from '@framework';\nimport { useUICapability } from '../hooks';\nimport { ComponentWrapper } from './component-wrapper';\nimport { UIComponent } from '@embedpdf/plugin-ui';\n\n/**\n * Interface for UI components organized by type/location\n */\nexport interface UIComponentsMap {\n headers: {\n top: ReactNode[];\n bottom: ReactNode[];\n left: ReactNode[];\n right: ReactNode[];\n };\n panels: {\n left: ReactNode[];\n right: ReactNode[];\n };\n floating: {\n insideScroller: ReactNode[];\n outsideScroller: ReactNode[];\n };\n commandMenu: ReactNode | null;\n}\n\n/**\n * Props for the PluginUIProvider\n */\nexport interface PluginUIProviderProps {\n /**\n * Render function that receives UI components\n */\n children: (components: UIComponentsMap) => ReactNode;\n}\n\n/**\n * PluginUIProvider collects all components from the UI plugin system\n * and provides them to a render function without imposing any structure.\n *\n * It uses the render props pattern for maximum flexibility.\n */\nexport function PluginUIProvider({ children }: PluginUIProviderProps) {\n const { provides: uiProvides } = useUICapability();\n\n // Helper function to wrap UIComponents as JSX elements\n const wrapComponents = (components: UIComponent<any>[]): ReactNode[] => {\n return components.map((component) => (\n <ComponentWrapper key={component.props.id} component={component} />\n ));\n };\n\n // Collect and wrap all components from UI plugin\n const componentMap: UIComponentsMap = {\n headers: {\n top: wrapComponents(uiProvides?.getHeadersByPlacement('top') || []),\n bottom: wrapComponents(uiProvides?.getHeadersByPlacement('bottom') || []),\n left: wrapComponents(uiProvides?.getHeadersByPlacement('left') || []),\n right: wrapComponents(uiProvides?.getHeadersByPlacement('right') || []),\n },\n panels: {\n left: wrapComponents(uiProvides?.getPanelsByLocation('left') || []),\n right: wrapComponents(uiProvides?.getPanelsByLocation('right') || []),\n },\n floating: {\n insideScroller: wrapComponents(uiProvides?.getFloatingComponents('inside') || []),\n outsideScroller: wrapComponents(uiProvides?.getFloatingComponents('outside') || []),\n },\n commandMenu: uiProvides?.getCommandMenu() ? (\n <ComponentWrapper component={uiProvides.getCommandMenu()!} />\n ) : null,\n };\n\n // Let the consumer determine the layout structure through the render prop\n return children(componentMap);\n}\n","import { useUICapability } from './use-ui';\nimport { IconIdentifier, Icon as IconType, IconRegistry } from '@embedpdf/plugin-ui';\n\n/**\n * Hook to access icon functionality in React\n */\nexport function useIcon() {\n const { provides: uiProvides } = useUICapability();\n\n if (!uiProvides) {\n throw new Error('useIcon must be used within a UI context');\n }\n\n const {\n registerIcon,\n registerIcons,\n getIcon,\n getAllIcons,\n getSvgString,\n isSvgString,\n isSvgDataUri,\n dataUriToSvgString,\n svgStringToDataUri,\n } = uiProvides;\n\n return {\n registerIcon,\n registerIcons,\n getIcon,\n getAllIcons,\n getSvgString,\n isSvgString,\n isSvgDataUri,\n dataUriToSvgString,\n svgStringToDataUri,\n };\n}\n"],"names":["useUICapability","useCapability","UIPlugin","id","ComponentWrapper","component","parentContext","_","forceUpdate","useState","useEffect","updateCallback","onUpdate","offUpdate","childContext","getChildContext","renderer","getRenderer","Error","getRenderType","props","options","merged","context","getChildren","filter","map","child","className","jsxRuntime","jsx","children","provides","uiProvides","wrapComponents","components","headers","top","getHeadersByPlacement","bottom","left","right","panels","getPanelsByLocation","floating","insideScroller","getFloatingComponents","outsideScroller","commandMenu","getCommandMenu","registerIcon","registerIcons","getIcon","getAllIcons","getSvgString","isSvgString","isSvgDataUri","dataUriToSvgString","svgStringToDataUri","usePlugin"],"mappings":"2MAIaA,EAAkB,IAAMC,gBAAwBC,EAAAA,SAASC,ICD/D,SAASC,GAAiBC,UAC/BA,EAAAC,cACAA,EAAgB,CAAA,IAKhB,MAAOC,EAAGC,GAAeC,EAAAA,SAAS,CAAA,GAElCC,EAAAA,WAAU,KACR,MAAMC,EAAiB,IAAMH,EAAY,IAKlC,OAHHH,EAAUO,SAASD,IACrBH,EAAY,CAAA,GAEP,IAAMH,EAAUQ,UAAUF,EAAc,GAC9C,CAACN,IAGE,MAAAS,EAAeT,EAAUU,gBAAgBT,GAKzCU,EAAWX,EAAUY,cAE3B,IAAKD,EACH,MAAM,IAAIE,MAAM,yBAAyBb,EAAUc,iBAwBrD,OAAOH,EAASX,EAAUe,OApB1B,SAA0BC,GAClB,MAAAC,SAASD,WAASE,SAAU,IAAKT,KAAiBO,EAAQE,SAAYT,EAC5E,OAAOT,EACJmB,cACAC,QAAO,EAAGtB,UAED,MAAAkB,OAAA,EAAAA,EAASI,SAAUJ,EAAQI,OAAOtB,KAE3CuB,KAAI,EAAGrB,UAAWsB,EAAOxB,KAAIyB,eAC5BA,EACEC,EAAAC,IAAC,MAAI,CAAAF,YACHG,SAACD,EAAAA,IAAA1B,EAAA,CAA0BC,UAAWsB,EAAOrB,cAAegB,GAArCnB,KAGxB2B,EAAAA,IAAA1B,EAAA,CAA0BC,UAAWsB,EAAOrB,cAAegB,GAArCnB,IAE3B,GAI+CW,EACrD,0BCbgB,UAAiBiB,SAAEA,IACjC,MAAQC,SAAUC,GAAejC,IAG3BkC,EAAkBC,GACfA,EAAWT,KAAKrB,GACrByB,EAAAA,IAAC1B,GAA0CC,aAApBA,EAAUe,MAAMjB,MA0B3C,OAAO4B,EArB+B,CACpCK,QAAS,CACPC,IAAKH,GAAe,MAAAD,OAAA,EAAAA,EAAYK,sBAAsB,SAAU,IAChEC,OAAQL,GAAe,MAAAD,OAAA,EAAAA,EAAYK,sBAAsB,YAAa,IACtEE,KAAMN,GAAe,MAAAD,OAAA,EAAAA,EAAYK,sBAAsB,UAAW,IAClEG,MAAOP,GAAe,MAAAD,OAAA,EAAAA,EAAYK,sBAAsB,WAAY,KAEtEI,OAAQ,CACNF,KAAMN,GAAe,MAAAD,OAAA,EAAAA,EAAYU,oBAAoB,UAAW,IAChEF,MAAOP,GAAe,MAAAD,OAAA,EAAAA,EAAYU,oBAAoB,WAAY,KAEpEC,SAAU,CACRC,eAAgBX,GAAe,MAAAD,OAAA,EAAAA,EAAYa,sBAAsB,YAAa,IAC9EC,gBAAiBb,GAAe,MAAAD,OAAA,EAAAA,EAAYa,sBAAsB,aAAc,KAElFE,aAAa,MAAAf,OAAA,EAAAA,EAAYgB,kBACvBnB,MAAC1B,GAAiBC,UAAW4B,EAAWgB,mBACtC,MAKR,kBCrEO,WACL,MAAQjB,SAAUC,GAAejC,IAEjC,IAAKiC,EACG,MAAA,IAAIf,MAAM,4CAGZ,MAAAgC,aACJA,EAAAC,cACAA,EAAAC,QACAA,EAAAC,YACAA,EAAAC,aACAA,EAAAC,YACAA,EAAAC,aACAA,EAAAC,mBACAA,EAAAC,mBACAA,GACEzB,EAEG,MAAA,CACLiB,eACAC,gBACAC,UACAC,cACAC,eACAC,cACAC,eACAC,qBACAC,qBAEJ,gDHjC2B,IAAMC,YAAoBzD,EAAAA,SAASC"}
1
+ {"version":3,"file":"index.cjs","sources":["../../src/shared/hooks/use-ui.ts","../../src/shared/components/component-wrapper.tsx","../../src/shared/components/plugin-ui-provider.tsx"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/@framework';\nimport { UIPlugin } from '@embedpdf/plugin-ui';\n\nexport const useUIPlugin = () => usePlugin<UIPlugin>(UIPlugin.id);\nexport const useUICapability = () => useCapability<UIPlugin>(UIPlugin.id);\n","import { useState, useEffect } from '@framework';\nimport { childrenFunctionOptions, UIComponent } from '@embedpdf/plugin-ui';\n\nexport function ComponentWrapper({\n component,\n parentContext = {},\n}: {\n component: UIComponent<any>;\n parentContext?: Record<string, any>;\n}) {\n const [_, forceUpdate] = useState({});\n\n useEffect(() => {\n const updateCallback = () => forceUpdate({});\n // If the component had updated before we attach the listener, force one re-render\n if (component.onUpdate(updateCallback)) {\n forceUpdate({});\n }\n return () => component.offUpdate(updateCallback);\n }, [component]);\n\n // Merge contexts from parent + the UIComponent's own child context\n const childContext = component.getChildContext(parentContext);\n\n // Instead of returning `component.render()`, we do the following:\n\n // 1) Look up the \"renderer function\" for this component type\n const renderer = component.getRenderer(); // We'll define getRenderer() below\n\n if (!renderer) {\n throw new Error(`No renderer for type: ${component.getRenderType}`);\n }\n\n // 2) Build a function that returns child wrappers\n function renderChildrenFn(options?: childrenFunctionOptions) {\n const merged = options?.context ? { ...childContext, ...options.context } : childContext;\n return component\n .getChildren()\n .filter(({ id }) => {\n // If filter function is provided, use it to determine if we should include this child\n return !options?.filter || options.filter(id);\n })\n .map(({ component: child, id, className }) =>\n className ? (\n <div className={className}>\n <ComponentWrapper key={id} component={child} parentContext={merged} />\n </div>\n ) : (\n <ComponentWrapper key={id} component={child} parentContext={merged} />\n ),\n );\n }\n\n // 3) Finally call the renderer with (props, childrenFn, context)\n return renderer(component.props, renderChildrenFn, childContext);\n}\n","import { ReactNode } from '@framework';\nimport { useUICapability } from '../hooks';\nimport { ComponentWrapper } from './component-wrapper';\nimport { UIComponent } from '@embedpdf/plugin-ui';\n\n/**\n * Interface for UI components organized by type/location\n */\nexport interface UIComponentsMap {\n headers: {\n top: ReactNode[];\n bottom: ReactNode[];\n left: ReactNode[];\n right: ReactNode[];\n };\n panels: {\n left: ReactNode[];\n right: ReactNode[];\n };\n floating: {\n insideScroller: ReactNode[];\n outsideScroller: ReactNode[];\n };\n commandMenu: ReactNode | null;\n}\n\n/**\n * Props for the PluginUIProvider\n */\nexport interface PluginUIProviderProps {\n /**\n * Render function that receives UI components\n */\n children: (components: UIComponentsMap) => ReactNode;\n}\n\n/**\n * PluginUIProvider collects all components from the UI plugin system\n * and provides them to a render function without imposing any structure.\n *\n * It uses the render props pattern for maximum flexibility.\n */\nexport function PluginUIProvider({ children }: PluginUIProviderProps) {\n const { provides: uiProvides } = useUICapability();\n\n // Helper function to wrap UIComponents as JSX elements\n const wrapComponents = (components: UIComponent<any>[]): ReactNode[] => {\n return components.map((component) => (\n <ComponentWrapper key={component.props.id} component={component} />\n ));\n };\n\n // Collect and wrap all components from UI plugin\n const componentMap: UIComponentsMap = {\n headers: {\n top: wrapComponents(uiProvides?.getHeadersByPlacement('top') || []),\n bottom: wrapComponents(uiProvides?.getHeadersByPlacement('bottom') || []),\n left: wrapComponents(uiProvides?.getHeadersByPlacement('left') || []),\n right: wrapComponents(uiProvides?.getHeadersByPlacement('right') || []),\n },\n panels: {\n left: wrapComponents(uiProvides?.getPanelsByLocation('left') || []),\n right: wrapComponents(uiProvides?.getPanelsByLocation('right') || []),\n },\n floating: {\n insideScroller: wrapComponents(uiProvides?.getFloatingComponents('inside') || []),\n outsideScroller: wrapComponents(uiProvides?.getFloatingComponents('outside') || []),\n },\n commandMenu: uiProvides?.getCommandMenu() ? (\n <ComponentWrapper component={uiProvides.getCommandMenu()!} />\n ) : null,\n };\n\n // Let the consumer determine the layout structure through the render prop\n return children(componentMap);\n}\n"],"names":["useUICapability","useCapability","UIPlugin","id","ComponentWrapper","component","parentContext","_","forceUpdate","useState","useEffect","updateCallback","onUpdate","offUpdate","childContext","getChildContext","renderer","getRenderer","Error","getRenderType","props","options","merged","context","getChildren","filter","map","child","className","jsxRuntime","jsx","children","provides","uiProvides","wrapComponents","components","headers","top","getHeadersByPlacement","bottom","left","right","panels","getPanelsByLocation","floating","insideScroller","getFloatingComponents","outsideScroller","commandMenu","getCommandMenu","usePlugin"],"mappings":"2MAIaA,EAAkB,IAAMC,gBAAwBC,EAAAA,SAASC,ICD/D,SAASC,GAAiBC,UAC/BA,EAAAC,cACAA,EAAgB,CAAA,IAKhB,MAAOC,EAAGC,GAAeC,EAAAA,SAAS,CAAA,GAElCC,EAAAA,WAAU,KACR,MAAMC,EAAiB,IAAMH,EAAY,IAKlC,OAHHH,EAAUO,SAASD,IACrBH,EAAY,CAAA,GAEP,IAAMH,EAAUQ,UAAUF,EAAc,GAC9C,CAACN,IAGE,MAAAS,EAAeT,EAAUU,gBAAgBT,GAKzCU,EAAWX,EAAUY,cAE3B,IAAKD,EACH,MAAM,IAAIE,MAAM,yBAAyBb,EAAUc,iBAwBrD,OAAOH,EAASX,EAAUe,OApB1B,SAA0BC,GAClB,MAAAC,SAASD,WAASE,SAAU,IAAKT,KAAiBO,EAAQE,SAAYT,EAC5E,OAAOT,EACJmB,cACAC,QAAO,EAAGtB,UAED,MAAAkB,OAAA,EAAAA,EAASI,SAAUJ,EAAQI,OAAOtB,KAE3CuB,KAAI,EAAGrB,UAAWsB,EAAOxB,KAAIyB,eAC5BA,EACEC,EAAAC,IAAC,MAAI,CAAAF,YACHG,SAACD,EAAAA,IAAA1B,EAAA,CAA0BC,UAAWsB,EAAOrB,cAAegB,GAArCnB,KAGxB2B,EAAAA,IAAA1B,EAAA,CAA0BC,UAAWsB,EAAOrB,cAAegB,GAArCnB,IAE3B,GAI+CW,EACrD,0BCbgB,UAAiBiB,SAAEA,IACjC,MAAQC,SAAUC,GAAejC,IAG3BkC,EAAkBC,GACfA,EAAWT,KAAKrB,GACrByB,EAAAA,IAAC1B,GAA0CC,aAApBA,EAAUe,MAAMjB,MA0B3C,OAAO4B,EArB+B,CACpCK,QAAS,CACPC,IAAKH,GAAe,MAAAD,OAAA,EAAAA,EAAYK,sBAAsB,SAAU,IAChEC,OAAQL,GAAe,MAAAD,OAAA,EAAAA,EAAYK,sBAAsB,YAAa,IACtEE,KAAMN,GAAe,MAAAD,OAAA,EAAAA,EAAYK,sBAAsB,UAAW,IAClEG,MAAOP,GAAe,MAAAD,OAAA,EAAAA,EAAYK,sBAAsB,WAAY,KAEtEI,OAAQ,CACNF,KAAMN,GAAe,MAAAD,OAAA,EAAAA,EAAYU,oBAAoB,UAAW,IAChEF,MAAOP,GAAe,MAAAD,OAAA,EAAAA,EAAYU,oBAAoB,WAAY,KAEpEC,SAAU,CACRC,eAAgBX,GAAe,MAAAD,OAAA,EAAAA,EAAYa,sBAAsB,YAAa,IAC9EC,gBAAiBb,GAAe,MAAAD,OAAA,EAAAA,EAAYa,sBAAsB,aAAc,KAElFE,aAAa,MAAAf,OAAA,EAAAA,EAAYgB,kBACvBnB,MAAC1B,GAAiBC,UAAW4B,EAAWgB,mBACtC,MAKR,gDFxE2B,IAAMC,YAAoBhD,EAAAA,SAASC"}
@@ -4,34 +4,6 @@ import { UIPlugin } from "@embedpdf/plugin-ui";
4
4
  import { useState, useEffect } from "react";
5
5
  const useUIPlugin = () => usePlugin(UIPlugin.id);
6
6
  const useUICapability = () => useCapability(UIPlugin.id);
7
- function useIcon() {
8
- const { provides: uiProvides } = useUICapability();
9
- if (!uiProvides) {
10
- throw new Error("useIcon must be used within a UI context");
11
- }
12
- const {
13
- registerIcon,
14
- registerIcons,
15
- getIcon,
16
- getAllIcons,
17
- getSvgString,
18
- isSvgString,
19
- isSvgDataUri,
20
- dataUriToSvgString,
21
- svgStringToDataUri
22
- } = uiProvides;
23
- return {
24
- registerIcon,
25
- registerIcons,
26
- getIcon,
27
- getAllIcons,
28
- getSvgString,
29
- isSvgString,
30
- isSvgDataUri,
31
- dataUriToSvgString,
32
- svgStringToDataUri
33
- };
34
- }
35
7
  function ComponentWrapper({
36
8
  component,
37
9
  parentContext = {}
@@ -85,7 +57,6 @@ function PluginUIProvider({ children }) {
85
57
  }
86
58
  export {
87
59
  PluginUIProvider,
88
- useIcon,
89
60
  useUICapability,
90
61
  useUIPlugin
91
62
  };