@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
package/dist/index.js
CHANGED
|
@@ -1,744 +1,1369 @@
|
|
|
1
|
-
import { BasePlugin,
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
1
|
+
import { BasePlugin, createBehaviorEmitter, createEmitter, createScopedEmitter } from "@embedpdf/core";
|
|
2
|
+
const UI_PLUGIN_ID = "ui";
|
|
3
|
+
const manifest = {
|
|
4
|
+
id: UI_PLUGIN_ID,
|
|
5
|
+
name: "UI Plugin",
|
|
6
|
+
version: "1.0.0",
|
|
7
|
+
provides: ["ui"],
|
|
8
|
+
requires: ["commands"],
|
|
9
|
+
// Depends on commands
|
|
10
|
+
optional: ["i18n"],
|
|
11
|
+
defaultConfig: {
|
|
12
|
+
enabled: true,
|
|
13
|
+
schema: {
|
|
14
|
+
id: "empty",
|
|
15
|
+
version: "1.0.0",
|
|
16
|
+
toolbars: {},
|
|
17
|
+
menus: {},
|
|
18
|
+
panels: {},
|
|
19
|
+
selectionMenus: {}
|
|
14
20
|
}
|
|
15
|
-
this.type = componentConfig.type;
|
|
16
|
-
this.registry = registry;
|
|
17
|
-
}
|
|
18
|
-
addChild(id, child, priority = 0, className) {
|
|
19
|
-
this.children.push({ id, component: child, priority, className });
|
|
20
|
-
this.sortChildren();
|
|
21
|
-
}
|
|
22
|
-
// Helper to sort children by priority
|
|
23
|
-
sortChildren() {
|
|
24
|
-
this.children.sort((a, b) => a.priority - b.priority);
|
|
25
|
-
}
|
|
26
|
-
removeChild(child) {
|
|
27
|
-
this.children = this.children.filter((c) => c.component !== child);
|
|
28
21
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
22
|
+
};
|
|
23
|
+
const INIT_UI_STATE = "UI/INIT_STATE";
|
|
24
|
+
const CLEANUP_UI_STATE = "UI/CLEANUP_STATE";
|
|
25
|
+
const SET_ACTIVE_TOOLBAR = "UI/SET_ACTIVE_TOOLBAR";
|
|
26
|
+
const CLOSE_TOOLBAR_SLOT = "UI/CLOSE_TOOLBAR_SLOT";
|
|
27
|
+
const SET_ACTIVE_PANEL = "UI/SET_ACTIVE_PANEL";
|
|
28
|
+
const CLOSE_PANEL_SLOT = "UI/CLOSE_PANEL_SLOT";
|
|
29
|
+
const SET_PANEL_TAB = "UI/SET_PANEL_TAB";
|
|
30
|
+
const OPEN_MODAL = "UI/OPEN_MODAL";
|
|
31
|
+
const CLOSE_MODAL = "UI/CLOSE_MODAL";
|
|
32
|
+
const OPEN_MENU = "UI/OPEN_MENU";
|
|
33
|
+
const CLOSE_MENU = "UI/CLOSE_MENU";
|
|
34
|
+
const CLOSE_ALL_MENUS = "UI/CLOSE_ALL_MENUS";
|
|
35
|
+
const SET_DISABLED_CATEGORIES = "UI/SET_DISABLED_CATEGORIES";
|
|
36
|
+
const initUIState = (documentId, schema) => ({
|
|
37
|
+
type: INIT_UI_STATE,
|
|
38
|
+
payload: { documentId, schema }
|
|
39
|
+
});
|
|
40
|
+
const cleanupUIState = (documentId) => ({
|
|
41
|
+
type: CLEANUP_UI_STATE,
|
|
42
|
+
payload: { documentId }
|
|
43
|
+
});
|
|
44
|
+
const setActiveToolbar = (documentId, placement, slot, toolbarId) => ({
|
|
45
|
+
type: SET_ACTIVE_TOOLBAR,
|
|
46
|
+
payload: { documentId, placement, slot, toolbarId }
|
|
47
|
+
});
|
|
48
|
+
const closeToolbarSlot = (documentId, placement, slot) => ({
|
|
49
|
+
type: CLOSE_TOOLBAR_SLOT,
|
|
50
|
+
payload: { documentId, placement, slot }
|
|
51
|
+
});
|
|
52
|
+
const setActivePanel = (documentId, placement, slot, panelId, activeTab) => ({
|
|
53
|
+
type: SET_ACTIVE_PANEL,
|
|
54
|
+
payload: { documentId, placement, slot, panelId, activeTab }
|
|
55
|
+
});
|
|
56
|
+
const closePanelSlot = (documentId, placement, slot) => ({
|
|
57
|
+
type: CLOSE_PANEL_SLOT,
|
|
58
|
+
payload: { documentId, placement, slot }
|
|
59
|
+
});
|
|
60
|
+
const setPanelTab = (documentId, panelId, tabId) => ({
|
|
61
|
+
type: SET_PANEL_TAB,
|
|
62
|
+
payload: { documentId, panelId, tabId }
|
|
63
|
+
});
|
|
64
|
+
const openModal = (documentId, modalId) => ({
|
|
65
|
+
type: OPEN_MODAL,
|
|
66
|
+
payload: { documentId, modalId }
|
|
67
|
+
});
|
|
68
|
+
const closeModal = (documentId) => ({
|
|
69
|
+
type: CLOSE_MODAL,
|
|
70
|
+
payload: { documentId }
|
|
71
|
+
});
|
|
72
|
+
const openMenu = (documentId, menuState) => ({
|
|
73
|
+
type: OPEN_MENU,
|
|
74
|
+
payload: { documentId, menuState }
|
|
75
|
+
});
|
|
76
|
+
const closeMenu = (documentId, menuId) => ({
|
|
77
|
+
type: CLOSE_MENU,
|
|
78
|
+
payload: { documentId, menuId }
|
|
79
|
+
});
|
|
80
|
+
const closeAllMenus = (documentId) => ({
|
|
81
|
+
type: CLOSE_ALL_MENUS,
|
|
82
|
+
payload: { documentId }
|
|
83
|
+
});
|
|
84
|
+
const setDisabledCategories = (categories) => ({
|
|
85
|
+
type: SET_DISABLED_CATEGORIES,
|
|
86
|
+
payload: { categories }
|
|
87
|
+
});
|
|
88
|
+
function mergeUISchema(base, override) {
|
|
89
|
+
return {
|
|
90
|
+
...base,
|
|
91
|
+
...override,
|
|
92
|
+
toolbars: mergeToolbars(base.toolbars, override.toolbars),
|
|
93
|
+
menus: mergeMenus(base.menus, override.menus),
|
|
94
|
+
panels: mergePanels(base.panels, override.panels)
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
function mergeToolbars(base, override) {
|
|
98
|
+
if (!override) return base;
|
|
99
|
+
const result = { ...base };
|
|
100
|
+
for (const [id, toolbar] of Object.entries(override)) {
|
|
101
|
+
if (result[id]) {
|
|
102
|
+
result[id] = {
|
|
103
|
+
...result[id],
|
|
104
|
+
...toolbar,
|
|
105
|
+
items: toolbar.items ?? result[id].items,
|
|
106
|
+
responsive: toolbar.responsive ?? result[id].responsive
|
|
107
|
+
};
|
|
108
|
+
} else {
|
|
109
|
+
result[id] = toolbar;
|
|
110
|
+
}
|
|
40
111
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
112
|
+
return result;
|
|
113
|
+
}
|
|
114
|
+
function mergeMenus(base, override) {
|
|
115
|
+
if (!override) return base;
|
|
116
|
+
const result = { ...base };
|
|
117
|
+
for (const [id, menu] of Object.entries(override)) {
|
|
118
|
+
if (result[id]) {
|
|
119
|
+
result[id] = {
|
|
120
|
+
...result[id],
|
|
121
|
+
...menu,
|
|
122
|
+
items: menu.items ?? result[id].items
|
|
123
|
+
};
|
|
124
|
+
} else {
|
|
125
|
+
result[id] = menu;
|
|
49
126
|
}
|
|
50
|
-
return context;
|
|
51
127
|
}
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
128
|
+
return result;
|
|
129
|
+
}
|
|
130
|
+
function mergePanels(base, override) {
|
|
131
|
+
if (!override) return base;
|
|
132
|
+
const result = { ...base };
|
|
133
|
+
for (const [id, panel] of Object.entries(override)) {
|
|
134
|
+
if (result[id]) {
|
|
135
|
+
result[id] = {
|
|
136
|
+
...result[id],
|
|
137
|
+
...panel,
|
|
138
|
+
content: panel.content ?? result[id].content
|
|
139
|
+
};
|
|
140
|
+
} else {
|
|
141
|
+
result[id] = panel;
|
|
57
142
|
}
|
|
58
|
-
this.notifyUpdate();
|
|
59
143
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
144
|
+
return result;
|
|
145
|
+
}
|
|
146
|
+
function removeFromSchema(schema, options) {
|
|
147
|
+
const result = { ...schema };
|
|
148
|
+
if (options.toolbars) {
|
|
149
|
+
result.toolbars = { ...result.toolbars };
|
|
150
|
+
options.toolbars.forEach((id) => delete result.toolbars[id]);
|
|
63
151
|
}
|
|
64
|
-
|
|
65
|
-
|
|
152
|
+
if (options.menus) {
|
|
153
|
+
result.menus = { ...result.menus };
|
|
154
|
+
options.menus.forEach((id) => delete result.menus[id]);
|
|
66
155
|
}
|
|
67
|
-
|
|
68
|
-
|
|
156
|
+
if (options.panels) {
|
|
157
|
+
result.panels = { ...result.panels };
|
|
158
|
+
options.panels.forEach((id) => delete result.panels[id]);
|
|
69
159
|
}
|
|
160
|
+
if (options.commands) {
|
|
161
|
+
result.toolbars = removeCommandsFromToolbars(result.toolbars, options.commands);
|
|
162
|
+
result.menus = removeCommandsFromMenus(result.menus, options.commands);
|
|
163
|
+
}
|
|
164
|
+
return result;
|
|
70
165
|
}
|
|
71
|
-
|
|
72
|
-
const
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
payload: state
|
|
80
|
-
});
|
|
81
|
-
const uiTogglePanel = (payload) => ({
|
|
82
|
-
type: UI_TOGGLE_PANEL,
|
|
83
|
-
payload
|
|
84
|
-
});
|
|
85
|
-
const uiSetHeaderVisible = (payload) => ({
|
|
86
|
-
type: UI_SET_HEADER_VISIBLE,
|
|
87
|
-
payload
|
|
88
|
-
});
|
|
89
|
-
const uiShowCommandMenu = (payload) => ({
|
|
90
|
-
type: UI_SHOW_COMMAND_MENU,
|
|
91
|
-
payload
|
|
92
|
-
});
|
|
93
|
-
const uiHideCommandMenu = (payload) => ({
|
|
94
|
-
type: UI_HIDE_COMMAND_MENU,
|
|
95
|
-
payload
|
|
96
|
-
});
|
|
97
|
-
const uiUpdateComponentState = (payload) => ({
|
|
98
|
-
type: UI_UPDATE_COMPONENT_STATE,
|
|
99
|
-
payload
|
|
100
|
-
});
|
|
101
|
-
const initialState = {
|
|
102
|
-
panel: {},
|
|
103
|
-
header: {},
|
|
104
|
-
groupedItems: {},
|
|
105
|
-
divider: {},
|
|
106
|
-
iconButton: {},
|
|
107
|
-
tabButton: {},
|
|
108
|
-
selectButton: {},
|
|
109
|
-
custom: {},
|
|
110
|
-
floating: {},
|
|
111
|
-
commandMenu: {}
|
|
112
|
-
};
|
|
113
|
-
const uiReducer = (state = initialState, action) => {
|
|
114
|
-
switch (action.type) {
|
|
115
|
-
case UI_INIT_COMPONENTS:
|
|
116
|
-
return {
|
|
117
|
-
...state,
|
|
118
|
-
...action.payload
|
|
119
|
-
};
|
|
120
|
-
case UI_TOGGLE_PANEL: {
|
|
121
|
-
const prevPanel = state.panel[action.payload.id] || {};
|
|
122
|
-
const { open: nextOpen, visibleChild: nextVisibleChild } = action.payload;
|
|
123
|
-
const prevVisibleChild = prevPanel.visibleChild;
|
|
124
|
-
let open = prevPanel.open;
|
|
125
|
-
let visibleChild = prevPanel.visibleChild;
|
|
126
|
-
if (nextVisibleChild === prevVisibleChild) {
|
|
127
|
-
open = nextOpen !== void 0 ? nextOpen : !prevPanel.open;
|
|
128
|
-
} else {
|
|
129
|
-
visibleChild = nextVisibleChild;
|
|
130
|
-
open = true;
|
|
131
|
-
}
|
|
132
|
-
return {
|
|
133
|
-
...state,
|
|
134
|
-
panel: {
|
|
135
|
-
...state.panel,
|
|
136
|
-
[action.payload.id]: {
|
|
137
|
-
...prevPanel,
|
|
138
|
-
open,
|
|
139
|
-
visibleChild
|
|
140
|
-
}
|
|
166
|
+
function removeCommandsFromToolbars(toolbars, commandIds) {
|
|
167
|
+
const result = {};
|
|
168
|
+
for (const [id, toolbar] of Object.entries(toolbars)) {
|
|
169
|
+
result[id] = {
|
|
170
|
+
...toolbar,
|
|
171
|
+
items: toolbar.items.filter((item) => {
|
|
172
|
+
if (item.type === "command-button") {
|
|
173
|
+
return !commandIds.includes(item.commandId);
|
|
141
174
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
...state,
|
|
147
|
-
header: {
|
|
148
|
-
...state.header,
|
|
149
|
-
[action.payload.id]: {
|
|
150
|
-
...state.header[action.payload.id],
|
|
151
|
-
visible: action.payload.visible,
|
|
152
|
-
visibleChild: action.payload.visibleChild
|
|
153
|
-
}
|
|
175
|
+
if (item.type === "group") {
|
|
176
|
+
return item.items.some(
|
|
177
|
+
(child) => child.type === "command-button" ? !commandIds.includes(child.commandId) : true
|
|
178
|
+
);
|
|
154
179
|
}
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
return {
|
|
158
|
-
...state,
|
|
159
|
-
commandMenu: {
|
|
160
|
-
...state.commandMenu,
|
|
161
|
-
[action.payload.id]: {
|
|
162
|
-
activeCommand: action.payload.commandId,
|
|
163
|
-
triggerElement: action.payload.triggerElement,
|
|
164
|
-
position: action.payload.position,
|
|
165
|
-
open: true,
|
|
166
|
-
flatten: action.payload.flatten
|
|
167
|
-
}
|
|
180
|
+
if (item.type === "tab-group") {
|
|
181
|
+
return item.tabs.some((tab) => !commandIds.includes(tab.commandId));
|
|
168
182
|
}
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
+
return true;
|
|
184
|
+
})
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
return result;
|
|
188
|
+
}
|
|
189
|
+
function removeCommandsFromMenus(menus, commandIds) {
|
|
190
|
+
const result = {};
|
|
191
|
+
for (const [id, menu] of Object.entries(menus)) {
|
|
192
|
+
result[id] = {
|
|
193
|
+
...menu,
|
|
194
|
+
items: menu.items.filter((item) => {
|
|
195
|
+
if (item.type === "command") {
|
|
196
|
+
return !commandIds.includes(item.commandId);
|
|
183
197
|
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
const current = state[componentType][componentId];
|
|
189
|
-
const filteredPatch = Object.fromEntries(Object.entries(patch).filter(([k]) => k in current));
|
|
190
|
-
if (Object.keys(filteredPatch).length === 0) return state;
|
|
191
|
-
return {
|
|
192
|
-
...state,
|
|
193
|
-
[componentType]: {
|
|
194
|
-
...state[componentType],
|
|
195
|
-
[componentId]: {
|
|
196
|
-
...current,
|
|
197
|
-
...filteredPatch
|
|
198
|
-
}
|
|
198
|
+
if (item.type === "section") {
|
|
199
|
+
return item.items.some(
|
|
200
|
+
(child) => child.type === "command" ? !commandIds.includes(child.commandId) : true
|
|
201
|
+
);
|
|
199
202
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
return state;
|
|
203
|
+
return true;
|
|
204
|
+
})
|
|
205
|
+
};
|
|
204
206
|
}
|
|
205
|
-
|
|
206
|
-
function defineComponent() {
|
|
207
|
-
return (c) => c;
|
|
207
|
+
return result;
|
|
208
208
|
}
|
|
209
|
-
function
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
209
|
+
function resolveResponsiveMetadata(schema, currentLocale) {
|
|
210
|
+
var _a;
|
|
211
|
+
if (!((_a = schema.responsive) == null ? void 0 : _a.breakpoints)) {
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
const effectiveBreakpoints = applyLocaleOverrides(
|
|
215
|
+
schema.responsive.breakpoints,
|
|
216
|
+
schema.responsive.localeOverrides,
|
|
217
|
+
currentLocale
|
|
218
|
+
);
|
|
219
|
+
const items = /* @__PURE__ */ new Map();
|
|
220
|
+
const breakpoints = /* @__PURE__ */ new Map();
|
|
221
|
+
for (const [breakpointId, config] of Object.entries(effectiveBreakpoints)) {
|
|
222
|
+
breakpoints.set(breakpointId, {
|
|
223
|
+
minWidth: config.minWidth,
|
|
224
|
+
maxWidth: config.maxWidth
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
const allItemIds = /* @__PURE__ */ new Set();
|
|
228
|
+
const collectItemIds = (items2) => {
|
|
229
|
+
items2.forEach((item) => {
|
|
230
|
+
allItemIds.add(item.id);
|
|
231
|
+
if (item.type === "group" && item.items) {
|
|
232
|
+
collectItemIds(item.items);
|
|
216
233
|
}
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
if (!eventMap.has(eventType)) {
|
|
220
|
-
eventMap.set(eventType, /* @__PURE__ */ new Set());
|
|
234
|
+
if (item.type === "tab-group" && item.tabs) {
|
|
235
|
+
collectItemIds(item.tabs);
|
|
221
236
|
}
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
return () => this.off(eventType, callback);
|
|
225
|
-
},
|
|
226
|
-
off(eventType, callback) {
|
|
227
|
-
const callbacks = eventMap.get(eventType);
|
|
228
|
-
if (callbacks) {
|
|
229
|
-
callbacks.delete(callback);
|
|
230
|
-
if (callbacks.size === 0) {
|
|
231
|
-
eventMap.delete(eventType);
|
|
232
|
-
}
|
|
237
|
+
if (item.type === "section" && item.items) {
|
|
238
|
+
collectItemIds(item.items);
|
|
233
239
|
}
|
|
234
|
-
}
|
|
240
|
+
});
|
|
235
241
|
};
|
|
242
|
+
collectItemIds(schema.items);
|
|
243
|
+
for (const itemId of allItemIds) {
|
|
244
|
+
const rules = [];
|
|
245
|
+
let defaultVisible = true;
|
|
246
|
+
const sortedBreakpoints = Array.from(Object.entries(effectiveBreakpoints)).sort((a, b) => {
|
|
247
|
+
const aMin = a[1].minWidth ?? 0;
|
|
248
|
+
const bMin = b[1].minWidth ?? 0;
|
|
249
|
+
return aMin - bMin;
|
|
250
|
+
});
|
|
251
|
+
sortedBreakpoints.forEach(([breakpointId, config], index) => {
|
|
252
|
+
var _a2, _b;
|
|
253
|
+
const isHidden = (_a2 = config.hide) == null ? void 0 : _a2.includes(itemId);
|
|
254
|
+
const isShown = (_b = config.show) == null ? void 0 : _b.includes(itemId);
|
|
255
|
+
if (!isHidden && !isShown) {
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
rules.push({
|
|
259
|
+
breakpointId,
|
|
260
|
+
minWidth: config.minWidth,
|
|
261
|
+
maxWidth: config.maxWidth,
|
|
262
|
+
visible: isShown || !isHidden,
|
|
263
|
+
priority: index
|
|
264
|
+
});
|
|
265
|
+
if (index === 0) {
|
|
266
|
+
defaultVisible = isShown || !isHidden;
|
|
267
|
+
}
|
|
268
|
+
});
|
|
269
|
+
if (rules.length > 0) {
|
|
270
|
+
items.set(itemId, {
|
|
271
|
+
itemId,
|
|
272
|
+
shouldRender: true,
|
|
273
|
+
// Always render for SSR
|
|
274
|
+
visibilityRules: rules,
|
|
275
|
+
defaultVisible
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
return { items, breakpoints };
|
|
236
280
|
}
|
|
237
|
-
function
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
281
|
+
function applyLocaleOverrides(baseBreakpoints, localeOverrides, currentLocale) {
|
|
282
|
+
if (!currentLocale || !(localeOverrides == null ? void 0 : localeOverrides.groups)) {
|
|
283
|
+
return baseBreakpoints;
|
|
284
|
+
}
|
|
285
|
+
const matchingGroup = localeOverrides.groups.find(
|
|
286
|
+
(group) => group.locales.includes(currentLocale)
|
|
287
|
+
);
|
|
288
|
+
if (!matchingGroup) {
|
|
289
|
+
return baseBreakpoints;
|
|
290
|
+
}
|
|
291
|
+
const effective = {};
|
|
292
|
+
for (const [breakpointId, baseRule] of Object.entries(baseBreakpoints)) {
|
|
293
|
+
const override = matchingGroup.breakpoints[breakpointId];
|
|
294
|
+
if (!override) {
|
|
295
|
+
effective[breakpointId] = baseRule;
|
|
296
|
+
continue;
|
|
297
|
+
}
|
|
298
|
+
effective[breakpointId] = {
|
|
299
|
+
// Width constraints never change!
|
|
300
|
+
minWidth: baseRule.minWidth,
|
|
301
|
+
maxWidth: baseRule.maxWidth,
|
|
302
|
+
// Merge hide lists (base + additional) or use replacement
|
|
303
|
+
hide: override.replaceHide ? override.replaceHide : [...baseRule.hide || [], ...override.hide || []],
|
|
304
|
+
// Merge show lists (base + additional) or use replacement
|
|
305
|
+
show: override.replaceShow ? override.replaceShow : [...baseRule.show || [], ...override.show || []]
|
|
243
306
|
};
|
|
244
307
|
}
|
|
245
|
-
return
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
308
|
+
return effective;
|
|
309
|
+
}
|
|
310
|
+
function getItemResponsiveMetadata(itemId, schema, currentLocale) {
|
|
311
|
+
const metadata = resolveResponsiveMetadata(schema, currentLocale);
|
|
312
|
+
return (metadata == null ? void 0 : metadata.items.get(itemId)) ?? null;
|
|
313
|
+
}
|
|
314
|
+
const UI_ATTRIBUTES = {
|
|
315
|
+
/** Root element marker */
|
|
316
|
+
ROOT: "data-epdf",
|
|
317
|
+
/** Style element marker for deduplication */
|
|
318
|
+
STYLES: "data-epdf-s",
|
|
319
|
+
/** Item ID for responsive and dependency rules */
|
|
320
|
+
ITEM: "data-epdf-i",
|
|
321
|
+
/** Item categories for category-based hiding */
|
|
322
|
+
CATEGORIES: "data-epdf-cat",
|
|
323
|
+
/** Disabled categories list on root element */
|
|
324
|
+
DISABLED_CATEGORIES: "data-epdf-dis"
|
|
325
|
+
};
|
|
326
|
+
const UI_SELECTORS = {
|
|
327
|
+
ROOT: `[${UI_ATTRIBUTES.ROOT}]`,
|
|
328
|
+
STYLES: `[${UI_ATTRIBUTES.STYLES}]`,
|
|
329
|
+
ITEM: (id) => `[${UI_ATTRIBUTES.ITEM}="${id}"]`,
|
|
330
|
+
CATEGORIES: (category) => `[${UI_ATTRIBUTES.CATEGORIES}~="${category}"]`,
|
|
331
|
+
DISABLED_CATEGORY: (category) => `[${UI_ATTRIBUTES.DISABLED_CATEGORIES}~="${category}"]`
|
|
332
|
+
};
|
|
333
|
+
const DEFAULT_CONFIG = {
|
|
334
|
+
useContainerQueries: true
|
|
335
|
+
};
|
|
336
|
+
function generateUIStylesheet(schema, options = {}) {
|
|
337
|
+
const cfg = { ...DEFAULT_CONFIG, ...options.config };
|
|
338
|
+
const locale = options.locale;
|
|
339
|
+
const analysis = analyzeSchema(schema, locale);
|
|
340
|
+
const sections = [];
|
|
341
|
+
sections.push(generateHeader(locale));
|
|
342
|
+
const responsiveCSS = generateResponsiveRules(analysis, cfg);
|
|
343
|
+
if (responsiveCSS) sections.push(responsiveCSS);
|
|
344
|
+
const categoryCSS = generateCategoryRules(analysis);
|
|
345
|
+
if (categoryCSS) sections.push(categoryCSS);
|
|
346
|
+
const dependencyCSS = generateDependencyRules(analysis, cfg);
|
|
347
|
+
if (dependencyCSS) sections.push(dependencyCSS);
|
|
348
|
+
return sections.filter((s) => s.trim()).join("\n\n");
|
|
254
349
|
}
|
|
255
|
-
function
|
|
256
|
-
const
|
|
257
|
-
|
|
258
|
-
|
|
350
|
+
function extractCategories(schema) {
|
|
351
|
+
const analysis = analyzeSchema(schema);
|
|
352
|
+
return Array.from(analysis.categories).sort();
|
|
353
|
+
}
|
|
354
|
+
function getStylesheetConfig(config = {}) {
|
|
355
|
+
return { ...DEFAULT_CONFIG, ...config };
|
|
356
|
+
}
|
|
357
|
+
function analyzeSchema(schema, locale) {
|
|
358
|
+
const categories = /* @__PURE__ */ new Set();
|
|
359
|
+
const itemCategories = /* @__PURE__ */ new Map();
|
|
360
|
+
const dependencies = [];
|
|
361
|
+
const menuBreakpoints = /* @__PURE__ */ new Map();
|
|
362
|
+
const responsiveItems = /* @__PURE__ */ new Map();
|
|
363
|
+
for (const [menuId, menu] of Object.entries(schema.menus)) {
|
|
364
|
+
analyzeMenu(
|
|
365
|
+
menuId,
|
|
366
|
+
menu,
|
|
367
|
+
categories,
|
|
368
|
+
itemCategories,
|
|
369
|
+
dependencies,
|
|
370
|
+
menuBreakpoints,
|
|
371
|
+
responsiveItems,
|
|
372
|
+
locale
|
|
373
|
+
);
|
|
374
|
+
}
|
|
375
|
+
for (const [toolbarId, toolbar] of Object.entries(schema.toolbars)) {
|
|
376
|
+
analyzeToolbar(
|
|
377
|
+
toolbarId,
|
|
378
|
+
toolbar,
|
|
379
|
+
categories,
|
|
380
|
+
itemCategories,
|
|
381
|
+
dependencies,
|
|
382
|
+
responsiveItems,
|
|
383
|
+
locale
|
|
384
|
+
);
|
|
259
385
|
}
|
|
260
|
-
|
|
386
|
+
for (const [panelId, panel] of Object.entries(schema.panels)) {
|
|
387
|
+
analyzePanel(panelId, panel, categories, itemCategories, dependencies);
|
|
388
|
+
}
|
|
389
|
+
for (const [selMenuId, selMenu] of Object.entries(schema.selectionMenus || {})) {
|
|
390
|
+
analyzeSelectionMenu(
|
|
391
|
+
selMenuId,
|
|
392
|
+
selMenu,
|
|
393
|
+
categories,
|
|
394
|
+
itemCategories,
|
|
395
|
+
dependencies,
|
|
396
|
+
responsiveItems,
|
|
397
|
+
locale
|
|
398
|
+
);
|
|
399
|
+
}
|
|
400
|
+
return { categories, itemCategories, dependencies, menuBreakpoints, responsiveItems };
|
|
261
401
|
}
|
|
262
|
-
function
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
402
|
+
function analyzeMenu(menuId, menu, categories, itemCategories, dependencies, menuBreakpoints, responsiveItems, locale) {
|
|
403
|
+
collectCategoriesAndDependency(
|
|
404
|
+
menuId,
|
|
405
|
+
menu.categories,
|
|
406
|
+
menu.visibilityDependsOn,
|
|
407
|
+
categories,
|
|
408
|
+
itemCategories,
|
|
409
|
+
dependencies
|
|
410
|
+
);
|
|
411
|
+
analyzeMenuItems(menu.items, categories, itemCategories, dependencies);
|
|
412
|
+
const metadata = resolveResponsiveMetadata(menu, locale);
|
|
413
|
+
if (metadata) {
|
|
414
|
+
metadata.items.forEach((itemMeta, itemId) => {
|
|
415
|
+
responsiveItems.set(itemId, itemMeta);
|
|
416
|
+
});
|
|
266
417
|
}
|
|
267
|
-
|
|
418
|
+
const breakpointVisibilities = computeMenuBreakpointVisibilities(menu, itemCategories, locale);
|
|
419
|
+
menuBreakpoints.set(menuId, breakpointVisibilities);
|
|
268
420
|
}
|
|
269
|
-
function
|
|
270
|
-
const
|
|
271
|
-
|
|
272
|
-
|
|
421
|
+
function analyzeMenuItems(items, categories, itemCategories, dependencies) {
|
|
422
|
+
for (const item of items) {
|
|
423
|
+
collectCategoriesAndDependency(
|
|
424
|
+
item.id,
|
|
425
|
+
item.categories,
|
|
426
|
+
item.visibilityDependsOn,
|
|
427
|
+
categories,
|
|
428
|
+
itemCategories,
|
|
429
|
+
dependencies
|
|
430
|
+
);
|
|
431
|
+
if (item.type === "section") {
|
|
432
|
+
analyzeMenuItems(item.items, categories, itemCategories, dependencies);
|
|
433
|
+
}
|
|
273
434
|
}
|
|
274
|
-
return resolved.disabled ? true : false;
|
|
275
435
|
}
|
|
276
|
-
function
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
436
|
+
function computeMenuBreakpointVisibilities(menu, itemCategories, locale) {
|
|
437
|
+
var _a;
|
|
438
|
+
const breakpointVisibilities = [];
|
|
439
|
+
const metadata = resolveResponsiveMetadata(menu, locale);
|
|
440
|
+
if (((_a = menu.responsive) == null ? void 0 : _a.breakpoints) && metadata) {
|
|
441
|
+
const sortedBreakpoints = Array.from(metadata.breakpoints.entries()).sort(
|
|
442
|
+
(a, b) => (a[1].minWidth ?? 0) - (b[1].minWidth ?? 0)
|
|
443
|
+
);
|
|
444
|
+
for (const [_bpId, bp] of sortedBreakpoints) {
|
|
445
|
+
const visibleItems = computeVisibleItemsAtBreakpoint(metadata, bp);
|
|
446
|
+
const visibleCats = /* @__PURE__ */ new Set();
|
|
447
|
+
for (const itemId of visibleItems) {
|
|
448
|
+
const cats = itemCategories.get(itemId);
|
|
449
|
+
if (cats) cats.forEach((c) => visibleCats.add(c));
|
|
450
|
+
}
|
|
451
|
+
breakpointVisibilities.push({
|
|
452
|
+
minWidth: bp.minWidth,
|
|
453
|
+
maxWidth: bp.maxWidth,
|
|
454
|
+
visibleCategories: visibleCats
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
} else {
|
|
458
|
+
const allCats = /* @__PURE__ */ new Set();
|
|
459
|
+
collectAllMenuItemCategories(menu.items, itemCategories, allCats);
|
|
460
|
+
breakpointVisibilities.push({ visibleCategories: allCats });
|
|
280
461
|
}
|
|
281
|
-
return
|
|
462
|
+
return breakpointVisibilities;
|
|
282
463
|
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
this.setupKeyboardListeners();
|
|
464
|
+
function collectAllMenuItemCategories(items, itemCategories, result) {
|
|
465
|
+
for (const item of items) {
|
|
466
|
+
const cats = itemCategories.get(item.id);
|
|
467
|
+
if (cats) cats.forEach((c) => result.add(c));
|
|
468
|
+
if (item.type === "section") {
|
|
469
|
+
collectAllMenuItemCategories(item.items, itemCategories, result);
|
|
470
|
+
}
|
|
291
471
|
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
472
|
+
}
|
|
473
|
+
function computeVisibleItemsAtBreakpoint(metadata, targetBp) {
|
|
474
|
+
const visible = [];
|
|
475
|
+
metadata.items.forEach((itemMeta, itemId) => {
|
|
476
|
+
let isVisible = itemMeta.defaultVisible;
|
|
477
|
+
for (const rule of itemMeta.visibilityRules) {
|
|
478
|
+
const ruleApplies = (rule.minWidth === void 0 || targetBp.minWidth !== void 0 && targetBp.minWidth >= rule.minWidth) && (rule.maxWidth === void 0 || targetBp.maxWidth !== void 0 && targetBp.maxWidth <= rule.maxWidth);
|
|
479
|
+
if (ruleApplies) {
|
|
480
|
+
isVisible = rule.visible;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
if (isVisible) {
|
|
484
|
+
visible.push(itemId);
|
|
485
|
+
}
|
|
486
|
+
});
|
|
487
|
+
return visible;
|
|
488
|
+
}
|
|
489
|
+
function analyzeToolbar(toolbarId, toolbar, categories, itemCategories, dependencies, responsiveItems, locale) {
|
|
490
|
+
collectCategoriesAndDependency(
|
|
491
|
+
toolbarId,
|
|
492
|
+
toolbar.categories,
|
|
493
|
+
toolbar.visibilityDependsOn,
|
|
494
|
+
categories,
|
|
495
|
+
itemCategories,
|
|
496
|
+
dependencies
|
|
497
|
+
);
|
|
498
|
+
const metadata = resolveResponsiveMetadata(toolbar, locale);
|
|
499
|
+
if (metadata) {
|
|
500
|
+
metadata.items.forEach((itemMeta, itemId) => {
|
|
501
|
+
responsiveItems.set(itemId, itemMeta);
|
|
502
|
+
});
|
|
297
503
|
}
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
504
|
+
analyzeToolbarItems(toolbar.items, categories, itemCategories, dependencies);
|
|
505
|
+
}
|
|
506
|
+
function analyzeToolbarItems(items, categories, itemCategories, dependencies) {
|
|
507
|
+
for (const item of items) {
|
|
508
|
+
collectCategoriesAndDependency(
|
|
509
|
+
item.id,
|
|
510
|
+
item.categories,
|
|
511
|
+
item.visibilityDependsOn,
|
|
512
|
+
categories,
|
|
513
|
+
itemCategories,
|
|
514
|
+
dependencies
|
|
515
|
+
);
|
|
516
|
+
if (item.type === "group" && item.items) {
|
|
517
|
+
analyzeToolbarItems(item.items, categories, itemCategories, dependencies);
|
|
304
518
|
}
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
this.shortcutMap[this.normalizeShortcut(item.shortcut)] = item.id;
|
|
519
|
+
if (item.type === "tab-group" && item.tabs) {
|
|
520
|
+
analyzeTabItems(item.tabs, categories, itemCategories, dependencies);
|
|
308
521
|
}
|
|
309
522
|
}
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
523
|
+
}
|
|
524
|
+
function analyzeTabItems(tabs, categories, itemCategories, dependencies) {
|
|
525
|
+
for (const tab of tabs) {
|
|
526
|
+
collectCategoriesAndDependency(
|
|
527
|
+
tab.id,
|
|
528
|
+
tab.categories,
|
|
529
|
+
tab.visibilityDependsOn,
|
|
530
|
+
categories,
|
|
531
|
+
itemCategories,
|
|
532
|
+
dependencies
|
|
533
|
+
);
|
|
317
534
|
}
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
535
|
+
}
|
|
536
|
+
function analyzePanel(panelId, panel, categories, itemCategories, dependencies) {
|
|
537
|
+
collectCategoriesAndDependency(
|
|
538
|
+
panelId,
|
|
539
|
+
panel.categories,
|
|
540
|
+
panel.visibilityDependsOn,
|
|
541
|
+
categories,
|
|
542
|
+
itemCategories,
|
|
543
|
+
dependencies
|
|
544
|
+
);
|
|
545
|
+
if (panel.content.type === "tabs") {
|
|
546
|
+
for (const tab of panel.content.tabs) {
|
|
547
|
+
collectCategoriesAndDependency(
|
|
548
|
+
tab.id,
|
|
549
|
+
tab.categories,
|
|
550
|
+
tab.visibilityDependsOn,
|
|
551
|
+
categories,
|
|
552
|
+
itemCategories,
|
|
553
|
+
dependencies
|
|
554
|
+
);
|
|
555
|
+
}
|
|
324
556
|
}
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
557
|
+
}
|
|
558
|
+
function analyzeSelectionMenu(selMenuId, selMenu, categories, itemCategories, dependencies, responsiveItems, locale) {
|
|
559
|
+
collectCategoriesAndDependency(
|
|
560
|
+
selMenuId,
|
|
561
|
+
selMenu.categories,
|
|
562
|
+
selMenu.visibilityDependsOn,
|
|
563
|
+
categories,
|
|
564
|
+
itemCategories,
|
|
565
|
+
dependencies
|
|
566
|
+
);
|
|
567
|
+
if (selMenu.responsive) {
|
|
568
|
+
const metadata = resolveResponsiveMetadata(selMenu, locale);
|
|
569
|
+
if (metadata) {
|
|
570
|
+
metadata.items.forEach((itemMeta, itemId) => {
|
|
571
|
+
responsiveItems.set(itemId, itemMeta);
|
|
572
|
+
});
|
|
573
|
+
}
|
|
337
574
|
}
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
575
|
+
analyzeSelectionMenuItems(selMenu.items, categories, itemCategories, dependencies);
|
|
576
|
+
}
|
|
577
|
+
function analyzeSelectionMenuItems(items, categories, itemCategories, dependencies) {
|
|
578
|
+
for (const item of items) {
|
|
579
|
+
collectCategoriesAndDependency(
|
|
580
|
+
item.id,
|
|
581
|
+
item.categories,
|
|
582
|
+
item.visibilityDependsOn,
|
|
583
|
+
categories,
|
|
584
|
+
itemCategories,
|
|
585
|
+
dependencies
|
|
586
|
+
);
|
|
587
|
+
if (item.type === "group" && item.items) {
|
|
588
|
+
analyzeSelectionMenuItems(item.items, categories, itemCategories, dependencies);
|
|
589
|
+
}
|
|
345
590
|
}
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
return resolved.item;
|
|
591
|
+
}
|
|
592
|
+
function collectCategoriesAndDependency(itemId, itemCats, visibilityDep, categories, itemCategories, dependencies) {
|
|
593
|
+
var _a;
|
|
594
|
+
if (itemCats == null ? void 0 : itemCats.length) {
|
|
595
|
+
itemCats.forEach((c) => categories.add(c));
|
|
596
|
+
itemCategories.set(itemId, itemCats);
|
|
353
597
|
}
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
598
|
+
if (visibilityDep && (visibilityDep.menuId || ((_a = visibilityDep.itemIds) == null ? void 0 : _a.length))) {
|
|
599
|
+
dependencies.push({
|
|
600
|
+
itemId,
|
|
601
|
+
dependsOnMenuId: visibilityDep.menuId,
|
|
602
|
+
dependsOnItemIds: visibilityDep.itemIds
|
|
603
|
+
});
|
|
359
604
|
}
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
605
|
+
}
|
|
606
|
+
function generateHeader(locale) {
|
|
607
|
+
const localeInfo = locale ? ` (locale: ${locale})` : "";
|
|
608
|
+
return `/* ═══════════════════════════════════════════════════════════════════════════ */
|
|
609
|
+
/* EmbedPDF UI Stylesheet - Auto-generated${localeInfo} */
|
|
610
|
+
/* DO NOT EDIT MANUALLY - This file is generated from your UI schema */
|
|
611
|
+
/* ═══════════════════════════════════════════════════════════════════════════ */`;
|
|
612
|
+
}
|
|
613
|
+
function generateResponsiveRules(analysis, cfg) {
|
|
614
|
+
const rules = [];
|
|
615
|
+
const queryType = cfg.useContainerQueries ? "@container" : "@media";
|
|
616
|
+
const processedItems = /* @__PURE__ */ new Set();
|
|
617
|
+
analysis.responsiveItems.forEach((itemMeta, itemId) => {
|
|
618
|
+
if (processedItems.has(itemId)) return;
|
|
619
|
+
processedItems.add(itemId);
|
|
620
|
+
const itemRules = generateItemResponsiveRules(itemId, itemMeta, queryType);
|
|
621
|
+
if (itemRules) rules.push(itemRules);
|
|
622
|
+
});
|
|
623
|
+
if (rules.length === 0) return "";
|
|
624
|
+
return `/* ─── Responsive Visibility Rules ─── */
|
|
625
|
+
/* Items show/hide based on container width */
|
|
626
|
+
|
|
627
|
+
${rules.join("\n\n")}`;
|
|
628
|
+
}
|
|
629
|
+
function generateItemResponsiveRules(itemId, metadata, queryType, cfg) {
|
|
630
|
+
if (metadata.visibilityRules.length === 0) return null;
|
|
631
|
+
const rules = [];
|
|
632
|
+
const selector = UI_SELECTORS.ITEM(itemId);
|
|
633
|
+
if (!metadata.defaultVisible) {
|
|
634
|
+
rules.push(`${selector} { display: none; }`);
|
|
365
635
|
}
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
636
|
+
for (const rule of metadata.visibilityRules) {
|
|
637
|
+
const conditions = [];
|
|
638
|
+
if (rule.minWidth !== void 0) {
|
|
639
|
+
conditions.push(`(min-width: ${rule.minWidth}px)`);
|
|
640
|
+
}
|
|
641
|
+
if (rule.maxWidth !== void 0) {
|
|
642
|
+
conditions.push(`(max-width: ${rule.maxWidth}px)`);
|
|
643
|
+
}
|
|
644
|
+
if (conditions.length > 0) {
|
|
645
|
+
const display = rule.visible ? "flex" : "none";
|
|
646
|
+
rules.push(`${queryType} ${conditions.join(" and ")} {
|
|
647
|
+
${selector} { display: ${display}; }
|
|
648
|
+
}`);
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
return rules.length > 0 ? rules.join("\n") : null;
|
|
652
|
+
}
|
|
653
|
+
function generateCategoryRules(analysis, cfg) {
|
|
654
|
+
if (analysis.categories.size === 0) return "";
|
|
655
|
+
const rules = [];
|
|
656
|
+
const sortedCategories = Array.from(analysis.categories).sort();
|
|
657
|
+
for (const category of sortedCategories) {
|
|
658
|
+
rules.push(
|
|
659
|
+
`${UI_SELECTORS.ROOT}[${UI_ATTRIBUTES.DISABLED_CATEGORIES}~="${category}"] [${UI_ATTRIBUTES.CATEGORIES}~="${category}"] {
|
|
660
|
+
display: none !important;
|
|
661
|
+
}`
|
|
662
|
+
);
|
|
663
|
+
}
|
|
664
|
+
return `/* ─── Category Visibility Rules ─── */
|
|
665
|
+
/* Items hide when ANY of their categories is disabled */
|
|
666
|
+
/* Use: data-disabled-categories="category1 category2" on root element */
|
|
667
|
+
|
|
668
|
+
${rules.join("\n\n")}`;
|
|
669
|
+
}
|
|
670
|
+
function generateDependencyRules(analysis, cfg) {
|
|
671
|
+
if (analysis.dependencies.length === 0) return "";
|
|
672
|
+
const rules = [];
|
|
673
|
+
const queryType = cfg.useContainerQueries ? "@container" : "@media";
|
|
674
|
+
for (const dep of analysis.dependencies) {
|
|
675
|
+
const depRules = generateSingleDependencyRules(dep, analysis, queryType);
|
|
676
|
+
if (depRules.length > 0) {
|
|
677
|
+
rules.push(...depRules);
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
if (rules.length === 0) return "";
|
|
681
|
+
return `/* ─── Dependency Visibility Rules ─── */
|
|
682
|
+
/* Container elements hide when all their dependencies are hidden */
|
|
683
|
+
|
|
684
|
+
${rules.join("\n\n")}`;
|
|
685
|
+
}
|
|
686
|
+
function generateSingleDependencyRules(dep, analysis, queryType, cfg) {
|
|
687
|
+
var _a;
|
|
688
|
+
const rules = [];
|
|
689
|
+
if (dep.dependsOnMenuId) {
|
|
690
|
+
const breakpoints = analysis.menuBreakpoints.get(dep.dependsOnMenuId);
|
|
691
|
+
if (breakpoints && breakpoints.length > 0) {
|
|
692
|
+
rules.push(`/* "${dep.itemId}" depends on menu "${dep.dependsOnMenuId}" */`);
|
|
693
|
+
for (const bp of breakpoints) {
|
|
694
|
+
if (bp.visibleCategories.size === 0) continue;
|
|
695
|
+
const categorySelectors = Array.from(bp.visibleCategories).sort().map((cat) => UI_SELECTORS.DISABLED_CATEGORY(cat)).join("");
|
|
696
|
+
const cssRule = `${UI_SELECTORS.ROOT}${categorySelectors} ${UI_SELECTORS.ITEM(dep.itemId)} {
|
|
697
|
+
display: none !important;
|
|
698
|
+
}`;
|
|
699
|
+
const conditions = [];
|
|
700
|
+
if (bp.minWidth !== void 0) conditions.push(`(min-width: ${bp.minWidth}px)`);
|
|
701
|
+
if (bp.maxWidth !== void 0) conditions.push(`(max-width: ${bp.maxWidth}px)`);
|
|
702
|
+
if (conditions.length > 0) {
|
|
703
|
+
rules.push(`${queryType} ${conditions.join(" and ")} {
|
|
704
|
+
${cssRule}
|
|
705
|
+
}`);
|
|
706
|
+
} else {
|
|
707
|
+
rules.push(cssRule);
|
|
708
|
+
}
|
|
389
709
|
}
|
|
390
710
|
}
|
|
391
|
-
return flattened;
|
|
392
711
|
}
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
if (
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
return;
|
|
406
|
-
}
|
|
407
|
-
const { item } = resolved;
|
|
408
|
-
if (item.disabled) {
|
|
409
|
-
console.warn(`Menu item '${id}' is disabled`);
|
|
410
|
-
return;
|
|
411
|
-
}
|
|
412
|
-
if (resolved.isAction) {
|
|
413
|
-
item.action(this.pluginRegistry, this.state);
|
|
414
|
-
this.eventController.emit(_MenuManager.EVENTS.COMMAND_EXECUTED, {
|
|
415
|
-
command: item,
|
|
416
|
-
source: options.source || "api"
|
|
417
|
-
});
|
|
418
|
-
} else if ("children" in item && ((_a = item.children) == null ? void 0 : _a.length)) {
|
|
419
|
-
this.handleSubmenu(item, options);
|
|
712
|
+
if ((_a = dep.dependsOnItemIds) == null ? void 0 : _a.length) {
|
|
713
|
+
const relevantCategories = /* @__PURE__ */ new Set();
|
|
714
|
+
for (const itemId of dep.dependsOnItemIds) {
|
|
715
|
+
const cats = analysis.itemCategories.get(itemId);
|
|
716
|
+
if (cats) cats.forEach((c) => relevantCategories.add(c));
|
|
717
|
+
}
|
|
718
|
+
if (relevantCategories.size > 0) {
|
|
719
|
+
const categorySelectors = Array.from(relevantCategories).sort().map((cat) => UI_SELECTORS.DISABLED_CATEGORY(cat)).join("");
|
|
720
|
+
rules.push(`/* "${dep.itemId}" depends on items: ${dep.dependsOnItemIds.join(", ")} */
|
|
721
|
+
${UI_SELECTORS.ROOT}${categorySelectors} ${UI_SELECTORS.ITEM(dep.itemId)} {
|
|
722
|
+
display: none !important;
|
|
723
|
+
}`);
|
|
420
724
|
}
|
|
421
725
|
}
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
726
|
+
return rules;
|
|
727
|
+
}
|
|
728
|
+
function getUIItemProps(item, extra) {
|
|
729
|
+
var _a;
|
|
730
|
+
const props = {
|
|
731
|
+
[UI_ATTRIBUTES.ITEM]: item.id,
|
|
732
|
+
[UI_ATTRIBUTES.CATEGORIES]: ((_a = item.categories) == null ? void 0 : _a.join(" ")) || void 0,
|
|
733
|
+
...extra
|
|
734
|
+
};
|
|
735
|
+
return props;
|
|
736
|
+
}
|
|
737
|
+
const _UIPlugin = class _UIPlugin extends BasePlugin {
|
|
738
|
+
constructor(id, registry, config) {
|
|
739
|
+
var _a, _b;
|
|
740
|
+
super(id, registry);
|
|
741
|
+
this.cachedStylesheet = null;
|
|
742
|
+
this.cachedLocale = null;
|
|
743
|
+
this.i18n = null;
|
|
744
|
+
this.i18nCleanup = null;
|
|
745
|
+
this.categoryChanged$ = createBehaviorEmitter();
|
|
746
|
+
this.stylesheetInvalidated$ = createEmitter();
|
|
747
|
+
this.toolbarChanged$ = createScopedEmitter((documentId, data) => ({ documentId, ...data }), { cache: false });
|
|
748
|
+
this.panelChanged$ = createScopedEmitter(
|
|
749
|
+
(documentId, data) => ({ documentId, ...data }),
|
|
750
|
+
{ cache: false }
|
|
751
|
+
);
|
|
752
|
+
this.modalChanged$ = createScopedEmitter(
|
|
753
|
+
(documentId, data) => ({ documentId, ...data }),
|
|
754
|
+
{ cache: false }
|
|
755
|
+
);
|
|
756
|
+
this.menuChanged$ = createScopedEmitter(
|
|
757
|
+
(documentId, data) => ({ documentId, ...data }),
|
|
758
|
+
{ cache: false }
|
|
759
|
+
);
|
|
760
|
+
this.schema = config.schema;
|
|
761
|
+
this.stylesheetConfig = config.stylesheetConfig || {};
|
|
762
|
+
if ((_a = config.disabledCategories) == null ? void 0 : _a.length) {
|
|
763
|
+
this.dispatch(setDisabledCategories(config.disabledCategories));
|
|
764
|
+
}
|
|
765
|
+
this.i18n = ((_b = registry.getPlugin("i18n")) == null ? void 0 : _b.provides()) ?? null;
|
|
766
|
+
if (this.i18n) {
|
|
767
|
+
this.i18nCleanup = this.i18n.onLocaleChange(({ currentLocale }) => {
|
|
768
|
+
this.handleLocaleChange(currentLocale);
|
|
433
769
|
});
|
|
434
|
-
|
|
770
|
+
this.cachedLocale = this.i18n.getLocale();
|
|
435
771
|
}
|
|
436
|
-
return false;
|
|
437
772
|
}
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
773
|
+
async initialize() {
|
|
774
|
+
this.logger.info("UIPlugin", "Initialize", "UI plugin initialized");
|
|
775
|
+
}
|
|
776
|
+
async destroy() {
|
|
777
|
+
if (this.i18nCleanup) {
|
|
778
|
+
this.i18nCleanup();
|
|
779
|
+
this.i18nCleanup = null;
|
|
780
|
+
}
|
|
781
|
+
this.toolbarChanged$.clear();
|
|
782
|
+
this.panelChanged$.clear();
|
|
783
|
+
this.modalChanged$.clear();
|
|
784
|
+
this.menuChanged$.clear();
|
|
785
|
+
this.stylesheetInvalidated$.clear();
|
|
786
|
+
super.destroy();
|
|
787
|
+
}
|
|
788
|
+
onDocumentLoadingStarted(documentId) {
|
|
789
|
+
this.dispatch(initUIState(documentId, this.schema));
|
|
790
|
+
}
|
|
791
|
+
onDocumentClosed(documentId) {
|
|
792
|
+
this.dispatch(cleanupUIState(documentId));
|
|
793
|
+
this.toolbarChanged$.clearScope(documentId);
|
|
794
|
+
this.panelChanged$.clearScope(documentId);
|
|
795
|
+
this.modalChanged$.clearScope(documentId);
|
|
796
|
+
this.menuChanged$.clearScope(documentId);
|
|
443
797
|
}
|
|
444
798
|
/**
|
|
445
|
-
*
|
|
799
|
+
* Handle locale changes from i18n plugin.
|
|
800
|
+
* Invalidates stylesheet and emits change event.
|
|
446
801
|
*/
|
|
447
|
-
|
|
448
|
-
this.
|
|
802
|
+
handleLocaleChange(newLocale) {
|
|
803
|
+
if (this.cachedLocale === newLocale) return;
|
|
804
|
+
this.logger.debug(
|
|
805
|
+
"UIPlugin",
|
|
806
|
+
"LocaleChange",
|
|
807
|
+
`Locale changed: ${this.cachedLocale} -> ${newLocale}`
|
|
808
|
+
);
|
|
809
|
+
this.cachedLocale = newLocale;
|
|
810
|
+
this.invalidateStylesheet();
|
|
811
|
+
this.stylesheetInvalidated$.emit();
|
|
449
812
|
}
|
|
450
813
|
/**
|
|
451
|
-
*
|
|
814
|
+
* Get the generated CSS stylesheet.
|
|
815
|
+
* Automatically regenerates if locale has changed.
|
|
816
|
+
* This is pure logic - DOM injection is handled by framework layer.
|
|
452
817
|
*/
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
818
|
+
getStylesheet() {
|
|
819
|
+
var _a;
|
|
820
|
+
const currentLocale = ((_a = this.i18n) == null ? void 0 : _a.getLocale()) ?? null;
|
|
821
|
+
if (this.cachedStylesheet && this.cachedLocale === currentLocale) {
|
|
822
|
+
return this.cachedStylesheet;
|
|
823
|
+
}
|
|
824
|
+
this.cachedStylesheet = generateUIStylesheet(this.schema, {
|
|
825
|
+
config: this.stylesheetConfig,
|
|
826
|
+
locale: currentLocale ?? void 0
|
|
459
827
|
});
|
|
828
|
+
this.cachedLocale = currentLocale;
|
|
829
|
+
return this.cachedStylesheet;
|
|
460
830
|
}
|
|
461
831
|
/**
|
|
462
|
-
*
|
|
832
|
+
* Get the current locale (if i18n is available)
|
|
463
833
|
*/
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
const target = event.target;
|
|
468
|
-
if (target.tagName === "INPUT" || target.tagName === "TEXTAREA" || target.isContentEditable) {
|
|
469
|
-
return;
|
|
470
|
-
}
|
|
471
|
-
const shortcut = this.buildShortcutString(event);
|
|
472
|
-
if (shortcut && this.executeShortcut(shortcut)) {
|
|
473
|
-
event.preventDefault();
|
|
474
|
-
}
|
|
475
|
-
};
|
|
476
|
-
document.addEventListener("keydown", handleKeyDown);
|
|
834
|
+
getLocale() {
|
|
835
|
+
var _a;
|
|
836
|
+
return ((_a = this.i18n) == null ? void 0 : _a.getLocale()) ?? null;
|
|
477
837
|
}
|
|
478
838
|
/**
|
|
479
|
-
*
|
|
839
|
+
* Regenerate stylesheet (call after schema changes)
|
|
480
840
|
*/
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
841
|
+
invalidateStylesheet() {
|
|
842
|
+
this.cachedStylesheet = null;
|
|
843
|
+
}
|
|
844
|
+
onStylesheetInvalidated(listener) {
|
|
845
|
+
return this.stylesheetInvalidated$.on(listener);
|
|
846
|
+
}
|
|
847
|
+
// ─────────────────────────────────────────────────────────
|
|
848
|
+
// Category Management
|
|
849
|
+
// ─────────────────────────────────────────────────────────
|
|
850
|
+
disableCategoryImpl(category) {
|
|
851
|
+
const current = new Set(this.state.disabledCategories);
|
|
852
|
+
if (!current.has(category)) {
|
|
853
|
+
current.add(category);
|
|
854
|
+
this.dispatch(setDisabledCategories(Array.from(current)));
|
|
855
|
+
this.categoryChanged$.emit({ disabledCategories: Array.from(current) });
|
|
492
856
|
}
|
|
493
|
-
return null;
|
|
494
857
|
}
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
858
|
+
enableCategoryImpl(category) {
|
|
859
|
+
const current = new Set(this.state.disabledCategories);
|
|
860
|
+
if (current.has(category)) {
|
|
861
|
+
current.delete(category);
|
|
862
|
+
this.dispatch(setDisabledCategories(Array.from(current)));
|
|
863
|
+
this.categoryChanged$.emit({ disabledCategories: Array.from(current) });
|
|
864
|
+
}
|
|
500
865
|
}
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
866
|
+
toggleCategoryImpl(category) {
|
|
867
|
+
if (this.state.disabledCategories.includes(category)) {
|
|
868
|
+
this.enableCategoryImpl(category);
|
|
869
|
+
} else {
|
|
870
|
+
this.disableCategoryImpl(category);
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
setDisabledCategoriesImpl(categories) {
|
|
874
|
+
this.dispatch(setDisabledCategories(categories));
|
|
875
|
+
this.categoryChanged$.emit({ disabledCategories: categories });
|
|
876
|
+
}
|
|
877
|
+
// ─────────────────────────────────────────────────────────
|
|
878
|
+
// Capability
|
|
879
|
+
// ─────────────────────────────────────────────────────────
|
|
880
|
+
buildCapability() {
|
|
505
881
|
return {
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
882
|
+
// Active document operations
|
|
883
|
+
setActiveToolbar: (placement, slot, toolbarId, documentId) => this.setToolbarForDocument(placement, slot, toolbarId, documentId),
|
|
884
|
+
setActivePanel: (placement, slot, panelId, documentId, activeTab) => this.setPanelForDocument(placement, slot, panelId, documentId, activeTab),
|
|
885
|
+
togglePanel: (placement, slot, panelId, documentId, activeTab) => this.togglePanelForDocument(placement, slot, panelId, documentId, activeTab),
|
|
886
|
+
openModal: (modalId, documentId) => this.openModalForDocument(modalId, documentId),
|
|
887
|
+
openMenu: (menuId, triggeredByCommandId, triggeredByItemId, documentId) => this.openMenuForDocument(menuId, triggeredByCommandId, triggeredByItemId, documentId),
|
|
888
|
+
toggleMenu: (menuId, triggeredByCommandId, triggeredByItemId, documentId) => this.toggleMenuForDocument(menuId, triggeredByCommandId, triggeredByItemId, documentId),
|
|
889
|
+
// Document-scoped operations
|
|
890
|
+
forDocument: (documentId) => this.createUIScope(documentId),
|
|
891
|
+
// Schema
|
|
892
|
+
getSchema: () => this.schema,
|
|
893
|
+
mergeSchema: (partial) => {
|
|
894
|
+
this.schema = mergeUISchema(this.schema, partial);
|
|
895
|
+
},
|
|
896
|
+
// Category management
|
|
897
|
+
disableCategory: (category) => this.disableCategoryImpl(category),
|
|
898
|
+
enableCategory: (category) => this.enableCategoryImpl(category),
|
|
899
|
+
toggleCategory: (category) => this.toggleCategoryImpl(category),
|
|
900
|
+
setDisabledCategories: (categories) => this.setDisabledCategoriesImpl(categories),
|
|
901
|
+
getDisabledCategories: () => this.state.disabledCategories,
|
|
902
|
+
isCategoryDisabled: (category) => this.state.disabledCategories.includes(category),
|
|
903
|
+
// Events
|
|
904
|
+
onToolbarChanged: this.toolbarChanged$.onGlobal,
|
|
905
|
+
onPanelChanged: this.panelChanged$.onGlobal,
|
|
906
|
+
onModalChanged: this.modalChanged$.onGlobal,
|
|
907
|
+
onMenuChanged: this.menuChanged$.onGlobal,
|
|
908
|
+
onCategoryChanged: this.categoryChanged$.on
|
|
514
909
|
};
|
|
515
910
|
}
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
911
|
+
// ─────────────────────────────────────────────────────────
|
|
912
|
+
// Document Scoping
|
|
913
|
+
// ─────────────────────────────────────────────────────────
|
|
914
|
+
createUIScope(documentId) {
|
|
915
|
+
return {
|
|
916
|
+
// ───── Toolbars ─────
|
|
917
|
+
setActiveToolbar: (placement, slot, toolbarId) => this.setToolbarForDocument(placement, slot, toolbarId, documentId),
|
|
918
|
+
getActiveToolbar: (placement, slot) => this.getToolbarForDocument(placement, slot, documentId),
|
|
919
|
+
closeToolbarSlot: (placement, slot) => this.closeToolbarForDocument(placement, slot, documentId),
|
|
920
|
+
isToolbarOpen: (placement, slot, toolbarId) => this.isToolbarOpenForDocument(placement, slot, toolbarId, documentId),
|
|
921
|
+
// ───── Panels ─────
|
|
922
|
+
setActivePanel: (placement, slot, panelId, activeTab) => this.setPanelForDocument(placement, slot, panelId, documentId, activeTab),
|
|
923
|
+
getActivePanel: (placement, slot) => this.getPanelForDocument(placement, slot, documentId),
|
|
924
|
+
closePanelSlot: (placement, slot) => this.closePanelForDocument(placement, slot, documentId),
|
|
925
|
+
togglePanel: (placement, slot, panelId, activeTab) => this.togglePanelForDocument(placement, slot, panelId, documentId, activeTab),
|
|
926
|
+
isPanelOpen: (placement, slot, panelId) => this.isPanelOpenForDocument(placement, slot, panelId, documentId),
|
|
927
|
+
// ───── Panel tabs ─────
|
|
928
|
+
setPanelTab: (panelId, tabId) => this.setPanelTabForDocument(panelId, tabId, documentId),
|
|
929
|
+
getPanelTab: (panelId) => this.getPanelTabForDocument(panelId, documentId),
|
|
930
|
+
// ───── Modals ─────
|
|
931
|
+
openModal: (modalId) => this.openModalForDocument(modalId, documentId),
|
|
932
|
+
closeModal: () => this.closeModalForDocument(documentId),
|
|
933
|
+
getActiveModal: () => this.getActiveModalForDocument(documentId),
|
|
934
|
+
// ───── Menus ─────
|
|
935
|
+
openMenu: (menuId, triggeredByCommandId, triggeredByItemId) => this.openMenuForDocument(menuId, triggeredByCommandId, triggeredByItemId, documentId),
|
|
936
|
+
closeMenu: (menuId) => this.closeMenuForDocument(menuId, documentId),
|
|
937
|
+
toggleMenu: (menuId, triggeredByCommandId, triggeredByItemId) => this.toggleMenuForDocument(menuId, triggeredByCommandId, triggeredByItemId, documentId),
|
|
938
|
+
closeAllMenus: () => this.closeAllMenusForDocument(documentId),
|
|
939
|
+
isMenuOpen: (menuId) => this.isMenuOpenForDocument(menuId, documentId),
|
|
940
|
+
getOpenMenus: () => this.getOpenMenusForDocument(documentId),
|
|
941
|
+
// ───── Schema & state ─────
|
|
942
|
+
getSchema: () => this.schema,
|
|
943
|
+
getState: () => this.getDocumentStateOrThrow(documentId),
|
|
944
|
+
// ───── Scoped events ─────
|
|
945
|
+
onToolbarChanged: this.toolbarChanged$.forScope(documentId),
|
|
946
|
+
onPanelChanged: this.panelChanged$.forScope(documentId),
|
|
947
|
+
onModalChanged: this.modalChanged$.forScope(documentId),
|
|
948
|
+
onMenuChanged: this.menuChanged$.forScope(documentId)
|
|
531
949
|
};
|
|
532
|
-
this.config = config;
|
|
533
|
-
this.menuManager = new MenuManager(config.menuItems || {}, this.registry);
|
|
534
|
-
this.setupCommandEventHandlers();
|
|
535
|
-
this.globalStoreSubscription = this.registry.getStore().subscribe((_action, newState) => {
|
|
536
|
-
this.onGlobalStoreChange(newState);
|
|
537
|
-
});
|
|
538
950
|
}
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
setupCommandEventHandlers() {
|
|
546
|
-
this.menuManager.on(MenuManager.EVENTS.MENU_REQUESTED, (data) => {
|
|
547
|
-
var _a;
|
|
548
|
-
const { menuId, triggerElement, position, flatten } = data;
|
|
549
|
-
const isOpen = ((_a = this.state.commandMenu.commandMenu) == null ? void 0 : _a.activeCommand) === menuId;
|
|
550
|
-
if (isOpen) {
|
|
551
|
-
return this.dispatch(uiHideCommandMenu({ id: "commandMenu" }));
|
|
552
|
-
}
|
|
553
|
-
this.dispatch(
|
|
554
|
-
uiShowCommandMenu({
|
|
555
|
-
id: "commandMenu",
|
|
556
|
-
commandId: menuId,
|
|
557
|
-
triggerElement,
|
|
558
|
-
position,
|
|
559
|
-
flatten
|
|
560
|
-
})
|
|
561
|
-
);
|
|
562
|
-
});
|
|
563
|
-
this.menuManager.on(MenuManager.EVENTS.COMMAND_EXECUTED, (data) => {
|
|
564
|
-
this.logger.debug("UIPlugin", "CommandExecuted", `Command executed: ${data.command.id}`, {
|
|
565
|
-
commandId: data.command.id,
|
|
566
|
-
source: data.source
|
|
567
|
-
});
|
|
568
|
-
});
|
|
951
|
+
// ─────────────────────────────────────────────────────────
|
|
952
|
+
// State Helpers
|
|
953
|
+
// ─────────────────────────────────────────────────────────
|
|
954
|
+
getDocumentState(documentId) {
|
|
955
|
+
const id = documentId ?? this.getActiveDocumentId();
|
|
956
|
+
return this.state.documents[id] ?? null;
|
|
569
957
|
}
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
"ComponentAlreadyExists",
|
|
575
|
-
`Component with ID ${id} already exists and will be overwritten`
|
|
576
|
-
);
|
|
577
|
-
}
|
|
578
|
-
const component = new UIComponent(componentConfig, this.componentRenderers);
|
|
579
|
-
this.components[id] = component;
|
|
580
|
-
if (typeof componentConfig.mapStateToProps === "function") {
|
|
581
|
-
this.mapStateCallbacks[id] = componentConfig.mapStateToProps;
|
|
958
|
+
getDocumentStateOrThrow(documentId) {
|
|
959
|
+
const state = this.getDocumentState(documentId);
|
|
960
|
+
if (!state) {
|
|
961
|
+
throw new Error(`UI state not found for document: ${documentId ?? "active"}`);
|
|
582
962
|
}
|
|
583
|
-
return
|
|
963
|
+
return state;
|
|
584
964
|
}
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
965
|
+
// ─────────────────────────────────────────────────────────
|
|
966
|
+
// Core Operations - Toolbars
|
|
967
|
+
// ─────────────────────────────────────────────────────────
|
|
968
|
+
setToolbarForDocument(placement, slot, toolbarId, documentId) {
|
|
969
|
+
const id = documentId ?? this.getActiveDocumentId();
|
|
970
|
+
this.dispatch(setActiveToolbar(id, placement, slot, toolbarId));
|
|
971
|
+
this.toolbarChanged$.emit(id, { placement, slot, toolbarId });
|
|
589
972
|
}
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
const props = component.componentConfig;
|
|
595
|
-
(_a = props.slots) == null ? void 0 : _a.forEach((slot) => {
|
|
596
|
-
const child = this.components[slot.componentId];
|
|
597
|
-
if (child) {
|
|
598
|
-
component.addChild(slot.componentId, child, slot.priority, slot.className);
|
|
599
|
-
} else {
|
|
600
|
-
this.logger.warn(
|
|
601
|
-
"UIPlugin",
|
|
602
|
-
"ChildComponentNotFound",
|
|
603
|
-
`Child component ${slot.componentId} not found for GroupedItems ${props.id}`
|
|
604
|
-
);
|
|
605
|
-
}
|
|
606
|
-
});
|
|
607
|
-
}
|
|
608
|
-
});
|
|
973
|
+
getToolbarForDocument(placement, slot, documentId) {
|
|
974
|
+
const slotKey = `${placement}-${slot}`;
|
|
975
|
+
const toolbarSlot = this.getDocumentStateOrThrow(documentId).activeToolbars[slotKey];
|
|
976
|
+
return (toolbarSlot == null ? void 0 : toolbarSlot.isOpen) ? toolbarSlot.toolbarId : null;
|
|
609
977
|
}
|
|
610
|
-
|
|
611
|
-
const
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
defaultState[definition.type][componentId] = definition.initialState;
|
|
615
|
-
} else {
|
|
616
|
-
defaultState[definition.type][componentId] = {};
|
|
617
|
-
}
|
|
618
|
-
});
|
|
619
|
-
this.dispatch(uiInitComponents(defaultState));
|
|
620
|
-
}
|
|
621
|
-
onGlobalStoreChange(state) {
|
|
622
|
-
for (const [id, uiComponent] of Object.entries(this.components)) {
|
|
623
|
-
const mapFn = this.mapStateCallbacks[id];
|
|
624
|
-
if (!mapFn) continue;
|
|
625
|
-
const { id: _id, ...ownProps } = uiComponent.props;
|
|
626
|
-
const partial = mapFn(state, ownProps);
|
|
627
|
-
const merged = { ...ownProps, ...partial };
|
|
628
|
-
if (!arePropsEqual(ownProps, merged)) {
|
|
629
|
-
uiComponent.update(partial);
|
|
630
|
-
}
|
|
631
|
-
}
|
|
978
|
+
closeToolbarForDocument(placement, slot, documentId) {
|
|
979
|
+
const id = documentId ?? this.getActiveDocumentId();
|
|
980
|
+
this.dispatch(closeToolbarSlot(id, placement, slot));
|
|
981
|
+
this.toolbarChanged$.emit(id, { placement, slot, toolbarId: "" });
|
|
632
982
|
}
|
|
633
|
-
|
|
634
|
-
const
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
983
|
+
isToolbarOpenForDocument(placement, slot, toolbarId, documentId) {
|
|
984
|
+
const slotKey = `${placement}-${slot}`;
|
|
985
|
+
const toolbarSlot = this.getDocumentStateOrThrow(documentId).activeToolbars[slotKey];
|
|
986
|
+
if (!toolbarSlot || !toolbarSlot.isOpen) return false;
|
|
987
|
+
return toolbarId ? toolbarSlot.toolbarId === toolbarId : true;
|
|
988
|
+
}
|
|
989
|
+
// ─────────────────────────────────────────────────────────
|
|
990
|
+
// Core Operations - Panels
|
|
991
|
+
// ─────────────────────────────────────────────────────────
|
|
992
|
+
setPanelForDocument(placement, slot, panelId, documentId, activeTab) {
|
|
993
|
+
const id = documentId ?? this.getActiveDocumentId();
|
|
994
|
+
this.dispatch(setActivePanel(id, placement, slot, panelId, activeTab));
|
|
995
|
+
this.panelChanged$.emit(id, { placement, slot, panelId });
|
|
996
|
+
}
|
|
997
|
+
getPanelForDocument(placement, slot, documentId) {
|
|
998
|
+
const slotKey = `${placement}-${slot}`;
|
|
999
|
+
const panelSlot = this.getDocumentStateOrThrow(documentId).activePanels[slotKey];
|
|
1000
|
+
return (panelSlot == null ? void 0 : panelSlot.isOpen) ? panelSlot.panelId : null;
|
|
1001
|
+
}
|
|
1002
|
+
closePanelForDocument(placement, slot, documentId) {
|
|
1003
|
+
const id = documentId ?? this.getActiveDocumentId();
|
|
1004
|
+
this.dispatch(closePanelSlot(id, placement, slot));
|
|
1005
|
+
this.panelChanged$.emit(id, { placement, slot, panelId: "" });
|
|
1006
|
+
}
|
|
1007
|
+
togglePanelForDocument(placement, slot, panelId, documentId, activeTab) {
|
|
1008
|
+
const id = documentId ?? this.getActiveDocumentId();
|
|
1009
|
+
const slotKey = `${placement}-${slot}`;
|
|
1010
|
+
const panelSlot = this.getDocumentStateOrThrow(id).activePanels[slotKey];
|
|
1011
|
+
if ((panelSlot == null ? void 0 : panelSlot.panelId) === panelId && (panelSlot == null ? void 0 : panelSlot.isOpen)) {
|
|
1012
|
+
this.dispatch(closePanelSlot(id, placement, slot));
|
|
1013
|
+
this.panelChanged$.emit(id, { placement, slot, panelId: "" });
|
|
1014
|
+
} else {
|
|
1015
|
+
this.dispatch(setActivePanel(id, placement, slot, panelId, activeTab));
|
|
1016
|
+
this.panelChanged$.emit(id, { placement, slot, panelId });
|
|
659
1017
|
}
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
1018
|
+
}
|
|
1019
|
+
isPanelOpenForDocument(placement, slot, panelId, documentId) {
|
|
1020
|
+
const slotKey = `${placement}-${slot}`;
|
|
1021
|
+
const panelSlot = this.getDocumentStateOrThrow(documentId).activePanels[slotKey];
|
|
1022
|
+
if (!panelSlot || !panelSlot.isOpen) return false;
|
|
1023
|
+
return panelId ? panelSlot.panelId === panelId : true;
|
|
1024
|
+
}
|
|
1025
|
+
// ─────────────────────────────────────────────────────────
|
|
1026
|
+
// Core Operations - Panel Tabs
|
|
1027
|
+
// ─────────────────────────────────────────────────────────
|
|
1028
|
+
setPanelTabForDocument(panelId, tabId, documentId) {
|
|
1029
|
+
const id = documentId ?? this.getActiveDocumentId();
|
|
1030
|
+
this.dispatch(setPanelTab(id, panelId, tabId));
|
|
1031
|
+
}
|
|
1032
|
+
getPanelTabForDocument(panelId, documentId) {
|
|
1033
|
+
return this.getDocumentStateOrThrow(documentId).panelTabs[panelId] ?? null;
|
|
1034
|
+
}
|
|
1035
|
+
// ─────────────────────────────────────────────────────────
|
|
1036
|
+
// Core Operations - Modals
|
|
1037
|
+
// ─────────────────────────────────────────────────────────
|
|
1038
|
+
openModalForDocument(modalId, documentId) {
|
|
1039
|
+
const id = documentId ?? this.getActiveDocumentId();
|
|
1040
|
+
this.dispatch(openModal(id, modalId));
|
|
1041
|
+
this.modalChanged$.emit(id, { modalId });
|
|
1042
|
+
}
|
|
1043
|
+
closeModalForDocument(documentId) {
|
|
1044
|
+
const id = documentId ?? this.getActiveDocumentId();
|
|
1045
|
+
this.dispatch(closeModal(id));
|
|
1046
|
+
this.modalChanged$.emit(id, { modalId: null });
|
|
1047
|
+
}
|
|
1048
|
+
getActiveModalForDocument(documentId) {
|
|
1049
|
+
return this.getDocumentStateOrThrow(documentId).activeModal;
|
|
1050
|
+
}
|
|
1051
|
+
// ─────────────────────────────────────────────────────────
|
|
1052
|
+
// Core Operations - Menus
|
|
1053
|
+
// ─────────────────────────────────────────────────────────
|
|
1054
|
+
openMenuForDocument(menuId, triggeredByCommandId, triggeredByItemId, documentId) {
|
|
1055
|
+
const id = documentId ?? this.getActiveDocumentId();
|
|
1056
|
+
this.dispatch(openMenu(id, { menuId, triggeredByCommandId, triggeredByItemId }));
|
|
1057
|
+
this.menuChanged$.emit(id, { menuId, isOpen: true });
|
|
1058
|
+
}
|
|
1059
|
+
closeMenuForDocument(menuId, documentId) {
|
|
1060
|
+
const id = documentId ?? this.getActiveDocumentId();
|
|
1061
|
+
this.dispatch(closeMenu(id, menuId));
|
|
1062
|
+
this.menuChanged$.emit(id, { menuId, isOpen: false });
|
|
1063
|
+
}
|
|
1064
|
+
toggleMenuForDocument(menuId, triggeredByCommandId, triggeredByItemId, documentId) {
|
|
1065
|
+
const id = documentId ?? this.getActiveDocumentId();
|
|
1066
|
+
const isOpen = !!this.getDocumentStateOrThrow(id).openMenus[menuId];
|
|
1067
|
+
if (isOpen) {
|
|
1068
|
+
this.dispatch(closeMenu(id, menuId));
|
|
1069
|
+
this.menuChanged$.emit(id, { menuId, isOpen: false });
|
|
1070
|
+
} else {
|
|
1071
|
+
this.dispatch(openMenu(id, { menuId, triggeredByCommandId, triggeredByItemId }));
|
|
1072
|
+
this.menuChanged$.emit(id, { menuId, isOpen: true });
|
|
665
1073
|
}
|
|
666
|
-
parentComponent.addChild(slotId, childComponent, slotPriority, className);
|
|
667
1074
|
}
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
this.componentRenderers[type] = renderer;
|
|
672
|
-
},
|
|
673
|
-
getComponent: (id) => {
|
|
674
|
-
return this.components[id];
|
|
675
|
-
},
|
|
676
|
-
registerComponent: this.addComponent.bind(this),
|
|
677
|
-
getCommandMenu: () => Object.values(this.components).find((component) => isCommandMenuComponent(component)),
|
|
678
|
-
hideCommandMenu: () => this.cooldownDispatch(uiHideCommandMenu({ id: "commandMenu" }), 100),
|
|
679
|
-
getFloatingComponents: (scrollerPosition) => Object.values(this.components).filter((component) => isFloatingComponent(component)).filter(
|
|
680
|
-
(component) => !scrollerPosition || component.props.scrollerPosition === scrollerPosition
|
|
681
|
-
),
|
|
682
|
-
getHeadersByPlacement: (placement) => Object.values(this.components).filter((component) => isHeaderComponent(component)).filter((component) => component.props.placement === placement),
|
|
683
|
-
getPanelsByLocation: (location) => Object.values(this.components).filter((component) => isPanelComponent(component)).filter((component) => component.props.location === location),
|
|
684
|
-
addSlot: this.addSlot.bind(this),
|
|
685
|
-
togglePanel: (payload) => {
|
|
686
|
-
this.dispatch(uiTogglePanel(payload));
|
|
687
|
-
},
|
|
688
|
-
setHeaderVisible: (payload) => {
|
|
689
|
-
this.dispatch(uiSetHeaderVisible(payload));
|
|
690
|
-
},
|
|
691
|
-
updateComponentState: (payload) => {
|
|
692
|
-
this.dispatch(uiUpdateComponentState(payload));
|
|
693
|
-
},
|
|
694
|
-
...this.menuManager.capabilities()
|
|
695
|
-
};
|
|
1075
|
+
closeAllMenusForDocument(documentId) {
|
|
1076
|
+
const id = documentId ?? this.getActiveDocumentId();
|
|
1077
|
+
this.dispatch(closeAllMenus(id));
|
|
696
1078
|
}
|
|
697
|
-
|
|
698
|
-
this.
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
this.
|
|
1079
|
+
isMenuOpenForDocument(menuId, documentId) {
|
|
1080
|
+
return !!this.getDocumentStateOrThrow(documentId).openMenus[menuId];
|
|
1081
|
+
}
|
|
1082
|
+
getOpenMenusForDocument(documentId) {
|
|
1083
|
+
return Object.values(this.getDocumentStateOrThrow(documentId).openMenus);
|
|
702
1084
|
}
|
|
703
1085
|
};
|
|
704
1086
|
_UIPlugin.id = "ui";
|
|
705
1087
|
let UIPlugin = _UIPlugin;
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
}
|
|
709
|
-
|
|
710
|
-
|
|
1088
|
+
const initialDocumentState = {
|
|
1089
|
+
activeToolbars: {},
|
|
1090
|
+
activePanels: {},
|
|
1091
|
+
activeModal: null,
|
|
1092
|
+
openMenus: {},
|
|
1093
|
+
panelTabs: {}
|
|
1094
|
+
};
|
|
1095
|
+
const initialState = {
|
|
1096
|
+
documents: {},
|
|
1097
|
+
disabledCategories: []
|
|
1098
|
+
};
|
|
1099
|
+
const uiReducer = (state = initialState, action) => {
|
|
1100
|
+
switch (action.type) {
|
|
1101
|
+
case INIT_UI_STATE: {
|
|
1102
|
+
const { documentId, schema } = action.payload;
|
|
1103
|
+
const activeToolbars = {};
|
|
1104
|
+
Object.values(schema.toolbars).forEach((toolbar) => {
|
|
1105
|
+
if (toolbar.permanent && toolbar.position) {
|
|
1106
|
+
const slotKey = `${toolbar.position.placement}-${toolbar.position.slot}`;
|
|
1107
|
+
activeToolbars[slotKey] = {
|
|
1108
|
+
toolbarId: toolbar.id,
|
|
1109
|
+
isOpen: true
|
|
1110
|
+
// Permanent toolbars are always open
|
|
1111
|
+
};
|
|
1112
|
+
}
|
|
1113
|
+
});
|
|
1114
|
+
return {
|
|
1115
|
+
...state,
|
|
1116
|
+
documents: {
|
|
1117
|
+
...state.documents,
|
|
1118
|
+
[documentId]: {
|
|
1119
|
+
...initialDocumentState,
|
|
1120
|
+
activeToolbars
|
|
1121
|
+
// Initialize with permanent toolbars
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
};
|
|
1125
|
+
}
|
|
1126
|
+
case CLEANUP_UI_STATE: {
|
|
1127
|
+
const { documentId } = action.payload;
|
|
1128
|
+
const { [documentId]: removed, ...remaining } = state.documents;
|
|
1129
|
+
return {
|
|
1130
|
+
...state,
|
|
1131
|
+
documents: remaining
|
|
1132
|
+
};
|
|
1133
|
+
}
|
|
1134
|
+
case SET_ACTIVE_TOOLBAR: {
|
|
1135
|
+
const { documentId, placement, slot, toolbarId } = action.payload;
|
|
1136
|
+
const docState = state.documents[documentId] || initialDocumentState;
|
|
1137
|
+
const slotKey = `${placement}-${slot}`;
|
|
1138
|
+
return {
|
|
1139
|
+
...state,
|
|
1140
|
+
documents: {
|
|
1141
|
+
...state.documents,
|
|
1142
|
+
[documentId]: {
|
|
1143
|
+
...docState,
|
|
1144
|
+
activeToolbars: {
|
|
1145
|
+
...docState.activeToolbars,
|
|
1146
|
+
[slotKey]: {
|
|
1147
|
+
toolbarId,
|
|
1148
|
+
isOpen: true
|
|
1149
|
+
}
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
}
|
|
1153
|
+
};
|
|
1154
|
+
}
|
|
1155
|
+
case SET_ACTIVE_PANEL: {
|
|
1156
|
+
const { documentId, placement, slot, panelId, activeTab } = action.payload;
|
|
1157
|
+
const docState = state.documents[documentId] || initialDocumentState;
|
|
1158
|
+
const slotKey = `${placement}-${slot}`;
|
|
1159
|
+
return {
|
|
1160
|
+
...state,
|
|
1161
|
+
documents: {
|
|
1162
|
+
...state.documents,
|
|
1163
|
+
[documentId]: {
|
|
1164
|
+
...docState,
|
|
1165
|
+
activePanels: {
|
|
1166
|
+
...docState.activePanels,
|
|
1167
|
+
[slotKey]: {
|
|
1168
|
+
panelId,
|
|
1169
|
+
isOpen: true
|
|
1170
|
+
}
|
|
1171
|
+
},
|
|
1172
|
+
...activeTab && {
|
|
1173
|
+
panelTabs: {
|
|
1174
|
+
...docState.panelTabs,
|
|
1175
|
+
[panelId]: activeTab
|
|
1176
|
+
}
|
|
1177
|
+
}
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
};
|
|
1181
|
+
}
|
|
1182
|
+
case CLOSE_PANEL_SLOT: {
|
|
1183
|
+
const { documentId, placement, slot } = action.payload;
|
|
1184
|
+
const docState = state.documents[documentId];
|
|
1185
|
+
if (!docState) return state;
|
|
1186
|
+
const slotKey = `${placement}-${slot}`;
|
|
1187
|
+
const panelSlot = docState.activePanels[slotKey];
|
|
1188
|
+
if (!panelSlot) return state;
|
|
1189
|
+
return {
|
|
1190
|
+
...state,
|
|
1191
|
+
documents: {
|
|
1192
|
+
...state.documents,
|
|
1193
|
+
[documentId]: {
|
|
1194
|
+
...docState,
|
|
1195
|
+
activePanels: {
|
|
1196
|
+
...docState.activePanels,
|
|
1197
|
+
[slotKey]: {
|
|
1198
|
+
...panelSlot,
|
|
1199
|
+
isOpen: false
|
|
1200
|
+
// Keep panel, just close it
|
|
1201
|
+
}
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1205
|
+
};
|
|
1206
|
+
}
|
|
1207
|
+
case CLOSE_TOOLBAR_SLOT: {
|
|
1208
|
+
const { documentId, placement, slot } = action.payload;
|
|
1209
|
+
const docState = state.documents[documentId];
|
|
1210
|
+
if (!docState) return state;
|
|
1211
|
+
const slotKey = `${placement}-${slot}`;
|
|
1212
|
+
const toolbarSlot = docState.activeToolbars[slotKey];
|
|
1213
|
+
if (!toolbarSlot) return state;
|
|
1214
|
+
return {
|
|
1215
|
+
...state,
|
|
1216
|
+
documents: {
|
|
1217
|
+
...state.documents,
|
|
1218
|
+
[documentId]: {
|
|
1219
|
+
...docState,
|
|
1220
|
+
activeToolbars: {
|
|
1221
|
+
...docState.activeToolbars,
|
|
1222
|
+
[slotKey]: {
|
|
1223
|
+
...toolbarSlot,
|
|
1224
|
+
isOpen: false
|
|
1225
|
+
// Keep toolbar, just close it
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
}
|
|
1230
|
+
};
|
|
1231
|
+
}
|
|
1232
|
+
case SET_PANEL_TAB: {
|
|
1233
|
+
const { documentId, panelId, tabId } = action.payload;
|
|
1234
|
+
const docState = state.documents[documentId] || initialDocumentState;
|
|
1235
|
+
return {
|
|
1236
|
+
...state,
|
|
1237
|
+
documents: {
|
|
1238
|
+
...state.documents,
|
|
1239
|
+
[documentId]: {
|
|
1240
|
+
...docState,
|
|
1241
|
+
panelTabs: {
|
|
1242
|
+
...docState.panelTabs,
|
|
1243
|
+
[panelId]: tabId
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
1247
|
+
};
|
|
1248
|
+
}
|
|
1249
|
+
case OPEN_MODAL: {
|
|
1250
|
+
const { documentId, modalId } = action.payload;
|
|
1251
|
+
const docState = state.documents[documentId] || initialDocumentState;
|
|
1252
|
+
return {
|
|
1253
|
+
...state,
|
|
1254
|
+
documents: {
|
|
1255
|
+
...state.documents,
|
|
1256
|
+
[documentId]: {
|
|
1257
|
+
...docState,
|
|
1258
|
+
activeModal: modalId,
|
|
1259
|
+
openMenus: {}
|
|
1260
|
+
// Close all menus when opening modal
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1263
|
+
};
|
|
1264
|
+
}
|
|
1265
|
+
case CLOSE_MODAL: {
|
|
1266
|
+
const { documentId } = action.payload;
|
|
1267
|
+
const docState = state.documents[documentId];
|
|
1268
|
+
if (!docState) return state;
|
|
1269
|
+
return {
|
|
1270
|
+
...state,
|
|
1271
|
+
documents: {
|
|
1272
|
+
...state.documents,
|
|
1273
|
+
[documentId]: {
|
|
1274
|
+
...docState,
|
|
1275
|
+
activeModal: null
|
|
1276
|
+
}
|
|
1277
|
+
}
|
|
1278
|
+
};
|
|
1279
|
+
}
|
|
1280
|
+
case OPEN_MENU: {
|
|
1281
|
+
const { documentId, menuState } = action.payload;
|
|
1282
|
+
const docState = state.documents[documentId] || initialDocumentState;
|
|
1283
|
+
return {
|
|
1284
|
+
...state,
|
|
1285
|
+
documents: {
|
|
1286
|
+
...state.documents,
|
|
1287
|
+
[documentId]: {
|
|
1288
|
+
...docState,
|
|
1289
|
+
openMenus: {
|
|
1290
|
+
// Close other menus, open this one
|
|
1291
|
+
[menuState.menuId]: menuState
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1294
|
+
}
|
|
1295
|
+
};
|
|
1296
|
+
}
|
|
1297
|
+
case CLOSE_MENU: {
|
|
1298
|
+
const { documentId, menuId } = action.payload;
|
|
1299
|
+
const docState = state.documents[documentId];
|
|
1300
|
+
if (!docState) return state;
|
|
1301
|
+
const { [menuId]: removed, ...remainingMenus } = docState.openMenus;
|
|
1302
|
+
return {
|
|
1303
|
+
...state,
|
|
1304
|
+
documents: {
|
|
1305
|
+
...state.documents,
|
|
1306
|
+
[documentId]: {
|
|
1307
|
+
...docState,
|
|
1308
|
+
openMenus: remainingMenus
|
|
1309
|
+
}
|
|
1310
|
+
}
|
|
1311
|
+
};
|
|
1312
|
+
}
|
|
1313
|
+
case CLOSE_ALL_MENUS: {
|
|
1314
|
+
const { documentId } = action.payload;
|
|
1315
|
+
const docState = state.documents[documentId];
|
|
1316
|
+
if (!docState) return state;
|
|
1317
|
+
return {
|
|
1318
|
+
...state,
|
|
1319
|
+
documents: {
|
|
1320
|
+
...state.documents,
|
|
1321
|
+
[documentId]: {
|
|
1322
|
+
...docState,
|
|
1323
|
+
openMenus: {}
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
};
|
|
1327
|
+
}
|
|
1328
|
+
case SET_DISABLED_CATEGORIES: {
|
|
1329
|
+
return {
|
|
1330
|
+
...state,
|
|
1331
|
+
disabledCategories: action.payload.categories
|
|
1332
|
+
};
|
|
1333
|
+
}
|
|
1334
|
+
default:
|
|
1335
|
+
return state;
|
|
1336
|
+
}
|
|
1337
|
+
};
|
|
1338
|
+
function selectUIState(plugins) {
|
|
1339
|
+
return plugins["ui"] ?? null;
|
|
711
1340
|
}
|
|
712
|
-
function
|
|
713
|
-
|
|
1341
|
+
function selectUIDocumentState(plugins, documentId) {
|
|
1342
|
+
const ui = selectUIState(plugins);
|
|
1343
|
+
return (ui == null ? void 0 : ui.documents[documentId]) ?? null;
|
|
714
1344
|
}
|
|
715
|
-
function
|
|
716
|
-
return
|
|
1345
|
+
function makeSlotKey(placement, slot) {
|
|
1346
|
+
return `${placement}-${slot}`;
|
|
717
1347
|
}
|
|
718
|
-
function
|
|
719
|
-
|
|
1348
|
+
function selectToolbarSlot(plugins, documentId, placement, slot) {
|
|
1349
|
+
const doc = selectUIDocumentState(plugins, documentId);
|
|
1350
|
+
if (!doc) return null;
|
|
1351
|
+
return doc.activeToolbars[makeSlotKey(placement, slot)] ?? null;
|
|
720
1352
|
}
|
|
721
|
-
function
|
|
722
|
-
|
|
1353
|
+
function isToolbarOpen(plugins, documentId, placement, slot, toolbarId) {
|
|
1354
|
+
const slotState = selectToolbarSlot(plugins, documentId, placement, slot);
|
|
1355
|
+
if (!slotState || !slotState.isOpen) return false;
|
|
1356
|
+
return toolbarId ? slotState.toolbarId === toolbarId : true;
|
|
723
1357
|
}
|
|
724
|
-
function
|
|
725
|
-
|
|
1358
|
+
function selectPanelSlot(plugins, documentId, placement, slot) {
|
|
1359
|
+
const doc = selectUIDocumentState(plugins, documentId);
|
|
1360
|
+
if (!doc) return null;
|
|
1361
|
+
return doc.activePanels[makeSlotKey(placement, slot)] ?? null;
|
|
726
1362
|
}
|
|
727
|
-
|
|
728
|
-
const
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
version: "1.0.0",
|
|
732
|
-
provides: ["ui"],
|
|
733
|
-
requires: [],
|
|
734
|
-
optional: [],
|
|
735
|
-
defaultConfig: {
|
|
736
|
-
enabled: true,
|
|
737
|
-
components: {}
|
|
738
|
-
}
|
|
739
|
-
};
|
|
740
|
-
function hasActive(command) {
|
|
741
|
-
return "active" in command;
|
|
1363
|
+
function isPanelOpen(plugins, documentId, placement, slot, panelId) {
|
|
1364
|
+
const slotState = selectPanelSlot(plugins, documentId, placement, slot);
|
|
1365
|
+
if (!slotState || !slotState.isOpen) return false;
|
|
1366
|
+
return panelId ? slotState.panelId === panelId : true;
|
|
742
1367
|
}
|
|
743
1368
|
const UIPluginPackage = {
|
|
744
1369
|
manifest,
|
|
@@ -747,18 +1372,51 @@ const UIPluginPackage = {
|
|
|
747
1372
|
initialState
|
|
748
1373
|
};
|
|
749
1374
|
export {
|
|
750
|
-
|
|
1375
|
+
CLEANUP_UI_STATE,
|
|
1376
|
+
CLOSE_ALL_MENUS,
|
|
1377
|
+
CLOSE_MENU,
|
|
1378
|
+
CLOSE_MODAL,
|
|
1379
|
+
CLOSE_PANEL_SLOT,
|
|
1380
|
+
CLOSE_TOOLBAR_SLOT,
|
|
1381
|
+
INIT_UI_STATE,
|
|
1382
|
+
OPEN_MENU,
|
|
1383
|
+
OPEN_MODAL,
|
|
1384
|
+
SET_ACTIVE_PANEL,
|
|
1385
|
+
SET_ACTIVE_TOOLBAR,
|
|
1386
|
+
SET_DISABLED_CATEGORIES,
|
|
1387
|
+
SET_PANEL_TAB,
|
|
751
1388
|
UIPlugin,
|
|
752
1389
|
UIPluginPackage,
|
|
1390
|
+
UI_ATTRIBUTES,
|
|
753
1391
|
UI_PLUGIN_ID,
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
1392
|
+
UI_SELECTORS,
|
|
1393
|
+
cleanupUIState,
|
|
1394
|
+
closeAllMenus,
|
|
1395
|
+
closeMenu,
|
|
1396
|
+
closeModal,
|
|
1397
|
+
closePanelSlot,
|
|
1398
|
+
closeToolbarSlot,
|
|
1399
|
+
extractCategories,
|
|
1400
|
+
generateUIStylesheet,
|
|
1401
|
+
getItemResponsiveMetadata,
|
|
1402
|
+
getStylesheetConfig,
|
|
1403
|
+
getUIItemProps,
|
|
1404
|
+
initUIState,
|
|
1405
|
+
isPanelOpen,
|
|
1406
|
+
isToolbarOpen,
|
|
761
1407
|
manifest,
|
|
762
|
-
|
|
1408
|
+
mergeUISchema,
|
|
1409
|
+
openMenu,
|
|
1410
|
+
openModal,
|
|
1411
|
+
removeFromSchema,
|
|
1412
|
+
resolveResponsiveMetadata,
|
|
1413
|
+
selectPanelSlot,
|
|
1414
|
+
selectToolbarSlot,
|
|
1415
|
+
selectUIDocumentState,
|
|
1416
|
+
selectUIState,
|
|
1417
|
+
setActivePanel,
|
|
1418
|
+
setActiveToolbar,
|
|
1419
|
+
setDisabledCategories,
|
|
1420
|
+
setPanelTab
|
|
763
1421
|
};
|
|
764
1422
|
//# sourceMappingURL=index.js.map
|