@zolomedia/bifrost-client 1.7.74
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/L1_Foundation/L1_Foundation.js +13 -0
- package/L1_Foundation/bootstrap/bootstrap.js +11 -0
- package/L1_Foundation/bootstrap/bootstrap_hooks.js +123 -0
- package/L1_Foundation/bootstrap/bootstrap_index.js +15 -0
- package/L1_Foundation/bootstrap/bootstrap_logger.js +135 -0
- package/L1_Foundation/bootstrap/cdn_loader.js +217 -0
- package/L1_Foundation/bootstrap/module_registry.js +102 -0
- package/L1_Foundation/bootstrap/prism_loader.js +164 -0
- package/L1_Foundation/config/client_config.js +110 -0
- package/L1_Foundation/config/config.js +7 -0
- package/L1_Foundation/connection/connection.js +8 -0
- package/L1_Foundation/connection/websocket_connection.js +122 -0
- package/L1_Foundation/constants/bifrost_constants.js +284 -0
- package/L1_Foundation/constants/constants.js +7 -0
- package/L1_Foundation/logger/logger.js +10 -0
- package/L2_Handling/L2_Handling.js +15 -0
- package/L2_Handling/cache/cache.js +22 -0
- package/L2_Handling/cache/cache_constants.js +69 -0
- package/L2_Handling/cache/orchestration/cache_manager.js +299 -0
- package/L2_Handling/cache/orchestration/cache_orchestrator.js +260 -0
- package/L2_Handling/cache/orchestration/orchestration.js +12 -0
- package/L2_Handling/cache/storage/session_manager.js +289 -0
- package/L2_Handling/cache/storage/storage.js +10 -0
- package/L2_Handling/cache/storage/storage_manager.js +590 -0
- package/L2_Handling/display/composite/composite.js +13 -0
- package/L2_Handling/display/composite/dashboard_renderer.js +221 -0
- package/L2_Handling/display/composite/swiper_renderer.js +564 -0
- package/L2_Handling/display/composite/terminal_renderer.js +922 -0
- package/L2_Handling/display/composite/wizard_conditional_renderer.js +274 -0
- package/L2_Handling/display/display.js +30 -0
- package/L2_Handling/display/feedback/feedback.js +11 -0
- package/L2_Handling/display/feedback/progressbar_renderer.js +418 -0
- package/L2_Handling/display/feedback/spinner_renderer.js +246 -0
- package/L2_Handling/display/inputs/button_renderer.js +634 -0
- package/L2_Handling/display/inputs/form_renderer.js +583 -0
- package/L2_Handling/display/inputs/input_renderer.js +658 -0
- package/L2_Handling/display/inputs/inputs.js +12 -0
- package/L2_Handling/display/navigation/menu_renderer.js +206 -0
- package/L2_Handling/display/navigation/navigation.js +11 -0
- package/L2_Handling/display/navigation/navigation_renderer.js +703 -0
- package/L2_Handling/display/orchestration/orchestration.js +11 -0
- package/L2_Handling/display/orchestration/renderer.js +430 -0
- package/L2_Handling/display/orchestration/zdisplay_orchestrator.js +1759 -0
- package/L2_Handling/display/outputs/alert_renderer.js +161 -0
- package/L2_Handling/display/outputs/audio_renderer.js +94 -0
- package/L2_Handling/display/outputs/card_renderer.js +229 -0
- package/L2_Handling/display/outputs/code_renderer.js +66 -0
- package/L2_Handling/display/outputs/dl_renderer.js +131 -0
- package/L2_Handling/display/outputs/header_renderer.js +162 -0
- package/L2_Handling/display/outputs/icon_renderer.js +107 -0
- package/L2_Handling/display/outputs/image_renderer.js +145 -0
- package/L2_Handling/display/outputs/list_renderer.js +190 -0
- package/L2_Handling/display/outputs/outputs.js +19 -0
- package/L2_Handling/display/outputs/table_renderer.js +765 -0
- package/L2_Handling/display/outputs/text_renderer.js +818 -0
- package/L2_Handling/display/outputs/typography_renderer.js +293 -0
- package/L2_Handling/display/outputs/video_renderer.js +116 -0
- package/L2_Handling/display/primitives/document_structure_primitives.js +319 -0
- package/L2_Handling/display/primitives/form_primitives.js +526 -0
- package/L2_Handling/display/primitives/generic_containers.js +109 -0
- package/L2_Handling/display/primitives/interactive_primitives.js +305 -0
- package/L2_Handling/display/primitives/link_primitives.js +552 -0
- package/L2_Handling/display/primitives/lists_primitives.js +262 -0
- package/L2_Handling/display/primitives/media_primitives.js +383 -0
- package/L2_Handling/display/primitives/primitives.js +19 -0
- package/L2_Handling/display/primitives/semantic_element_primitive.js +226 -0
- package/L2_Handling/display/primitives/table_primitives.js +528 -0
- package/L2_Handling/display/primitives/typography_primitives.js +175 -0
- package/L2_Handling/display/specialized/input_request_renderer.js +467 -0
- package/L2_Handling/display/specialized/specialized.js +10 -0
- package/L2_Handling/hooks/hooks.js +9 -0
- package/L2_Handling/hooks/menu_integration.js +57 -0
- package/L2_Handling/hooks/widget_hook_manager.js +292 -0
- package/L2_Handling/message/message.js +8 -0
- package/L2_Handling/message/message_handler.js +701 -0
- package/L2_Handling/navigation/navigation.js +8 -0
- package/L2_Handling/navigation/navigation_manager.js +403 -0
- package/L2_Handling/zhooks/features/cache_live.js +287 -0
- package/L2_Handling/zhooks/features/crumbs_live.js +292 -0
- package/L2_Handling/zhooks/zhooks_manager.js +65 -0
- package/L2_Handling/zvaf/zvaf.js +8 -0
- package/L2_Handling/zvaf/zvaf_manager.js +334 -0
- package/L3_Abstraction/L3_Abstraction.js +12 -0
- package/L3_Abstraction/orchestrator/container_unwrapper.js +101 -0
- package/L3_Abstraction/orchestrator/group_renderer.js +698 -0
- package/L3_Abstraction/orchestrator/input_event_handler.js +797 -0
- package/L3_Abstraction/orchestrator/metadata_processor.js +249 -0
- package/L3_Abstraction/orchestrator/navbar_builder.js +201 -0
- package/L3_Abstraction/orchestrator/orchestrator.js +13 -0
- package/L3_Abstraction/orchestrator/wizard_gate_handler.js +360 -0
- package/L3_Abstraction/renderer/renderer.js +1 -0
- package/L3_Abstraction/session/session.js +1 -0
- package/L4_Orchestration/L4_Orchestration.js +11 -0
- package/L4_Orchestration/client/client.js +1 -0
- package/L4_Orchestration/facade/facade.js +9 -0
- package/L4_Orchestration/facade/manager_registry.js +118 -0
- package/L4_Orchestration/facade/renderer_registry.js +274 -0
- package/L4_Orchestration/lifecycle/asset_loader.js +255 -0
- package/L4_Orchestration/lifecycle/initializer.js +135 -0
- package/L4_Orchestration/lifecycle/lifecycle.js +8 -0
- package/L4_Orchestration/rendering/facade.js +94 -0
- package/L4_Orchestration/rendering/rendering.js +7 -0
- package/LICENSE +21 -0
- package/README.md +82 -0
- package/bifrost_client.js +204 -0
- package/bifrost_core.js +1686 -0
- package/docs/ARCHITECTURE.md +111 -0
- package/docs/PROTOCOL.md +106 -0
- package/docs/RENDERERS.md +101 -0
- package/docs/SECURITY.md +92 -0
- package/package.json +24 -0
- package/syntax/prism-zconfig.js +41 -0
- package/syntax/prism-zenv.js +69 -0
- package/syntax/prism-zolo-theme.css +288 -0
- package/syntax/prism-zolo.js +380 -0
- package/syntax/prism-zschema.js +38 -0
- package/syntax/prism-zspark.js +25 -0
- package/syntax/prism-zui.js +68 -0
- package/zSys/accessibility/accessibility.js +10 -0
- package/zSys/accessibility/emoji_accessibility.js +173 -0
- package/zSys/dom/block_utils.js +122 -0
- package/zSys/dom/container_utils.js +370 -0
- package/zSys/dom/dom.js +13 -0
- package/zSys/dom/dom_utils.js +328 -0
- package/zSys/dom/encoding_utils.js +117 -0
- package/zSys/dom/style_utils.js +71 -0
- package/zSys/errors/error_display.js +299 -0
- package/zSys/errors/errors.js +10 -0
- package/zSys/theme/color_utils.js +274 -0
- package/zSys/theme/dark_mode_utils.js +272 -0
- package/zSys/theme/size_utils.js +256 -0
- package/zSys/theme/spacing_utils.js +405 -0
- package/zSys/theme/theme.js +14 -0
- package/zSys/theme/zbase.css +1735 -0
- package/zSys/theme/zbase_inject.js +161 -0
- package/zSys/theme/ztheme_utils.js +305 -0
- package/zSys/validation/error_boundary.js +201 -0
- package/zSys/validation/validation.js +11 -0
- package/zSys/validation/validation_utils.js +238 -0
- package/zSys/zSys.js +14 -0
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DashboardRenderer — zTheme native tab layout for zDash
|
|
3
|
+
*
|
|
4
|
+
* Structure:
|
|
5
|
+
* .zDash-container
|
|
6
|
+
* .zRow.zG-0
|
|
7
|
+
* .zCol-auto → nav.zNav.zFlex-column.zNav-pills.zDash-sidebar [role=tablist]
|
|
8
|
+
* .zCol → .zTab-content.zDash-panel
|
|
9
|
+
* .zTab-pane#panel-{Name} (one per sidebar item)
|
|
10
|
+
*
|
|
11
|
+
* Tab switching:
|
|
12
|
+
* - The renderer owns click→activate (set .zActive on link + .zTab-pane). It
|
|
13
|
+
* does NOT rely on window.zTheme.initTabs(), which can be the host page's
|
|
14
|
+
* external theme at render time and leave panes unwired (race).
|
|
15
|
+
* - zdisplay_orchestrator.js targets .zDash-panel .zTab-pane.zActive for rendering
|
|
16
|
+
*
|
|
17
|
+
* Content loading:
|
|
18
|
+
* - Default panel: deferred WS execute_walker on init (setTimeout 0)
|
|
19
|
+
* - Other panels: lazy-loaded via WS on first click (once per pane)
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import { createDiv } from '../primitives/generic_containers.js';
|
|
23
|
+
|
|
24
|
+
export default class DashboardRenderer {
|
|
25
|
+
constructor(logger, client) {
|
|
26
|
+
this.logger = logger;
|
|
27
|
+
this.client = client;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// ── Public API ──────────────────────────────────────────────────────────────
|
|
31
|
+
|
|
32
|
+
async render(config, targetElement) {
|
|
33
|
+
const { folder, sidebar, panels = {}, default: defaultPanel, type = 'sidebar', _zClass } = config;
|
|
34
|
+
this.logger.log('[DashboardRenderer] render config:', config);
|
|
35
|
+
|
|
36
|
+
const container = this._buildStructure(sidebar, panels, defaultPanel, type);
|
|
37
|
+
// Apply _zClass from zUI onto the container (e.g. _zClass: crm-dashboard)
|
|
38
|
+
if (_zClass) {
|
|
39
|
+
_zClass.split(/[\s,]+/).filter(Boolean).forEach(c => container.classList.add(c));
|
|
40
|
+
}
|
|
41
|
+
const nav = container.querySelector('.zDash-sidebar');
|
|
42
|
+
const tabContent = container.querySelector('.zDash-panel');
|
|
43
|
+
const toggleBtn = container.querySelector('.zDash-sidebar-toggle');
|
|
44
|
+
|
|
45
|
+
if (targetElement) {
|
|
46
|
+
targetElement.appendChild(container);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Wire mobile sidebar toggle (hamburger)
|
|
50
|
+
if (toggleBtn) {
|
|
51
|
+
toggleBtn.addEventListener('click', (e) => {
|
|
52
|
+
e.stopPropagation();
|
|
53
|
+
container.classList.toggle('zDash-sidebar-open');
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// Close sidebar on outside click
|
|
57
|
+
document.addEventListener('click', (e) => {
|
|
58
|
+
if (!container.contains(e.target)) {
|
|
59
|
+
container.classList.remove('zDash-sidebar-open');
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// ── Tab switching + lazy panel load — OWNED by the renderer ───────────────
|
|
65
|
+
// We deliberately do NOT depend on window.zTheme.initTabs() here. The host
|
|
66
|
+
// page (zVaF.html) loads its own ztheme.js, so at render time window.zTheme
|
|
67
|
+
// can be that *external* theme whose initTabs() doesn't wire zBifrost panes;
|
|
68
|
+
// zBifrost's own initTabs only becomes active after injectZBase swaps the
|
|
69
|
+
// global in — which races behind this render and leaves links unwired.
|
|
70
|
+
// Owning the click here makes zDash navigation deterministic regardless of
|
|
71
|
+
// which theme is on window.zTheme.
|
|
72
|
+
const links = nav ? [...nav.querySelectorAll('[data-bs-toggle="tab"]')] : [];
|
|
73
|
+
|
|
74
|
+
const _activatePane = (panelName) => {
|
|
75
|
+
links.forEach((l) => {
|
|
76
|
+
const on = l.dataset.panel === panelName;
|
|
77
|
+
l.classList.toggle('zActive', on);
|
|
78
|
+
l.setAttribute('aria-selected', on ? 'true' : 'false');
|
|
79
|
+
if (on) l.removeAttribute('tabindex'); else l.setAttribute('tabindex', '-1');
|
|
80
|
+
});
|
|
81
|
+
tabContent?.querySelectorAll('.zTab-pane').forEach((p) => {
|
|
82
|
+
const on = p.id === `panel-${panelName}`;
|
|
83
|
+
p.classList.toggle('zActive', on);
|
|
84
|
+
if (on) {
|
|
85
|
+
requestAnimationFrame(() => p.classList.add('zShow'));
|
|
86
|
+
} else {
|
|
87
|
+
p.classList.remove('zShow');
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
links.forEach((link) => {
|
|
93
|
+
link.addEventListener('click', async (e) => {
|
|
94
|
+
e.preventDefault();
|
|
95
|
+
const panelName = link.dataset.panel;
|
|
96
|
+
container.classList.remove('zDash-sidebar-open');
|
|
97
|
+
_activatePane(panelName);
|
|
98
|
+
const pane = tabContent?.querySelector(`#panel-${panelName}`);
|
|
99
|
+
if (pane && !pane.dataset.loaded) {
|
|
100
|
+
await this._loadPanel(folder, panelName, pane);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// Load default panel once in the DOM
|
|
106
|
+
const defaultPaneName = defaultPanel || (sidebar?.[0] ?? null);
|
|
107
|
+
if (defaultPaneName) {
|
|
108
|
+
setTimeout(() => {
|
|
109
|
+
const pane = tabContent?.querySelector(`#panel-${defaultPaneName}`);
|
|
110
|
+
if (pane && !pane.dataset.loaded) {
|
|
111
|
+
this._loadPanel(folder, defaultPaneName, pane);
|
|
112
|
+
}
|
|
113
|
+
}, 0);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return container;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// ── Private helpers ─────────────────────────────────────────────────────────
|
|
120
|
+
|
|
121
|
+
_buildStructure(sidebar, panels, defaultPanel, type = 'sidebar') {
|
|
122
|
+
const container = createDiv({ class: `zContainer-fluid zDash-container zDash-format-${type}` });
|
|
123
|
+
const row = createDiv({ class: 'zRow zG-0' });
|
|
124
|
+
const sidebarCol = createDiv({ class: 'zCol-auto' });
|
|
125
|
+
const contentCol = createDiv({ class: 'zCol' });
|
|
126
|
+
|
|
127
|
+
const nav = document.createElement('nav');
|
|
128
|
+
nav.className = 'zNav zFlex-column zNav-pills zDash-sidebar';
|
|
129
|
+
nav.setAttribute('role', 'tablist');
|
|
130
|
+
|
|
131
|
+
const tabContent = createDiv({ class: 'zTab-content zDash-panel' });
|
|
132
|
+
|
|
133
|
+
(sidebar || []).forEach((panelName) => {
|
|
134
|
+
const isDefault = panelName === defaultPanel;
|
|
135
|
+
const meta = panels[panelName] || {};
|
|
136
|
+
const label = meta.label || panelName.replace(/_/g, ' ');
|
|
137
|
+
const paneId = `panel-${panelName}`;
|
|
138
|
+
|
|
139
|
+
// Nav link — zTheme uses data-bs-target to show/hide panes
|
|
140
|
+
const link = document.createElement('a');
|
|
141
|
+
link.className = `zNav-link${isDefault ? ' zActive' : ''}`;
|
|
142
|
+
link.href = `#${paneId}`;
|
|
143
|
+
link.setAttribute('data-bs-toggle', 'tab');
|
|
144
|
+
link.setAttribute('data-bs-target', `#${paneId}`);
|
|
145
|
+
link.setAttribute('role', 'tab');
|
|
146
|
+
link.setAttribute('aria-selected', isDefault ? 'true' : 'false');
|
|
147
|
+
link.dataset.panel = panelName;
|
|
148
|
+
if (!isDefault) link.setAttribute('tabindex', '-1');
|
|
149
|
+
|
|
150
|
+
if (meta.icon) {
|
|
151
|
+
const icon = document.createElement('i');
|
|
152
|
+
icon.className = `bi ${meta.icon} zme-2`;
|
|
153
|
+
link.appendChild(icon);
|
|
154
|
+
}
|
|
155
|
+
link.appendChild(document.createTextNode(label));
|
|
156
|
+
nav.appendChild(link);
|
|
157
|
+
|
|
158
|
+
// Tab pane — chunk renderer targets .zDash-panel .zTab-pane.zActive
|
|
159
|
+
const pane = createDiv({
|
|
160
|
+
id: paneId,
|
|
161
|
+
class: `zTab-pane${isDefault ? ' zActive' : ''}`,
|
|
162
|
+
role: 'tabpanel',
|
|
163
|
+
});
|
|
164
|
+
pane.dataset.panel = panelName;
|
|
165
|
+
tabContent.appendChild(pane);
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
// Mobile hamburger — visible only on small viewports via CSS
|
|
169
|
+
const toggleBtn = document.createElement('button');
|
|
170
|
+
toggleBtn.className = 'zDash-sidebar-toggle';
|
|
171
|
+
toggleBtn.setAttribute('aria-label', 'Toggle navigation');
|
|
172
|
+
toggleBtn.setAttribute('aria-expanded', 'false');
|
|
173
|
+
toggleBtn.innerHTML = '☰ Menu';
|
|
174
|
+
|
|
175
|
+
sidebarCol.appendChild(nav);
|
|
176
|
+
contentCol.appendChild(toggleBtn);
|
|
177
|
+
contentCol.appendChild(tabContent);
|
|
178
|
+
row.appendChild(sidebarCol);
|
|
179
|
+
row.appendChild(contentCol);
|
|
180
|
+
container.appendChild(row);
|
|
181
|
+
|
|
182
|
+
return container;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
async _loadPanel(folder, panelName, pane) {
|
|
186
|
+
if (!this.client?.connection) {
|
|
187
|
+
this.logger.warn('[DashboardRenderer] No WS connection — cannot load panel', panelName);
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
pane.dataset.loaded = 'pending';
|
|
192
|
+
pane.innerHTML = '<div class="zSpinner-border zSpinner-border-sm zText-muted zm-3" role="status"></div>';
|
|
193
|
+
|
|
194
|
+
// SSOT render-target: pin the exact pane element so the streamed chunks paint
|
|
195
|
+
// HERE regardless of DOM timing — no reliance on querySelector('.zActive')
|
|
196
|
+
// resolving correctly at the moment each chunk arrives.
|
|
197
|
+
this.client._renderTarget = { el: pane, mode: 'replace', once: false };
|
|
198
|
+
|
|
199
|
+
try {
|
|
200
|
+
await this.client.connection.send(JSON.stringify({
|
|
201
|
+
event: 'execute_walker',
|
|
202
|
+
zBlock: panelName,
|
|
203
|
+
zVaFile: `zUI.${panelName}`,
|
|
204
|
+
zVaFolder: folder,
|
|
205
|
+
// Server contract: presence of _renderTarget marks this as a dashboard
|
|
206
|
+
// PANEL load (not a full-page nav). The server uses it to stamp
|
|
207
|
+
// session['_panel_zVaFile'] so a later in-panel $delta/zDelegate (e.g.
|
|
208
|
+
// $Edit_Profile, a ^bounce living in the panel's own file) resolves
|
|
209
|
+
// against that file instead of the dashboard host (zUI.zAccountHome).
|
|
210
|
+
// NOT dead — render-targeting moved to client._renderTarget, but this
|
|
211
|
+
// flag is the server's only signal that the load is panel-scoped.
|
|
212
|
+
_renderTarget: 'dashboard-panel-content',
|
|
213
|
+
}));
|
|
214
|
+
setTimeout(() => { pane.dataset.loaded = 'done'; }, 2000);
|
|
215
|
+
} catch (err) {
|
|
216
|
+
this.logger.error(`[DashboardRenderer] Failed to load panel ${panelName}:`, err);
|
|
217
|
+
pane.innerHTML = `<div class="zAlert zAlert-danger zm-2">Failed to load ${panelName}</div>`;
|
|
218
|
+
pane.dataset.loaded = 'error';
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|