@embedpdf/plugin-ui 1.4.1 → 2.0.0-next.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/dist/index.cjs +1 -1
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.js +1313 -655
  4. package/dist/index.js.map +1 -1
  5. package/dist/lib/actions.d.ts +110 -74
  6. package/dist/lib/index.d.ts +8 -7
  7. package/dist/lib/reducer.d.ts +5 -5
  8. package/dist/lib/schema.d.ts +257 -0
  9. package/dist/lib/selectors.d.ts +16 -0
  10. package/dist/lib/types.d.ts +185 -202
  11. package/dist/lib/ui-plugin.d.ts +66 -18
  12. package/dist/lib/utils/consts.d.ts +25 -0
  13. package/dist/lib/utils/index.d.ts +5 -0
  14. package/dist/lib/utils/responsive-utils.d.ts +10 -0
  15. package/dist/lib/utils/schema-merger.d.ts +15 -0
  16. package/dist/lib/utils/stylesheet-generator.d.ts +40 -0
  17. package/dist/lib/utils/ui-props.d.ts +14 -0
  18. package/dist/preact/adapter.d.ts +4 -2
  19. package/dist/preact/index.cjs +1 -1
  20. package/dist/preact/index.cjs.map +1 -1
  21. package/dist/preact/index.js +450 -49
  22. package/dist/preact/index.js.map +1 -1
  23. package/dist/preact/utils.d.ts +1 -0
  24. package/dist/react/adapter.d.ts +2 -2
  25. package/dist/react/index.cjs +1 -1
  26. package/dist/react/index.cjs.map +1 -1
  27. package/dist/react/index.js +449 -48
  28. package/dist/react/index.js.map +1 -1
  29. package/dist/react/utils.d.ts +1 -0
  30. package/dist/shared/auto-menu-renderer.d.ts +13 -0
  31. package/dist/shared/hooks/index.d.ts +4 -0
  32. package/dist/shared/hooks/use-item-renderer.d.ts +14 -0
  33. package/dist/shared/hooks/use-register-anchor.d.ts +17 -0
  34. package/dist/shared/hooks/use-schema-renderer.d.ts +61 -0
  35. package/dist/shared/hooks/use-selection-menu.d.ts +11 -0
  36. package/dist/shared/hooks/use-ui.d.ts +13 -5
  37. package/dist/shared/index.d.ts +4 -1
  38. package/dist/shared/provider.d.ts +68 -0
  39. package/dist/shared/registries/anchor-registry.d.ts +16 -0
  40. package/dist/shared/registries/component-registry.d.ts +20 -0
  41. package/dist/shared/registries/index.d.ts +3 -0
  42. package/dist/shared/registries/renderers-registry.d.ts +8 -0
  43. package/dist/shared/root.d.ts +12 -0
  44. package/dist/shared/types.d.ts +67 -0
  45. package/dist/shared-preact/auto-menu-renderer.d.ts +13 -0
  46. package/dist/shared-preact/hooks/index.d.ts +4 -0
  47. package/dist/shared-preact/hooks/use-item-renderer.d.ts +14 -0
  48. package/dist/shared-preact/hooks/use-register-anchor.d.ts +17 -0
  49. package/dist/shared-preact/hooks/use-schema-renderer.d.ts +61 -0
  50. package/dist/shared-preact/hooks/use-selection-menu.d.ts +11 -0
  51. package/dist/shared-preact/hooks/use-ui.d.ts +13 -5
  52. package/dist/shared-preact/index.d.ts +4 -1
  53. package/dist/shared-preact/provider.d.ts +68 -0
  54. package/dist/shared-preact/registries/anchor-registry.d.ts +16 -0
  55. package/dist/shared-preact/registries/component-registry.d.ts +20 -0
  56. package/dist/shared-preact/registries/index.d.ts +3 -0
  57. package/dist/shared-preact/registries/renderers-registry.d.ts +8 -0
  58. package/dist/shared-preact/root.d.ts +12 -0
  59. package/dist/shared-preact/types.d.ts +67 -0
  60. package/dist/shared-react/auto-menu-renderer.d.ts +13 -0
  61. package/dist/shared-react/hooks/index.d.ts +4 -0
  62. package/dist/shared-react/hooks/use-item-renderer.d.ts +14 -0
  63. package/dist/shared-react/hooks/use-register-anchor.d.ts +17 -0
  64. package/dist/shared-react/hooks/use-schema-renderer.d.ts +61 -0
  65. package/dist/shared-react/hooks/use-selection-menu.d.ts +11 -0
  66. package/dist/shared-react/hooks/use-ui.d.ts +13 -5
  67. package/dist/shared-react/index.d.ts +4 -1
  68. package/dist/shared-react/provider.d.ts +68 -0
  69. package/dist/shared-react/registries/anchor-registry.d.ts +16 -0
  70. package/dist/shared-react/registries/component-registry.d.ts +20 -0
  71. package/dist/shared-react/registries/index.d.ts +3 -0
  72. package/dist/shared-react/registries/renderers-registry.d.ts +8 -0
  73. package/dist/shared-react/root.d.ts +12 -0
  74. package/dist/shared-react/types.d.ts +67 -0
  75. package/dist/svelte/auto-menu-renderer.svelte.d.ts +15 -0
  76. package/dist/svelte/hooks/index.d.ts +5 -0
  77. package/dist/svelte/hooks/use-item-renderer.svelte.d.ts +24 -0
  78. package/dist/svelte/hooks/use-register-anchor.svelte.d.ts +18 -0
  79. package/dist/svelte/hooks/use-schema-renderer.svelte.d.ts +78 -0
  80. package/dist/svelte/hooks/use-selection-menu.svelte.d.ts +9 -0
  81. package/dist/svelte/hooks/use-ui.svelte.d.ts +34 -0
  82. package/dist/svelte/index.cjs +2 -0
  83. package/dist/svelte/index.cjs.map +1 -0
  84. package/dist/svelte/index.d.ts +6 -0
  85. package/dist/svelte/index.js +553 -0
  86. package/dist/svelte/index.js.map +1 -0
  87. package/dist/svelte/provider.svelte.d.ts +33 -0
  88. package/dist/svelte/registries/anchor-registry.svelte.d.ts +14 -0
  89. package/dist/svelte/registries/component-registry.svelte.d.ts +17 -0
  90. package/dist/svelte/registries/index.d.ts +3 -0
  91. package/dist/svelte/registries/renderers-registry.svelte.d.ts +3 -0
  92. package/dist/svelte/root.svelte.d.ts +8 -0
  93. package/dist/svelte/types.d.ts +67 -0
  94. package/dist/vue/auto-menu-renderer.vue.d.ts +15 -0
  95. package/dist/vue/hooks/index.d.ts +5 -0
  96. package/dist/vue/hooks/use-item-renderer.d.ts +16 -0
  97. package/dist/vue/hooks/use-register-anchor.d.ts +19 -0
  98. package/dist/vue/hooks/use-schema-renderer.d.ts +63 -0
  99. package/dist/vue/hooks/use-selection-menu.d.ts +28 -0
  100. package/dist/vue/hooks/use-ui.d.ts +940 -0
  101. package/dist/vue/index.cjs +2 -0
  102. package/dist/vue/index.cjs.map +1 -0
  103. package/dist/vue/index.d.ts +6 -0
  104. package/dist/vue/index.js +544 -0
  105. package/dist/vue/index.js.map +1 -0
  106. package/dist/vue/provider.vue.d.ts +43 -0
  107. package/dist/vue/registries/anchor-registry.d.ts +14 -0
  108. package/dist/vue/registries/component-registry.d.ts +17 -0
  109. package/dist/vue/registries/index.d.ts +3 -0
  110. package/dist/vue/registries/renderers-registry.d.ts +3 -0
  111. package/dist/vue/root.vue.d.ts +13 -0
  112. package/dist/vue/types.d.ts +67 -0
  113. package/package.json +32 -9
  114. package/dist/lib/menu/menu-manager.d.ts +0 -98
  115. package/dist/lib/menu/types.d.ts +0 -91
  116. package/dist/lib/menu/utils.d.ts +0 -6
  117. package/dist/lib/ui-component.d.ts +0 -30
  118. package/dist/lib/utils.d.ts +0 -33
  119. package/dist/shared/components/component-wrapper.d.ts +0 -5
  120. package/dist/shared/components/index.d.ts +0 -1
  121. package/dist/shared/components/plugin-ui-provider.d.ts +0 -37
  122. package/dist/shared-preact/components/component-wrapper.d.ts +0 -5
  123. package/dist/shared-preact/components/index.d.ts +0 -1
  124. package/dist/shared-preact/components/plugin-ui-provider.d.ts +0 -37
  125. package/dist/shared-react/components/component-wrapper.d.ts +0 -5
  126. package/dist/shared-react/components/index.d.ts +0 -1
  127. package/dist/shared-react/components/plugin-ui-provider.d.ts +0 -37
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../../src/svelte/hooks/use-ui.svelte.ts","../../src/svelte/registries/anchor-registry.svelte.ts","../../src/svelte/hooks/use-register-anchor.svelte.ts","../../src/svelte/registries/component-registry.svelte.ts","../../src/svelte/hooks/use-item-renderer.svelte.ts","../../src/svelte/registries/renderers-registry.svelte.ts","../../src/svelte/hooks/use-schema-renderer.svelte.ts","../../src/svelte/hooks/use-selection-menu.svelte.ts","../../src/svelte/auto-menu-renderer.svelte","../../src/svelte/root.svelte","../../src/svelte/provider.svelte"],"sourcesContent":["import { useCapability, usePlugin } from '@embedpdf/core/svelte';\nimport { UIPlugin, UIDocumentState, UISchema, UIScope } from '@embedpdf/plugin-ui';\n\n/**\n * Hook to get the raw UI plugin instance.\n */\nexport const useUIPlugin = () => usePlugin<UIPlugin>(UIPlugin.id);\n\n/**\n * Hook to get the UI plugin's capability API.\n */\nexport const useUICapability = () => useCapability<UIPlugin>(UIPlugin.id);\n\n// Define the return type explicitly to maintain type safety\ninterface UseUIStateReturn {\n provides: UIScope | null;\n state: UIDocumentState | null;\n}\n\n/**\n * Hook for UI state for a specific document\n * @param getDocumentId Function that returns the document ID\n */\nexport const useUIState = (getDocumentId: () => string | null): UseUIStateReturn => {\n const capability = useUICapability();\n\n let state = $state<UIDocumentState | null>(null);\n\n // Reactive documentId\n const documentId = $derived(getDocumentId());\n\n // Scoped capability for current docId\n const scopedProvides = $derived(\n capability.provides && documentId ? capability.provides.forDocument(documentId) : null,\n );\n\n $effect(() => {\n const provides = capability.provides;\n const docId = documentId;\n\n if (!provides || !docId) {\n state = null;\n return;\n }\n\n const scope = provides.forDocument(docId);\n\n // Set initial state\n state = scope.getState();\n\n // Subscribe to all changes and update state\n const unsubToolbar = scope.onToolbarChanged(() => {\n state = scope.getState();\n });\n const unsubPanel = scope.onPanelChanged(() => {\n state = scope.getState();\n });\n const unsubModal = scope.onModalChanged(() => {\n state = scope.getState();\n });\n const unsubMenu = scope.onMenuChanged(() => {\n state = scope.getState();\n });\n\n return () => {\n unsubToolbar();\n unsubPanel();\n unsubModal();\n unsubMenu();\n };\n });\n\n return {\n get provides() {\n return scopedProvides;\n },\n get state() {\n return state;\n },\n };\n};\n\n/**\n * Hook to get UI schema\n * Returns an object with a reactive getter for the schema\n */\nexport const useUISchema = () => {\n const capability = useUICapability();\n\n return {\n get schema() {\n return capability.provides?.getSchema() ?? null;\n },\n };\n};\n","import { getContext, setContext } from 'svelte';\n\n/**\n * Anchor Registry\n *\n * Tracks DOM elements for menu positioning.\n * Each anchor is scoped by documentId and itemId.\n */\nexport interface AnchorRegistry {\n register(documentId: string, itemId: string, element: HTMLElement): void;\n unregister(documentId: string, itemId: string): void;\n getAnchor(documentId: string, itemId: string): HTMLElement | null;\n}\n\nconst ANCHOR_REGISTRY_KEY = Symbol('AnchorRegistry');\n\nexport function createAnchorRegistry(): AnchorRegistry {\n const anchors = new Map<string, HTMLElement>();\n\n return {\n register(documentId: string, itemId: string, element: HTMLElement) {\n const key = `${documentId}:${itemId}`;\n anchors.set(key, element);\n },\n\n unregister(documentId: string, itemId: string) {\n const key = `${documentId}:${itemId}`;\n anchors.delete(key);\n },\n\n getAnchor(documentId: string, itemId: string) {\n const key = `${documentId}:${itemId}`;\n return anchors.get(key) || null;\n },\n };\n}\n\nexport function provideAnchorRegistry() {\n const registry = createAnchorRegistry();\n setContext(ANCHOR_REGISTRY_KEY, registry);\n return registry;\n}\n\nexport function useAnchorRegistry(): AnchorRegistry {\n const registry = getContext<AnchorRegistry>(ANCHOR_REGISTRY_KEY);\n if (!registry) {\n throw new Error('useAnchorRegistry must be used within UIProvider');\n }\n return registry;\n}\n","import { onDestroy } from 'svelte';\nimport { useAnchorRegistry } from '../registries/anchor-registry.svelte';\n\n/**\n * Register a DOM element as an anchor for menus\n *\n * @param getDocumentId - Function returning document ID\n * @param getItemId - Function returning item ID (typically matches the toolbar/menu item ID)\n * @returns Function to attach to the element via use:action\n *\n * @example\n *\n * <script lang=\"ts\">\n * const registerAnchor = useRegisterAnchor(() => documentId, () => 'zoom-button');\n * </script>\n *\n * <button use:registerAnchor>Zoom</button>\n * */\nexport function useRegisterAnchor(getDocumentId: () => string | null, getItemId: () => string) {\n const registry = useAnchorRegistry();\n let currentElement = $state<HTMLElement | null>(null);\n\n // Reactive values - these update when the functions return different values\n const documentId = $derived(getDocumentId());\n const itemId = $derived(getItemId());\n\n // Re-register anchor when documentId, itemId, or element changes\n $effect(() => {\n const docId = documentId;\n const item = itemId;\n const element = currentElement;\n\n // Only register if we have all required values\n if (element && docId && item) {\n registry.register(docId, item, element);\n\n // Cleanup: unregister when effect re-runs or component unmounts\n return () => {\n registry.unregister(docId, item);\n };\n }\n });\n\n // Svelte action function\n const action = (element: HTMLElement) => {\n currentElement = element;\n\n return {\n destroy() {\n // Clear the element reference when the action is destroyed\n currentElement = null;\n },\n };\n };\n\n return action;\n}\n","import { getContext, setContext, type Component } from 'svelte';\nimport type { BaseComponentProps } from '../types';\n\n/**\n * Component Registry\n *\n * Stores custom components that can be referenced in the UI schema.\n */\nexport interface ComponentRegistry {\n register(id: string, component: Component<BaseComponentProps>): void;\n unregister(id: string): void;\n get(id: string): Component<BaseComponentProps> | undefined;\n has(id: string): boolean;\n getRegisteredIds(): string[];\n}\n\nconst COMPONENT_REGISTRY_KEY = Symbol('ComponentRegistry');\n\nexport function createComponentRegistry(\n initialComponents: Record<string, Component<BaseComponentProps>> = {},\n): ComponentRegistry {\n const components = new Map<string, Component<BaseComponentProps>>(\n Object.entries(initialComponents),\n );\n\n return {\n register(id: string, component: Component<BaseComponentProps>) {\n components.set(id, component);\n },\n\n unregister(id: string) {\n components.delete(id);\n },\n\n get(id: string) {\n return components.get(id);\n },\n\n has(id: string) {\n return components.has(id);\n },\n\n getRegisteredIds() {\n return Array.from(components.keys());\n },\n };\n}\n\nexport function provideComponentRegistry(\n initialComponents: Record<string, Component<BaseComponentProps>> = {},\n) {\n const registry = createComponentRegistry(initialComponents);\n setContext(COMPONENT_REGISTRY_KEY, registry);\n return registry;\n}\n\nexport function useComponentRegistry(): ComponentRegistry {\n const registry = getContext<ComponentRegistry>(COMPONENT_REGISTRY_KEY);\n if (!registry) {\n throw new Error('useComponentRegistry must be used within UIProvider');\n }\n return registry;\n}\n","import { useComponentRegistry } from '../registries/component-registry.svelte';\n\n/**\n * Helper utilities for building renderers\n */\nexport function useItemRenderer() {\n const componentRegistry = useComponentRegistry();\n\n return {\n /**\n * Get a custom component by ID\n *\n * @param componentId - Component ID from schema\n * @returns Component constructor or undefined if not found\n *\n * @example\n * ```svelte\n * <script lang=\"ts\">\n * const { getCustomComponent } = useItemRenderer();\n * const MyComponent = getCustomComponent('my-component-id');\n * </script>\n *\n * {#if MyComponent}\n * <MyComponent {documentId} {...props} />\n * {/if}\n * ```\n */\n getCustomComponent: (componentId: string) => {\n const Component = componentRegistry.get(componentId);\n\n if (!Component) {\n console.error(`Component \"${componentId}\" not found in registry`);\n return undefined;\n }\n\n return Component;\n },\n };\n}\n","import { getContext, setContext } from 'svelte';\nimport type { UIRenderers } from '../types';\n\n/**\n * Renderers Registry\n *\n * Provides access to user-supplied renderers (toolbar, panel, menu).\n */\nconst RENDERERS_KEY = Symbol('Renderers');\n\nexport function provideRenderers(renderers: UIRenderers) {\n setContext(RENDERERS_KEY, renderers);\n}\n\nexport function useRenderers(): UIRenderers {\n const renderers = getContext<UIRenderers>(RENDERERS_KEY);\n if (!renderers) {\n throw new Error('useRenderers must be used within UIProvider');\n }\n return renderers;\n}\n","import { useUICapability } from './use-ui.svelte';\nimport { useRenderers } from '../registries/renderers-registry.svelte';\n\n/**\n * High-level hook for rendering UI from schema\n *\n * Provides information about active toolbars and panels by placement+slot.\n * Always includes isOpen state so renderers can control animations.\n *\n * Use with Svelte's component binding to render toolbars and panels.\n *\n * @example\n * ```svelte\n * <script lang=\"ts\">\n * const { getToolbarInfo, getPanelInfo } = useSchemaRenderer(() => documentId);\n *\n * const topMainToolbar = $derived(getToolbarInfo('top', 'main'));\n * const leftMainPanel = $derived(getPanelInfo('left', 'main'));\n * </script>\n *\n * {#if topMainToolbar}\n * {@const ToolbarRenderer = topMainToolbar.renderer}\n * <ToolbarRenderer\n * schema={topMainToolbar.schema}\n * documentId={topMainToolbar.documentId}\n * isOpen={topMainToolbar.isOpen}\n * onClose={topMainToolbar.onClose}\n * />\n * {/if}\n * ```\n */\nexport function useSchemaRenderer(getDocumentId: () => string | null) {\n const renderers = useRenderers();\n const capability = useUICapability();\n const uiState = useUIState(getDocumentId);\n\n return {\n /**\n * Get toolbar information by placement and slot\n *\n * @param placement - 'top' | 'bottom' | 'left' | 'right'\n * @param slot - Slot name (e.g. 'main', 'secondary')\n * @returns Toolbar info or null if no toolbar in slot\n */\n getToolbarInfo: (placement: 'top' | 'bottom' | 'left' | 'right', slot: string) => {\n const schema = capability.provides?.getSchema();\n const documentId = getDocumentId();\n\n if (!schema || !uiState.provides || !uiState.state || !documentId) return null;\n\n const slotKey = `${placement}-${slot}`;\n const toolbarSlot = uiState.state.activeToolbars[slotKey];\n\n // If no toolbar in this slot, nothing to render\n if (!toolbarSlot) return null;\n\n const toolbarSchema = schema.toolbars[toolbarSlot.toolbarId];\n if (!toolbarSchema) {\n console.warn(`Toolbar \"${toolbarSlot.toolbarId}\" not found in schema`);\n return null;\n }\n\n // Check if toolbar is closable\n const isClosable = !toolbarSchema.permanent;\n\n const handleClose = isClosable\n ? () => {\n uiState.provides?.closeToolbarSlot(placement, slot);\n }\n : undefined;\n\n return {\n renderer: renderers.toolbar,\n schema: toolbarSchema,\n documentId,\n isOpen: toolbarSlot.isOpen,\n onClose: handleClose,\n };\n },\n\n /**\n * Get panel information by placement and slot\n *\n * @param placement - 'left' | 'right' | 'top' | 'bottom'\n * @param slot - Slot name (e.g. 'main', 'secondary', 'inspector')\n * @returns Panel info or null if no panel in slot\n */\n getPanelInfo: (placement: 'left' | 'right' | 'top' | 'bottom', slot: string) => {\n const schema = capability.provides?.getSchema();\n const documentId = getDocumentId();\n\n if (!schema || !uiState.provides || !uiState.state || !documentId) return null;\n\n const slotKey = `${placement}-${slot}`;\n const panelSlot = uiState.state.activePanels[slotKey];\n\n // If no panel in this slot, nothing to render\n if (!panelSlot) return null;\n\n const panelSchema = schema.panels[panelSlot.panelId];\n if (!panelSchema) {\n console.warn(`Panel \"${panelSlot.panelId}\" not found in schema`);\n return null;\n }\n\n const handleClose = () => {\n uiState.provides?.closePanelSlot(placement, slot);\n };\n\n return {\n renderer: renderers.panel,\n schema: panelSchema,\n documentId,\n isOpen: panelSlot.isOpen,\n onClose: handleClose,\n };\n },\n\n /**\n * Helper: Get all active toolbars for this document\n * Useful for batch rendering or debugging\n */\n getActiveToolbars: () => {\n if (!uiState.state) return [];\n return Object.entries(uiState.state.activeToolbars).map(([slotKey, toolbarSlot]) => {\n const [placement, slot] = slotKey.split('-');\n return {\n placement,\n slot,\n toolbarId: toolbarSlot.toolbarId,\n isOpen: toolbarSlot.isOpen,\n };\n });\n },\n\n /**\n * Helper: Get all active panels for this document\n * Useful for batch rendering or debugging\n */\n getActivePanels: () => {\n if (!uiState.state) return [];\n return Object.entries(uiState.state.activePanels).map(([slotKey, panelSlot]) => {\n const [placement, slot] = slotKey.split('-');\n return {\n placement,\n slot,\n panelId: panelSlot.panelId,\n isOpen: panelSlot.isOpen,\n };\n });\n },\n };\n}\n\n// Import after definition to avoid circular dependency\nimport { useUIState } from './use-ui.svelte';\n","import type {\n SelectionMenuPropsBase,\n SelectionMenuRenderFn,\n SelectionMenuRenderResult,\n} from '@embedpdf/utils/svelte';\nimport { useUICapability } from './use-ui.svelte';\nimport { useRenderers } from '../registries/renderers-registry.svelte';\n\n/**\n * Hook for schema-driven selection menus\n */\nexport function useSelectionMenu<TContext extends { type: string }>(\n menuId: string | (() => string),\n getDocumentId: () => string,\n) {\n const uiCapability = useUICapability();\n const renderers = useRenderers();\n\n // Normalize menuId to always be a function, then make it reactive\n const getMenuIdFn = typeof menuId === 'function' ? menuId : () => menuId;\n const menuIdValue = $derived(getMenuIdFn());\n const documentId = $derived(getDocumentId());\n const schema = $derived(uiCapability.provides?.getSchema());\n const menuSchema = $derived(schema?.selectionMenus?.[menuIdValue]);\n\n const renderFn = $derived.by<SelectionMenuRenderFn<TContext> | undefined>(() => {\n if (!menuSchema) return undefined;\n\n const currentMenuSchema = menuSchema;\n const currentDocumentId = documentId;\n const SelectionMenuRenderer = renderers.selectionMenu;\n\n return (props: SelectionMenuPropsBase<TContext>): SelectionMenuRenderResult | null => {\n if (!props.selected) return null;\n\n return {\n component: SelectionMenuRenderer,\n props: {\n schema: currentMenuSchema,\n documentId: currentDocumentId,\n props,\n },\n };\n };\n });\n\n return {\n get renderFn() {\n return renderFn;\n },\n };\n}\n","<script lang=\"ts\">\n import { useUIState, useUICapability } from './hooks/use-ui.svelte';\n import { useAnchorRegistry } from './registries/anchor-registry.svelte';\n import { useRenderers } from './registries/renderers-registry.svelte';\n\n /**\n * Automatically renders menus when opened\n *\n * This component:\n * 1. Listens to UI plugin state for open menus\n * 2. Looks up anchor elements from the anchor registry\n * 3. Renders menus using the user-provided menu renderer\n */\n\n interface Props {\n documentId: string; // Which document's menus to render\n container?: HTMLElement | null;\n }\n\n let { documentId, container = null }: Props = $props();\n\n const uiState = useUIState(() => documentId);\n const capability = useUICapability();\n const anchorRegistry = useAnchorRegistry();\n const renderers = useRenderers();\n\n // Derived state for active menu\n const activeMenu = $derived.by(() => {\n const openMenus = uiState.state?.openMenus || {};\n const openMenuIds = Object.keys(openMenus);\n\n if (openMenuIds.length === 0) return null;\n\n // Show the first open menu (in practice, should only be one)\n const menuId = openMenuIds[0];\n if (!menuId) return null;\n\n const menuState = openMenus[menuId];\n if (!menuState || !menuState.triggeredByItemId) return null;\n\n // Look up anchor with documentId scope\n const anchor = anchorRegistry.getAnchor(documentId, menuState.triggeredByItemId);\n return { menuId, anchorEl: anchor };\n });\n\n const schema = $derived(capability.provides?.getSchema());\n\n const menuSchema = $derived.by(() => {\n if (!activeMenu || !schema) return null;\n\n const menuSchemaValue = schema.menus[activeMenu.menuId];\n if (!menuSchemaValue) {\n console.warn(`Menu \"${activeMenu.menuId}\" not found in schema`);\n return null;\n }\n\n return menuSchemaValue;\n });\n\n const handleClose = () => {\n if (activeMenu) {\n uiState.provides?.closeMenu(activeMenu.menuId);\n }\n };\n\n // Use the user-provided menu renderer\n const MenuRenderer = renderers.menu;\n</script>\n\n{#if activeMenu && menuSchema && MenuRenderer}\n <MenuRenderer\n schema={menuSchema}\n {documentId}\n anchorEl={activeMenu.anchorEl}\n onClose={handleClose}\n {container}\n />\n{/if}\n","<script lang=\"ts\">\n import { UI_ATTRIBUTES, UI_SELECTORS } from '@embedpdf/plugin-ui';\n import { useUIPlugin, useUICapability } from './hooks/use-ui.svelte';\n import type { Snippet } from 'svelte';\n import type { HTMLAttributes } from 'svelte/elements';\n\n type Props = HTMLAttributes<HTMLDivElement> & {\n children?: Snippet;\n };\n\n let { children, class: className, ...restProps }: Props = $props();\n\n const { plugin } = useUIPlugin();\n const { provides } = useUICapability();\n\n let disabledCategories = $state<string[]>([]);\n let rootElement: HTMLDivElement | null = $state(null);\n let styleEl: HTMLStyleElement | null = null;\n let styleTarget: HTMLElement | ShadowRoot | null = null;\n\n function getStyleTarget(element: HTMLElement): HTMLElement | ShadowRoot {\n const root = element.getRootNode();\n if (root instanceof ShadowRoot) {\n return root;\n }\n return document.head;\n }\n\n $effect(() => {\n if (!rootElement || !plugin) {\n styleTarget = null;\n return;\n }\n\n styleTarget = getStyleTarget(rootElement);\n\n const existingStyle = styleTarget.querySelector(UI_SELECTORS.STYLES) as HTMLStyleElement | null;\n\n if (existingStyle) {\n styleEl = existingStyle;\n existingStyle.textContent = plugin.getStylesheet();\n return;\n }\n\n const stylesheet = plugin.getStylesheet();\n const newStyleEl = document.createElement('style');\n newStyleEl.setAttribute(UI_ATTRIBUTES.STYLES, '');\n newStyleEl.textContent = stylesheet;\n\n if (styleTarget instanceof ShadowRoot) {\n styleTarget.insertBefore(newStyleEl, styleTarget.firstChild);\n } else {\n styleTarget.appendChild(newStyleEl);\n }\n\n styleEl = newStyleEl;\n\n return () => {\n if (styleEl?.parentNode) {\n styleEl.remove();\n }\n styleEl = null;\n styleTarget = null;\n };\n });\n\n $effect(() => {\n if (!plugin) return;\n\n return plugin.onStylesheetInvalidated(() => {\n if (styleEl) {\n styleEl.textContent = plugin.getStylesheet();\n }\n });\n });\n\n $effect(() => {\n if (!provides) return;\n\n disabledCategories = provides.getDisabledCategories();\n\n return provides.onCategoryChanged((event) => {\n disabledCategories = event.disabledCategories;\n });\n });\n\n const disabledCategoriesAttr = $derived(\n disabledCategories.length > 0 ? disabledCategories.join(' ') : undefined,\n );\n</script>\n\n<div\n bind:this={rootElement}\n {...restProps}\n {...{ [UI_ATTRIBUTES.ROOT]: '' }}\n {...disabledCategoriesAttr ? { [UI_ATTRIBUTES.DISABLED_CATEGORIES]: disabledCategoriesAttr } : {}}\n class={className}\n style:container-type=\"inline-size\"\n>\n {#if children}\n {@render children()}\n {/if}\n</div>\n","<script lang=\"ts\">\n import type { Component, Snippet } from 'svelte';\n import { provideAnchorRegistry } from './registries/anchor-registry.svelte';\n import { provideComponentRegistry } from './registries/component-registry.svelte';\n import { provideRenderers } from './registries/renderers-registry.svelte';\n import type { UIComponents, UIRenderers } from './types';\n import AutoMenuRenderer from './auto-menu-renderer.svelte';\n import UIRoot from './root.svelte';\n import type { HTMLAttributes } from 'svelte/elements';\n\n /**\n * UIProvider Props\n */\n type ProviderProps = HTMLAttributes<HTMLDivElement> & {\n children: Snippet;\n\n /**\n * Document ID for this UI context\n * Required for menu rendering\n */\n documentId: string;\n\n /**\n * Custom component registry\n * Maps component IDs to components\n */\n components?: UIComponents;\n\n /**\n * REQUIRED: User-provided renderers\n * These define how toolbars, panels, and menus are displayed\n */\n renderers: UIRenderers;\n\n /**\n * Optional: Container for menu portal\n * Defaults to document.body\n */\n menuContainer?: HTMLElement | null;\n\n class?: string;\n };\n\n let {\n children,\n documentId,\n components = {},\n renderers,\n menuContainer = null,\n class: className,\n ...restProps\n }: ProviderProps = $props();\n\n /**\n * UIProvider - Single provider for all UI plugin functionality\n *\n * Manages:\n * - Anchor registry for menu positioning\n * - Component registry for custom components\n * - Renderers for toolbars, panels, and menus\n * - Automatic menu rendering\n *\n * @example\n * ```svelte\n * <EmbedPDF {engine} {plugins}>\n * {#snippet children({ pluginsReady, activeDocumentId })}\n * {#if pluginsReady && activeDocumentId}\n * <UIProvider\n * documentId={activeDocumentId}\n * components={{\n * 'thumbnail-panel': ThumbnailPanel,\n * 'bookmark-panel': BookmarkPanel,\n * }}\n * renderers={{\n * toolbar: ToolbarRenderer,\n * panel: PanelRenderer,\n * menu: MenuRenderer,\n * }}\n * >\n * {#snippet children()}\n * <ViewerLayout />\n * {/snippet}\n * </UIProvider>\n * {/if}\n * {/snippet}\n * </EmbedPDF>\n * ```\n */\n\n // Provide all registries\n provideAnchorRegistry();\n provideComponentRegistry(components);\n provideRenderers(renderers);\n</script>\n\n<UIRoot class={className} {...restProps}>\n {@render children()}\n <AutoMenuRenderer {documentId} container={menuContainer} />\n</UIRoot>\n"],"names":["_a"],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import { Component, Snippet } from 'svelte';
2
+ import { UIComponents, UIRenderers } from './types';
3
+ import { HTMLAttributes } from 'svelte/elements';
4
+ /**
5
+ * UIProvider Props
6
+ */
7
+ type ProviderProps = HTMLAttributes<HTMLDivElement> & {
8
+ children: Snippet;
9
+ /**
10
+ * Document ID for this UI context
11
+ * Required for menu rendering
12
+ */
13
+ documentId: string;
14
+ /**
15
+ * Custom component registry
16
+ * Maps component IDs to components
17
+ */
18
+ components?: UIComponents;
19
+ /**
20
+ * REQUIRED: User-provided renderers
21
+ * These define how toolbars, panels, and menus are displayed
22
+ */
23
+ renderers: UIRenderers;
24
+ /**
25
+ * Optional: Container for menu portal
26
+ * Defaults to document.body
27
+ */
28
+ menuContainer?: HTMLElement | null;
29
+ class?: string;
30
+ };
31
+ declare const Provider: Component<ProviderProps, {}, "">;
32
+ type Provider = ReturnType<typeof Provider>;
33
+ export default Provider;
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Anchor Registry
3
+ *
4
+ * Tracks DOM elements for menu positioning.
5
+ * Each anchor is scoped by documentId and itemId.
6
+ */
7
+ export interface AnchorRegistry {
8
+ register(documentId: string, itemId: string, element: HTMLElement): void;
9
+ unregister(documentId: string, itemId: string): void;
10
+ getAnchor(documentId: string, itemId: string): HTMLElement | null;
11
+ }
12
+ export declare function createAnchorRegistry(): AnchorRegistry;
13
+ export declare function provideAnchorRegistry(): AnchorRegistry;
14
+ export declare function useAnchorRegistry(): AnchorRegistry;
@@ -0,0 +1,17 @@
1
+ import { Component } from 'svelte';
2
+ import { BaseComponentProps } from '../types';
3
+ /**
4
+ * Component Registry
5
+ *
6
+ * Stores custom components that can be referenced in the UI schema.
7
+ */
8
+ export interface ComponentRegistry {
9
+ register(id: string, component: Component<BaseComponentProps>): void;
10
+ unregister(id: string): void;
11
+ get(id: string): Component<BaseComponentProps> | undefined;
12
+ has(id: string): boolean;
13
+ getRegisteredIds(): string[];
14
+ }
15
+ export declare function createComponentRegistry(initialComponents?: Record<string, Component<BaseComponentProps>>): ComponentRegistry;
16
+ export declare function provideComponentRegistry(initialComponents?: Record<string, Component<BaseComponentProps>>): ComponentRegistry;
17
+ export declare function useComponentRegistry(): ComponentRegistry;
@@ -0,0 +1,3 @@
1
+ export * from './anchor-registry.svelte';
2
+ export * from './component-registry.svelte';
3
+ export * from './renderers-registry.svelte';
@@ -0,0 +1,3 @@
1
+ import { UIRenderers } from '../types';
2
+ export declare function provideRenderers(renderers: UIRenderers): void;
3
+ export declare function useRenderers(): UIRenderers;
@@ -0,0 +1,8 @@
1
+ import { Snippet } from 'svelte';
2
+ import { HTMLAttributes } from 'svelte/elements';
3
+ type Props = HTMLAttributes<HTMLDivElement> & {
4
+ children?: Snippet;
5
+ };
6
+ declare const Root: import('svelte', { with: { "resolution-mode": "import" } }).Component<Props, {}, "">;
7
+ type Root = ReturnType<typeof Root>;
8
+ export default Root;
@@ -0,0 +1,67 @@
1
+ import { Component } from 'svelte';
2
+ import { ToolbarSchema, PanelSchema, MenuSchema, SelectionMenuSchema } from '../lib';
3
+ import { SelectionMenuPropsBase } from '@embedpdf/utils/svelte';
4
+ export type { SelectionMenuPropsBase };
5
+ export type UIComponents = Record<string, Component<BaseComponentProps>>;
6
+ /**
7
+ * Base props that all custom components must accept
8
+ */
9
+ export interface BaseComponentProps {
10
+ documentId: string;
11
+ [key: string]: any;
12
+ }
13
+ /**
14
+ * Props for toolbar renderer
15
+ * The app provides a component matching this contract
16
+ */
17
+ export interface ToolbarRendererProps {
18
+ schema: ToolbarSchema;
19
+ documentId: string;
20
+ isOpen: boolean;
21
+ onClose?: () => void;
22
+ className?: string;
23
+ }
24
+ export type ToolbarRenderer = Component<ToolbarRendererProps>;
25
+ /**
26
+ * Props for panel renderer
27
+ * The app provides a component matching this contract
28
+ */
29
+ export interface PanelRendererProps {
30
+ schema: PanelSchema;
31
+ documentId: string;
32
+ isOpen: boolean;
33
+ onClose: () => void;
34
+ className?: string;
35
+ }
36
+ export type PanelRenderer = Component<PanelRendererProps>;
37
+ /**
38
+ * Props for menu renderer
39
+ * The app provides a component matching this contract
40
+ */
41
+ export interface MenuRendererProps {
42
+ schema: MenuSchema;
43
+ documentId: string;
44
+ anchorEl: HTMLElement | null;
45
+ onClose: () => void;
46
+ container?: HTMLElement | null;
47
+ }
48
+ export type MenuRenderer = Component<MenuRendererProps>;
49
+ /**
50
+ * Props for the selection menu renderer component
51
+ */
52
+ export interface SelectionMenuRendererProps {
53
+ schema: SelectionMenuSchema;
54
+ documentId: string;
55
+ /** Full props from the layer including context */
56
+ props: SelectionMenuPropsBase;
57
+ }
58
+ export type SelectionMenuRenderer = Component<SelectionMenuRendererProps>;
59
+ /**
60
+ * All renderers the app must provide
61
+ */
62
+ export interface UIRenderers {
63
+ toolbar: ToolbarRenderer;
64
+ panel: PanelRenderer;
65
+ menu: MenuRenderer;
66
+ selectionMenu: SelectionMenuRenderer;
67
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Automatically renders menus when opened
3
+ *
4
+ * This component:
5
+ * 1. Listens to UI plugin state for open menus
6
+ * 2. Looks up anchor elements from the anchor registry
7
+ * 3. Renders menus using the user-provided menu renderer
8
+ */
9
+ interface Props {
10
+ documentId: string;
11
+ container?: HTMLElement | null;
12
+ }
13
+ declare const __VLS_export: import('vue').DefineComponent<Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<Props> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
14
+ declare const _default: typeof __VLS_export;
15
+ export default _default;
@@ -0,0 +1,5 @@
1
+ export * from './use-ui';
2
+ export * from './use-register-anchor';
3
+ export * from './use-item-renderer';
4
+ export * from './use-schema-renderer';
5
+ export * from './use-selection-menu';
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Helper utilities for building renderers
3
+ */
4
+ export declare function useItemRenderer(): {
5
+ /**
6
+ * Render a custom component by ID
7
+ *
8
+ * @param componentId - Component ID from schema
9
+ * @param documentId - Document ID
10
+ * @param props - Additional props to pass to component
11
+ * @returns Rendered component or null if not found
12
+ */
13
+ renderCustomComponent: (componentId: string, documentId: string, props?: any) => import('vue').VNode<import('vue').RendererNode, import('vue').RendererElement, {
14
+ [key: string]: any;
15
+ }> | null;
16
+ };
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Register a DOM element as an anchor for menus
3
+ *
4
+ * @param documentId - Document ID
5
+ * @param itemId - Item ID (typically matches the toolbar/menu item ID)
6
+ * @returns Ref to attach to the element (use with :ref="anchorRef")
7
+ *
8
+ * @example
9
+ * ```vue
10
+ * <script setup lang="ts">
11
+ * const anchorRef = useRegisterAnchor(props.documentId, 'zoom-button');
12
+ * </script>
13
+ *
14
+ * <template>
15
+ * <button :ref="anchorRef">Zoom</button>
16
+ * </template>
17
+ * ```
18
+ */
19
+ export declare function useRegisterAnchor(documentId: string, itemId: string): (el: any) => void;
@@ -0,0 +1,63 @@
1
+ import { VNode, MaybeRefOrGetter } from 'vue';
2
+ /**
3
+ * High-level composable for rendering UI from schema
4
+ *
5
+ * Provides simple functions to render toolbars and panels by placement+slot.
6
+ * Always passes isOpen state to renderers so they can control animations.
7
+ *
8
+ * Automatically subscribes to UI state changes for the given document.
9
+ * @param documentId Document ID (can be ref, computed, getter, or plain value)
10
+ */
11
+ export declare function useSchemaRenderer(documentId: MaybeRefOrGetter<string>): {
12
+ /**
13
+ * Render a toolbar by placement and slot
14
+ *
15
+ * Always renders with isOpen state when toolbar exists in slot.
16
+ *
17
+ * @param placement - 'top' | 'bottom' | 'left' | 'right'
18
+ * @param slot - Slot name (e.g. 'main', 'secondary')
19
+ *
20
+ * @example
21
+ * ```vue
22
+ * <component :is="renderToolbar('top', 'main')" />
23
+ * <component :is="renderToolbar('top', 'secondary')" />
24
+ * ```
25
+ */
26
+ renderToolbar: (placement: "top" | "bottom" | "left" | "right", slot: string) => VNode | null;
27
+ /**
28
+ * Render a panel by placement and slot
29
+ *
30
+ * ALWAYS renders (when panel exists in slot) with isOpen state.
31
+ * Your renderer controls whether to display or animate.
32
+ *
33
+ * @param placement - 'left' | 'right' | 'top' | 'bottom'
34
+ * @param slot - Slot name (e.g. 'main', 'secondary', 'inspector')
35
+ *
36
+ * @example
37
+ * ```vue
38
+ * <component :is="renderPanel('left', 'main')" />
39
+ * <component :is="renderPanel('right', 'main')" />
40
+ * ```
41
+ */
42
+ renderPanel: (placement: "left" | "right" | "top" | "bottom", slot: string) => VNode | null;
43
+ /**
44
+ * Helper: Get all active toolbars for this document
45
+ * Useful for batch rendering or debugging
46
+ */
47
+ getActiveToolbars: () => {
48
+ placement: string;
49
+ slot: string;
50
+ toolbarId: string;
51
+ isOpen: boolean;
52
+ }[];
53
+ /**
54
+ * Helper: Get all active panels for this document
55
+ * Useful for batch rendering or debugging
56
+ */
57
+ getActivePanels: () => {
58
+ placement: string;
59
+ slot: string;
60
+ panelId: string;
61
+ isOpen: boolean;
62
+ }[];
63
+ };
@@ -0,0 +1,28 @@
1
+ import { MaybeRefOrGetter } from 'vue';
2
+ import { SelectionMenuRenderFn } from '@embedpdf/utils/vue';
3
+ /**
4
+ * Creates a render function for a selection menu from the schema
5
+ *
6
+ * @param menuId - The selection menu ID from schema
7
+ * @param documentId - Document ID (can be ref, computed, getter, or plain value)
8
+ * @returns A computed ref containing the render function or undefined
9
+ *
10
+ * @example
11
+ * ```vue
12
+ * <script setup lang="ts">
13
+ * const annotationMenu = useSelectionMenu('annotation', () => props.documentId);
14
+ * </script>
15
+ *
16
+ * <template>
17
+ * <AnnotationLayer
18
+ * :documentId="documentId"
19
+ * :selectionMenu="annotationMenu"
20
+ * />
21
+ * </template>
22
+ * ```
23
+ */
24
+ export declare function useSelectionMenu<TContext extends {
25
+ type: string;
26
+ } = {
27
+ type: string;
28
+ }>(menuId: MaybeRefOrGetter<string>, documentId: MaybeRefOrGetter<string>): import('vue').ComputedRef<SelectionMenuRenderFn<TContext> | undefined>;