@blorkfield/blork-tabs 0.3.0 → 0.3.1

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/README.md CHANGED
@@ -312,11 +312,13 @@ debug.clear();
312
312
 
313
313
  The debug panel has a special "focus mode" for reading logs:
314
314
 
315
- 1. **Hover for 5 seconds** → Panel enlarges to 75% of screen with doubled text size
315
+ 1. **Hover for configurable delay** → Panel enlarges to 75% of screen with doubled text size (default: 5 seconds, configurable via `hoverDelay`)
316
316
  2. **Mouse can move freely** → Panel stays enlarged, won't close on mouse leave
317
317
  3. **Click × or backdrop** → Returns to normal size
318
318
 
319
- The × button is only visible when enlarged.
319
+ The × button is only visible when enlarged. Set `hoverDelay: 0` to disable the enlarge feature entirely.
320
+
321
+ **Auto-hide interaction:** When hovering a debug panel that has auto-hide enabled, the auto-hide timer is paused so the panel won't disappear before the hover-to-enlarge triggers.
320
322
 
321
323
  ### Configuration Options
322
324
 
@@ -324,6 +326,7 @@ The × button is only visible when enlarged.
324
326
  |--------|------|---------|-------------|
325
327
  | `maxEntries` | `number` | `50` | Maximum log entries before oldest are removed |
326
328
  | `showTimestamps` | `boolean` | `false` | Show timestamps on each entry |
329
+ | `hoverDelay` | `number` | `5000` | Milliseconds to hover before enlarging (0 = disable) |
327
330
 
328
331
  Plus all standard `PanelConfig` options (`id`, `title`, `width`, `initialPosition`, `startCollapsed`, etc.)
329
332
 
@@ -334,6 +337,41 @@ Plus all standard `PanelConfig` options (`id`, `title`, `width`, `initialPositio
334
337
  debug.panel; // PanelState - for advanced manipulation
335
338
  ```
336
339
 
340
+ ### Embeddable Debug Log
341
+
342
+ You can embed a debug log inside any panel or container element using `createDebugLog()`:
343
+
344
+ ```typescript
345
+ const manager = new TabManager();
346
+
347
+ // Create a panel with custom content
348
+ const panel = manager.addPanel({
349
+ id: 'my-panel',
350
+ title: 'My Panel',
351
+ content: '<div id="my-content">Some content</div>',
352
+ });
353
+
354
+ // Add a debug log section to the panel
355
+ const logSection = document.createElement('div');
356
+ panel.contentWrapper.appendChild(logSection);
357
+
358
+ // Create the embedded debug log (shares hover-to-enlarge with standalone panels)
359
+ const embeddedLog = manager.createDebugLog(logSection, {
360
+ maxEntries: 20,
361
+ showTimestamps: true,
362
+ hoverDelay: 3000, // 3 second hover delay (0 to disable, default: 5000)
363
+ });
364
+
365
+ // Use it like a regular debug panel
366
+ embeddedLog.log('event', { data: 'value' });
367
+ embeddedLog.info('status', { connected: true });
368
+ embeddedLog.warn('warning', { message: 'Low memory' });
369
+ embeddedLog.error('error', { code: 500 });
370
+ embeddedLog.clear();
371
+ ```
372
+
373
+ The embedded log supports the same hover-to-enlarge behavior as the standalone debug panel.
374
+
337
375
  ## CSS Customization
338
376
 
339
377
  Override CSS variables to customize appearance:
package/dist/index.cjs CHANGED
@@ -26,6 +26,7 @@ __export(index_exports, {
26
26
  SnapPreview: () => SnapPreview,
27
27
  TabManager: () => TabManager,
28
28
  areInSameChain: () => areInSameChain,
29
+ createDebugLog: () => createDebugLog,
29
30
  createDebugPanelContent: () => createDebugPanelContent,
30
31
  createDebugPanelInterface: () => createDebugPanelInterface,
31
32
  createPanelElement: () => createPanelElement,
@@ -44,6 +45,7 @@ __export(index_exports, {
44
45
  hidePanel: () => hidePanel,
45
46
  setPanelPosition: () => setPanelPosition,
46
47
  setPanelZIndex: () => setPanelZIndex,
48
+ setupHoverEnlarge: () => setupHoverEnlarge,
47
49
  showPanel: () => showPanel,
48
50
  snapPanels: () => snapPanels,
49
51
  snapPanelsToTarget: () => snapPanelsToTarget,
@@ -65,11 +67,24 @@ function createDebugPanelContent(_config, classes) {
65
67
  };
66
68
  }
67
69
  function createDebugPanelInterface(panel, elements, config, classes) {
70
+ const debugLog = createDebugLogInterface(elements.logContainer, config, classes);
71
+ return {
72
+ panel,
73
+ ...debugLog
74
+ };
75
+ }
76
+ function escapeHtml(str) {
77
+ const div = document.createElement("div");
78
+ div.textContent = str;
79
+ return div.innerHTML;
80
+ }
81
+ function createDebugLogInterface(logContainer, config, classes) {
68
82
  const maxEntries = config.maxEntries ?? 50;
69
83
  const showTimestamps = config.showTimestamps ?? false;
84
+ const entryClass = classes.debugLogEntry;
70
85
  function addEntry(level, eventName, data) {
71
86
  const entry = document.createElement("div");
72
- entry.className = classes.debugLogEntry;
87
+ entry.className = entryClass;
73
88
  if (level === "warn") entry.classList.add(classes.debugLogEntryWarn);
74
89
  if (level === "error") entry.classList.add(classes.debugLogEntryError);
75
90
  let html = "";
@@ -88,27 +103,99 @@ function createDebugPanelInterface(panel, elements, config, classes) {
88
103
  html += `<span class="${classes.debugLogData}">${escapeHtml(dataStr)}</span>`;
89
104
  }
90
105
  entry.innerHTML = html;
91
- elements.logContainer.appendChild(entry);
92
- elements.logContainer.scrollTop = elements.logContainer.scrollHeight;
93
- while (elements.logContainer.children.length > maxEntries) {
94
- elements.logContainer.removeChild(elements.logContainer.children[0]);
106
+ logContainer.appendChild(entry);
107
+ logContainer.scrollTop = logContainer.scrollHeight;
108
+ const entries = logContainer.querySelectorAll(`.${entryClass}`);
109
+ if (entries.length > maxEntries) {
110
+ const toRemove = entries.length - maxEntries;
111
+ for (let i = 0; i < toRemove; i++) {
112
+ entries[i].remove();
113
+ }
95
114
  }
96
115
  }
116
+ function clearEntries() {
117
+ const entries = logContainer.querySelectorAll(`.${entryClass}`);
118
+ entries.forEach((entry) => entry.remove());
119
+ }
97
120
  return {
98
- panel,
99
121
  log: (name, data) => addEntry("log", name, data),
100
122
  info: (name, data) => addEntry("info", name, data),
101
123
  warn: (name, data) => addEntry("warn", name, data),
102
124
  error: (name, data) => addEntry("error", name, data),
103
- clear: () => {
104
- elements.logContainer.innerHTML = "";
105
- }
125
+ clear: clearEntries
106
126
  };
107
127
  }
108
- function escapeHtml(str) {
109
- const div = document.createElement("div");
110
- div.textContent = str;
111
- return div.innerHTML;
128
+ function createDebugLog(container, config, classes) {
129
+ const logContainer = document.createElement("div");
130
+ logContainer.className = classes.debugLog;
131
+ container.appendChild(logContainer);
132
+ const debugLog = createDebugLogInterface(logContainer, config, classes);
133
+ return { debugLog, logContainer };
134
+ }
135
+ function setupHoverEnlarge(config) {
136
+ const { logContainer, hoverDelay, backdropContainer, classes, onHoverStart, onHoverEnd, onClose } = config;
137
+ logContainer.classList.add(classes.debugPanel);
138
+ const closeBtn = document.createElement("button");
139
+ closeBtn.className = classes.debugClearButton;
140
+ closeBtn.textContent = "\xD7";
141
+ closeBtn.title = "Close enlarged view";
142
+ logContainer.appendChild(closeBtn);
143
+ let hoverTimeout = null;
144
+ let isEnlarged = false;
145
+ let backdrop = null;
146
+ let originalParent = null;
147
+ let placeholder = null;
148
+ const closeEnlarged = () => {
149
+ if (!isEnlarged) return;
150
+ isEnlarged = false;
151
+ logContainer.classList.remove(classes.debugPanelEnlarged);
152
+ if (originalParent && placeholder) {
153
+ originalParent.insertBefore(logContainer, placeholder);
154
+ placeholder.remove();
155
+ placeholder = null;
156
+ originalParent = null;
157
+ }
158
+ if (backdrop) {
159
+ backdrop.remove();
160
+ backdrop = null;
161
+ }
162
+ onClose?.();
163
+ };
164
+ const openEnlarged = () => {
165
+ if (isEnlarged) return;
166
+ isEnlarged = true;
167
+ backdrop = document.createElement("div");
168
+ backdrop.className = classes.debugBackdrop;
169
+ backdropContainer.appendChild(backdrop);
170
+ backdrop.addEventListener("click", closeEnlarged);
171
+ originalParent = logContainer.parentElement;
172
+ placeholder = document.createComment("debug-log-placeholder");
173
+ originalParent?.insertBefore(placeholder, logContainer);
174
+ backdropContainer.appendChild(logContainer);
175
+ logContainer.classList.add(classes.debugPanelEnlarged);
176
+ };
177
+ logContainer.addEventListener("mouseenter", () => {
178
+ onHoverStart?.();
179
+ if (isEnlarged) return;
180
+ if (hoverDelay > 0) {
181
+ hoverTimeout = setTimeout(() => {
182
+ openEnlarged();
183
+ }, hoverDelay);
184
+ }
185
+ });
186
+ logContainer.addEventListener("mouseleave", () => {
187
+ if (hoverTimeout) {
188
+ clearTimeout(hoverTimeout);
189
+ hoverTimeout = null;
190
+ }
191
+ if (!isEnlarged) {
192
+ onHoverEnd?.();
193
+ }
194
+ });
195
+ closeBtn.addEventListener("click", (e) => {
196
+ e.stopPropagation();
197
+ closeEnlarged();
198
+ });
112
199
  }
113
200
 
114
201
  // src/Panel.ts
@@ -901,6 +988,7 @@ var SnapPreview = class {
901
988
  var AutoHideManager = class {
902
989
  constructor(panels, classes, callbacks) {
903
990
  this.hideTimers = /* @__PURE__ */ new Map();
991
+ this.pausedPanels = /* @__PURE__ */ new Set();
904
992
  this.listenersAttached = false;
905
993
  this.panels = panels;
906
994
  this.classes = classes;
@@ -922,6 +1010,7 @@ var AutoHideManager = class {
922
1010
  */
923
1011
  handleActivity() {
924
1012
  for (const panel of this.panels.values()) {
1013
+ if (this.pausedPanels.has(panel.id)) continue;
925
1014
  if (panel.resolvedAutoHideDelay !== void 0 || panel.isHidden) {
926
1015
  this.show(panel, "activity");
927
1016
  if (panel.resolvedAutoHideDelay !== void 0) {
@@ -951,6 +1040,23 @@ var AutoHideManager = class {
951
1040
  this.hideTimers.delete(panelId);
952
1041
  }
953
1042
  }
1043
+ /**
1044
+ * Pause auto-hide timer for a panel (e.g., during debug hover)
1045
+ */
1046
+ pauseTimer(panelId) {
1047
+ this.clearTimer(panelId);
1048
+ this.pausedPanels.add(panelId);
1049
+ }
1050
+ /**
1051
+ * Resume auto-hide timer for a panel
1052
+ */
1053
+ resumeTimer(panelId) {
1054
+ this.pausedPanels.delete(panelId);
1055
+ const panel = this.panels.get(panelId);
1056
+ if (panel && panel.resolvedAutoHideDelay !== void 0) {
1057
+ this.scheduleHide(panel);
1058
+ }
1059
+ }
954
1060
  /**
955
1061
  * Show a panel
956
1062
  */
@@ -1157,58 +1263,38 @@ var TabManager = class {
1157
1263
  startCollapsed: config.startCollapsed ?? true
1158
1264
  };
1159
1265
  const state = this.addPanel(panelConfig);
1160
- state.element.classList.add(this.classes.debugPanel);
1161
- const closeBtn = document.createElement("button");
1162
- closeBtn.className = this.classes.debugClearButton;
1163
- closeBtn.textContent = "\xD7";
1164
- closeBtn.title = "Close enlarged view";
1165
- if (state.collapseButton) {
1166
- state.collapseButton.parentElement?.insertBefore(closeBtn, state.collapseButton);
1167
- }
1168
- elements.clearButton = closeBtn;
1169
1266
  this.debugPanelElements.set(state.id, elements);
1170
1267
  const debugPanel = createDebugPanelInterface(state, elements, config, this.classes);
1171
- let hoverTimeout = null;
1172
- let isEnlarged = false;
1173
- let backdrop = null;
1174
- const enlargedClass = this.classes.debugPanelEnlarged;
1175
- const backdropClass = this.classes.debugBackdrop;
1176
- const closeEnlarged = () => {
1177
- if (!isEnlarged) return;
1178
- isEnlarged = false;
1179
- state.element.classList.remove(enlargedClass);
1180
- if (backdrop) {
1181
- backdrop.remove();
1182
- backdrop = null;
1183
- }
1184
- };
1185
- const openEnlarged = () => {
1186
- if (isEnlarged) return;
1187
- isEnlarged = true;
1188
- backdrop = document.createElement("div");
1189
- backdrop.className = backdropClass;
1190
- this.config.container.appendChild(backdrop);
1191
- backdrop.addEventListener("click", closeEnlarged);
1192
- state.element.classList.add(enlargedClass);
1193
- };
1194
- state.element.addEventListener("mouseenter", () => {
1195
- if (isEnlarged) return;
1196
- hoverTimeout = setTimeout(() => {
1197
- openEnlarged();
1198
- }, 5e3);
1199
- });
1200
- state.element.addEventListener("mouseleave", () => {
1201
- if (hoverTimeout) {
1202
- clearTimeout(hoverTimeout);
1203
- hoverTimeout = null;
1204
- }
1205
- });
1206
- closeBtn.addEventListener("click", (e) => {
1207
- e.stopPropagation();
1208
- closeEnlarged();
1209
- });
1268
+ const hoverDelay = config.hoverDelay ?? 5e3;
1269
+ if (hoverDelay > 0) {
1270
+ setupHoverEnlarge({
1271
+ logContainer: elements.logContainer,
1272
+ hoverDelay,
1273
+ backdropContainer: this.config.container,
1274
+ classes: this.classes,
1275
+ onHoverStart: () => this.autoHideManager.pauseTimer(state.id),
1276
+ onHoverEnd: () => this.autoHideManager.resumeTimer(state.id),
1277
+ onClose: () => this.autoHideManager.resumeTimer(state.id)
1278
+ });
1279
+ }
1210
1280
  return debugPanel;
1211
1281
  }
1282
+ /**
1283
+ * Create an embeddable debug log in any container element
1284
+ */
1285
+ createDebugLog(container, config = {}) {
1286
+ const { debugLog, logContainer } = createDebugLog(container, config, this.classes);
1287
+ const hoverDelay = config.hoverDelay ?? 5e3;
1288
+ if (hoverDelay > 0) {
1289
+ setupHoverEnlarge({
1290
+ logContainer,
1291
+ hoverDelay,
1292
+ backdropContainer: this.config.container,
1293
+ classes: this.classes
1294
+ });
1295
+ }
1296
+ return debugLog;
1297
+ }
1212
1298
  /**
1213
1299
  * Set up event handlers for a panel
1214
1300
  */
@@ -1476,6 +1562,7 @@ var TabManager = class {
1476
1562
  SnapPreview,
1477
1563
  TabManager,
1478
1564
  areInSameChain,
1565
+ createDebugLog,
1479
1566
  createDebugPanelContent,
1480
1567
  createDebugPanelInterface,
1481
1568
  createPanelElement,
@@ -1494,6 +1581,7 @@ var TabManager = class {
1494
1581
  hidePanel,
1495
1582
  setPanelPosition,
1496
1583
  setPanelZIndex,
1584
+ setupHoverEnlarge,
1497
1585
  showPanel,
1498
1586
  snapPanels,
1499
1587
  snapPanelsToTarget,
package/dist/index.d.cts CHANGED
@@ -324,6 +324,19 @@ interface DebugPanelConfig extends Omit<PanelConfig, 'content'> {
324
324
  maxEntries?: number;
325
325
  /** Show timestamps on entries (default: false) */
326
326
  showTimestamps?: boolean;
327
+ /** Milliseconds to hover before enlarging (default: 5000, 0 = disable) */
328
+ hoverDelay?: number;
329
+ }
330
+ /**
331
+ * Configuration for creating an embeddable debug log
332
+ */
333
+ interface DebugLogConfig {
334
+ /** Maximum log entries before oldest are removed (default: 50) */
335
+ maxEntries?: number;
336
+ /** Show timestamps on entries (default: false) */
337
+ showTimestamps?: boolean;
338
+ /** Milliseconds to hover before enlarging (default: 5000, 0 = disable) */
339
+ hoverDelay?: number;
327
340
  }
328
341
  /**
329
342
  * Log level for debug entries
@@ -346,6 +359,21 @@ interface DebugPanel {
346
359
  /** The underlying panel state */
347
360
  panel: PanelState;
348
361
  }
362
+ /**
363
+ * Interface for an embeddable debug log (without panel)
364
+ */
365
+ interface DebugLog {
366
+ /** Log an event (alias for info) */
367
+ log(eventName: string, data?: Record<string, unknown>): void;
368
+ /** Log an info event (blue) */
369
+ info(eventName: string, data?: Record<string, unknown>): void;
370
+ /** Log a warning event (yellow) */
371
+ warn(eventName: string, data?: Record<string, unknown>): void;
372
+ /** Log an error event (red) */
373
+ error(eventName: string, data?: Record<string, unknown>): void;
374
+ /** Clear all log entries */
375
+ clear(): void;
376
+ }
349
377
 
350
378
  /**
351
379
  * @blorkfield/blork-tabs - TabManager
@@ -396,6 +424,10 @@ declare class TabManager {
396
424
  * Add a debug panel with built-in logging functionality
397
425
  */
398
426
  addDebugPanel(config: DebugPanelConfig): DebugPanel;
427
+ /**
428
+ * Create an embeddable debug log in any container element
429
+ */
430
+ createDebugLog(container: HTMLElement, config?: DebugLogConfig): DebugLog;
399
431
  /**
400
432
  * Set up event handlers for a panel
401
433
  */
@@ -666,6 +698,7 @@ declare class AutoHideManager {
666
698
  private classes;
667
699
  private callbacks;
668
700
  private hideTimers;
701
+ private pausedPanels;
669
702
  private boundActivityHandler;
670
703
  private listenersAttached;
671
704
  constructor(panels: Map<string, PanelState>, classes: CSSClasses, callbacks: AutoHideCallbacks);
@@ -680,11 +713,19 @@ declare class AutoHideManager {
680
713
  /**
681
714
  * Schedule a panel to hide after its delay
682
715
  */
683
- private scheduleHide;
716
+ scheduleHide(panel: PanelState): void;
684
717
  /**
685
718
  * Clear hide timer for a panel
686
719
  */
687
- private clearTimer;
720
+ clearTimer(panelId: string): void;
721
+ /**
722
+ * Pause auto-hide timer for a panel (e.g., during debug hover)
723
+ */
724
+ pauseTimer(panelId: string): void;
725
+ /**
726
+ * Resume auto-hide timer for a panel
727
+ */
728
+ resumeTimer(panelId: string): void;
688
729
  /**
689
730
  * Show a panel
690
731
  */
@@ -724,9 +765,39 @@ declare function createDebugPanelContent(_config: DebugPanelConfig, classes: CSS
724
765
  elements: DebugPanelElements;
725
766
  };
726
767
  /**
727
- * Create the interface for interacting with a debug panel
768
+ * Create the interface for interacting with a debug panel.
769
+ * Uses the shared createDebugLogInterface internally.
728
770
  */
729
771
  declare function createDebugPanelInterface(panel: PanelState, elements: DebugPanelElements, config: DebugPanelConfig, classes: CSSClasses): DebugPanel;
772
+ interface DebugLogSetup {
773
+ debugLog: DebugLog;
774
+ logContainer: HTMLDivElement;
775
+ }
776
+ /**
777
+ * Create an embeddable debug log in any container element
778
+ */
779
+ declare function createDebugLog(container: HTMLElement, config: DebugLogConfig, classes: CSSClasses): DebugLogSetup;
780
+ interface HoverEnlargeConfig {
781
+ /** The log container element (.blork-tabs-debug-log) to enlarge */
782
+ logContainer: HTMLElement;
783
+ /** Hover delay in ms (0 = disable) */
784
+ hoverDelay: number;
785
+ /** Container to append backdrop to */
786
+ backdropContainer: HTMLElement;
787
+ /** CSS classes */
788
+ classes: CSSClasses;
789
+ /** Called when hovering starts */
790
+ onHoverStart?: () => void;
791
+ /** Called when hovering ends (without enlarging) */
792
+ onHoverEnd?: () => void;
793
+ /** Called when enlarged view is closed */
794
+ onClose?: () => void;
795
+ }
796
+ /**
797
+ * Set up hover-to-enlarge behavior for a debug log container.
798
+ * Works the same for both standalone debug panels and embedded logs.
799
+ */
800
+ declare function setupHoverEnlarge(config: HoverEnlargeConfig): void;
730
801
 
731
802
  /**
732
803
  * @blorkfield/blork-tabs - Panel
@@ -843,4 +914,4 @@ declare function snapPanels(leftPanel: PanelState, rightPanel: PanelState): void
843
914
  */
844
915
  declare function unsnap(leftPanel: PanelState, rightPanel: PanelState): void;
845
916
 
846
- export { type AnchorConfig, AnchorManager, type AnchorPreset, type AnchorSnapEvent, type AnchorSnapResult, type AnchorState, type AutoHideCallbacks, AutoHideManager, type Bounds, type CSSClasses, type DebugLogLevel, type DebugPanel, type DebugPanelConfig, type DragEndEvent, DragManager, type DragMode, type DragMoveEvent, type DragStartEvent, type DragState, type EventListener, type PanelAddedEvent, type PanelCollapseEvent, type PanelConfig, type PanelDetachedEvent, type PanelHideEvent, type PanelRemovedEvent, type PanelShowEvent, type PanelSnapEvent, type PanelState, type Position, type ResolvedTabManagerConfig, SnapPreview, type SnapSide, type SnapTarget, TabManager, type TabManagerConfig, type TabManagerEvents, areInSameChain, createDebugPanelContent, createDebugPanelInterface, createPanelElement, createPanelState, createPresetAnchor, detachFromGroup, findSnapTarget, getConnectedGroup, getDefaultAnchorConfigs, getDefaultZIndex, getDragZIndex, getLeftmostPanel, getPanelDimensions, getPanelPosition, getRightmostPanel, hidePanel, setPanelPosition, setPanelZIndex, showPanel, snapPanels, snapPanelsToTarget, toggleCollapse, unsnap, updateSnappedPositions };
917
+ export { type AnchorConfig, AnchorManager, type AnchorPreset, type AnchorSnapEvent, type AnchorSnapResult, type AnchorState, type AutoHideCallbacks, AutoHideManager, type Bounds, type CSSClasses, type DebugLog, type DebugLogConfig, type DebugLogLevel, type DebugPanel, type DebugPanelConfig, type DragEndEvent, DragManager, type DragMode, type DragMoveEvent, type DragStartEvent, type DragState, type EventListener, type PanelAddedEvent, type PanelCollapseEvent, type PanelConfig, type PanelDetachedEvent, type PanelHideEvent, type PanelRemovedEvent, type PanelShowEvent, type PanelSnapEvent, type PanelState, type Position, type ResolvedTabManagerConfig, SnapPreview, type SnapSide, type SnapTarget, TabManager, type TabManagerConfig, type TabManagerEvents, areInSameChain, createDebugLog, createDebugPanelContent, createDebugPanelInterface, createPanelElement, createPanelState, createPresetAnchor, detachFromGroup, findSnapTarget, getConnectedGroup, getDefaultAnchorConfigs, getDefaultZIndex, getDragZIndex, getLeftmostPanel, getPanelDimensions, getPanelPosition, getRightmostPanel, hidePanel, setPanelPosition, setPanelZIndex, setupHoverEnlarge, showPanel, snapPanels, snapPanelsToTarget, toggleCollapse, unsnap, updateSnappedPositions };
package/dist/index.d.ts CHANGED
@@ -324,6 +324,19 @@ interface DebugPanelConfig extends Omit<PanelConfig, 'content'> {
324
324
  maxEntries?: number;
325
325
  /** Show timestamps on entries (default: false) */
326
326
  showTimestamps?: boolean;
327
+ /** Milliseconds to hover before enlarging (default: 5000, 0 = disable) */
328
+ hoverDelay?: number;
329
+ }
330
+ /**
331
+ * Configuration for creating an embeddable debug log
332
+ */
333
+ interface DebugLogConfig {
334
+ /** Maximum log entries before oldest are removed (default: 50) */
335
+ maxEntries?: number;
336
+ /** Show timestamps on entries (default: false) */
337
+ showTimestamps?: boolean;
338
+ /** Milliseconds to hover before enlarging (default: 5000, 0 = disable) */
339
+ hoverDelay?: number;
327
340
  }
328
341
  /**
329
342
  * Log level for debug entries
@@ -346,6 +359,21 @@ interface DebugPanel {
346
359
  /** The underlying panel state */
347
360
  panel: PanelState;
348
361
  }
362
+ /**
363
+ * Interface for an embeddable debug log (without panel)
364
+ */
365
+ interface DebugLog {
366
+ /** Log an event (alias for info) */
367
+ log(eventName: string, data?: Record<string, unknown>): void;
368
+ /** Log an info event (blue) */
369
+ info(eventName: string, data?: Record<string, unknown>): void;
370
+ /** Log a warning event (yellow) */
371
+ warn(eventName: string, data?: Record<string, unknown>): void;
372
+ /** Log an error event (red) */
373
+ error(eventName: string, data?: Record<string, unknown>): void;
374
+ /** Clear all log entries */
375
+ clear(): void;
376
+ }
349
377
 
350
378
  /**
351
379
  * @blorkfield/blork-tabs - TabManager
@@ -396,6 +424,10 @@ declare class TabManager {
396
424
  * Add a debug panel with built-in logging functionality
397
425
  */
398
426
  addDebugPanel(config: DebugPanelConfig): DebugPanel;
427
+ /**
428
+ * Create an embeddable debug log in any container element
429
+ */
430
+ createDebugLog(container: HTMLElement, config?: DebugLogConfig): DebugLog;
399
431
  /**
400
432
  * Set up event handlers for a panel
401
433
  */
@@ -666,6 +698,7 @@ declare class AutoHideManager {
666
698
  private classes;
667
699
  private callbacks;
668
700
  private hideTimers;
701
+ private pausedPanels;
669
702
  private boundActivityHandler;
670
703
  private listenersAttached;
671
704
  constructor(panels: Map<string, PanelState>, classes: CSSClasses, callbacks: AutoHideCallbacks);
@@ -680,11 +713,19 @@ declare class AutoHideManager {
680
713
  /**
681
714
  * Schedule a panel to hide after its delay
682
715
  */
683
- private scheduleHide;
716
+ scheduleHide(panel: PanelState): void;
684
717
  /**
685
718
  * Clear hide timer for a panel
686
719
  */
687
- private clearTimer;
720
+ clearTimer(panelId: string): void;
721
+ /**
722
+ * Pause auto-hide timer for a panel (e.g., during debug hover)
723
+ */
724
+ pauseTimer(panelId: string): void;
725
+ /**
726
+ * Resume auto-hide timer for a panel
727
+ */
728
+ resumeTimer(panelId: string): void;
688
729
  /**
689
730
  * Show a panel
690
731
  */
@@ -724,9 +765,39 @@ declare function createDebugPanelContent(_config: DebugPanelConfig, classes: CSS
724
765
  elements: DebugPanelElements;
725
766
  };
726
767
  /**
727
- * Create the interface for interacting with a debug panel
768
+ * Create the interface for interacting with a debug panel.
769
+ * Uses the shared createDebugLogInterface internally.
728
770
  */
729
771
  declare function createDebugPanelInterface(panel: PanelState, elements: DebugPanelElements, config: DebugPanelConfig, classes: CSSClasses): DebugPanel;
772
+ interface DebugLogSetup {
773
+ debugLog: DebugLog;
774
+ logContainer: HTMLDivElement;
775
+ }
776
+ /**
777
+ * Create an embeddable debug log in any container element
778
+ */
779
+ declare function createDebugLog(container: HTMLElement, config: DebugLogConfig, classes: CSSClasses): DebugLogSetup;
780
+ interface HoverEnlargeConfig {
781
+ /** The log container element (.blork-tabs-debug-log) to enlarge */
782
+ logContainer: HTMLElement;
783
+ /** Hover delay in ms (0 = disable) */
784
+ hoverDelay: number;
785
+ /** Container to append backdrop to */
786
+ backdropContainer: HTMLElement;
787
+ /** CSS classes */
788
+ classes: CSSClasses;
789
+ /** Called when hovering starts */
790
+ onHoverStart?: () => void;
791
+ /** Called when hovering ends (without enlarging) */
792
+ onHoverEnd?: () => void;
793
+ /** Called when enlarged view is closed */
794
+ onClose?: () => void;
795
+ }
796
+ /**
797
+ * Set up hover-to-enlarge behavior for a debug log container.
798
+ * Works the same for both standalone debug panels and embedded logs.
799
+ */
800
+ declare function setupHoverEnlarge(config: HoverEnlargeConfig): void;
730
801
 
731
802
  /**
732
803
  * @blorkfield/blork-tabs - Panel
@@ -843,4 +914,4 @@ declare function snapPanels(leftPanel: PanelState, rightPanel: PanelState): void
843
914
  */
844
915
  declare function unsnap(leftPanel: PanelState, rightPanel: PanelState): void;
845
916
 
846
- export { type AnchorConfig, AnchorManager, type AnchorPreset, type AnchorSnapEvent, type AnchorSnapResult, type AnchorState, type AutoHideCallbacks, AutoHideManager, type Bounds, type CSSClasses, type DebugLogLevel, type DebugPanel, type DebugPanelConfig, type DragEndEvent, DragManager, type DragMode, type DragMoveEvent, type DragStartEvent, type DragState, type EventListener, type PanelAddedEvent, type PanelCollapseEvent, type PanelConfig, type PanelDetachedEvent, type PanelHideEvent, type PanelRemovedEvent, type PanelShowEvent, type PanelSnapEvent, type PanelState, type Position, type ResolvedTabManagerConfig, SnapPreview, type SnapSide, type SnapTarget, TabManager, type TabManagerConfig, type TabManagerEvents, areInSameChain, createDebugPanelContent, createDebugPanelInterface, createPanelElement, createPanelState, createPresetAnchor, detachFromGroup, findSnapTarget, getConnectedGroup, getDefaultAnchorConfigs, getDefaultZIndex, getDragZIndex, getLeftmostPanel, getPanelDimensions, getPanelPosition, getRightmostPanel, hidePanel, setPanelPosition, setPanelZIndex, showPanel, snapPanels, snapPanelsToTarget, toggleCollapse, unsnap, updateSnappedPositions };
917
+ export { type AnchorConfig, AnchorManager, type AnchorPreset, type AnchorSnapEvent, type AnchorSnapResult, type AnchorState, type AutoHideCallbacks, AutoHideManager, type Bounds, type CSSClasses, type DebugLog, type DebugLogConfig, type DebugLogLevel, type DebugPanel, type DebugPanelConfig, type DragEndEvent, DragManager, type DragMode, type DragMoveEvent, type DragStartEvent, type DragState, type EventListener, type PanelAddedEvent, type PanelCollapseEvent, type PanelConfig, type PanelDetachedEvent, type PanelHideEvent, type PanelRemovedEvent, type PanelShowEvent, type PanelSnapEvent, type PanelState, type Position, type ResolvedTabManagerConfig, SnapPreview, type SnapSide, type SnapTarget, TabManager, type TabManagerConfig, type TabManagerEvents, areInSameChain, createDebugLog, createDebugPanelContent, createDebugPanelInterface, createPanelElement, createPanelState, createPresetAnchor, detachFromGroup, findSnapTarget, getConnectedGroup, getDefaultAnchorConfigs, getDefaultZIndex, getDragZIndex, getLeftmostPanel, getPanelDimensions, getPanelPosition, getRightmostPanel, hidePanel, setPanelPosition, setPanelZIndex, setupHoverEnlarge, showPanel, snapPanels, snapPanelsToTarget, toggleCollapse, unsnap, updateSnappedPositions };