@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.
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1313 -655
- package/dist/index.js.map +1 -1
- package/dist/lib/actions.d.ts +110 -74
- package/dist/lib/index.d.ts +8 -7
- package/dist/lib/reducer.d.ts +5 -5
- package/dist/lib/schema.d.ts +257 -0
- package/dist/lib/selectors.d.ts +16 -0
- package/dist/lib/types.d.ts +185 -202
- package/dist/lib/ui-plugin.d.ts +66 -18
- package/dist/lib/utils/consts.d.ts +25 -0
- package/dist/lib/utils/index.d.ts +5 -0
- package/dist/lib/utils/responsive-utils.d.ts +10 -0
- package/dist/lib/utils/schema-merger.d.ts +15 -0
- package/dist/lib/utils/stylesheet-generator.d.ts +40 -0
- package/dist/lib/utils/ui-props.d.ts +14 -0
- package/dist/preact/adapter.d.ts +4 -2
- package/dist/preact/index.cjs +1 -1
- package/dist/preact/index.cjs.map +1 -1
- package/dist/preact/index.js +450 -49
- package/dist/preact/index.js.map +1 -1
- package/dist/preact/utils.d.ts +1 -0
- package/dist/react/adapter.d.ts +2 -2
- package/dist/react/index.cjs +1 -1
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.js +449 -48
- package/dist/react/index.js.map +1 -1
- package/dist/react/utils.d.ts +1 -0
- package/dist/shared/auto-menu-renderer.d.ts +13 -0
- package/dist/shared/hooks/index.d.ts +4 -0
- package/dist/shared/hooks/use-item-renderer.d.ts +14 -0
- package/dist/shared/hooks/use-register-anchor.d.ts +17 -0
- package/dist/shared/hooks/use-schema-renderer.d.ts +61 -0
- package/dist/shared/hooks/use-selection-menu.d.ts +11 -0
- package/dist/shared/hooks/use-ui.d.ts +13 -5
- package/dist/shared/index.d.ts +4 -1
- package/dist/shared/provider.d.ts +68 -0
- package/dist/shared/registries/anchor-registry.d.ts +16 -0
- package/dist/shared/registries/component-registry.d.ts +20 -0
- package/dist/shared/registries/index.d.ts +3 -0
- package/dist/shared/registries/renderers-registry.d.ts +8 -0
- package/dist/shared/root.d.ts +12 -0
- package/dist/shared/types.d.ts +67 -0
- package/dist/shared-preact/auto-menu-renderer.d.ts +13 -0
- package/dist/shared-preact/hooks/index.d.ts +4 -0
- package/dist/shared-preact/hooks/use-item-renderer.d.ts +14 -0
- package/dist/shared-preact/hooks/use-register-anchor.d.ts +17 -0
- package/dist/shared-preact/hooks/use-schema-renderer.d.ts +61 -0
- package/dist/shared-preact/hooks/use-selection-menu.d.ts +11 -0
- package/dist/shared-preact/hooks/use-ui.d.ts +13 -5
- package/dist/shared-preact/index.d.ts +4 -1
- package/dist/shared-preact/provider.d.ts +68 -0
- package/dist/shared-preact/registries/anchor-registry.d.ts +16 -0
- package/dist/shared-preact/registries/component-registry.d.ts +20 -0
- package/dist/shared-preact/registries/index.d.ts +3 -0
- package/dist/shared-preact/registries/renderers-registry.d.ts +8 -0
- package/dist/shared-preact/root.d.ts +12 -0
- package/dist/shared-preact/types.d.ts +67 -0
- package/dist/shared-react/auto-menu-renderer.d.ts +13 -0
- package/dist/shared-react/hooks/index.d.ts +4 -0
- package/dist/shared-react/hooks/use-item-renderer.d.ts +14 -0
- package/dist/shared-react/hooks/use-register-anchor.d.ts +17 -0
- package/dist/shared-react/hooks/use-schema-renderer.d.ts +61 -0
- package/dist/shared-react/hooks/use-selection-menu.d.ts +11 -0
- package/dist/shared-react/hooks/use-ui.d.ts +13 -5
- package/dist/shared-react/index.d.ts +4 -1
- package/dist/shared-react/provider.d.ts +68 -0
- package/dist/shared-react/registries/anchor-registry.d.ts +16 -0
- package/dist/shared-react/registries/component-registry.d.ts +20 -0
- package/dist/shared-react/registries/index.d.ts +3 -0
- package/dist/shared-react/registries/renderers-registry.d.ts +8 -0
- package/dist/shared-react/root.d.ts +12 -0
- package/dist/shared-react/types.d.ts +67 -0
- package/dist/svelte/auto-menu-renderer.svelte.d.ts +15 -0
- package/dist/svelte/hooks/index.d.ts +5 -0
- package/dist/svelte/hooks/use-item-renderer.svelte.d.ts +24 -0
- package/dist/svelte/hooks/use-register-anchor.svelte.d.ts +18 -0
- package/dist/svelte/hooks/use-schema-renderer.svelte.d.ts +78 -0
- package/dist/svelte/hooks/use-selection-menu.svelte.d.ts +9 -0
- package/dist/svelte/hooks/use-ui.svelte.d.ts +34 -0
- package/dist/svelte/index.cjs +2 -0
- package/dist/svelte/index.cjs.map +1 -0
- package/dist/svelte/index.d.ts +6 -0
- package/dist/svelte/index.js +553 -0
- package/dist/svelte/index.js.map +1 -0
- package/dist/svelte/provider.svelte.d.ts +33 -0
- package/dist/svelte/registries/anchor-registry.svelte.d.ts +14 -0
- package/dist/svelte/registries/component-registry.svelte.d.ts +17 -0
- package/dist/svelte/registries/index.d.ts +3 -0
- package/dist/svelte/registries/renderers-registry.svelte.d.ts +3 -0
- package/dist/svelte/root.svelte.d.ts +8 -0
- package/dist/svelte/types.d.ts +67 -0
- package/dist/vue/auto-menu-renderer.vue.d.ts +15 -0
- package/dist/vue/hooks/index.d.ts +5 -0
- package/dist/vue/hooks/use-item-renderer.d.ts +16 -0
- package/dist/vue/hooks/use-register-anchor.d.ts +19 -0
- package/dist/vue/hooks/use-schema-renderer.d.ts +63 -0
- package/dist/vue/hooks/use-selection-menu.d.ts +28 -0
- package/dist/vue/hooks/use-ui.d.ts +940 -0
- package/dist/vue/index.cjs +2 -0
- package/dist/vue/index.cjs.map +1 -0
- package/dist/vue/index.d.ts +6 -0
- package/dist/vue/index.js +544 -0
- package/dist/vue/index.js.map +1 -0
- package/dist/vue/provider.vue.d.ts +43 -0
- package/dist/vue/registries/anchor-registry.d.ts +14 -0
- package/dist/vue/registries/component-registry.d.ts +17 -0
- package/dist/vue/registries/index.d.ts +3 -0
- package/dist/vue/registries/renderers-registry.d.ts +3 -0
- package/dist/vue/root.vue.d.ts +13 -0
- package/dist/vue/types.d.ts +67 -0
- package/package.json +32 -9
- package/dist/lib/menu/menu-manager.d.ts +0 -98
- package/dist/lib/menu/types.d.ts +0 -91
- package/dist/lib/menu/utils.d.ts +0 -6
- package/dist/lib/ui-component.d.ts +0 -30
- package/dist/lib/utils.d.ts +0 -33
- package/dist/shared/components/component-wrapper.d.ts +0 -5
- package/dist/shared/components/index.d.ts +0 -1
- package/dist/shared/components/plugin-ui-provider.d.ts +0 -37
- package/dist/shared-preact/components/component-wrapper.d.ts +0 -5
- package/dist/shared-preact/components/index.d.ts +0 -1
- package/dist/shared-preact/components/plugin-ui-provider.d.ts +0 -37
- package/dist/shared-react/components/component-wrapper.d.ts +0 -5
- package/dist/shared-react/components/index.d.ts +0 -1
- package/dist/shared-react/components/plugin-ui-provider.d.ts +0 -37
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/vue/hooks/use-ui.ts","../../src/vue/registries/anchor-registry.ts","../../src/vue/hooks/use-register-anchor.ts","../../src/vue/registries/component-registry.ts","../../src/vue/hooks/use-item-renderer.ts","../../src/vue/registries/renderers-registry.ts","../../src/vue/hooks/use-schema-renderer.ts","../../src/vue/hooks/use-selection-menu.ts","../../src/vue/auto-menu-renderer.vue","../../src/vue/root.vue","../../src/vue/provider.vue"],"sourcesContent":["import { ref, watch, computed, readonly, toValue, type MaybeRefOrGetter } from 'vue';\nimport { useCapability, usePlugin } from '@embedpdf/core/vue';\nimport { UIPlugin, UIDocumentState, UISchema } from '@embedpdf/plugin-ui';\n\nexport const useUIPlugin = () => usePlugin<UIPlugin>(UIPlugin.id);\nexport const useUICapability = () => useCapability<UIPlugin>(UIPlugin.id);\n\n/**\n * Hook for UI state for a specific document\n * @param documentId Document ID (can be ref, computed, getter, or plain value)\n */\nexport const useUIState = (documentId: MaybeRefOrGetter<string>) => {\n const { provides } = useUICapability();\n const state = ref<UIDocumentState | null>(null);\n\n watch(\n [provides, () => toValue(documentId)],\n ([providesValue, docId], _, onCleanup) => {\n if (!providesValue) {\n state.value = null;\n return;\n }\n\n const scope = providesValue.forDocument(docId);\n\n // Set initial state\n state.value = scope.getState();\n\n // Subscribe to all changes\n const unsubToolbar = scope.onToolbarChanged(() => {\n state.value = scope.getState();\n });\n const unsubPanel = scope.onPanelChanged(() => {\n state.value = scope.getState();\n });\n const unsubModal = scope.onModalChanged(() => {\n state.value = scope.getState();\n });\n const unsubMenu = scope.onMenuChanged(() => {\n state.value = scope.getState();\n });\n\n onCleanup(() => {\n unsubToolbar();\n unsubPanel();\n unsubModal();\n unsubMenu();\n });\n },\n { immediate: true },\n );\n\n // Return a computed ref for the scoped capability\n const scopedProvides = computed(() => {\n const docId = toValue(documentId);\n return provides.value?.forDocument(docId) ?? null;\n });\n\n return {\n provides: scopedProvides,\n state: readonly(state),\n };\n};\n\n/**\n * Hook to get UI schema\n */\nexport const useUISchema = () => {\n const { provides } = useUICapability();\n const schema = computed<UISchema | null>(() => provides.value?.getSchema() ?? null);\n\n return readonly(schema);\n};\n","import { ref, inject, provide, type InjectionKey, type Ref } from 'vue';\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 AnchorRegistryKey: InjectionKey<AnchorRegistry> = Symbol('AnchorRegistry');\n\nexport function createAnchorRegistry(): AnchorRegistry {\n const anchors: Ref<Map<string, HTMLElement>> = ref(new Map());\n\n return {\n register(documentId: string, itemId: string, element: HTMLElement) {\n const key = `${documentId}:${itemId}`;\n anchors.value.set(key, element);\n },\n\n unregister(documentId: string, itemId: string) {\n const key = `${documentId}:${itemId}`;\n anchors.value.delete(key);\n },\n\n getAnchor(documentId: string, itemId: string) {\n const key = `${documentId}:${itemId}`;\n return anchors.value.get(key) || null;\n },\n };\n}\n\nexport function provideAnchorRegistry() {\n const registry = createAnchorRegistry();\n provide(AnchorRegistryKey, registry);\n return registry;\n}\n\nexport function useAnchorRegistry(): AnchorRegistry {\n const registry = inject(AnchorRegistryKey);\n if (!registry) {\n throw new Error('useAnchorRegistry must be used within UIProvider');\n }\n return registry;\n}\n","import { onBeforeUnmount, ref, watch } from 'vue';\nimport { useAnchorRegistry } from '../registries/anchor-registry';\n\n/**\n * Register a DOM element as an anchor for menus\n *\n * @param documentId - Document ID\n * @param itemId - Item ID (typically matches the toolbar/menu item ID)\n * @returns Ref to attach to the element (use with :ref=\"anchorRef\")\n *\n * @example\n * ```vue\n * <script setup lang=\"ts\">\n * const anchorRef = useRegisterAnchor(props.documentId, 'zoom-button');\n * </script>\n *\n * <template>\n * <button :ref=\"anchorRef\">Zoom</button>\n * </template>\n * ```\n */\nexport function useRegisterAnchor(documentId: string, itemId: string) {\n const registry = useAnchorRegistry();\n const elementRef = ref<HTMLElement | null>(null);\n\n // Function to set ref\n const setRef = (el: any) => {\n // Handle Vue 3 ref binding\n const element = el?.$el || el;\n\n // Unregister previous element if exists\n if (elementRef.value && elementRef.value !== element) {\n registry.unregister(documentId, itemId);\n }\n\n elementRef.value = element;\n\n // Register new element\n if (element) {\n registry.register(documentId, itemId, element);\n }\n };\n\n // Cleanup on unmount\n onBeforeUnmount(() => {\n if (elementRef.value) {\n registry.unregister(documentId, itemId);\n }\n });\n\n return setRef;\n}\n","import { ref, inject, provide, type Component, type InjectionKey, type Ref } from 'vue';\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 ComponentRegistryKey: InjectionKey<ComponentRegistry> = Symbol('ComponentRegistry');\n\nexport function createComponentRegistry(\n initialComponents: Record<string, Component<BaseComponentProps>> = {},\n): ComponentRegistry {\n const components: Ref<Map<string, Component<BaseComponentProps>>> = ref(\n new Map(Object.entries(initialComponents)),\n );\n\n return {\n register(id: string, component: Component<BaseComponentProps>) {\n components.value.set(id, component);\n },\n\n unregister(id: string) {\n components.value.delete(id);\n },\n\n get(id: string) {\n return components.value.get(id);\n },\n\n has(id: string) {\n return components.value.has(id);\n },\n\n getRegisteredIds() {\n return Array.from(components.value.keys());\n },\n };\n}\n\nexport function provideComponentRegistry(\n initialComponents: Record<string, Component<BaseComponentProps>> = {},\n) {\n const registry = createComponentRegistry(initialComponents);\n provide(ComponentRegistryKey, registry);\n return registry;\n}\n\nexport function useComponentRegistry(): ComponentRegistry {\n const registry = inject(ComponentRegistryKey);\n if (!registry) {\n throw new Error('useComponentRegistry must be used within UIProvider');\n }\n return registry;\n}\n","import { h } from 'vue';\nimport { useComponentRegistry } from '../registries/component-registry';\n\n/**\n * Helper utilities for building renderers\n */\nexport function useItemRenderer() {\n const componentRegistry = useComponentRegistry();\n\n return {\n /**\n * Render a custom component by ID\n *\n * @param componentId - Component ID from schema\n * @param documentId - Document ID\n * @param props - Additional props to pass to component\n * @returns Rendered component or null if not found\n */\n renderCustomComponent: (componentId: string, documentId: string, props?: any) => {\n const Component = componentRegistry.get(componentId);\n\n if (!Component) {\n console.error(`Component \"${componentId}\" not found in registry`);\n return null;\n }\n\n return h(Component, { documentId, ...(props || {}) });\n },\n };\n}\n","import { inject, provide, type InjectionKey } from 'vue';\nimport type { UIRenderers } from '../types';\n\n/**\n * Renderers Registry\n *\n * Provides access to user-supplied renderers (toolbar, panel, menu).\n */\nconst RenderersKey: InjectionKey<UIRenderers> = Symbol('Renderers');\n\nexport function provideRenderers(renderers: UIRenderers) {\n provide(RenderersKey, renderers);\n}\n\nexport function useRenderers(): UIRenderers {\n const renderers = inject(RenderersKey);\n if (!renderers) {\n throw new Error('useRenderers must be used within UIProvider');\n }\n return renderers;\n}\n","import { h, toValue, type VNode, type MaybeRefOrGetter } from 'vue';\nimport { useUICapability, useUIState } from './use-ui';\nimport { useRenderers } from '../registries/renderers-registry';\n\n/**\n * High-level composable for rendering UI from schema\n *\n * Provides simple functions to render toolbars and panels by placement+slot.\n * Always passes isOpen state to renderers so they can control animations.\n *\n * Automatically subscribes to UI state changes for the given document.\n * @param documentId Document ID (can be ref, computed, getter, or plain value)\n */\nexport function useSchemaRenderer(documentId: MaybeRefOrGetter<string>) {\n const renderers = useRenderers();\n const { provides } = useUICapability();\n const { state: uiState } = useUIState(documentId);\n\n return {\n /**\n * Render a toolbar by placement and slot\n *\n * Always renders with isOpen state when toolbar exists in slot.\n *\n * @param placement - 'top' | 'bottom' | 'left' | 'right'\n * @param slot - Slot name (e.g. 'main', 'secondary')\n *\n * @example\n * ```vue\n * <component :is=\"renderToolbar('top', 'main')\" />\n * <component :is=\"renderToolbar('top', 'secondary')\" />\n * ```\n */\n renderToolbar: (placement: 'top' | 'bottom' | 'left' | 'right', slot: string): VNode | null => {\n const schema = provides.value?.getSchema();\n\n if (!schema || !provides.value || !uiState.value) return null;\n\n const slotKey = `${placement}-${slot}`;\n const toolbarSlot = uiState.value.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 provides.value?.forDocument(toValue(documentId)).closeToolbarSlot(placement, slot);\n }\n : undefined;\n\n const ToolbarRenderer = renderers.toolbar;\n\n // ALWAYS render, pass isOpen state\n return h(ToolbarRenderer, {\n key: toolbarSlot.toolbarId,\n schema: toolbarSchema,\n documentId: toValue(documentId),\n isOpen: toolbarSlot.isOpen,\n onClose: handleClose,\n });\n },\n\n /**\n * Render a panel by placement and slot\n *\n * ALWAYS renders (when panel exists in slot) with isOpen state.\n * Your renderer controls whether to display or animate.\n *\n * @param placement - 'left' | 'right' | 'top' | 'bottom'\n * @param slot - Slot name (e.g. 'main', 'secondary', 'inspector')\n *\n * @example\n * ```vue\n * <component :is=\"renderPanel('left', 'main')\" />\n * <component :is=\"renderPanel('right', 'main')\" />\n * ```\n */\n renderPanel: (placement: 'left' | 'right' | 'top' | 'bottom', slot: string): VNode | null => {\n const schema = provides.value?.getSchema();\n\n if (!schema || !provides.value || !uiState.value) return null;\n\n const slotKey = `${placement}-${slot}`;\n const panelSlot = uiState.value.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 provides.value?.forDocument(toValue(documentId)).closePanelSlot(placement, slot);\n };\n\n const PanelRenderer = renderers.panel;\n\n // ALWAYS render, pass isOpen state\n // Your renderer decides whether to return null or animate\n return h(PanelRenderer, {\n key: panelSlot.panelId,\n schema: panelSchema,\n documentId: toValue(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.value) return [];\n return Object.entries(uiState.value.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.value) return [];\n return Object.entries(uiState.value.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","import { computed, h, toValue, type VNode, type MaybeRefOrGetter } from 'vue';\nimport type { SelectionMenuPropsBase, SelectionMenuRenderFn } from '@embedpdf/utils/vue';\nimport { useUICapability } from './use-ui';\nimport { useRenderers } from '../registries/renderers-registry';\n\n/**\n * Creates a render function for a selection menu from the schema\n *\n * @param menuId - The selection menu ID from schema\n * @param documentId - Document ID (can be ref, computed, getter, or plain value)\n * @returns A computed ref containing the render function or undefined\n *\n * @example\n * ```vue\n * <script setup lang=\"ts\">\n * const annotationMenu = useSelectionMenu('annotation', () => props.documentId);\n * </script>\n *\n * <template>\n * <AnnotationLayer\n * :documentId=\"documentId\"\n * :selectionMenu=\"annotationMenu\"\n * />\n * </template>\n * ```\n */\nexport function useSelectionMenu<TContext extends { type: string } = { type: string }>(\n menuId: MaybeRefOrGetter<string>,\n documentId: MaybeRefOrGetter<string>,\n) {\n const { provides } = useUICapability();\n const renderers = useRenderers();\n\n const schema = computed(() => provides.value?.getSchema());\n const menuSchema = computed(() => schema.value?.selectionMenus?.[toValue(menuId)]);\n\n // Return a computed that produces the render function (or undefined)\n const renderFn = computed<SelectionMenuRenderFn<TContext> | undefined>(() => {\n // If no schema for this menu, return undefined\n if (!menuSchema.value) {\n return undefined;\n }\n\n // Capture current values for the closure\n const currentMenuSchema = menuSchema.value;\n const currentDocumentId = toValue(documentId);\n const SelectionMenuRenderer = renderers.selectionMenu;\n\n // Return the render function\n return (props: SelectionMenuPropsBase<TContext>): VNode | null => {\n if (!props.selected) {\n return null;\n }\n\n return h(SelectionMenuRenderer, {\n schema: currentMenuSchema,\n documentId: currentDocumentId,\n props,\n });\n };\n });\n\n return renderFn;\n}\n","<template>\n <component\n v-if=\"activeMenu && menuSchema && MenuRenderer\"\n :is=\"MenuRenderer\"\n :schema=\"menuSchema\"\n :documentId=\"documentId\"\n :anchorEl=\"activeMenu.anchorEl\"\n :onClose=\"handleClose\"\n :container=\"container\"\n />\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, watch } from 'vue';\nimport { useUIState, useUICapability } from './hooks/use-ui';\nimport { useAnchorRegistry } from './registries/anchor-registry';\nimport { useRenderers } from './registries/renderers-registry';\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\ninterface Props {\n documentId: string; // Which document's menus to render\n container?: HTMLElement | null;\n}\n\nconst props = defineProps<Props>();\n\nconst { state: uiState } = useUIState(props.documentId);\nconst { provides } = useUICapability();\nconst anchorRegistry = useAnchorRegistry();\nconst renderers = useRenderers();\n\nconst activeMenu = ref<{\n menuId: string;\n anchorEl: HTMLElement | null;\n} | null>(null);\n\nconst openMenus = computed(() => uiState.value?.openMenus || {});\nconst schema = computed(() => provides.value?.getSchema());\n\n// Update active menu when state changes\nwatch(\n openMenus,\n (menus) => {\n const openMenuIds = Object.keys(menus);\n\n if (openMenuIds.length > 0) {\n // Show the first open menu (in practice, should only be one)\n const menuId = openMenuIds[0];\n if (!menuId) {\n activeMenu.value = null;\n return;\n }\n\n const menuState = menus[menuId];\n if (menuState && menuState.triggeredByItemId) {\n // Look up anchor with documentId scope\n const anchor = anchorRegistry.getAnchor(props.documentId, menuState.triggeredByItemId);\n activeMenu.value = { menuId, anchorEl: anchor };\n } else {\n activeMenu.value = null;\n }\n } else {\n activeMenu.value = null;\n }\n },\n { immediate: true },\n);\n\nconst menuSchema = computed(() => {\n if (!activeMenu.value || !schema.value) return null;\n\n const menuSchemaValue = schema.value.menus[activeMenu.value.menuId];\n if (!menuSchemaValue) {\n console.warn(`Menu \"${activeMenu.value.menuId}\" not found in schema`);\n return null;\n }\n\n return menuSchemaValue;\n});\n\nconst handleClose = () => {\n if (activeMenu.value) {\n provides.value?.forDocument(props.documentId).closeMenu(activeMenu.value.menuId);\n }\n};\n\n// Use the user-provided menu renderer\nconst MenuRenderer = computed(() => renderers.menu);\n</script>\n","<template>\n <div\n ref=\"rootRef\"\n v-bind=\"{ ...attrs, ...(rootAttrs as any) }\"\n :style=\"{ containerType: 'inline-size' }\"\n >\n <slot />\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, onMounted, onUnmounted, watch, useAttrs } from 'vue';\nimport { UI_ATTRIBUTES, UI_SELECTORS } from '@embedpdf/plugin-ui';\nimport { useUIPlugin, useUICapability } from './hooks/use-ui';\n\n// Disable automatic attribute inheritance since we handle it manually\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst attrs = useAttrs();\n\nconst { plugin } = useUIPlugin();\nconst { provides } = useUICapability();\n\nconst disabledCategories = ref<string[]>([]);\nconst rootRef = ref<HTMLDivElement | null>(null);\n\nlet styleEl: HTMLStyleElement | null = null;\nlet styleTarget: HTMLElement | ShadowRoot | null = null;\n\n/**\n * Find the style injection target for an element.\n * Returns the shadow root if inside one, otherwise document.head.\n */\nfunction 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/**\n * Inject or update stylesheet\n */\nfunction injectStyles() {\n if (!rootRef.value || !plugin.value) {\n return;\n }\n\n styleTarget = getStyleTarget(rootRef.value);\n\n // Check if styles already exist in this target\n const existingStyle = styleTarget.querySelector(UI_SELECTORS.STYLES) as HTMLStyleElement | null;\n\n if (existingStyle) {\n styleEl = existingStyle;\n // Update content in case locale changed\n existingStyle.textContent = plugin.value.getStylesheet();\n return;\n }\n\n // Create and inject stylesheet\n const stylesheet = plugin.value.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\n/**\n * Cleanup styles\n */\nfunction cleanupStyles() {\n if (styleEl?.parentNode) {\n styleEl.remove();\n }\n styleEl = null;\n styleTarget = null;\n}\n\n// Build root element attributes\nconst rootAttrs = computed(() => {\n const result: Record<string, string> = {\n [UI_ATTRIBUTES.ROOT]: '',\n };\n\n if (disabledCategories.value.length > 0) {\n result[UI_ATTRIBUTES.DISABLED_CATEGORIES] = disabledCategories.value.join(' ');\n }\n\n return result;\n});\n\n// Stylesheet invalidation cleanup\nlet stylesheetCleanup: (() => void) | null = null;\n\n// Category change cleanup\nlet categoryCleanup: (() => void) | null = null;\n\nonMounted(() => {\n // Inject styles on mount\n injectStyles();\n\n // Subscribe to stylesheet invalidation\n if (plugin.value) {\n stylesheetCleanup = plugin.value.onStylesheetInvalidated(() => {\n if (styleEl && plugin.value) {\n styleEl.textContent = plugin.value.getStylesheet();\n }\n });\n }\n\n // Subscribe to category changes\n if (provides.value) {\n disabledCategories.value = provides.value.getDisabledCategories();\n\n categoryCleanup = provides.value.onCategoryChanged((event) => {\n disabledCategories.value = event.disabledCategories;\n });\n }\n});\n\nonUnmounted(() => {\n cleanupStyles();\n stylesheetCleanup?.();\n categoryCleanup?.();\n});\n\n// Re-inject styles if plugin changes\nwatch(plugin, () => {\n if (rootRef.value && plugin.value) {\n injectStyles();\n }\n});\n</script>\n","<template>\n <UIRoot v-bind=\"attrs\">\n <slot />\n <!-- Automatically render menus for this document -->\n <AutoMenuRenderer :documentId=\"documentId\" :container=\"menuContainer\" />\n </UIRoot>\n</template>\n\n<script setup lang=\"ts\">\nimport type { Component } from 'vue';\nimport { useAttrs } from 'vue';\nimport { provideAnchorRegistry } from './registries/anchor-registry';\nimport { provideComponentRegistry } from './registries/component-registry';\nimport { provideRenderers } from './registries/renderers-registry';\nimport type { BaseComponentProps, UIRenderers } from './types';\nimport AutoMenuRenderer from './auto-menu-renderer.vue';\nimport UIRoot from './root.vue';\n\n// Disable automatic attribute inheritance since we pass them to UIRoot\ndefineOptions({\n inheritAttrs: false,\n});\n\nconst attrs = useAttrs();\n\n/**\n * UIProvider Props\n */\ninterface Props {\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?: Record<string, Component<BaseComponentProps>>;\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\nconst props = withDefaults(defineProps<Props>(), {\n components: () => ({}),\n menuContainer: null,\n});\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 * ```vue\n * <EmbedPDF :engine=\"engine\" :plugins=\"plugins\">\n * <template v-slot=\"{ pluginsReady, activeDocumentId }\">\n * <UIProvider\n * v-if=\"pluginsReady && activeDocumentId\"\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 * class=\"relative flex h-full w-full\"\n * >\n * <ViewerLayout />\n * </UIProvider>\n * </template>\n * </EmbedPDF>\n * ```\n */\n\n// Provide all registries\nprovideAnchorRegistry();\nprovideComponentRegistry(props.components);\nprovideRenderers(props.renderers);\n</script>\n"],"names":["_a","_openBlock","_createBlock","_resolveDynamicComponent","_createElementBlock","_mergeProps","_unref","_renderSlot","UIRoot","_createVNode","AutoMenuRenderer"],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Component } from 'vue';
|
|
2
|
+
import { BaseComponentProps, UIRenderers } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* UIProvider Props
|
|
5
|
+
*/
|
|
6
|
+
interface Props {
|
|
7
|
+
/**
|
|
8
|
+
* Document ID for this UI context
|
|
9
|
+
* Required for menu rendering
|
|
10
|
+
*/
|
|
11
|
+
documentId: string;
|
|
12
|
+
/**
|
|
13
|
+
* Custom component registry
|
|
14
|
+
* Maps component IDs to components
|
|
15
|
+
*/
|
|
16
|
+
components?: Record<string, Component<BaseComponentProps>>;
|
|
17
|
+
/**
|
|
18
|
+
* REQUIRED: User-provided renderers
|
|
19
|
+
* These define how toolbars, panels, and menus are displayed
|
|
20
|
+
*/
|
|
21
|
+
renderers: UIRenderers;
|
|
22
|
+
/**
|
|
23
|
+
* Optional: Container for menu portal
|
|
24
|
+
* Defaults to document.body
|
|
25
|
+
*/
|
|
26
|
+
menuContainer?: HTMLElement | null;
|
|
27
|
+
}
|
|
28
|
+
declare var __VLS_6: {};
|
|
29
|
+
type __VLS_Slots = {} & {
|
|
30
|
+
default?: (props: typeof __VLS_6) => any;
|
|
31
|
+
};
|
|
32
|
+
declare const __VLS_base: import('vue').DefineComponent<Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<Props> & Readonly<{}>, {
|
|
33
|
+
components: Record<string, Component<BaseComponentProps>>;
|
|
34
|
+
menuContainer: HTMLElement | null;
|
|
35
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, any>;
|
|
36
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
37
|
+
declare const _default: typeof __VLS_export;
|
|
38
|
+
export default _default;
|
|
39
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
40
|
+
new (): {
|
|
41
|
+
$slots: S;
|
|
42
|
+
};
|
|
43
|
+
};
|
|
@@ -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 'vue';
|
|
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,13 @@
|
|
|
1
|
+
declare var __VLS_1: {};
|
|
2
|
+
type __VLS_Slots = {} & {
|
|
3
|
+
default?: (props: typeof __VLS_1) => any;
|
|
4
|
+
};
|
|
5
|
+
declare const __VLS_base: import('vue').DefineComponent<{}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
|
|
6
|
+
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
|
7
|
+
declare const _default: typeof __VLS_export;
|
|
8
|
+
export default _default;
|
|
9
|
+
type __VLS_WithSlots<T, S> = T & {
|
|
10
|
+
new (): {
|
|
11
|
+
$slots: S;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { Component } from 'vue';
|
|
2
|
+
import { ToolbarSchema, PanelSchema, MenuSchema, SelectionMenuSchema } from '../lib';
|
|
3
|
+
import { SelectionMenuPropsBase } from '@embedpdf/utils/vue';
|
|
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
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@embedpdf/plugin-ui",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0-next.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -12,31 +12,52 @@
|
|
|
12
12
|
"import": "./dist/index.js",
|
|
13
13
|
"require": "./dist/index.cjs"
|
|
14
14
|
},
|
|
15
|
+
"./preact": {
|
|
16
|
+
"types": "./dist/preact/index.d.ts",
|
|
17
|
+
"import": "./dist/preact/index.js",
|
|
18
|
+
"require": "./dist/preact/index.cjs"
|
|
19
|
+
},
|
|
15
20
|
"./react": {
|
|
16
21
|
"types": "./dist/react/index.d.ts",
|
|
17
22
|
"import": "./dist/react/index.js",
|
|
18
23
|
"require": "./dist/react/index.cjs"
|
|
19
24
|
},
|
|
20
|
-
"./
|
|
21
|
-
"types": "./dist/
|
|
22
|
-
"import": "./dist/
|
|
23
|
-
"require": "./dist/
|
|
25
|
+
"./vue": {
|
|
26
|
+
"types": "./dist/vue/index.d.ts",
|
|
27
|
+
"import": "./dist/vue/index.js",
|
|
28
|
+
"require": "./dist/vue/index.cjs"
|
|
29
|
+
},
|
|
30
|
+
"./svelte": {
|
|
31
|
+
"types": "./dist/svelte/index.d.ts",
|
|
32
|
+
"svelte": "./dist/svelte/index.js",
|
|
33
|
+
"import": "./dist/svelte/index.js",
|
|
34
|
+
"require": "./dist/svelte/index.cjs"
|
|
24
35
|
}
|
|
25
36
|
},
|
|
26
37
|
"dependencies": {
|
|
27
|
-
"@embedpdf/models": "
|
|
38
|
+
"@embedpdf/models": "2.0.0-next.0"
|
|
28
39
|
},
|
|
29
40
|
"devDependencies": {
|
|
30
41
|
"@types/react": "^18.2.0",
|
|
31
42
|
"typescript": "^5.0.0",
|
|
43
|
+
"@embedpdf/core": "2.0.0-next.0",
|
|
32
44
|
"@embedpdf/build": "1.1.0",
|
|
33
|
-
"@embedpdf/
|
|
45
|
+
"@embedpdf/plugin-render": "2.0.0-next.0",
|
|
46
|
+
"@embedpdf/plugin-scroll": "2.0.0-next.0",
|
|
47
|
+
"@embedpdf/plugin-viewport": "2.0.0-next.0",
|
|
48
|
+
"@embedpdf/plugin-i18n": "2.0.0-next.0",
|
|
49
|
+
"@embedpdf/utils": "2.0.0-next.0"
|
|
34
50
|
},
|
|
35
51
|
"peerDependencies": {
|
|
36
52
|
"react": ">=16.8.0",
|
|
37
53
|
"react-dom": ">=16.8.0",
|
|
38
54
|
"preact": "^10.26.4",
|
|
39
|
-
"
|
|
55
|
+
"vue": ">=3.2.0",
|
|
56
|
+
"svelte": ">=5 <6",
|
|
57
|
+
"@embedpdf/core": "2.0.0-next.0",
|
|
58
|
+
"@embedpdf/plugin-render": "2.0.0-next.0",
|
|
59
|
+
"@embedpdf/plugin-viewport": "2.0.0-next.0",
|
|
60
|
+
"@embedpdf/plugin-scroll": "2.0.0-next.0"
|
|
40
61
|
},
|
|
41
62
|
"files": [
|
|
42
63
|
"dist",
|
|
@@ -58,7 +79,9 @@
|
|
|
58
79
|
"build:base": "vite build --mode base",
|
|
59
80
|
"build:react": "vite build --mode react",
|
|
60
81
|
"build:preact": "vite build --mode preact",
|
|
61
|
-
"build": "
|
|
82
|
+
"build:vue": "vite build --mode vue",
|
|
83
|
+
"build:svelte": "vite build --mode svelte",
|
|
84
|
+
"build": "pnpm run clean && concurrently -c auto -n base,react,preact,vue,svelte \"vite build --mode base\" \"vite build --mode react\" \"vite build --mode preact\" \"vite build --mode vue\" \"vite build --mode svelte\"",
|
|
62
85
|
"clean": "rimraf dist",
|
|
63
86
|
"lint": "eslint src --color",
|
|
64
87
|
"lint:fix": "eslint src --color --fix"
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import { PluginRegistry } from '@embedpdf/core';
|
|
2
|
-
import { MenuItem, ExecuteOptions, ResolvedMenuItem, MenuRegistry, MenuManagerCapabilities, ResolvedMenuItemResult, ResolvedMenu, ResolvedAction } from './types';
|
|
3
|
-
import { EventCallback } from '../utils';
|
|
4
|
-
/**
|
|
5
|
-
* MenuManager manages a registry of menu items and handles their execution.
|
|
6
|
-
* It also manages keyboard shortcuts and implements responsive behavior.
|
|
7
|
-
*/
|
|
8
|
-
export declare class MenuManager {
|
|
9
|
-
private registry;
|
|
10
|
-
private shortcutMap;
|
|
11
|
-
private eventController;
|
|
12
|
-
private pluginRegistry;
|
|
13
|
-
static readonly EVENTS: {
|
|
14
|
-
COMMAND_EXECUTED: string;
|
|
15
|
-
MENU_REQUESTED: string;
|
|
16
|
-
SHORTCUT_EXECUTED: string;
|
|
17
|
-
};
|
|
18
|
-
constructor(items: MenuRegistry | undefined, pluginRegistry: PluginRegistry);
|
|
19
|
-
/**
|
|
20
|
-
* Get the current state of the plugin registry
|
|
21
|
-
*/
|
|
22
|
-
private get state();
|
|
23
|
-
/**
|
|
24
|
-
* Register a single menu item
|
|
25
|
-
*/
|
|
26
|
-
registerItem(item: MenuItem): void;
|
|
27
|
-
/**
|
|
28
|
-
* Register multiple menu items at once
|
|
29
|
-
*/
|
|
30
|
-
registerItems(items: MenuRegistry): void;
|
|
31
|
-
/**
|
|
32
|
-
* Resolve a menu item by ID
|
|
33
|
-
*/
|
|
34
|
-
resolve(id: string): ResolvedMenuItem;
|
|
35
|
-
/**
|
|
36
|
-
* Get a menu item by ID with type information
|
|
37
|
-
*/
|
|
38
|
-
getMenuItem(id: string): ResolvedMenuItemResult | undefined;
|
|
39
|
-
/**
|
|
40
|
-
* Get a action by ID (only returns Action type items)
|
|
41
|
-
*/
|
|
42
|
-
getAction(id: string): ResolvedAction | undefined;
|
|
43
|
-
/**
|
|
44
|
-
* Get menu or action by ID
|
|
45
|
-
*/
|
|
46
|
-
getMenuOrAction(id: string): ResolvedMenu | ResolvedAction | undefined;
|
|
47
|
-
/**
|
|
48
|
-
* Get all registered menu items
|
|
49
|
-
*/
|
|
50
|
-
getAllItems(): MenuRegistry;
|
|
51
|
-
/**
|
|
52
|
-
* Get menu items by their IDs
|
|
53
|
-
*/
|
|
54
|
-
getItemsByIds(ids: string[]): ResolvedMenuItem[];
|
|
55
|
-
/**
|
|
56
|
-
* Get child items for a given menu ID
|
|
57
|
-
* If flatten is true, it will recursively include submenu children but not groups
|
|
58
|
-
*/
|
|
59
|
-
getChildItems(menuId: string, options?: {
|
|
60
|
-
flatten?: boolean;
|
|
61
|
-
}): ResolvedMenuItem[];
|
|
62
|
-
/**
|
|
63
|
-
* Execute a command by ID
|
|
64
|
-
*/
|
|
65
|
-
executeCommand(id: string, options?: ExecuteOptions): void;
|
|
66
|
-
/**
|
|
67
|
-
* Execute a command from a keyboard shortcut
|
|
68
|
-
*/
|
|
69
|
-
executeShortcut(shortcut: string): boolean;
|
|
70
|
-
/**
|
|
71
|
-
* Subscribe to menu events
|
|
72
|
-
*/
|
|
73
|
-
on(eventType: string, callback: EventCallback): () => void;
|
|
74
|
-
/**
|
|
75
|
-
* Remove an event subscription
|
|
76
|
-
*/
|
|
77
|
-
off(eventType: string, callback: EventCallback): void;
|
|
78
|
-
/**
|
|
79
|
-
* Handle a menu item that has children (showing a submenu)
|
|
80
|
-
*/
|
|
81
|
-
private handleSubmenu;
|
|
82
|
-
/**
|
|
83
|
-
* Set up keyboard listeners for shortcuts
|
|
84
|
-
*/
|
|
85
|
-
private setupKeyboardListeners;
|
|
86
|
-
/**
|
|
87
|
-
* Convert a KeyboardEvent to a shortcut string
|
|
88
|
-
*/
|
|
89
|
-
private buildShortcutString;
|
|
90
|
-
/**
|
|
91
|
-
* Normalize a shortcut string for consistent comparison
|
|
92
|
-
*/
|
|
93
|
-
private normalizeShortcut;
|
|
94
|
-
/**
|
|
95
|
-
* Get capabilities for the MenuManager
|
|
96
|
-
*/
|
|
97
|
-
capabilities(): MenuManagerCapabilities;
|
|
98
|
-
}
|
package/dist/lib/menu/types.d.ts
DELETED
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import { PluginRegistry } from '@embedpdf/core';
|
|
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
|
-
};
|
|
9
|
-
export interface MenuItemBase<TStore = any> {
|
|
10
|
-
icon?: Dynamic<TStore, string>;
|
|
11
|
-
iconProps?: Dynamic<TStore, IconProps>;
|
|
12
|
-
label: Dynamic<TStore, string>;
|
|
13
|
-
active?: Dynamic<TStore, boolean>;
|
|
14
|
-
disabled?: Dynamic<TStore, boolean>;
|
|
15
|
-
shortcut?: string;
|
|
16
|
-
shortcutLabel?: string;
|
|
17
|
-
visible?: Dynamic<TStore, boolean>;
|
|
18
|
-
dividerBefore?: boolean;
|
|
19
|
-
}
|
|
20
|
-
export interface Action<TStore = any> extends MenuItemBase<TStore> {
|
|
21
|
-
id: string;
|
|
22
|
-
type: 'action';
|
|
23
|
-
action: (registry: PluginRegistry, state: TStore) => void;
|
|
24
|
-
}
|
|
25
|
-
export interface Group<TStore = any> {
|
|
26
|
-
id: string;
|
|
27
|
-
type: 'group';
|
|
28
|
-
label: Dynamic<TStore, string>;
|
|
29
|
-
children: string[];
|
|
30
|
-
}
|
|
31
|
-
export interface Menu<TStore = any> extends MenuItemBase<TStore> {
|
|
32
|
-
id: string;
|
|
33
|
-
type: 'menu';
|
|
34
|
-
children: string[];
|
|
35
|
-
}
|
|
36
|
-
export type MenuItem<TStore = any> = Action<TStore> | Group | Menu<TStore>;
|
|
37
|
-
export type MenuRegistry = Record<string, MenuItem>;
|
|
38
|
-
export interface ExecuteOptions {
|
|
39
|
-
source?: 'click' | 'shortcut' | 'api';
|
|
40
|
-
triggerElement?: HTMLElement;
|
|
41
|
-
flatten?: boolean;
|
|
42
|
-
position?: 'top' | 'bottom' | 'left' | 'right';
|
|
43
|
-
}
|
|
44
|
-
export declare function hasActive<TStore>(command: MenuItem<TStore>): command is Action<TStore>;
|
|
45
|
-
export interface MenuManagerCapabilities {
|
|
46
|
-
registerItem: (commandItem: MenuItem) => void;
|
|
47
|
-
registerItems: (commands: MenuRegistry) => void;
|
|
48
|
-
executeCommand: (id: string, options?: ExecuteOptions) => void;
|
|
49
|
-
getAction: (id: string) => ResolvedAction | undefined;
|
|
50
|
-
getMenuOrAction: (id: string) => ResolvedMenu | ResolvedAction | undefined;
|
|
51
|
-
getChildItems: (commandId: string, options?: {
|
|
52
|
-
flatten?: boolean;
|
|
53
|
-
}) => ResolvedMenuItem[];
|
|
54
|
-
getItemsByIds: (ids: string[]) => ResolvedMenuItem[];
|
|
55
|
-
getAllItems: () => MenuRegistry;
|
|
56
|
-
}
|
|
57
|
-
export type Resolved<TStore, T> = T extends Dynamic<TStore, infer U> ? U : T;
|
|
58
|
-
export interface ResolvedMenuItemBase<TStore = any> {
|
|
59
|
-
icon?: string;
|
|
60
|
-
iconProps?: IconProps;
|
|
61
|
-
label: string;
|
|
62
|
-
active?: boolean;
|
|
63
|
-
disabled?: boolean;
|
|
64
|
-
shortcut?: string;
|
|
65
|
-
shortcutLabel?: string;
|
|
66
|
-
visible?: boolean;
|
|
67
|
-
dividerBefore?: boolean;
|
|
68
|
-
}
|
|
69
|
-
export interface ResolvedAction<TStore = any> extends ResolvedMenuItemBase<TStore> {
|
|
70
|
-
id: string;
|
|
71
|
-
type: 'action';
|
|
72
|
-
action: (registry: PluginRegistry, state: TStore) => void;
|
|
73
|
-
}
|
|
74
|
-
export interface ResolvedGroup<TStore = any> {
|
|
75
|
-
id: string;
|
|
76
|
-
type: 'group';
|
|
77
|
-
label: string;
|
|
78
|
-
children: string[];
|
|
79
|
-
}
|
|
80
|
-
export interface ResolvedMenu<TStore = any> extends ResolvedMenuItemBase<TStore> {
|
|
81
|
-
id: string;
|
|
82
|
-
type: 'menu';
|
|
83
|
-
children: string[];
|
|
84
|
-
}
|
|
85
|
-
export type ResolvedMenuItem<TStore = any> = ResolvedAction<TStore> | ResolvedGroup<TStore> | ResolvedMenu<TStore>;
|
|
86
|
-
export interface ResolvedMenuItemResult<TStore = any> {
|
|
87
|
-
item: ResolvedMenuItem<TStore>;
|
|
88
|
-
isGroup: boolean;
|
|
89
|
-
isMenu: boolean;
|
|
90
|
-
isAction: boolean;
|
|
91
|
-
}
|
package/dist/lib/menu/utils.d.ts
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import { MenuItem, ResolvedMenuItem } from './types';
|
|
2
|
-
export declare function resolveMenuItem<TStore>(item: MenuItem<TStore>, state: TStore): ResolvedMenuItem<TStore>;
|
|
3
|
-
export declare function isActive<TStore>(item: MenuItem<TStore>, state: TStore): boolean;
|
|
4
|
-
export declare function isVisible<TStore>(item: MenuItem<TStore>, state: TStore): boolean;
|
|
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,30 +0,0 @@
|
|
|
1
|
-
import { BaseUIComponent, childrenFunctionOptions } from './types';
|
|
2
|
-
export declare class UIComponent<T extends BaseUIComponent<any, any, any>> {
|
|
3
|
-
componentConfig: T;
|
|
4
|
-
props: T['id'] extends string ? T extends BaseUIComponent<infer P, any, any> ? P & {
|
|
5
|
-
id: string;
|
|
6
|
-
} : any : any;
|
|
7
|
-
type: string;
|
|
8
|
-
private children;
|
|
9
|
-
private registry;
|
|
10
|
-
private updateCallbacks;
|
|
11
|
-
private hadUpdateBeforeListeners;
|
|
12
|
-
constructor(componentConfig: T, registry: Record<string, (props: any, children: (options?: childrenFunctionOptions) => any[], context?: Record<string, any>) => any>);
|
|
13
|
-
addChild(id: string, child: UIComponent<any>, priority?: number, className?: string): void;
|
|
14
|
-
private sortChildren;
|
|
15
|
-
removeChild(child: UIComponent<any>): void;
|
|
16
|
-
clearChildren(): void;
|
|
17
|
-
get getRenderType(): string;
|
|
18
|
-
getRenderer(): (props: any, children: (options?: childrenFunctionOptions) => any[], context?: Record<string, any>) => any;
|
|
19
|
-
getChildren(): {
|
|
20
|
-
id: string;
|
|
21
|
-
component: UIComponent<any>;
|
|
22
|
-
priority: number;
|
|
23
|
-
className?: string;
|
|
24
|
-
}[];
|
|
25
|
-
getChildContext(context: Record<string, any>): Record<string, any>;
|
|
26
|
-
update(newProps: Partial<T extends BaseUIComponent<infer P, any, any> ? P : any>): void;
|
|
27
|
-
onUpdate(callback: () => void): boolean;
|
|
28
|
-
offUpdate(callback: () => void): void;
|
|
29
|
-
protected notifyUpdate(): void;
|
|
30
|
-
}
|
package/dist/lib/utils.d.ts
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { CustomComponent } from './types';
|
|
2
|
-
export declare function defineComponent<TInit, TProps, TStore = any>(): <C extends CustomComponent<TStore> & {
|
|
3
|
-
initialState: TInit;
|
|
4
|
-
props: (init: TInit) => TProps;
|
|
5
|
-
mapStateToProps: (storeState: TStore, ownProps: TProps) => TProps;
|
|
6
|
-
}>(c: C) => C;
|
|
7
|
-
/**
|
|
8
|
-
* Type definition for event callbacks
|
|
9
|
-
*/
|
|
10
|
-
export type EventCallback = (data: any) => void;
|
|
11
|
-
/**
|
|
12
|
-
* Interface for the event controller
|
|
13
|
-
*/
|
|
14
|
-
export interface EventController {
|
|
15
|
-
/**
|
|
16
|
-
* Emit an event of the specified type with the given data
|
|
17
|
-
*/
|
|
18
|
-
emit(eventType: string, data: any): void;
|
|
19
|
-
/**
|
|
20
|
-
* Subscribe to events of the specified type
|
|
21
|
-
* Returns a function that can be called to unsubscribe
|
|
22
|
-
*/
|
|
23
|
-
on(eventType: string, callback: EventCallback): () => void;
|
|
24
|
-
/**
|
|
25
|
-
* Unsubscribe a specific callback from events of the specified type
|
|
26
|
-
*/
|
|
27
|
-
off(eventType: string, callback: EventCallback): void;
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Creates an event controller that manages event subscriptions and dispatching
|
|
31
|
-
* This is a lightweight pub/sub implementation for typed events
|
|
32
|
-
*/
|
|
33
|
-
export declare function createEventController(): EventController;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './plugin-ui-provider';
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { ReactNode } from '../../react/adapter.ts';
|
|
2
|
-
/**
|
|
3
|
-
* Interface for UI components organized by type/location
|
|
4
|
-
*/
|
|
5
|
-
export interface UIComponentsMap {
|
|
6
|
-
headers: {
|
|
7
|
-
top: ReactNode[];
|
|
8
|
-
bottom: ReactNode[];
|
|
9
|
-
left: ReactNode[];
|
|
10
|
-
right: ReactNode[];
|
|
11
|
-
};
|
|
12
|
-
panels: {
|
|
13
|
-
left: ReactNode[];
|
|
14
|
-
right: ReactNode[];
|
|
15
|
-
};
|
|
16
|
-
floating: {
|
|
17
|
-
insideScroller: ReactNode[];
|
|
18
|
-
outsideScroller: ReactNode[];
|
|
19
|
-
};
|
|
20
|
-
commandMenu: ReactNode | null;
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Props for the PluginUIProvider
|
|
24
|
-
*/
|
|
25
|
-
export interface PluginUIProviderProps {
|
|
26
|
-
/**
|
|
27
|
-
* Render function that receives UI components
|
|
28
|
-
*/
|
|
29
|
-
children: (components: UIComponentsMap) => ReactNode;
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* PluginUIProvider collects all components from the UI plugin system
|
|
33
|
-
* and provides them to a render function without imposing any structure.
|
|
34
|
-
*
|
|
35
|
-
* It uses the render props pattern for maximum flexibility.
|
|
36
|
-
*/
|
|
37
|
-
export declare function PluginUIProvider({ children }: PluginUIProviderProps): ReactNode;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './plugin-ui-provider';
|