@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.
Files changed (140) hide show
  1. package/L1_Foundation/L1_Foundation.js +13 -0
  2. package/L1_Foundation/bootstrap/bootstrap.js +11 -0
  3. package/L1_Foundation/bootstrap/bootstrap_hooks.js +123 -0
  4. package/L1_Foundation/bootstrap/bootstrap_index.js +15 -0
  5. package/L1_Foundation/bootstrap/bootstrap_logger.js +135 -0
  6. package/L1_Foundation/bootstrap/cdn_loader.js +217 -0
  7. package/L1_Foundation/bootstrap/module_registry.js +102 -0
  8. package/L1_Foundation/bootstrap/prism_loader.js +164 -0
  9. package/L1_Foundation/config/client_config.js +110 -0
  10. package/L1_Foundation/config/config.js +7 -0
  11. package/L1_Foundation/connection/connection.js +8 -0
  12. package/L1_Foundation/connection/websocket_connection.js +122 -0
  13. package/L1_Foundation/constants/bifrost_constants.js +284 -0
  14. package/L1_Foundation/constants/constants.js +7 -0
  15. package/L1_Foundation/logger/logger.js +10 -0
  16. package/L2_Handling/L2_Handling.js +15 -0
  17. package/L2_Handling/cache/cache.js +22 -0
  18. package/L2_Handling/cache/cache_constants.js +69 -0
  19. package/L2_Handling/cache/orchestration/cache_manager.js +299 -0
  20. package/L2_Handling/cache/orchestration/cache_orchestrator.js +260 -0
  21. package/L2_Handling/cache/orchestration/orchestration.js +12 -0
  22. package/L2_Handling/cache/storage/session_manager.js +289 -0
  23. package/L2_Handling/cache/storage/storage.js +10 -0
  24. package/L2_Handling/cache/storage/storage_manager.js +590 -0
  25. package/L2_Handling/display/composite/composite.js +13 -0
  26. package/L2_Handling/display/composite/dashboard_renderer.js +221 -0
  27. package/L2_Handling/display/composite/swiper_renderer.js +564 -0
  28. package/L2_Handling/display/composite/terminal_renderer.js +922 -0
  29. package/L2_Handling/display/composite/wizard_conditional_renderer.js +274 -0
  30. package/L2_Handling/display/display.js +30 -0
  31. package/L2_Handling/display/feedback/feedback.js +11 -0
  32. package/L2_Handling/display/feedback/progressbar_renderer.js +418 -0
  33. package/L2_Handling/display/feedback/spinner_renderer.js +246 -0
  34. package/L2_Handling/display/inputs/button_renderer.js +634 -0
  35. package/L2_Handling/display/inputs/form_renderer.js +583 -0
  36. package/L2_Handling/display/inputs/input_renderer.js +658 -0
  37. package/L2_Handling/display/inputs/inputs.js +12 -0
  38. package/L2_Handling/display/navigation/menu_renderer.js +206 -0
  39. package/L2_Handling/display/navigation/navigation.js +11 -0
  40. package/L2_Handling/display/navigation/navigation_renderer.js +703 -0
  41. package/L2_Handling/display/orchestration/orchestration.js +11 -0
  42. package/L2_Handling/display/orchestration/renderer.js +430 -0
  43. package/L2_Handling/display/orchestration/zdisplay_orchestrator.js +1759 -0
  44. package/L2_Handling/display/outputs/alert_renderer.js +161 -0
  45. package/L2_Handling/display/outputs/audio_renderer.js +94 -0
  46. package/L2_Handling/display/outputs/card_renderer.js +229 -0
  47. package/L2_Handling/display/outputs/code_renderer.js +66 -0
  48. package/L2_Handling/display/outputs/dl_renderer.js +131 -0
  49. package/L2_Handling/display/outputs/header_renderer.js +162 -0
  50. package/L2_Handling/display/outputs/icon_renderer.js +107 -0
  51. package/L2_Handling/display/outputs/image_renderer.js +145 -0
  52. package/L2_Handling/display/outputs/list_renderer.js +190 -0
  53. package/L2_Handling/display/outputs/outputs.js +19 -0
  54. package/L2_Handling/display/outputs/table_renderer.js +765 -0
  55. package/L2_Handling/display/outputs/text_renderer.js +818 -0
  56. package/L2_Handling/display/outputs/typography_renderer.js +293 -0
  57. package/L2_Handling/display/outputs/video_renderer.js +116 -0
  58. package/L2_Handling/display/primitives/document_structure_primitives.js +319 -0
  59. package/L2_Handling/display/primitives/form_primitives.js +526 -0
  60. package/L2_Handling/display/primitives/generic_containers.js +109 -0
  61. package/L2_Handling/display/primitives/interactive_primitives.js +305 -0
  62. package/L2_Handling/display/primitives/link_primitives.js +552 -0
  63. package/L2_Handling/display/primitives/lists_primitives.js +262 -0
  64. package/L2_Handling/display/primitives/media_primitives.js +383 -0
  65. package/L2_Handling/display/primitives/primitives.js +19 -0
  66. package/L2_Handling/display/primitives/semantic_element_primitive.js +226 -0
  67. package/L2_Handling/display/primitives/table_primitives.js +528 -0
  68. package/L2_Handling/display/primitives/typography_primitives.js +175 -0
  69. package/L2_Handling/display/specialized/input_request_renderer.js +467 -0
  70. package/L2_Handling/display/specialized/specialized.js +10 -0
  71. package/L2_Handling/hooks/hooks.js +9 -0
  72. package/L2_Handling/hooks/menu_integration.js +57 -0
  73. package/L2_Handling/hooks/widget_hook_manager.js +292 -0
  74. package/L2_Handling/message/message.js +8 -0
  75. package/L2_Handling/message/message_handler.js +701 -0
  76. package/L2_Handling/navigation/navigation.js +8 -0
  77. package/L2_Handling/navigation/navigation_manager.js +403 -0
  78. package/L2_Handling/zhooks/features/cache_live.js +287 -0
  79. package/L2_Handling/zhooks/features/crumbs_live.js +292 -0
  80. package/L2_Handling/zhooks/zhooks_manager.js +65 -0
  81. package/L2_Handling/zvaf/zvaf.js +8 -0
  82. package/L2_Handling/zvaf/zvaf_manager.js +334 -0
  83. package/L3_Abstraction/L3_Abstraction.js +12 -0
  84. package/L3_Abstraction/orchestrator/container_unwrapper.js +101 -0
  85. package/L3_Abstraction/orchestrator/group_renderer.js +698 -0
  86. package/L3_Abstraction/orchestrator/input_event_handler.js +797 -0
  87. package/L3_Abstraction/orchestrator/metadata_processor.js +249 -0
  88. package/L3_Abstraction/orchestrator/navbar_builder.js +201 -0
  89. package/L3_Abstraction/orchestrator/orchestrator.js +13 -0
  90. package/L3_Abstraction/orchestrator/wizard_gate_handler.js +360 -0
  91. package/L3_Abstraction/renderer/renderer.js +1 -0
  92. package/L3_Abstraction/session/session.js +1 -0
  93. package/L4_Orchestration/L4_Orchestration.js +11 -0
  94. package/L4_Orchestration/client/client.js +1 -0
  95. package/L4_Orchestration/facade/facade.js +9 -0
  96. package/L4_Orchestration/facade/manager_registry.js +118 -0
  97. package/L4_Orchestration/facade/renderer_registry.js +274 -0
  98. package/L4_Orchestration/lifecycle/asset_loader.js +255 -0
  99. package/L4_Orchestration/lifecycle/initializer.js +135 -0
  100. package/L4_Orchestration/lifecycle/lifecycle.js +8 -0
  101. package/L4_Orchestration/rendering/facade.js +94 -0
  102. package/L4_Orchestration/rendering/rendering.js +7 -0
  103. package/LICENSE +21 -0
  104. package/README.md +82 -0
  105. package/bifrost_client.js +204 -0
  106. package/bifrost_core.js +1686 -0
  107. package/docs/ARCHITECTURE.md +111 -0
  108. package/docs/PROTOCOL.md +106 -0
  109. package/docs/RENDERERS.md +101 -0
  110. package/docs/SECURITY.md +92 -0
  111. package/package.json +24 -0
  112. package/syntax/prism-zconfig.js +41 -0
  113. package/syntax/prism-zenv.js +69 -0
  114. package/syntax/prism-zolo-theme.css +288 -0
  115. package/syntax/prism-zolo.js +380 -0
  116. package/syntax/prism-zschema.js +38 -0
  117. package/syntax/prism-zspark.js +25 -0
  118. package/syntax/prism-zui.js +68 -0
  119. package/zSys/accessibility/accessibility.js +10 -0
  120. package/zSys/accessibility/emoji_accessibility.js +173 -0
  121. package/zSys/dom/block_utils.js +122 -0
  122. package/zSys/dom/container_utils.js +370 -0
  123. package/zSys/dom/dom.js +13 -0
  124. package/zSys/dom/dom_utils.js +328 -0
  125. package/zSys/dom/encoding_utils.js +117 -0
  126. package/zSys/dom/style_utils.js +71 -0
  127. package/zSys/errors/error_display.js +299 -0
  128. package/zSys/errors/errors.js +10 -0
  129. package/zSys/theme/color_utils.js +274 -0
  130. package/zSys/theme/dark_mode_utils.js +272 -0
  131. package/zSys/theme/size_utils.js +256 -0
  132. package/zSys/theme/spacing_utils.js +405 -0
  133. package/zSys/theme/theme.js +14 -0
  134. package/zSys/theme/zbase.css +1735 -0
  135. package/zSys/theme/zbase_inject.js +161 -0
  136. package/zSys/theme/ztheme_utils.js +305 -0
  137. package/zSys/validation/error_boundary.js +201 -0
  138. package/zSys/validation/validation.js +11 -0
  139. package/zSys/validation/validation_utils.js +238 -0
  140. 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
+ }