@embedpdf/plugin-ui 1.5.0 → 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
@@ -1,203 +1,186 @@
1
- import { CoreState } from '@embedpdf/core';
2
- import { UI_PLUGIN_ID } from './manifest';
3
- import { UIComponent } from './ui-component';
4
- import { MenuRegistry, MenuManagerCapabilities, IconProps } from './menu/types';
5
- import { SetHeaderVisiblePayload, TogglePanelPayload, UpdateComponentStatePayload } from './actions';
6
- export interface UIPluginConfig {
7
- enabled: boolean;
8
- components: Record<string, UIComponentType>;
9
- menuItems?: MenuRegistry;
10
- }
11
- export interface UIPluginState {
12
- panel: {
13
- [id: string]: PanelState;
14
- };
15
- header: {
16
- [id: string]: HeaderState;
17
- };
18
- groupedItems: {
19
- [id: string]: {};
20
- };
21
- divider: {
22
- [id: string]: {};
23
- };
24
- iconButton: {
25
- [id: string]: {};
26
- };
27
- tabButton: {
28
- [id: string]: {};
29
- };
30
- selectButton: {
31
- [id: string]: {};
32
- };
33
- custom: {
34
- [id: string]: any;
35
- };
36
- floating: {
37
- [id: string]: FloatingState;
38
- };
39
- commandMenu: {
40
- [id: string]: CommandMenuState;
41
- };
42
- }
43
- export type NavbarPlacement = 'top' | 'bottom' | 'left' | 'right';
44
- export interface childrenFunctionOptions {
45
- context?: Record<string, any>;
46
- filter?: (childId: string) => boolean;
47
- }
48
- export type UICapability = MenuManagerCapabilities & {
49
- registerComponentRenderer: (type: string, renderer: (props: any, children: (options?: childrenFunctionOptions) => any[], context?: Record<string, any>) => any) => void;
50
- getComponent: <T extends BaseUIComponent<any, any, any>>(id: string) => UIComponent<T> | undefined;
51
- getCommandMenu: () => UIComponent<CommandMenuComponent> | undefined;
52
- hideCommandMenu: () => void;
53
- getHeadersByPlacement: (placement: 'top' | 'bottom' | 'left' | 'right') => UIComponent<HeaderComponent<any>>[];
54
- getPanelsByLocation: (location: 'left' | 'right') => UIComponent<PanelComponent<any>>[];
55
- getFloatingComponents: (viewportPosition?: 'inside' | 'outside') => UIComponent<FloatingComponent>[];
56
- addSlot: (parentId: string, slotId: string, priority?: number) => void;
57
- registerComponent: (componentId: string, componentProps: UIComponentType) => UIComponent<any>;
58
- togglePanel: (payload: TogglePanelPayload) => void;
59
- setHeaderVisible: (payload: SetHeaderVisiblePayload) => void;
60
- updateComponentState: <T>(payload: UpdateComponentStatePayload<T>) => void;
61
- };
62
- export interface BaseUIComponent<TProps, TInitial = undefined, TStore = any> {
63
- id: string;
64
- type: string;
65
- render?: string;
66
- /**
67
- * A function that returns a context object for the component's children.
68
- */
69
- getChildContext?: ((props: TProps) => Record<string, any>) | Record<string, any>;
70
- /**
71
- * A function that returns a partial set of props from the initial state.
72
- */
73
- props?: ((init: TInitial) => TProps) | TProps;
74
- /**
75
- * An object containing the initial state for the component, typed as TInitial.
76
- */
77
- initialState?: TInitial;
78
- /**
79
- * A function that, on store changes, returns new or changed props to update
80
- * the component with (Redux-like).
81
- */
82
- mapStateToProps?: (storeState: TStore, ownProps: TProps) => TProps;
83
- }
84
- export interface Slot {
85
- componentId: string;
1
+ import { BasePluginConfig, EventHook } from '@embedpdf/core';
2
+ import { UISchema } from './schema';
3
+ import { StylesheetConfig } from './utils';
4
+ export * from './schema';
5
+ export interface UIPluginConfig extends BasePluginConfig {
6
+ /** UI schema */
7
+ schema: UISchema;
8
+ /** Categories to disable at initialization */
9
+ disabledCategories?: string[];
10
+ /** Config for stylesheet generation */
11
+ stylesheetConfig?: StylesheetConfig;
12
+ }
13
+ export interface UIState {
14
+ documents: Record<string, UIDocumentState>;
15
+ /** Globally disabled categories */
16
+ disabledCategories: string[];
17
+ }
18
+ /**
19
+ * Toolbar slot state
20
+ */
21
+ export interface ToolbarSlotState {
22
+ toolbarId: string;
23
+ isOpen: boolean;
24
+ }
25
+ /**
26
+ * Panel slot state
27
+ */
28
+ export interface PanelSlotState {
29
+ panelId: string;
30
+ isOpen: boolean;
31
+ }
32
+ export interface UIDocumentState {
33
+ activeToolbars: Record<string, ToolbarSlotState>;
34
+ activePanels: Record<string, PanelSlotState>;
35
+ activeModal: string | null;
36
+ openMenus: Record<string, OpenMenuState>;
37
+ panelTabs: Record<string, string>;
38
+ }
39
+ /**
40
+ * Responsive visibility rule for a single item at a specific breakpoint
41
+ */
42
+ export interface ResponsiveVisibilityRule {
43
+ breakpointId: string;
44
+ minWidth?: number;
45
+ maxWidth?: number;
46
+ visible: boolean;
86
47
  priority: number;
87
- className?: string;
88
- }
89
- export interface PanelState {
90
- open: boolean;
91
- visibleChild: string | null;
92
- }
93
- export interface PanelProps {
94
- location: 'left' | 'right';
95
- open: boolean;
96
- visibleChild: string | null;
97
- [name: string]: any;
98
- }
99
- export interface PanelComponent<TStore = any> extends BaseUIComponent<PanelProps, PanelState, TStore> {
100
- type: 'panel';
101
- slots: Slot[];
102
- }
103
- export interface HeaderState {
104
- visible?: boolean;
105
- visibleChild?: string | null;
106
- }
107
- export interface HeaderProps {
108
- placement: 'top' | 'bottom' | 'left' | 'right';
109
- style?: Record<string, string>;
110
- visible?: boolean;
111
- visibleChild?: string | null;
112
- }
113
- export interface HeaderComponent<TStore = any> extends BaseUIComponent<HeaderProps, HeaderState, TStore> {
114
- type: 'header';
115
- slots: Slot[];
116
- }
117
- export interface GroupedItemsProps {
118
- justifyContent?: 'start' | 'center' | 'end';
119
- grow?: number;
120
- gap?: number;
121
- }
122
- export interface GroupedItemsComponent<TStore = any> extends BaseUIComponent<GroupedItemsProps, undefined, TStore> {
123
- type: 'groupedItems';
124
- slots: Slot[];
125
- }
126
- export interface DividerComponent<TStore = any> extends BaseUIComponent<undefined, undefined, TStore> {
127
- type: 'divider';
128
- }
129
- export interface IconButtonProps {
130
- active?: boolean;
131
- disabled?: boolean;
132
- commandId?: string;
133
- iconProps?: IconProps;
134
- onClick?: () => void;
135
- label?: string;
136
- img?: string;
137
- color?: string;
138
- }
139
- export interface IconButtonComponent<TStore = any> extends BaseUIComponent<IconButtonProps, undefined, TStore> {
140
- type: 'iconButton';
141
- }
142
- export interface TabButtonProps {
143
- active?: boolean;
144
- commandId?: string;
145
- onClick?: () => void;
146
- label: string;
147
- }
148
- export interface TabButtonComponent<TStore = any> extends BaseUIComponent<TabButtonProps, undefined, TStore> {
149
- type: 'tabButton';
150
- }
151
- export interface SelectButtonProps {
152
- active?: boolean;
153
- commandIds: string[];
154
- menuCommandId: string;
155
- activeCommandId: string;
156
- }
157
- export interface SelectButtonComponent<TStore = any> extends BaseUIComponent<SelectButtonProps, undefined, TStore> {
158
- type: 'selectButton';
159
- }
160
- export interface CustomComponent<TStore = any> extends BaseUIComponent<any, any, TStore> {
161
- type: 'custom';
162
- render: string;
163
- slots?: Slot[];
164
- }
165
- export interface FloatingState {
166
- [name: string]: any;
167
- }
168
- export interface FloatingComponentProps {
169
- scrollerPosition: 'inside' | 'outside';
170
- [name: string]: any;
171
- }
172
- export interface FloatingComponent<TStore = any> extends BaseUIComponent<FloatingComponentProps, FloatingState, TStore> {
173
- type: 'floating';
174
- slots?: Slot[];
175
- }
176
- export interface CommandMenuState {
177
- triggerElement?: HTMLElement;
178
- activeCommand: string | null;
179
- open: boolean;
180
- position?: 'top' | 'bottom' | 'left' | 'right';
181
- flatten?: boolean;
182
- }
183
- export interface CommandMenuProps {
184
- triggerElement?: HTMLElement;
185
- activeCommand: string | null;
186
- open: boolean;
187
- position?: 'top' | 'bottom' | 'left' | 'right';
188
- flatten?: boolean;
189
- }
190
- export interface CommandMenuComponent<TStore = any> extends BaseUIComponent<CommandMenuProps, CommandMenuState, TStore> {
191
- type: 'commandMenu';
192
- }
193
- export type WithComponentId<TProps> = TProps & {
194
- id: string;
195
- };
196
- export type ComponentRenderFunction<TProps> = (props: WithComponentId<TProps>, children: (options?: childrenFunctionOptions) => any[], context?: Record<string, any>) => any;
197
- export interface GlobalStoreState<TPlugins extends Record<string, any> = {}> {
198
- core: CoreState;
199
- plugins: {
200
- [UI_PLUGIN_ID]: UIPluginState;
201
- } & TPlugins;
202
- }
203
- export type UIComponentType<TStore = any> = GroupedItemsComponent<TStore> | DividerComponent<TStore> | IconButtonComponent<TStore> | TabButtonComponent<TStore> | HeaderComponent<TStore> | PanelComponent<TStore> | CustomComponent<TStore> | FloatingComponent<TStore> | CommandMenuComponent<TStore> | SelectButtonComponent<TStore>;
48
+ }
49
+ /**
50
+ * Computed responsive metadata for an item
51
+ */
52
+ export interface ResponsiveItemMetadata {
53
+ itemId: string;
54
+ /** Always true for SSR/hydration - actual visibility controlled by CSS/styles */
55
+ shouldRender: boolean;
56
+ /** Ordered rules from lowest to highest breakpoint */
57
+ visibilityRules: ResponsiveVisibilityRule[];
58
+ /** Quick lookup: is visible at default/base size? */
59
+ defaultVisible: boolean;
60
+ }
61
+ /**
62
+ * Result of processing all responsive rules
63
+ */
64
+ export interface ResponsiveMetadata {
65
+ items: Map<string, ResponsiveItemMetadata>;
66
+ breakpoints: Map<string, {
67
+ minWidth?: number;
68
+ maxWidth?: number;
69
+ }>;
70
+ }
71
+ export interface ToolbarChangedData {
72
+ placement: string;
73
+ slot: string;
74
+ toolbarId: string;
75
+ }
76
+ export interface ToolbarChangedEvent extends ToolbarChangedData {
77
+ documentId: string;
78
+ }
79
+ export interface PanelChangedData {
80
+ placement: string;
81
+ slot: string;
82
+ panelId: string;
83
+ }
84
+ export interface PanelChangedEvent extends PanelChangedData {
85
+ documentId: string;
86
+ }
87
+ export interface ModalChangedData {
88
+ modalId: string | null;
89
+ }
90
+ export interface ModalChangedEvent extends ModalChangedData {
91
+ documentId: string;
92
+ }
93
+ export interface MenuChangedData {
94
+ menuId: string;
95
+ isOpen: boolean;
96
+ }
97
+ export interface MenuChangedEvent extends MenuChangedData {
98
+ documentId: string;
99
+ }
100
+ export interface OpenMenuState {
101
+ menuId: string;
102
+ triggeredByCommandId?: string;
103
+ triggeredByItemId?: string;
104
+ }
105
+ export interface UIScope {
106
+ setActiveToolbar(placement: string, slot: string, toolbarId: string): void;
107
+ getActiveToolbar(placement: string, slot: string): string | null;
108
+ closeToolbarSlot(placement: string, slot: string): void;
109
+ isToolbarOpen(placement: string, slot: string, toolbarId?: string): boolean;
110
+ setActivePanel(placement: string, slot: string, panelId: string, activeTab?: string): void;
111
+ getActivePanel(placement: string, slot: string): string | null;
112
+ closePanelSlot(placement: string, slot: string): void;
113
+ togglePanel(placement: string, slot: string, panelId: string, activeTab?: string): void;
114
+ setPanelTab(panelId: string, tabId: string): void;
115
+ getPanelTab(panelId: string): string | null;
116
+ isPanelOpen(placement: string, slot: string, panelId?: string): boolean;
117
+ openModal(modalId: string): void;
118
+ closeModal(): void;
119
+ getActiveModal(): string | null;
120
+ openMenu(menuId: string, triggeredByCommandId: string, triggeredByItemId: string): void;
121
+ closeMenu(menuId: string): void;
122
+ toggleMenu(menuId: string, triggeredByCommandId: string, triggeredByItemId: string): void;
123
+ closeAllMenus(): void;
124
+ isMenuOpen(menuId: string): boolean;
125
+ getOpenMenus(): OpenMenuState[];
126
+ getSchema(): UISchema;
127
+ getState(): UIDocumentState;
128
+ onToolbarChanged: EventHook<{
129
+ placement: string;
130
+ slot: string;
131
+ toolbarId: string;
132
+ }>;
133
+ onPanelChanged: EventHook<{
134
+ placement: string;
135
+ slot: string;
136
+ panelId: string;
137
+ }>;
138
+ onModalChanged: EventHook<{
139
+ modalId: string | null;
140
+ }>;
141
+ onMenuChanged: EventHook<{
142
+ menuId: string;
143
+ isOpen: boolean;
144
+ }>;
145
+ }
146
+ export interface UICapability {
147
+ setActiveToolbar(placement: string, slot: string, toolbarId: string, documentId?: string): void;
148
+ setActivePanel(placement: string, slot: string, panelId: string, documentId?: string, activeTab?: string): void;
149
+ togglePanel(placement: string, slot: string, panelId: string, documentId?: string, activeTab?: string): void;
150
+ openModal(modalId: string, documentId?: string): void;
151
+ openMenu(menuId: string, triggeredByCommandId: string, triggeredByItemId: string, documentId?: string): void;
152
+ toggleMenu(menuId: string, triggeredByCommandId: string, triggeredByItemId: string, documentId?: string): void;
153
+ forDocument(documentId: string): UIScope;
154
+ getSchema(): UISchema;
155
+ mergeSchema(partial: Partial<UISchema>): void;
156
+ disableCategory(category: string): void;
157
+ enableCategory(category: string): void;
158
+ toggleCategory(category: string): void;
159
+ setDisabledCategories(categories: string[]): void;
160
+ getDisabledCategories(): string[];
161
+ isCategoryDisabled(category: string): boolean;
162
+ onToolbarChanged: EventHook<{
163
+ documentId: string;
164
+ placement: string;
165
+ slot: string;
166
+ toolbarId: string;
167
+ }>;
168
+ onPanelChanged: EventHook<{
169
+ documentId: string;
170
+ placement: string;
171
+ slot: string;
172
+ panelId: string;
173
+ }>;
174
+ onModalChanged: EventHook<{
175
+ documentId: string;
176
+ modalId: string | null;
177
+ }>;
178
+ onMenuChanged: EventHook<{
179
+ documentId: string;
180
+ menuId: string;
181
+ isOpen: boolean;
182
+ }>;
183
+ onCategoryChanged: EventHook<{
184
+ disabledCategories: string[];
185
+ }>;
186
+ }
@@ -1,23 +1,71 @@
1
- import { BasePlugin, PluginRegistry } from '@embedpdf/core';
2
- import { UICapability, UIPluginConfig, UIPluginState } from './types';
3
- import { UIPluginAction } from './actions';
4
- export declare class UIPlugin extends BasePlugin<UIPluginConfig, UICapability, UIPluginState, UIPluginAction> {
1
+ import { BasePlugin, Listener, PluginRegistry, Unsubscribe } from '@embedpdf/core';
2
+ import { UICapability, UIPluginConfig, UIState } from './types';
3
+ import { UIAction } from './actions';
4
+ export declare class UIPlugin extends BasePlugin<UIPluginConfig, UICapability, UIState, UIAction> {
5
5
  static readonly id: "ui";
6
- private componentRenderers;
7
- private components;
8
- private config;
9
- private mapStateCallbacks;
10
- private globalStoreSubscription;
11
- private menuManager;
6
+ private schema;
7
+ private stylesheetConfig;
8
+ private cachedStylesheet;
9
+ private cachedLocale;
10
+ private i18n;
11
+ private i18nCleanup;
12
+ private readonly categoryChanged$;
13
+ private readonly stylesheetInvalidated$;
14
+ private readonly toolbarChanged$;
15
+ private readonly panelChanged$;
16
+ private readonly modalChanged$;
17
+ private readonly menuChanged$;
12
18
  constructor(id: string, registry: PluginRegistry, config: UIPluginConfig);
13
19
  initialize(): Promise<void>;
14
- private setupCommandEventHandlers;
15
- private addComponent;
16
- private buildComponents;
17
- private linkGroupedItems;
18
- private setInitialStateUIComponents;
19
- private onGlobalStoreChange;
20
- private addSlot;
21
- protected buildCapability(): UICapability;
22
20
  destroy(): Promise<void>;
21
+ protected onDocumentLoadingStarted(documentId: string): void;
22
+ protected onDocumentClosed(documentId: string): void;
23
+ /**
24
+ * Handle locale changes from i18n plugin.
25
+ * Invalidates stylesheet and emits change event.
26
+ */
27
+ private handleLocaleChange;
28
+ /**
29
+ * Get the generated CSS stylesheet.
30
+ * Automatically regenerates if locale has changed.
31
+ * This is pure logic - DOM injection is handled by framework layer.
32
+ */
33
+ getStylesheet(): string;
34
+ /**
35
+ * Get the current locale (if i18n is available)
36
+ */
37
+ getLocale(): string | null;
38
+ /**
39
+ * Regenerate stylesheet (call after schema changes)
40
+ */
41
+ invalidateStylesheet(): void;
42
+ onStylesheetInvalidated(listener: Listener<void>): Unsubscribe;
43
+ private disableCategoryImpl;
44
+ private enableCategoryImpl;
45
+ private toggleCategoryImpl;
46
+ private setDisabledCategoriesImpl;
47
+ protected buildCapability(): UICapability;
48
+ private createUIScope;
49
+ private getDocumentState;
50
+ private getDocumentStateOrThrow;
51
+ private setToolbarForDocument;
52
+ private getToolbarForDocument;
53
+ private closeToolbarForDocument;
54
+ private isToolbarOpenForDocument;
55
+ private setPanelForDocument;
56
+ private getPanelForDocument;
57
+ private closePanelForDocument;
58
+ private togglePanelForDocument;
59
+ private isPanelOpenForDocument;
60
+ private setPanelTabForDocument;
61
+ private getPanelTabForDocument;
62
+ private openModalForDocument;
63
+ private closeModalForDocument;
64
+ private getActiveModalForDocument;
65
+ private openMenuForDocument;
66
+ private closeMenuForDocument;
67
+ private toggleMenuForDocument;
68
+ private closeAllMenusForDocument;
69
+ private isMenuOpenForDocument;
70
+ private getOpenMenusForDocument;
23
71
  }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Using 'embedpdf' prefix to avoid conflicts with other libraries.
3
+ */
4
+ export declare const UI_ATTRIBUTES: {
5
+ /** Root element marker */
6
+ readonly ROOT: "data-epdf";
7
+ /** Style element marker for deduplication */
8
+ readonly STYLES: "data-epdf-s";
9
+ /** Item ID for responsive and dependency rules */
10
+ readonly ITEM: "data-epdf-i";
11
+ /** Item categories for category-based hiding */
12
+ readonly CATEGORIES: "data-epdf-cat";
13
+ /** Disabled categories list on root element */
14
+ readonly DISABLED_CATEGORIES: "data-epdf-dis";
15
+ };
16
+ /**
17
+ * CSS selectors derived from attributes
18
+ */
19
+ export declare const UI_SELECTORS: {
20
+ readonly ROOT: "[data-epdf]";
21
+ readonly STYLES: "[data-epdf-s]";
22
+ readonly ITEM: (id: string) => string;
23
+ readonly CATEGORIES: (category: string) => string;
24
+ readonly DISABLED_CATEGORY: (category: string) => string;
25
+ };
@@ -0,0 +1,5 @@
1
+ export * from './responsive-utils';
2
+ export * from './schema-merger';
3
+ export * from './stylesheet-generator';
4
+ export * from './ui-props';
5
+ export * from './consts';
@@ -0,0 +1,10 @@
1
+ import { ToolbarSchema, MenuSchema, ResponsiveMetadata, ResponsiveItemMetadata, SelectionMenuSchema } from '../types';
2
+ /**
3
+ * Processes responsive configuration and returns metadata for all items
4
+ * This is framework-agnostic and lives in plugin-ui
5
+ */
6
+ export declare function resolveResponsiveMetadata(schema: ToolbarSchema | MenuSchema | SelectionMenuSchema, currentLocale?: string): ResponsiveMetadata | null;
7
+ /**
8
+ * Get responsive metadata for a specific item
9
+ */
10
+ export declare function getItemResponsiveMetadata(itemId: string, schema: ToolbarSchema | MenuSchema, currentLocale?: string): ResponsiveItemMetadata | null;
@@ -0,0 +1,15 @@
1
+ import { UISchema } from '../types';
2
+ /**
3
+ * Deep merge UI schemas
4
+ * Allows users to override/extend default schema
5
+ */
6
+ export declare function mergeUISchema(base: UISchema, override: Partial<UISchema>): UISchema;
7
+ /**
8
+ * Helper to remove items from schema
9
+ */
10
+ export declare function removeFromSchema(schema: UISchema, options: {
11
+ toolbars?: string[];
12
+ menus?: string[];
13
+ panels?: string[];
14
+ commands?: string[];
15
+ }): UISchema;
@@ -0,0 +1,40 @@
1
+ import { UISchema } from '../types';
2
+ export interface StylesheetConfig {
3
+ /** Use container queries (@container) instead of media queries (@media). Default: true */
4
+ useContainerQueries?: boolean;
5
+ }
6
+ export interface StylesheetGenerationOptions {
7
+ config?: StylesheetConfig;
8
+ /** Current locale for locale-aware responsive rules */
9
+ locale?: string;
10
+ }
11
+ /**
12
+ * Generates complete CSS stylesheet for UI visibility.
13
+ *
14
+ * Includes:
15
+ * 1. Responsive visibility rules (container queries or media queries)
16
+ * 2. Category visibility rules
17
+ * 3. Breakpoint-aware dependency rules
18
+ *
19
+ * This is pure logic - no DOM manipulation.
20
+ *
21
+ * @param schema - The UI schema to generate CSS for
22
+ * @param options - Generation options including config and locale
23
+ * @returns Generated CSS string
24
+ */
25
+ export declare function generateUIStylesheet(schema: UISchema, options?: StylesheetGenerationOptions): string;
26
+ /**
27
+ * Extract all unique categories from the schema.
28
+ * Useful for building UI to toggle categories.
29
+ *
30
+ * @param schema - The UI schema to extract categories from
31
+ * @returns Sorted array of unique category names
32
+ */
33
+ export declare function extractCategories(schema: UISchema): string[];
34
+ /**
35
+ * Get the stylesheet configuration with defaults applied.
36
+ *
37
+ * @param config - Optional partial configuration
38
+ * @returns Complete configuration with defaults
39
+ */
40
+ export declare function getStylesheetConfig(config?: StylesheetConfig): Required<StylesheetConfig>;
@@ -0,0 +1,14 @@
1
+ import { UI_ATTRIBUTES } from './consts';
2
+ export interface UIItemLike {
3
+ id: string;
4
+ categories?: string[];
5
+ }
6
+ export interface UIItemProps {
7
+ [UI_ATTRIBUTES.ITEM]: string;
8
+ [UI_ATTRIBUTES.CATEGORIES]?: string;
9
+ }
10
+ /**
11
+ * Get data attribute props for a UI item.
12
+ * Spread these onto the wrapper element for CSS-based visibility control.
13
+ */
14
+ export declare function getUIItemProps<T extends Record<string, string | undefined> = Record<string, never>>(item: UIItemLike, extra?: T): UIItemProps & T;
@@ -1,5 +1,7 @@
1
- export { Fragment } from 'preact';
2
- export { useEffect, useRef, useState, useCallback, useMemo } from 'preact/hooks';
1
+ import { FunctionComponent } from 'preact';
2
+ export { Fragment, createContext } from 'preact';
3
+ export { useEffect, useRef, useState, useCallback, useMemo, useContext } from 'preact/hooks';
3
4
  export type { ComponentChildren as ReactNode } from 'preact';
4
5
  export type CSSProperties = import('preact').JSX.CSSProperties;
5
6
  export type HTMLAttributes<T = any> = import('preact').JSX.HTMLAttributes<T extends EventTarget ? T : never>;
7
+ export type ComponentType<P = any> = FunctionComponent<P>;
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("preact/jsx-runtime"),t=require("@embedpdf/core/preact"),n=require("@embedpdf/plugin-ui");require("preact");const o=require("preact/hooks"),r=()=>t.useCapability(n.UIPlugin.id);function i({component:t,parentContext:n={}}){const[r,l]=o.useState({});o.useEffect((()=>{const e=()=>l({});return t.onUpdate(e)&&l({}),()=>t.offUpdate(e)}),[t]);const s=t.getChildContext(n),d=t.getRenderer();if(!d)throw new Error(`No renderer for type: ${t.getRenderType}`);return d(t.props,(function(n){const o=(null==n?void 0:n.context)?{...s,...n.context}:s;return t.getChildren().filter((({id:e})=>!(null==n?void 0:n.filter)||n.filter(e))).map((({component:t,id:n,className:r})=>r?e.jsx("div",{className:r,children:e.jsx(i,{component:t,parentContext:o},n)}):e.jsx(i,{component:t,parentContext:o},n)))}),s)}exports.PluginUIProvider=function({children:t}){const{provides:n}=r(),o=t=>t.map((t=>e.jsx(i,{component:t},t.props.id)));return t({headers:{top:o((null==n?void 0:n.getHeadersByPlacement("top"))||[]),bottom:o((null==n?void 0:n.getHeadersByPlacement("bottom"))||[]),left:o((null==n?void 0:n.getHeadersByPlacement("left"))||[]),right:o((null==n?void 0:n.getHeadersByPlacement("right"))||[])},panels:{left:o((null==n?void 0:n.getPanelsByLocation("left"))||[]),right:o((null==n?void 0:n.getPanelsByLocation("right"))||[])},floating:{insideScroller:o((null==n?void 0:n.getFloatingComponents("inside"))||[]),outsideScroller:o((null==n?void 0:n.getFloatingComponents("outside"))||[])},commandMenu:(null==n?void 0:n.getCommandMenu())?e.jsx(i,{component:n.getCommandMenu()}):null})},exports.useUICapability=r,exports.useUIPlugin=()=>t.usePlugin(n.UIPlugin.id),Object.keys(n).forEach((e=>{"default"===e||Object.prototype.hasOwnProperty.call(exports,e)||Object.defineProperty(exports,e,{enumerable:!0,get:()=>n[e]})}));
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("@embedpdf/core/preact"),n=require("@embedpdf/plugin-ui"),t=require("preact"),r=require("preact/hooks"),o=require("preact/jsx-runtime"),s=()=>e.useCapability(n.UIPlugin.id),u=()=>e.usePlugin(n.UIPlugin.id),l=e=>{const{provides:n}=s(),[t,o]=r.useState(null);return r.useEffect(()=>{if(!n)return;const t=n.forDocument(e);o(t.getState());const r=t.onToolbarChanged(()=>o(t.getState())),s=t.onPanelChanged(()=>o(t.getState())),u=t.onModalChanged(()=>o(t.getState())),l=t.onMenuChanged(()=>o(t.getState()));return()=>{r(),s(),u(),l()}},[n,e]),t},c=t.createContext(null);function i({children:e}){const n=r.useRef(new Map),t={register:r.useCallback((e,t,r)=>{const o=`${e}:${t}`;n.current.set(o,r)},[]),unregister:r.useCallback((e,t)=>{const r=`${e}:${t}`;n.current.delete(r)},[]),getAnchor:r.useCallback((e,t)=>{const r=`${e}:${t}`;return n.current.get(r)||null},[])};return o.jsx(c.Provider,{value:t,children:e})}function a(){const e=r.useContext(c);if(!e)throw new Error("useAnchorRegistry must be used within UIProvider");return e}const d=t.createContext(null);function p({children:e,initialComponents:n={}}){const t=r.useRef(new Map(Object.entries(n))),s={register:r.useCallback((e,n)=>{t.current.set(e,n)},[]),unregister:r.useCallback(e=>{t.current.delete(e)},[]),get:r.useCallback(e=>t.current.get(e),[]),has:r.useCallback(e=>t.current.has(e),[]),getRegisteredIds:r.useCallback(()=>Array.from(t.current.keys()),[])};return o.jsx(d.Provider,{value:s,children:e})}function f(){const e=r.useContext(d);if(!e)throw new Error("useComponentRegistry must be used within UIProvider");return e}const m=t.createContext(null);function h({children:e,renderers:n}){return o.jsx(m.Provider,{value:n,children:e})}function g(){const e=r.useContext(m);if(!e)throw new Error("useRenderers must be used within UIProvider");return e}function I({container:e,documentId:n}){const t=l(n),{provides:u}=s(),c=a(),i=g(),[d,p]=r.useState(null),f=(null==t?void 0:t.openMenus)||{},m=null==u?void 0:u.getSchema();r.useEffect(()=>{const e=Object.keys(f);if(e.length>0){const t=e[0];if(!t)return void p(null);const r=f[t];if(r&&r.triggeredByItemId){const e=c.getAnchor(n,r.triggeredByItemId);p({menuId:t,anchorEl:e})}else p(null)}else p(null)},[f,c,n]);if(!d||!m)return null;const h=m.menus[d.menuId];if(!h)return console.warn(`Menu "${d.menuId}" not found in schema`),null;const I=i.menu;return o.jsx(I,{schema:h,documentId:n,anchorEl:d.anchorEl,onClose:()=>{d&&(null==u||u.forDocument(n).closeMenu(d.menuId))},container:e})}function v({children:e,...t}){const{plugin:l}=u(),{provides:c}=s(),[i,a]=r.useState([]),d=r.useRef(null),p=r.useRef(null),f=r.useRef(null),m=r.useCallback(e=>{const t=f.current;if(f.current=e,e&&e!==t&&l){const t=function(e){const n=e.getRootNode();return n instanceof ShadowRoot?n:document.head}(e);p.current=t;const r=t.querySelector(n.UI_SELECTORS.STYLES);if(r)return d.current=r,void(r.textContent=l.getStylesheet());const o=l.getStylesheet(),s=document.createElement("style");s.setAttribute(n.UI_ATTRIBUTES.STYLES,""),s.textContent=o,t instanceof ShadowRoot?t.insertBefore(s,t.firstChild):t.appendChild(s),d.current=s}},[l]);r.useEffect(()=>()=>{var e;(null==(e=d.current)?void 0:e.parentNode)&&!f.current&&d.current.remove(),d.current=null,p.current=null},[]),r.useEffect(()=>{if(l)return l.onStylesheetInvalidated(()=>{d.current&&(d.current.textContent=l.getStylesheet())})},[l]),r.useEffect(()=>{if(c)return a(c.getDisabledCategories()),c.onCategoryChanged(({disabledCategories:e})=>{a(e)})},[c]);const h=r.useMemo(()=>i.length>0?i.join(" "):void 0,[i]),g={[n.UI_ATTRIBUTES.ROOT]:"",[n.UI_ATTRIBUTES.DISABLED_CATEGORIES]:h};return o.jsx("div",{ref:m,...g,...t,style:{containerType:"inline-size",...t.style},children:e})}exports.AnchorRegistryProvider=i,exports.ComponentRegistryProvider=p,exports.RenderersProvider=h,exports.UIProvider=function({children:e,documentId:n,components:t={},renderers:r,menuContainer:s,...u}){return o.jsx(i,{children:o.jsx(p,{initialComponents:t,children:o.jsx(h,{renderers:r,children:o.jsxs(v,{...u,children:[e,o.jsx(I,{documentId:n,container:s})]})})})})},exports.useAnchorRegistry=a,exports.useComponentRegistry=f,exports.useItemRenderer=function(){const e=f();return{renderCustomComponent:(n,t,r)=>{const s=e.get(n);return s?o.jsx(s,{documentId:t,...r||{}}):(console.error(`Component "${n}" not found in registry`),null)}}},exports.useRegisterAnchor=function(e,n){const t=a(),o=r.useRef(null),s=r.useRef(e),u=r.useRef(n);return s.current=e,u.current=n,r.useCallback(e=>{const n=o.current;o.current=e,e?e!==n&&t.register(s.current,u.current,e):n&&t.unregister(s.current,u.current)},[t])},exports.useRenderers=g,exports.useSchemaRenderer=function(e){const n=g(),{provides:t}=s(),r=null==t?void 0:t.getSchema(),u=l(e);return{renderToolbar:(s,l)=>{if(!r||!t||!u)return null;const c=`${s}-${l}`,i=u.activeToolbars[c];if(!i)return null;const a=r.toolbars[i.toolbarId];if(!a)return console.warn(`Toolbar "${i.toolbarId}" not found in schema`),null;const d=!a.permanent?()=>{t.forDocument(e).closeToolbarSlot(s,l)}:void 0,p=n.toolbar;return o.jsx(p,{schema:a,documentId:e,isOpen:i.isOpen,onClose:d},i.toolbarId)},renderPanel:(s,l)=>{if(!r||!t||!u)return null;const c=`${s}-${l}`,i=u.activePanels[c];if(!i)return null;const a=r.panels[i.panelId];if(!a)return console.warn(`Panel "${i.panelId}" not found in schema`),null;const d=n.panel;return o.jsx(d,{schema:a,documentId:e,isOpen:i.isOpen,onClose:()=>{t.forDocument(e).closePanelSlot(s,l)}},i.panelId)},getActiveToolbars:()=>u?Object.entries(u.activeToolbars).map(([e,n])=>{const[t,r]=e.split("-");return{placement:t,slot:r,toolbarId:n.toolbarId,isOpen:n.isOpen}}):[],getActivePanels:()=>u?Object.entries(u.activePanels).map(([e,n])=>{const[t,r]=e.split("-");return{placement:t,slot:r,panelId:n.panelId,isOpen:n.isOpen}}):[]}},exports.useSelectionMenu=function(e,n){var t;const{provides:u}=s(),l=g(),c=r.useCallback(t=>{var r;const s=null==u?void 0:u.getSchema(),c=null==(r=null==s?void 0:s.selectionMenus)?void 0:r[e];if(!c)return null;if(!t.selected)return null;const i=l.selectionMenu;return o.jsx(i,{schema:c,documentId:n,props:t})},[u,l,e,n]),i=null==u?void 0:u.getSchema();if(null==(t=null==i?void 0:i.selectionMenus)?void 0:t[e])return c},exports.useUICapability=s,exports.useUIPlugin=u,exports.useUISchema=()=>{const{provides:e}=s();return(null==e?void 0:e.getSchema())??null},exports.useUIState=l,Object.keys(n).forEach(e=>{"default"===e||Object.prototype.hasOwnProperty.call(exports,e)||Object.defineProperty(exports,e,{enumerable:!0,get:()=>n[e]})});
2
2
  //# sourceMappingURL=index.cjs.map