@djangocfg/debuger 2.1.234 → 2.1.235
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 +20 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.mjs +21 -26
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -6
- package/src/DebugButton.tsx +44 -49
package/dist/index.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import { __name } from './chunk-PAWJFY3S.mjs';
|
|
|
6
6
|
import { useState, useRef, useEffect, useCallback, useMemo } from 'react';
|
|
7
7
|
import { CheckCircle, AlertCircle, AlertTriangle, Info, Bug, ChevronUp, ChevronDown, Search, Download, Trash2, Radio, ScrollText, Maximize2, Minimize2, X, Database } from 'lucide-react';
|
|
8
8
|
import { Badge, Input, Tooltip, TooltipTrigger, Button, TooltipContent, CopyButton, ScrollArea } from '@djangocfg/ui-core/components';
|
|
9
|
-
import { cn, isDev
|
|
9
|
+
import { cn, isDev } from '@djangocfg/ui-core/lib';
|
|
10
10
|
import { monitorStore, EventLevel, MONITOR_VERSION, useDebugMode } from '@djangocfg/monitor/client';
|
|
11
11
|
import { create } from 'zustand';
|
|
12
12
|
import { useHotkey } from '@djangocfg/ui-core/hooks';
|
|
@@ -31,7 +31,7 @@ var useDebugStore = create((set) => ({
|
|
|
31
31
|
function useDebugShortcut() {
|
|
32
32
|
const toggle = useDebugStore((s) => s.toggle);
|
|
33
33
|
const isUnlocked = useDebugStore((s) => s.isUnlocked);
|
|
34
|
-
const isDev2 = typeof process !== "undefined" &&
|
|
34
|
+
const isDev2 = typeof process !== "undefined" && process.env.NODE_ENV !== "production";
|
|
35
35
|
useHotkey(
|
|
36
36
|
"meta+d",
|
|
37
37
|
(e) => {
|
|
@@ -540,30 +540,19 @@ function DebugPanel({
|
|
|
540
540
|
);
|
|
541
541
|
}
|
|
542
542
|
__name(DebugPanel, "DebugPanel");
|
|
543
|
-
function
|
|
544
|
-
const clicks = useRef([]);
|
|
545
|
-
return useCallback(() => {
|
|
546
|
-
const now = Date.now();
|
|
547
|
-
clicks.current = [...clicks.current.filter((t) => now - t < 2e3), now];
|
|
548
|
-
if (clicks.current.length >= 5) {
|
|
549
|
-
clicks.current = [];
|
|
550
|
-
onTriggered();
|
|
551
|
-
}
|
|
552
|
-
}, [onTriggered]);
|
|
553
|
-
}
|
|
554
|
-
__name(useEasterEgg, "useEasterEgg");
|
|
555
|
-
function DebugButton({ className, panel = {}, defaultUnlocked = isDev }) {
|
|
543
|
+
function DebugButton({ className, panel = {}, enabled }) {
|
|
556
544
|
const isOpen = useDebugStore((s) => s.isOpen);
|
|
557
545
|
const isUnlocked = useDebugStore((s) => s.isUnlocked);
|
|
558
546
|
const unlock = useDebugStore((s) => s.unlock);
|
|
559
547
|
const toggle = useDebugStore((s) => s.toggle);
|
|
560
548
|
const isDebugMode = useDebugMode();
|
|
561
|
-
useEffect(() => {
|
|
562
|
-
if (defaultUnlocked || isDebugMode) unlock("1");
|
|
563
|
-
}, [defaultUnlocked, isDebugMode, unlock]);
|
|
564
549
|
const errorCount = useDebugErrorCount();
|
|
565
|
-
if (isProd && !defaultUnlocked && !isDebugMode) return null;
|
|
566
550
|
useDebugShortcut();
|
|
551
|
+
const shouldUnlock = isDev || isDebugMode;
|
|
552
|
+
if (typeof window !== "undefined") console.info("[DebugButton]", { isDev, isDebugMode, shouldUnlock, isUnlocked, enabled });
|
|
553
|
+
useEffect(() => {
|
|
554
|
+
if (shouldUnlock) unlock("1");
|
|
555
|
+
}, [shouldUnlock, unlock]);
|
|
567
556
|
useEffect(() => {
|
|
568
557
|
if (typeof document === "undefined") return;
|
|
569
558
|
const apply = /* @__PURE__ */ __name(() => {
|
|
@@ -576,22 +565,28 @@ function DebugButton({ className, panel = {}, defaultUnlocked = isDev }) {
|
|
|
576
565
|
observer.observe(document.body, { childList: true });
|
|
577
566
|
return () => observer.disconnect();
|
|
578
567
|
}, [isOpen]);
|
|
579
|
-
const
|
|
580
|
-
|
|
581
|
-
|
|
568
|
+
const clicks = useRef([]);
|
|
569
|
+
const handleEasterEgg = useCallback(() => {
|
|
570
|
+
const now = Date.now();
|
|
571
|
+
clicks.current = [...clicks.current.filter((t) => now - t < 2e3), now];
|
|
572
|
+
if (clicks.current.length >= 5) {
|
|
573
|
+
clicks.current = [];
|
|
574
|
+
unlock("1");
|
|
575
|
+
toggle();
|
|
576
|
+
}
|
|
582
577
|
}, [unlock, toggle]);
|
|
583
|
-
|
|
578
|
+
if (enabled === false && !isDebugMode) return null;
|
|
584
579
|
if (!isUnlocked) {
|
|
585
580
|
return /* @__PURE__ */ jsx(
|
|
586
581
|
"div",
|
|
587
582
|
{
|
|
588
|
-
className: "fixed bottom-5 left-5 w-9 h-9 z-[99999] opacity-0",
|
|
589
|
-
onClick:
|
|
583
|
+
className: "fixed bottom-5 left-5 w-9 h-9 z-[99999] opacity-0 cursor-default",
|
|
584
|
+
onClick: handleEasterEgg
|
|
590
585
|
}
|
|
591
586
|
);
|
|
592
587
|
}
|
|
593
588
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
594
|
-
!isOpen && /* @__PURE__ */ jsx("div", { className: "fixed bottom-5
|
|
589
|
+
!isOpen && /* @__PURE__ */ jsx("div", { className: cn("fixed bottom-5 z-[99999]", isDev ? "left-16" : "left-5"), children: /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
595
590
|
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
596
591
|
"button",
|
|
597
592
|
{
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/store/debugStore.ts","../src/hooks/useDebugShortcut.ts","../src/bridges/monitorBridge.ts","../src/panels/LogsPanel.tsx","../src/hooks/useAudioEventLog.ts","../src/panels/AudioDebugPanel.tsx","../src/DebugPanel.tsx","../src/DebugButton.tsx","../src/hooks/useStoreSnapshot.ts","../src/panels/StorePanel.tsx","../src/hooks/useCustomEventLog.ts"],"names":["isDev","useState","useRef","useCallback","useEffect","jsxs","jsx","Badge","cn","Button","Trash2","Radio","Bug","Tooltip","TooltipTrigger","TooltipContent","ScrollArea","LazyJsonTree","MAX_EVENTS"],"mappings":"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","file":"index.mjs","sourcesContent":["'use client';\n\nimport { create } from 'zustand';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type DebugTab = 'logs' | 'audio' | 'pipeline' | 'custom';\n\nexport interface DebugStore {\n isOpen: boolean;\n tab: DebugTab;\n isUnlocked: boolean;\n open: () => void;\n close: () => void;\n toggle: () => void;\n setTab: (t: DebugTab) => void;\n unlock: (key: string) => boolean;\n}\n\n// ============================================================================\n// Store\n// ============================================================================\n\nexport const useDebugStore = create<DebugStore>((set) => ({\n isOpen: false,\n tab: 'logs',\n isUnlocked: false,\n\n open: () => set({ isOpen: true }),\n close: () => set({ isOpen: false }),\n toggle: () => set((s) => ({ isOpen: !s.isOpen })),\n setTab: (tab) => set({ tab }),\n\n unlock: (_key) => {\n // Any non-empty value unlocks — no secret key required\n const valid = true;\n if (valid) set({ isUnlocked: true });\n return valid;\n },\n}));\n","'use client';\n\nimport { useHotkey } from '@djangocfg/ui-core/hooks';\nimport { useDebugStore } from '../store/debugStore';\n\n/**\n * Registers a global keyboard shortcut to toggle the debug panel.\n * Default: Cmd+D (meta+d) on Mac / Win+D on Windows.\n *\n * Guards:\n * - In production: only fires if `isUnlocked === true`\n */\nexport function useDebugShortcut(): void {\n const toggle = useDebugStore((s) => s.toggle);\n const isUnlocked = useDebugStore((s) => s.isUnlocked);\n const isDev = typeof process !== 'undefined' && process.env?.NODE_ENV !== 'production';\n\n useHotkey(\n 'meta+d',\n (e) => {\n e.preventDefault();\n if (!isDev && !isUnlocked) return;\n toggle();\n },\n { preventDefault: true },\n );\n}\n","'use client';\n\n/**\n * monitorBridge — subscribes to @djangocfg/monitor store and forwards\n * captured events into debugger's logStore.\n *\n * Call once at app startup (e.g. inside DebugPanel or a provider).\n * Safe to call multiple times — only installs one subscription.\n *\n * @example\n * import { installMonitorBridge } from '@djangocfg/debuger/bridges'\n * installMonitorBridge()\n */\n\nimport { monitorStore, EventLevel } from '@djangocfg/monitor/client';\nimport { useDebugLogStore } from '../logger/logStore';\nimport type { LogLevel } from '../logger/types';\n\nlet _installed = false;\n\nexport function installMonitorBridge(): (() => void) | undefined {\n if (typeof window === 'undefined') return;\n if (_installed) return;\n\n let prevLen = monitorStore.getState().buffer.length;\n\n const unsub = monitorStore.subscribe((state) => {\n const buffer = state.buffer;\n if (buffer.length <= prevLen) { prevLen = buffer.length; return; }\n const newEvents = buffer.slice(prevLen);\n prevLen = buffer.length;\n\n for (const event of newEvents) {\n const level: LogLevel =\n event.level === EventLevel.ERROR ? 'error'\n : event.level === EventLevel.WARNING ? 'warn'\n : 'info';\n\n useDebugLogStore.getState().addLog({\n level,\n component: `monitor:${event.event_type ?? 'event'}`,\n message: event.message ?? '',\n data: {\n ...(event.url && { url: event.url }),\n ...(event.session_id && { session_id: event.session_id }),\n ...(event.http_status !== undefined && {\n http_status: event.http_status,\n http_method: event.http_method,\n http_url: event.http_url,\n }),\n ...(event.extra ? { extra: event.extra } : {}),\n },\n stack: event.stack_trace,\n });\n }\n });\n\n _installed = true;\n return () => {\n unsub();\n _installed = false;\n };\n}\n","'use client';\n\nimport React, { useState, useCallback, useEffect, useRef } from 'react';\nimport {\n useDebugLogStore,\n useDebugFilteredLogs,\n useDebugLogCount,\n useDebugErrorCount,\n type LogLevel,\n type LogEntry,\n} from '../logger';\nimport {\n Button,\n CopyButton,\n Badge,\n Input,\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from '@djangocfg/ui-core/components';\nimport { LazyJsonTree } from '@djangocfg/ui-tools';\nimport { useVirtualizer, type VirtualItem } from '@tanstack/react-virtual';\nimport {\n Bug, Trash2, Download, ChevronDown, ChevronUp,\n AlertCircle, Info, AlertTriangle, CheckCircle, Search,\n} from 'lucide-react';\nimport { cn } from '@djangocfg/ui-core/lib';\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst ROW_ESTIMATE_PX = 32;\nconst OVERSCAN = 5;\n\nconst LOG_LEVEL_CONFIG: Record<LogLevel, { icon: React.ElementType; color: string }> = {\n debug: { icon: Bug, color: 'text-muted-foreground' },\n info: { icon: Info, color: 'text-blue-500' },\n warn: { icon: AlertTriangle, color: 'text-yellow-500' },\n error: { icon: AlertCircle, color: 'text-red-500' },\n success: { icon: CheckCircle, color: 'text-green-500' },\n};\n\nconst LOG_LEVELS = Object.keys(LOG_LEVEL_CONFIG) as LogLevel[];\n\n// ============================================================================\n// LogEntryRow\n// ============================================================================\n\ninterface LogEntryRowProps {\n entry: LogEntry;\n expanded: boolean;\n onToggle: () => void;\n}\n\nfunction LogEntryRow({ entry, expanded, onToggle }: LogEntryRowProps) {\n const config = LOG_LEVEL_CONFIG[entry.level];\n const Icon = config.icon;\n const pad = (n: number, len = 2) => String(n).padStart(len, '0');\n const d = entry.timestamp;\n const time = `${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}.${pad(d.getMilliseconds(), 3)}`;\n const hasData = entry.data && Object.keys(entry.data).length > 0;\n const hasStack = !!entry.stack;\n const isExpandable = hasData || hasStack;\n\n return (\n <div className=\"border-b border-border/50 last:border-0\">\n <button\n type=\"button\"\n onClick={isExpandable ? onToggle : undefined}\n disabled={!isExpandable}\n className={cn(\n 'flex w-full items-start gap-2 px-3 py-1.5 text-left text-xs',\n isExpandable ? 'hover:bg-muted/50 cursor-pointer' : 'cursor-default'\n )}\n >\n <Icon className={cn('h-3.5 w-3.5 mt-0.5 shrink-0', config.color)} />\n <span className=\"text-muted-foreground font-mono shrink-0\">{time}</span>\n <Badge variant=\"outline\" className=\"shrink-0 text-[10px] px-1 py-0\">{entry.component}</Badge>\n <span className=\"flex-1 truncate\">{entry.message}</span>\n {isExpandable && (\n <span className=\"shrink-0 text-muted-foreground\">\n {expanded ? <ChevronUp className=\"h-3 w-3\" /> : <ChevronDown className=\"h-3 w-3\" />}\n </span>\n )}\n </button>\n {expanded && isExpandable && (\n <div className=\"px-3 pb-2 pl-8\">\n {hasData && <div className=\"mt-1\"><LazyJsonTree data={entry.data} mode=\"compact\" /></div>}\n {hasStack && (\n <pre className=\"mt-2 text-[10px] text-red-400 whitespace-pre-wrap font-mono bg-red-950/20 p-2 rounded\">\n {entry.stack}\n </pre>\n )}\n </div>\n )}\n </div>\n );\n}\n\n// ============================================================================\n// LogsPanel\n// ============================================================================\n\nexport function LogsPanel({ isActive }: { isActive: boolean }) {\n const [expandedLogs, setExpandedLogs] = useState<Set<string>>(new Set());\n const [searchQuery, setSearchQuery] = useState('');\n const [selectedLevels, setSelectedLevels] = useState<Set<LogLevel>>(\n new Set(['debug', 'info', 'warn', 'error', 'success'])\n );\n const [componentFilter, setComponentFilter] = useState('');\n\n const logs = useDebugFilteredLogs();\n const logCount = useDebugLogCount();\n const errorCount = useDebugErrorCount();\n const clearLogs = useDebugLogStore((s) => s.clearLogs);\n const setFilter = useDebugLogStore((s) => s.setFilter);\n const exportLogs = useDebugLogStore((s) => s.exportLogs);\n\n // Virtualizer\n const scrollRef = useRef<HTMLDivElement>(null);\n const virtualizer = useVirtualizer({\n count: logs.length,\n getScrollElement: () => scrollRef.current,\n estimateSize: () => ROW_ESTIMATE_PX,\n overscan: OVERSCAN,\n });\n\n useEffect(() => {\n if (!isActive) return;\n setFilter({\n levels: Array.from(selectedLevels),\n component: componentFilter || undefined,\n search: searchQuery || undefined,\n });\n }, [isActive, selectedLevels, componentFilter, searchQuery, setFilter]);\n\n const handleToggleExpand = useCallback((id: string) => {\n setExpandedLogs((prev) => {\n const next = new Set(prev);\n next.has(id) ? next.delete(id) : next.add(id);\n return next;\n });\n }, []);\n\n const handleToggleLevel = useCallback((level: LogLevel) => {\n setSelectedLevels((prev) => {\n const next = new Set(prev);\n next.has(level) ? next.delete(level) : next.add(level);\n return next;\n });\n }, []);\n\n const handleExport = useCallback(() => {\n const json = exportLogs();\n const blob = new Blob([json], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = `debug-logs-${new Date().toISOString().slice(0, 19).replace(/:/g, '-')}.json`;\n a.click();\n URL.revokeObjectURL(url);\n }, [exportLogs]);\n\n const handleClear = useCallback(() => {\n clearLogs();\n setExpandedLogs(new Set());\n }, [clearLogs]);\n\n const logsJson = exportLogs();\n const virtualItems = virtualizer.getVirtualItems();\n const totalSize = virtualizer.getTotalSize();\n\n return (\n <div className=\"flex flex-col h-full\">\n {/* Stats */}\n <div className=\"flex items-center gap-2 border-b border-border px-3 py-1.5 shrink-0\">\n <Badge variant=\"secondary\" className=\"text-[10px]\">{logCount} logs</Badge>\n {errorCount > 0 && <Badge variant=\"destructive\" className=\"text-[10px]\">{errorCount} errors</Badge>}\n </div>\n\n {/* Filters */}\n <div className=\"flex flex-wrap items-center gap-2 border-b border-border px-3 py-2 shrink-0\">\n <div className=\"relative flex-1 min-w-[140px]\">\n <Search className=\"absolute left-2 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-muted-foreground\" />\n <Input\n placeholder=\"Search...\"\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n className=\"h-7 pl-7 text-xs\"\n />\n </div>\n <Input\n placeholder=\"Component...\"\n value={componentFilter}\n onChange={(e) => setComponentFilter(e.target.value)}\n className=\"h-7 w-24 text-xs\"\n />\n <div className=\"flex items-center gap-0.5\">\n {LOG_LEVELS.map((level) => {\n const { icon: Icon, color } = LOG_LEVEL_CONFIG[level];\n const active = selectedLevels.has(level);\n return (\n <Tooltip key={level}>\n <TooltipTrigger asChild>\n <Button variant={active ? 'secondary' : 'ghost'} size=\"icon\" className=\"h-6 w-6\" onClick={() => handleToggleLevel(level)}>\n <Icon className={cn('h-3.5 w-3.5', active && color)} />\n </Button>\n </TooltipTrigger>\n <TooltipContent>{level}</TooltipContent>\n </Tooltip>\n );\n })}\n </div>\n <div className=\"flex items-center gap-0.5 ml-auto\">\n <CopyButton value={logsJson} size=\"icon\" className=\"h-6 w-6\" />\n <Tooltip>\n <TooltipTrigger asChild>\n <Button variant=\"ghost\" size=\"icon\" className=\"h-6 w-6\" onClick={handleExport}>\n <Download className=\"h-3.5 w-3.5\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Export JSON</TooltipContent>\n </Tooltip>\n <Tooltip>\n <TooltipTrigger asChild>\n <Button variant=\"ghost\" size=\"icon\" className=\"h-6 w-6\" onClick={handleClear}>\n <Trash2 className=\"h-3.5 w-3.5\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Clear</TooltipContent>\n </Tooltip>\n </div>\n </div>\n\n {/* Virtualized log list */}\n <div ref={scrollRef} className=\"flex-1 overflow-auto\">\n {logs.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center py-10 text-muted-foreground\">\n <Bug className=\"h-8 w-8 mb-2 opacity-40\" />\n <p className=\"text-sm\">No logs yet</p>\n </div>\n ) : (\n <div style={{ height: `${totalSize}px`, position: 'relative' }}>\n {virtualItems.map((vItem: VirtualItem) => {\n const entry = logs[vItem.index];\n return (\n <div\n key={entry.id}\n data-index={vItem.index}\n ref={virtualizer.measureElement}\n style={{ position: 'absolute', top: 0, left: 0, width: '100%', transform: `translateY(${vItem.start}px)` }}\n >\n <LogEntryRow\n entry={entry}\n expanded={expandedLogs.has(entry.id)}\n onToggle={() => handleToggleExpand(entry.id)}\n />\n </div>\n );\n })}\n </div>\n )}\n </div>\n </div>\n );\n}\n","'use client';\n\nimport { useState, useEffect, useRef, useCallback } from 'react';\nimport { subscribeAudioEvents, clearAudioEventBuffer } from '../emitters/audioEmitter';\nimport type { AudioDebugEvent, AudioEventKind } from '../emitters/audioEmitter';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface AudioLogEntry extends AudioDebugEvent {\n /** Local unique key for React rendering */\n id: string;\n}\n\nexport interface UseAudioEventLogResult {\n events: AudioLogEntry[];\n clear: () => void;\n /** Seek events per second (rolling 5s window) */\n seekRate: number;\n /** Average interval between 'sync' ticks in ms (e.g. RAF loop cadence) */\n syncIntervalMs: number | null;\n /** Running count per event kind */\n kindCounts: Partial<Record<AudioEventKind, number>>;\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst MAX_EVENTS = 200;\n\n// ============================================================================\n// Hook\n// ============================================================================\n\n/**\n * Subscribes to audio debug events and maintains a ring-buffer log.\n *\n * RAF batching: incoming events are queued in a ref and flushed into React\n * state once per animation frame — prevents render storms at 60fps.\n *\n * Only subscribes while `active` is true (panel tab is visible).\n */\nexport function useAudioEventLog(active: boolean): UseAudioEventLogResult {\n const [events, setEvents] = useState<AudioLogEntry[]>([]);\n const [syncIntervalMs, setSyncIntervalMs] = useState<number | null>(null);\n const [kindCounts, setKindCounts] = useState<Partial<Record<AudioEventKind, number>>>({});\n const [seekRate, setSeekRate] = useState(0);\n\n // Refs — mutated in the emitter callback without triggering renders\n const queueRef = useRef<AudioLogEntry[]>([]);\n const counterRef = useRef(0);\n const lastSyncTs = useRef<number | null>(null);\n const seekTimestamps = useRef<number[]>([]);\n const kindCountsRef = useRef<Partial<Record<AudioEventKind, number>>>({});\n\n const clear = useCallback(() => {\n clearAudioEventBuffer();\n queueRef.current = [];\n counterRef.current = 0;\n kindCountsRef.current = {};\n seekTimestamps.current = [];\n lastSyncTs.current = null;\n setEvents([]);\n setSyncIntervalMs(null);\n setKindCounts({});\n setSeekRate(0);\n }, []);\n\n // Subscribe — enqueue events without touching React state\n useEffect(() => {\n if (!active) return;\n\n const unsubscribe = subscribeAudioEvents((event) => {\n const entry: AudioLogEntry = { ...event, id: String(++counterRef.current) };\n queueRef.current.push(entry);\n\n // Track sync interval (no setState — RAF will pick it up)\n if (event.kind === 'sync') {\n if (lastSyncTs.current !== null) {\n const interval = event.ts - lastSyncTs.current;\n // Store on ref; RAF flush will call setSyncIntervalMs\n (entry as AudioLogEntry & { _interval?: number })._interval = interval;\n }\n lastSyncTs.current = event.ts;\n }\n\n // Track seeks\n if (event.kind === 'seek') {\n seekTimestamps.current.push(event.ts);\n }\n\n // Accumulate kind counts on ref\n kindCountsRef.current = {\n ...kindCountsRef.current,\n [event.kind]: (kindCountsRef.current[event.kind] ?? 0) + 1,\n };\n });\n\n return unsubscribe;\n }, [active]);\n\n // RAF flush loop — drains queue into React state once per frame\n useEffect(() => {\n if (!active) return;\n let rafId: number;\n\n const flush = () => {\n if (queueRef.current.length > 0) {\n const incoming = queueRef.current.splice(0);\n\n // Extract sync interval from last sync event in batch\n const lastSync = [...incoming].reverse().find((e) => e.kind === 'sync') as\n | (AudioLogEntry & { _interval?: number })\n | undefined;\n if (lastSync?._interval !== undefined) {\n setSyncIntervalMs(lastSync._interval);\n }\n\n setEvents((prev) => {\n const next = [...prev, ...incoming];\n return next.length > MAX_EVENTS ? next.slice(-MAX_EVENTS) : next;\n });\n\n setKindCounts({ ...kindCountsRef.current });\n }\n rafId = requestAnimationFrame(flush);\n };\n\n rafId = requestAnimationFrame(flush);\n return () => cancelAnimationFrame(rafId);\n }, [active]);\n\n // Rolling seek rate — recompute every second\n useEffect(() => {\n if (!active) return;\n const id = setInterval(() => {\n const now = Date.now();\n seekTimestamps.current = seekTimestamps.current.filter((t) => now - t < 5000);\n setSeekRate(Math.round((seekTimestamps.current.length / 5) * 10) / 10);\n }, 1000);\n return () => clearInterval(id);\n }, [active]);\n\n return { events, clear, seekRate, syncIntervalMs, kindCounts };\n}\n","'use client';\n\nimport React, { useCallback, useState } from 'react';\nimport {\n Button,\n Badge,\n ScrollArea,\n} from '@djangocfg/ui-core/components';\nimport { cn } from '@djangocfg/ui-core/lib';\nimport { Trash2, Radio } from 'lucide-react';\nimport { useAudioEventLog } from '../hooks/useAudioEventLog';\nimport type { AudioEventKind } from '../emitters/audioEmitter';\n\n// ============================================================================\n// Types / constants\n// ============================================================================\n\ntype DebugAudioMode = 'off' | 'on' | 'verbose';\n\nconst DEBUG_MODES: DebugAudioMode[] = ['off', 'on', 'verbose'];\n\nconst KIND_STYLES: Record<AudioEventKind, { label: string; className: string }> = {\n play: { label: 'play', className: 'text-green-400' },\n pause: { label: 'pause', className: 'text-yellow-400' },\n seek: { label: 'seek', className: 'text-blue-400' },\n ended: { label: 'ended', className: 'text-muted-foreground' },\n sync: { label: 'sync', className: 'text-muted-foreground/50' },\n load: { label: 'load', className: 'text-purple-400' },\n error: { label: 'error', className: 'text-red-400' },\n engine: { label: 'eng', className: 'text-cyan-400' },\n custom: { label: 'custom', className: 'text-orange-400' },\n};\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nfunction getDebugAudioMode(): DebugAudioMode {\n try {\n const v = localStorage.getItem('DEBUG_AUDIO');\n if (v === 'verbose') return 'verbose';\n if (v) return 'on';\n } catch { /* ssr */ }\n return 'off';\n}\n\nfunction formatTs(ts: number): string {\n const d = new Date(ts);\n return `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}:${String(d.getSeconds()).padStart(2, '0')}.${String(d.getMilliseconds()).padStart(3, '0')}`;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\ninterface AudioDebugPanelProps {\n isActive: boolean;\n}\n\nexport function AudioDebugPanel({ isActive }: AudioDebugPanelProps) {\n const { events, clear, seekRate, syncIntervalMs, kindCounts } = useAudioEventLog(isActive);\n const [debugMode, setDebugMode] = useState<DebugAudioMode>(getDebugAudioMode);\n\n const handleSetDebugAudio = useCallback((mode: DebugAudioMode) => {\n if (mode === 'off') {\n localStorage.removeItem('DEBUG_AUDIO');\n } else {\n localStorage.setItem('DEBUG_AUDIO', mode === 'verbose' ? 'verbose' : '1');\n }\n setDebugMode(mode);\n }, []);\n\n const kindEntries = Object.entries(kindCounts) as [AudioEventKind, number][];\n const activeKinds = kindEntries.filter(([, count]) => count > 0);\n const reversedEvents = [...events].reverse();\n\n return (\n <div className=\"flex flex-col h-full\">\n {/* Metrics bar */}\n <div className=\"flex flex-wrap items-center gap-2 border-b border-border px-3 py-2 text-xs\">\n <span className=\"text-muted-foreground\">\n Sync interval:{' '}\n <span className=\"text-foreground font-mono\">\n {syncIntervalMs !== null ? `${syncIntervalMs.toFixed(1)}ms` : '—'}\n </span>\n </span>\n <span className=\"text-muted-foreground\">\n Seeks/s: <span className=\"text-foreground font-mono\">{seekRate}</span>\n </span>\n <span className=\"text-muted-foreground\">\n Total: <span className=\"text-foreground font-mono\">{events.length}</span>\n </span>\n\n <div className=\"flex gap-1 flex-wrap ml-auto\">\n {activeKinds.map(([kind, count]) => (\n <Badge key={kind} variant=\"outline\" className={cn('text-[10px] px-1 py-0', KIND_STYLES[kind]?.className)}>\n {KIND_STYLES[kind]?.label ?? kind} {count}\n </Badge>\n ))}\n </div>\n\n <Button variant=\"ghost\" size=\"icon\" className=\"h-6 w-6 ml-1\" onClick={clear}>\n <Trash2 className=\"h-3.5 w-3.5\" />\n </Button>\n </div>\n\n {/* DEBUG_AUDIO toggles */}\n <div className=\"flex items-center gap-1.5 border-b border-border px-3 py-1.5\">\n <span className=\"text-[10px] text-muted-foreground mr-1\">DEBUG_AUDIO:</span>\n {DEBUG_MODES.map((mode) => (\n <button\n key={mode}\n type=\"button\"\n className={cn(\n 'text-[10px] px-2 py-0.5 rounded border transition-colors',\n debugMode === mode\n ? 'border-primary bg-primary/10 text-primary'\n : 'border-border hover:bg-muted text-muted-foreground'\n )}\n onClick={() => handleSetDebugAudio(mode)}\n >\n {mode}\n </button>\n ))}\n </div>\n\n {/* Event log */}\n <ScrollArea className=\"flex-1\">\n {reversedEvents.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center py-10 text-muted-foreground\">\n <Radio className=\"h-8 w-8 mb-2 opacity-40\" />\n <p className=\"text-sm\">No audio events yet</p>\n <p className=\"text-xs mt-1\">\n Wire <code className=\"text-xs\">emitAudioEvent()</code> into your audio engine\n </p>\n </div>\n ) : (\n <div className=\"divide-y divide-border/30\">\n {reversedEvents.map((entry) => {\n const style = KIND_STYLES[entry.kind] ?? { label: entry.kind, className: 'text-foreground' };\n return (\n <div key={entry.id} className=\"flex items-start gap-2 px-3 py-1 text-xs\">\n <span className=\"font-mono text-muted-foreground shrink-0 w-[88px]\">{formatTs(entry.ts)}</span>\n <span className={cn('shrink-0 w-12 font-medium', style.className)}>{style.label}</span>\n {entry.trackId && (\n <span className=\"shrink-0 font-mono text-muted-foreground\">{entry.trackId.slice(0, 6)}</span>\n )}\n <span className=\"truncate text-foreground/80\">{entry.msg}</span>\n </div>\n );\n })}\n </div>\n )}\n </ScrollArea>\n </div>\n );\n}\n","'use client';\n\nimport React, { useMemo, useState, useEffect } from 'react';\nimport { installMonitorBridge } from './bridges';\nimport { MONITOR_VERSION } from '@djangocfg/monitor/client';\nimport {\n Button,\n Badge,\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from '@djangocfg/ui-core/components';\nimport { cn } from '@djangocfg/ui-core/lib';\nimport { useDebugErrorCount } from './logger';\nimport {\n X, Bug, Minimize2, Maximize2,\n ScrollText, Radio,\n} from 'lucide-react';\nimport { useDebugStore } from './store/debugStore';\nimport type { DebugTab } from './store/debugStore';\nimport { LogsPanel } from './panels/LogsPanel';\nimport { AudioDebugPanel } from './panels/AudioDebugPanel';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface CustomDebugTab {\n /** Unique id — will be added to DebugTab union at runtime */\n id: string;\n label: string;\n icon: React.ElementType;\n panel: React.ComponentType<{ isActive: boolean }>;\n}\n\nexport interface DebugPanelProps {\n /** Additional app-specific tabs */\n tabs?: CustomDebugTab[];\n position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';\n defaultHeight?: number;\n defaultWidth?: number;\n}\n\n// ============================================================================\n// Built-in tabs\n// ============================================================================\n\nconst BUILTIN_TABS = [\n { id: 'logs', label: 'Logs', icon: ScrollText },\n { id: 'audio', label: 'Audio', icon: Radio },\n] as const;\n\nconst POSITION_CLASSES: Record<NonNullable<DebugPanelProps['position']>, string> = {\n 'bottom-right': 'bottom-4 right-4',\n 'bottom-left': 'bottom-4 left-4',\n 'top-right': 'top-4 right-4',\n 'top-left': 'top-4 left-4',\n};\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport function DebugPanel({\n tabs: customTabs = [],\n position = 'bottom-left',\n defaultHeight = 480,\n defaultWidth = 560,\n}: DebugPanelProps) {\n const isOpen = useDebugStore((s) => s.isOpen);\n const activeTab = useDebugStore((s) => s.tab);\n const setTab = useDebugStore((s) => s.setTab);\n const close = useDebugStore((s) => s.close);\n const errorCount = useDebugErrorCount();\n\n const [isMinimized, setIsMinimized] = useState(false);\n\n useEffect(() => {\n const unsub = installMonitorBridge();\n return () => unsub?.();\n }, []);\n\n const allTabs = useMemo(() => [\n ...BUILTIN_TABS,\n ...customTabs.map((t) => ({ id: t.id, label: t.label, icon: t.icon })),\n ], [customTabs]);\n\n const panelHeight = isMinimized ? 48 : defaultHeight;\n\n if (!isOpen) return null;\n\n return (\n <div\n className={cn(\n 'fixed z-[100] flex flex-col overflow-hidden rounded-lg border border-border bg-background shadow-xl',\n POSITION_CLASSES[position]\n )}\n style={{ width: defaultWidth, height: panelHeight }}\n >\n {/* Header */}\n <div className=\"flex items-center gap-2 border-b border-border bg-muted/50 px-3 py-2 shrink-0\">\n <Bug className=\"h-4 w-4 text-primary\" />\n <span className=\"text-sm font-medium\">Debug</span>\n <span className=\"text-[10px] text-muted-foreground font-mono\">v{MONITOR_VERSION}</span>\n\n {errorCount > 0 && (\n <Badge variant=\"destructive\" className=\"ml-1 text-[10px]\">{errorCount} errors</Badge>\n )}\n\n {/* Tab bar */}\n {!isMinimized && (\n <div className=\"flex items-center gap-0.5 ml-3\">\n {allTabs.map((tab) => {\n const Icon = tab.icon;\n const isActive = activeTab === tab.id;\n return (\n <button\n key={tab.id}\n type=\"button\"\n onClick={() => setTab(tab.id as DebugTab)}\n className={cn(\n 'flex items-center gap-1.5 px-2 py-0.5 rounded text-xs transition-colors',\n isActive\n ? 'bg-background text-foreground shadow-sm'\n : 'text-muted-foreground hover:text-foreground hover:bg-muted'\n )}\n >\n <Icon className=\"h-3 w-3\" />\n {tab.label}\n </button>\n );\n })}\n </div>\n )}\n\n <div className=\"flex items-center gap-1 ml-auto\">\n <Tooltip>\n <TooltipTrigger asChild>\n <Button variant=\"ghost\" size=\"icon\" className=\"h-6 w-6\" onClick={() => setIsMinimized((v) => !v)}>\n {isMinimized ? <Maximize2 className=\"h-3.5 w-3.5\" /> : <Minimize2 className=\"h-3.5 w-3.5\" />}\n </Button>\n </TooltipTrigger>\n <TooltipContent>{isMinimized ? 'Expand' : 'Minimize'}</TooltipContent>\n </Tooltip>\n <Tooltip>\n <TooltipTrigger asChild>\n <Button variant=\"ghost\" size=\"icon\" className=\"h-6 w-6\" onClick={close}>\n <X className=\"h-3.5 w-3.5\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Close</TooltipContent>\n </Tooltip>\n </div>\n </div>\n\n {/* Panel content */}\n {!isMinimized && (\n <div className=\"flex-1 overflow-hidden\">\n {activeTab === 'logs' && <LogsPanel isActive={activeTab === 'logs'} />}\n {activeTab === 'audio' && <AudioDebugPanel isActive={activeTab === 'audio'} />}\n {customTabs.map((tab) => {\n const Panel = tab.panel;\n return (\n <div key={tab.id} className={cn('h-full', activeTab !== tab.id && 'hidden')}>\n <Panel isActive={activeTab === tab.id} />\n </div>\n );\n })}\n </div>\n )}\n </div>\n );\n}\n","'use client';\n\nimport React, { useCallback, useEffect, useRef } from 'react';\nimport { Bug } from 'lucide-react';\nimport {\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from '@djangocfg/ui-core/components';\nimport { cn, isDev, isProd } from '@djangocfg/ui-core/lib';\nimport { useDebugMode } from '@djangocfg/monitor/client';\nimport { useDebugStore } from './store/debugStore';\nimport { useDebugShortcut } from './hooks/useDebugShortcut';\nimport { useDebugErrorCount } from './logger';\nimport { DebugPanel } from './DebugPanel';\nimport type { DebugPanelProps } from './DebugPanel';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface DebugButtonProps {\n className?: string;\n /** Props forwarded to DebugPanel */\n panel?: Omit<DebugPanelProps, never>;\n /** Start unlocked. Default: true in development (process.env.NODE_ENV === 'development'), false otherwise */\n defaultUnlocked?: boolean;\n}\n\n// ============================================================================\n// Easter-egg: 5 clicks in 2 seconds → unlock\n// ============================================================================\n\nfunction useEasterEgg(onTriggered: () => void) {\n const clicks = useRef<number[]>([]);\n\n return useCallback(() => {\n const now = Date.now();\n clicks.current = [...clicks.current.filter((t) => now - t < 2000), now];\n if (clicks.current.length >= 5) {\n clicks.current = [];\n onTriggered();\n }\n }, [onTriggered]);\n}\n\n// ============================================================================\n// DebugButton\n// ============================================================================\n\nexport function DebugButton({ className, panel = {}, defaultUnlocked = isDev }: DebugButtonProps) {\n const isOpen = useDebugStore((s) => s.isOpen);\n const isUnlocked = useDebugStore((s) => s.isUnlocked);\n const unlock = useDebugStore((s) => s.unlock);\n const toggle = useDebugStore((s) => s.toggle);\n\n const isDebugMode = useDebugMode();\n\n // Auto-unlock when defaultUnlocked or debug mode is active\n useEffect(() => {\n if (defaultUnlocked || isDebugMode) unlock('1');\n }, [defaultUnlocked, isDebugMode, unlock]);\n const errorCount = useDebugErrorCount();\n\n // Don't render in production unless explicitly unlocked via ?debug=1\n if (isProd && !defaultUnlocked && !isDebugMode) return null;\n\n // Keyboard shortcut\n useDebugShortcut();\n\n // Hide Next.js dev indicator badge while panel is open.\n // Uses MutationObserver because <nextjs-portal> is mounted asynchronously after hydration.\n useEffect(() => {\n if (typeof document === 'undefined') return;\n\n const apply = () => {\n document.querySelectorAll<HTMLElement>('nextjs-portal').forEach((el) => {\n el.style.display = isOpen ? 'none' : '';\n });\n };\n\n apply(); // handle already-mounted elements\n\n const observer = new MutationObserver(apply);\n observer.observe(document.body, { childList: true });\n\n return () => observer.disconnect();\n }, [isOpen]);\n\n // Easter-egg: 5 clicks in 2s → unlock directly\n const handleEasterEggClick = useCallback(() => { unlock('1'); toggle(); }, [unlock, toggle]);\n const handleEasterEggTrigger = useEasterEgg(handleEasterEggClick);\n\n // Visibility guard: button only shown when explicitly unlocked (?debug=1 or easter egg)\n // Always render invisible click trap for easter-egg regardless of env\n if (!isUnlocked) {\n return (\n <div\n className=\"fixed bottom-5 left-5 w-9 h-9 z-[99999] opacity-0\"\n onClick={handleEasterEggTrigger}\n />\n );\n }\n\n return (\n <>\n {/* Trigger button — hidden when panel is open */}\n {!isOpen && (\n <div className=\"fixed bottom-5 left-16 z-[99999]\">\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n className={cn(\n 'relative w-9 h-9 flex items-center justify-center rounded-full',\n 'bg-black/80 backdrop-blur-xl',\n 'shadow-[0_0_0_1px_#171717,inset_0_0_0_1px_hsla(0,0%,100%,0.14),0px_16px_32px_-8px_rgba(0,0,0,0.24)]',\n 'transition-all duration-150 hover:scale-105',\n 'focus:outline-none focus-visible:ring-2 focus-visible:ring-white/50',\n errorCount > 0 && 'bg-red-600/90',\n className\n )}\n onClick={toggle}\n >\n <Bug className={cn('h-4 w-4', errorCount > 0 ? 'text-white' : 'text-white/80')} />\n {errorCount > 0 && (\n <span className=\"absolute -right-1 -top-1 flex h-4 min-w-4 items-center justify-center rounded-full bg-white text-[10px] font-semibold text-red-600 shadow-sm\">\n {errorCount}\n </span>\n )}\n </button>\n </TooltipTrigger>\n <TooltipContent side=\"top\">Debug Panel <kbd className=\"ml-1 text-[10px] opacity-60\">⌘D</kbd></TooltipContent>\n </Tooltip>\n </div>\n )}\n\n <DebugPanel {...panel} />\n </>\n );\n}\n","'use client';\n\nimport { useState, useEffect, useRef } from 'react';\n\n// ============================================================================\n// Shallow equal (avoids unnecessary re-renders)\n// ============================================================================\n\nfunction shallowEqual(a: unknown, b: unknown): boolean {\n if (a === b) return true;\n if (typeof a !== 'object' || typeof b !== 'object') return false;\n if (a === null || b === null) return false;\n const keysA = Object.keys(a as object);\n const keysB = Object.keys(b as object);\n if (keysA.length !== keysB.length) return false;\n for (const key of keysA) {\n if ((a as Record<string, unknown>)[key] !== (b as Record<string, unknown>)[key]) return false;\n }\n return true;\n}\n\n// ============================================================================\n// Hook\n// ============================================================================\n\n/**\n * Polling-based external Zustand store snapshot.\n *\n * Reads the store state via `getState()` on an interval — NOT via reactive\n * subscription. This prevents debug panel renders from being triggered by\n * high-frequency store updates and avoids Zustand v5 infinite loop issues\n * (returning new object references from selectors without useShallow).\n *\n * Only polls while `active` is true (panel tab is visible).\n *\n * @param getState A stable function that returns the current store state slice.\n * Use `() => useMyStore.getState()` — the hook ref-stabilizes it.\n * @param intervalMs Poll interval in ms. Default 200ms.\n * @param active Whether to poll. Pass `isActive` from panel props.\n *\n * @example\n * const snap = useStoreSnapshot(\n * () => useTimelineStore.getState(),\n * 200,\n * isActive\n * );\n */\nexport function useStoreSnapshot<T>(\n getState: () => T,\n intervalMs = 200,\n active = true,\n): T {\n const getStateRef = useRef(getState);\n getStateRef.current = getState;\n\n const [snapshot, setSnapshot] = useState<T>(() => getState());\n\n useEffect(() => {\n if (!active) return;\n\n const id = setInterval(() => {\n const next = getStateRef.current();\n setSnapshot((prev) => (shallowEqual(prev, next) ? prev : next));\n }, intervalMs);\n\n return () => clearInterval(id);\n }, [active, intervalMs]);\n\n return snapshot;\n}\n","'use client';\n\nimport React from 'react';\nimport { ScrollArea } from '@djangocfg/ui-core/components';\nimport { LazyJsonTree } from '@djangocfg/ui-tools';\nimport { Database } from 'lucide-react';\nimport { useStoreSnapshot } from '../hooks/useStoreSnapshot';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface StorePanelProps {\n /** Display label shown above the JSON tree */\n label: string;\n /**\n * Getter for the store state slice to display.\n * Use `() => useMyStore.getState()` — stable function ref is not required,\n * the hook handles stabilization internally.\n */\n getState: () => Record<string, unknown>;\n /**\n * Poll interval in ms. Default 200ms.\n * Use higher values for stores that update very frequently.\n */\n intervalMs?: number;\n /** Only polls when active (panel tab is visible) */\n isActive: boolean;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\n/**\n * Generic Zustand store viewer for the debug panel.\n *\n * Uses polling (not reactive subscription) to read external store state.\n * This avoids Zustand v5 infinite loop issues and prevents the debug panel\n * from re-rendering on every store change.\n *\n * @example — in consuming app's custom tab:\n * import { StorePanel } from '@org/debuger';\n * import { useTimelineStore } from '@stores/timelineStore';\n *\n * <StorePanel\n * label=\"Timeline Store\"\n * getState={() => useTimelineStore.getState()}\n * isActive={isActive}\n * />\n */\nexport function StorePanel({ label, getState, intervalMs = 200, isActive }: StorePanelProps) {\n const snapshot = useStoreSnapshot(getState, intervalMs, isActive);\n\n return (\n <div className=\"flex flex-col h-full\">\n <div className=\"flex items-center gap-2 border-b border-border px-3 py-2 shrink-0\">\n <Database className=\"h-3.5 w-3.5 text-muted-foreground\" />\n <span className=\"text-xs font-medium text-muted-foreground\">{label}</span>\n <span className=\"ml-auto text-[10px] text-muted-foreground/60\">\n polling {intervalMs}ms\n </span>\n </div>\n <ScrollArea className=\"flex-1\">\n <div className=\"p-2\">\n <LazyJsonTree data={snapshot} mode=\"full\" />\n </div>\n </ScrollArea>\n </div>\n );\n}\n","'use client';\n\nimport { useState, useEffect, useRef, useCallback } from 'react';\nimport { subscribeCustomEvents } from '../emitters/customEmitter';\nimport type { CustomDebugEvent } from '../emitters/customEmitter';\n\nexport interface CustomLogEntry extends CustomDebugEvent {\n id: string;\n}\n\nconst MAX_EVENTS = 300;\n\n/**\n * Subscribes to custom channel events and maintains a ring-buffer per channel.\n * Pass `channel` to filter — or undefined to receive all channels.\n */\nexport function useCustomEventLog(active: boolean, channel?: string) {\n const [events, setEvents] = useState<CustomLogEntry[]>([]);\n const counterRef = useRef(0);\n\n const clear = useCallback(() => setEvents([]), []);\n\n useEffect(() => {\n if (!active) return;\n\n const unsubscribe = subscribeCustomEvents((event) => {\n if (channel && event.channel !== channel) return;\n const entry: CustomLogEntry = { ...event, id: String(++counterRef.current) };\n setEvents((prev) => {\n const next = [...prev, entry];\n return next.length > MAX_EVENTS ? next.slice(-MAX_EVENTS) : next;\n });\n });\n\n return unsubscribe;\n }, [active, channel]);\n\n return { events, clear };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/store/debugStore.ts","../src/hooks/useDebugShortcut.ts","../src/bridges/monitorBridge.ts","../src/panels/LogsPanel.tsx","../src/hooks/useAudioEventLog.ts","../src/panels/AudioDebugPanel.tsx","../src/DebugPanel.tsx","../src/DebugButton.tsx","../src/hooks/useStoreSnapshot.ts","../src/panels/StorePanel.tsx","../src/hooks/useCustomEventLog.ts"],"names":["isDev","useState","useRef","useCallback","useEffect","jsxs","jsx","Badge","cn","Button","Trash2","Radio","Bug","Tooltip","TooltipTrigger","TooltipContent","ScrollArea","LazyJsonTree","MAX_EVENTS"],"mappings":"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","file":"index.mjs","sourcesContent":["'use client';\n\nimport { create } from 'zustand';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport type DebugTab = 'logs' | 'audio' | 'pipeline' | 'custom';\n\nexport interface DebugStore {\n isOpen: boolean;\n tab: DebugTab;\n isUnlocked: boolean;\n open: () => void;\n close: () => void;\n toggle: () => void;\n setTab: (t: DebugTab) => void;\n unlock: (key: string) => boolean;\n}\n\n// ============================================================================\n// Store\n// ============================================================================\n\nexport const useDebugStore = create<DebugStore>((set) => ({\n isOpen: false,\n tab: 'logs',\n isUnlocked: false,\n\n open: () => set({ isOpen: true }),\n close: () => set({ isOpen: false }),\n toggle: () => set((s) => ({ isOpen: !s.isOpen })),\n setTab: (tab) => set({ tab }),\n\n unlock: (_key) => {\n // Any non-empty value unlocks — no secret key required\n const valid = true;\n if (valid) set({ isUnlocked: true });\n return valid;\n },\n}));\n","'use client';\n\nimport { useHotkey } from '@djangocfg/ui-core/hooks';\nimport { useDebugStore } from '../store/debugStore';\n\n/**\n * Registers a global keyboard shortcut to toggle the debug panel.\n * Default: Cmd+D (meta+d) on Mac / Win+D on Windows.\n *\n * Guards:\n * - In production: only fires if `isUnlocked === true`\n */\nexport function useDebugShortcut(): void {\n const toggle = useDebugStore((s) => s.toggle);\n const isUnlocked = useDebugStore((s) => s.isUnlocked);\n const isDev = typeof process !== 'undefined' && process.env?.NODE_ENV !== 'production';\n\n useHotkey(\n 'meta+d',\n (e) => {\n e.preventDefault();\n if (!isDev && !isUnlocked) return;\n toggle();\n },\n { preventDefault: true },\n );\n}\n","'use client';\n\n/**\n * monitorBridge — subscribes to @djangocfg/monitor store and forwards\n * captured events into debugger's logStore.\n *\n * Call once at app startup (e.g. inside DebugPanel or a provider).\n * Safe to call multiple times — only installs one subscription.\n *\n * @example\n * import { installMonitorBridge } from '@djangocfg/debuger/bridges'\n * installMonitorBridge()\n */\n\nimport { monitorStore, EventLevel } from '@djangocfg/monitor/client';\nimport { useDebugLogStore } from '../logger/logStore';\nimport type { LogLevel } from '../logger/types';\n\nlet _installed = false;\n\nexport function installMonitorBridge(): (() => void) | undefined {\n if (typeof window === 'undefined') return;\n if (_installed) return;\n\n let prevLen = monitorStore.getState().buffer.length;\n\n const unsub = monitorStore.subscribe((state) => {\n const buffer = state.buffer;\n if (buffer.length <= prevLen) { prevLen = buffer.length; return; }\n const newEvents = buffer.slice(prevLen);\n prevLen = buffer.length;\n\n for (const event of newEvents) {\n const level: LogLevel =\n event.level === EventLevel.ERROR ? 'error'\n : event.level === EventLevel.WARNING ? 'warn'\n : 'info';\n\n useDebugLogStore.getState().addLog({\n level,\n component: `monitor:${event.event_type ?? 'event'}`,\n message: event.message ?? '',\n data: {\n ...(event.url && { url: event.url }),\n ...(event.session_id && { session_id: event.session_id }),\n ...(event.http_status !== undefined && {\n http_status: event.http_status,\n http_method: event.http_method,\n http_url: event.http_url,\n }),\n ...(event.extra ? { extra: event.extra } : {}),\n },\n stack: event.stack_trace,\n });\n }\n });\n\n _installed = true;\n return () => {\n unsub();\n _installed = false;\n };\n}\n","'use client';\n\nimport React, { useState, useCallback, useEffect, useRef } from 'react';\nimport {\n useDebugLogStore,\n useDebugFilteredLogs,\n useDebugLogCount,\n useDebugErrorCount,\n type LogLevel,\n type LogEntry,\n} from '../logger';\nimport {\n Button,\n CopyButton,\n Badge,\n Input,\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from '@djangocfg/ui-core/components';\nimport { LazyJsonTree } from '@djangocfg/ui-tools';\nimport { useVirtualizer, type VirtualItem } from '@tanstack/react-virtual';\nimport {\n Bug, Trash2, Download, ChevronDown, ChevronUp,\n AlertCircle, Info, AlertTriangle, CheckCircle, Search,\n} from 'lucide-react';\nimport { cn } from '@djangocfg/ui-core/lib';\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst ROW_ESTIMATE_PX = 32;\nconst OVERSCAN = 5;\n\nconst LOG_LEVEL_CONFIG: Record<LogLevel, { icon: React.ElementType; color: string }> = {\n debug: { icon: Bug, color: 'text-muted-foreground' },\n info: { icon: Info, color: 'text-blue-500' },\n warn: { icon: AlertTriangle, color: 'text-yellow-500' },\n error: { icon: AlertCircle, color: 'text-red-500' },\n success: { icon: CheckCircle, color: 'text-green-500' },\n};\n\nconst LOG_LEVELS = Object.keys(LOG_LEVEL_CONFIG) as LogLevel[];\n\n// ============================================================================\n// LogEntryRow\n// ============================================================================\n\ninterface LogEntryRowProps {\n entry: LogEntry;\n expanded: boolean;\n onToggle: () => void;\n}\n\nfunction LogEntryRow({ entry, expanded, onToggle }: LogEntryRowProps) {\n const config = LOG_LEVEL_CONFIG[entry.level];\n const Icon = config.icon;\n const pad = (n: number, len = 2) => String(n).padStart(len, '0');\n const d = entry.timestamp;\n const time = `${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(d.getSeconds())}.${pad(d.getMilliseconds(), 3)}`;\n const hasData = entry.data && Object.keys(entry.data).length > 0;\n const hasStack = !!entry.stack;\n const isExpandable = hasData || hasStack;\n\n return (\n <div className=\"border-b border-border/50 last:border-0\">\n <button\n type=\"button\"\n onClick={isExpandable ? onToggle : undefined}\n disabled={!isExpandable}\n className={cn(\n 'flex w-full items-start gap-2 px-3 py-1.5 text-left text-xs',\n isExpandable ? 'hover:bg-muted/50 cursor-pointer' : 'cursor-default'\n )}\n >\n <Icon className={cn('h-3.5 w-3.5 mt-0.5 shrink-0', config.color)} />\n <span className=\"text-muted-foreground font-mono shrink-0\">{time}</span>\n <Badge variant=\"outline\" className=\"shrink-0 text-[10px] px-1 py-0\">{entry.component}</Badge>\n <span className=\"flex-1 truncate\">{entry.message}</span>\n {isExpandable && (\n <span className=\"shrink-0 text-muted-foreground\">\n {expanded ? <ChevronUp className=\"h-3 w-3\" /> : <ChevronDown className=\"h-3 w-3\" />}\n </span>\n )}\n </button>\n {expanded && isExpandable && (\n <div className=\"px-3 pb-2 pl-8\">\n {hasData && <div className=\"mt-1\"><LazyJsonTree data={entry.data} mode=\"compact\" /></div>}\n {hasStack && (\n <pre className=\"mt-2 text-[10px] text-red-400 whitespace-pre-wrap font-mono bg-red-950/20 p-2 rounded\">\n {entry.stack}\n </pre>\n )}\n </div>\n )}\n </div>\n );\n}\n\n// ============================================================================\n// LogsPanel\n// ============================================================================\n\nexport function LogsPanel({ isActive }: { isActive: boolean }) {\n const [expandedLogs, setExpandedLogs] = useState<Set<string>>(new Set());\n const [searchQuery, setSearchQuery] = useState('');\n const [selectedLevels, setSelectedLevels] = useState<Set<LogLevel>>(\n new Set(['debug', 'info', 'warn', 'error', 'success'])\n );\n const [componentFilter, setComponentFilter] = useState('');\n\n const logs = useDebugFilteredLogs();\n const logCount = useDebugLogCount();\n const errorCount = useDebugErrorCount();\n const clearLogs = useDebugLogStore((s) => s.clearLogs);\n const setFilter = useDebugLogStore((s) => s.setFilter);\n const exportLogs = useDebugLogStore((s) => s.exportLogs);\n\n // Virtualizer\n const scrollRef = useRef<HTMLDivElement>(null);\n const virtualizer = useVirtualizer({\n count: logs.length,\n getScrollElement: () => scrollRef.current,\n estimateSize: () => ROW_ESTIMATE_PX,\n overscan: OVERSCAN,\n });\n\n useEffect(() => {\n if (!isActive) return;\n setFilter({\n levels: Array.from(selectedLevels),\n component: componentFilter || undefined,\n search: searchQuery || undefined,\n });\n }, [isActive, selectedLevels, componentFilter, searchQuery, setFilter]);\n\n const handleToggleExpand = useCallback((id: string) => {\n setExpandedLogs((prev) => {\n const next = new Set(prev);\n next.has(id) ? next.delete(id) : next.add(id);\n return next;\n });\n }, []);\n\n const handleToggleLevel = useCallback((level: LogLevel) => {\n setSelectedLevels((prev) => {\n const next = new Set(prev);\n next.has(level) ? next.delete(level) : next.add(level);\n return next;\n });\n }, []);\n\n const handleExport = useCallback(() => {\n const json = exportLogs();\n const blob = new Blob([json], { type: 'application/json' });\n const url = URL.createObjectURL(blob);\n const a = document.createElement('a');\n a.href = url;\n a.download = `debug-logs-${new Date().toISOString().slice(0, 19).replace(/:/g, '-')}.json`;\n a.click();\n URL.revokeObjectURL(url);\n }, [exportLogs]);\n\n const handleClear = useCallback(() => {\n clearLogs();\n setExpandedLogs(new Set());\n }, [clearLogs]);\n\n const logsJson = exportLogs();\n const virtualItems = virtualizer.getVirtualItems();\n const totalSize = virtualizer.getTotalSize();\n\n return (\n <div className=\"flex flex-col h-full\">\n {/* Stats */}\n <div className=\"flex items-center gap-2 border-b border-border px-3 py-1.5 shrink-0\">\n <Badge variant=\"secondary\" className=\"text-[10px]\">{logCount} logs</Badge>\n {errorCount > 0 && <Badge variant=\"destructive\" className=\"text-[10px]\">{errorCount} errors</Badge>}\n </div>\n\n {/* Filters */}\n <div className=\"flex flex-wrap items-center gap-2 border-b border-border px-3 py-2 shrink-0\">\n <div className=\"relative flex-1 min-w-[140px]\">\n <Search className=\"absolute left-2 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-muted-foreground\" />\n <Input\n placeholder=\"Search...\"\n value={searchQuery}\n onChange={(e) => setSearchQuery(e.target.value)}\n className=\"h-7 pl-7 text-xs\"\n />\n </div>\n <Input\n placeholder=\"Component...\"\n value={componentFilter}\n onChange={(e) => setComponentFilter(e.target.value)}\n className=\"h-7 w-24 text-xs\"\n />\n <div className=\"flex items-center gap-0.5\">\n {LOG_LEVELS.map((level) => {\n const { icon: Icon, color } = LOG_LEVEL_CONFIG[level];\n const active = selectedLevels.has(level);\n return (\n <Tooltip key={level}>\n <TooltipTrigger asChild>\n <Button variant={active ? 'secondary' : 'ghost'} size=\"icon\" className=\"h-6 w-6\" onClick={() => handleToggleLevel(level)}>\n <Icon className={cn('h-3.5 w-3.5', active && color)} />\n </Button>\n </TooltipTrigger>\n <TooltipContent>{level}</TooltipContent>\n </Tooltip>\n );\n })}\n </div>\n <div className=\"flex items-center gap-0.5 ml-auto\">\n <CopyButton value={logsJson} size=\"icon\" className=\"h-6 w-6\" />\n <Tooltip>\n <TooltipTrigger asChild>\n <Button variant=\"ghost\" size=\"icon\" className=\"h-6 w-6\" onClick={handleExport}>\n <Download className=\"h-3.5 w-3.5\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Export JSON</TooltipContent>\n </Tooltip>\n <Tooltip>\n <TooltipTrigger asChild>\n <Button variant=\"ghost\" size=\"icon\" className=\"h-6 w-6\" onClick={handleClear}>\n <Trash2 className=\"h-3.5 w-3.5\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Clear</TooltipContent>\n </Tooltip>\n </div>\n </div>\n\n {/* Virtualized log list */}\n <div ref={scrollRef} className=\"flex-1 overflow-auto\">\n {logs.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center py-10 text-muted-foreground\">\n <Bug className=\"h-8 w-8 mb-2 opacity-40\" />\n <p className=\"text-sm\">No logs yet</p>\n </div>\n ) : (\n <div style={{ height: `${totalSize}px`, position: 'relative' }}>\n {virtualItems.map((vItem: VirtualItem) => {\n const entry = logs[vItem.index];\n return (\n <div\n key={entry.id}\n data-index={vItem.index}\n ref={virtualizer.measureElement}\n style={{ position: 'absolute', top: 0, left: 0, width: '100%', transform: `translateY(${vItem.start}px)` }}\n >\n <LogEntryRow\n entry={entry}\n expanded={expandedLogs.has(entry.id)}\n onToggle={() => handleToggleExpand(entry.id)}\n />\n </div>\n );\n })}\n </div>\n )}\n </div>\n </div>\n );\n}\n","'use client';\n\nimport { useState, useEffect, useRef, useCallback } from 'react';\nimport { subscribeAudioEvents, clearAudioEventBuffer } from '../emitters/audioEmitter';\nimport type { AudioDebugEvent, AudioEventKind } from '../emitters/audioEmitter';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface AudioLogEntry extends AudioDebugEvent {\n /** Local unique key for React rendering */\n id: string;\n}\n\nexport interface UseAudioEventLogResult {\n events: AudioLogEntry[];\n clear: () => void;\n /** Seek events per second (rolling 5s window) */\n seekRate: number;\n /** Average interval between 'sync' ticks in ms (e.g. RAF loop cadence) */\n syncIntervalMs: number | null;\n /** Running count per event kind */\n kindCounts: Partial<Record<AudioEventKind, number>>;\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\nconst MAX_EVENTS = 200;\n\n// ============================================================================\n// Hook\n// ============================================================================\n\n/**\n * Subscribes to audio debug events and maintains a ring-buffer log.\n *\n * RAF batching: incoming events are queued in a ref and flushed into React\n * state once per animation frame — prevents render storms at 60fps.\n *\n * Only subscribes while `active` is true (panel tab is visible).\n */\nexport function useAudioEventLog(active: boolean): UseAudioEventLogResult {\n const [events, setEvents] = useState<AudioLogEntry[]>([]);\n const [syncIntervalMs, setSyncIntervalMs] = useState<number | null>(null);\n const [kindCounts, setKindCounts] = useState<Partial<Record<AudioEventKind, number>>>({});\n const [seekRate, setSeekRate] = useState(0);\n\n // Refs — mutated in the emitter callback without triggering renders\n const queueRef = useRef<AudioLogEntry[]>([]);\n const counterRef = useRef(0);\n const lastSyncTs = useRef<number | null>(null);\n const seekTimestamps = useRef<number[]>([]);\n const kindCountsRef = useRef<Partial<Record<AudioEventKind, number>>>({});\n\n const clear = useCallback(() => {\n clearAudioEventBuffer();\n queueRef.current = [];\n counterRef.current = 0;\n kindCountsRef.current = {};\n seekTimestamps.current = [];\n lastSyncTs.current = null;\n setEvents([]);\n setSyncIntervalMs(null);\n setKindCounts({});\n setSeekRate(0);\n }, []);\n\n // Subscribe — enqueue events without touching React state\n useEffect(() => {\n if (!active) return;\n\n const unsubscribe = subscribeAudioEvents((event) => {\n const entry: AudioLogEntry = { ...event, id: String(++counterRef.current) };\n queueRef.current.push(entry);\n\n // Track sync interval (no setState — RAF will pick it up)\n if (event.kind === 'sync') {\n if (lastSyncTs.current !== null) {\n const interval = event.ts - lastSyncTs.current;\n // Store on ref; RAF flush will call setSyncIntervalMs\n (entry as AudioLogEntry & { _interval?: number })._interval = interval;\n }\n lastSyncTs.current = event.ts;\n }\n\n // Track seeks\n if (event.kind === 'seek') {\n seekTimestamps.current.push(event.ts);\n }\n\n // Accumulate kind counts on ref\n kindCountsRef.current = {\n ...kindCountsRef.current,\n [event.kind]: (kindCountsRef.current[event.kind] ?? 0) + 1,\n };\n });\n\n return unsubscribe;\n }, [active]);\n\n // RAF flush loop — drains queue into React state once per frame\n useEffect(() => {\n if (!active) return;\n let rafId: number;\n\n const flush = () => {\n if (queueRef.current.length > 0) {\n const incoming = queueRef.current.splice(0);\n\n // Extract sync interval from last sync event in batch\n const lastSync = [...incoming].reverse().find((e) => e.kind === 'sync') as\n | (AudioLogEntry & { _interval?: number })\n | undefined;\n if (lastSync?._interval !== undefined) {\n setSyncIntervalMs(lastSync._interval);\n }\n\n setEvents((prev) => {\n const next = [...prev, ...incoming];\n return next.length > MAX_EVENTS ? next.slice(-MAX_EVENTS) : next;\n });\n\n setKindCounts({ ...kindCountsRef.current });\n }\n rafId = requestAnimationFrame(flush);\n };\n\n rafId = requestAnimationFrame(flush);\n return () => cancelAnimationFrame(rafId);\n }, [active]);\n\n // Rolling seek rate — recompute every second\n useEffect(() => {\n if (!active) return;\n const id = setInterval(() => {\n const now = Date.now();\n seekTimestamps.current = seekTimestamps.current.filter((t) => now - t < 5000);\n setSeekRate(Math.round((seekTimestamps.current.length / 5) * 10) / 10);\n }, 1000);\n return () => clearInterval(id);\n }, [active]);\n\n return { events, clear, seekRate, syncIntervalMs, kindCounts };\n}\n","'use client';\n\nimport React, { useCallback, useState } from 'react';\nimport {\n Button,\n Badge,\n ScrollArea,\n} from '@djangocfg/ui-core/components';\nimport { cn } from '@djangocfg/ui-core/lib';\nimport { Trash2, Radio } from 'lucide-react';\nimport { useAudioEventLog } from '../hooks/useAudioEventLog';\nimport type { AudioEventKind } from '../emitters/audioEmitter';\n\n// ============================================================================\n// Types / constants\n// ============================================================================\n\ntype DebugAudioMode = 'off' | 'on' | 'verbose';\n\nconst DEBUG_MODES: DebugAudioMode[] = ['off', 'on', 'verbose'];\n\nconst KIND_STYLES: Record<AudioEventKind, { label: string; className: string }> = {\n play: { label: 'play', className: 'text-green-400' },\n pause: { label: 'pause', className: 'text-yellow-400' },\n seek: { label: 'seek', className: 'text-blue-400' },\n ended: { label: 'ended', className: 'text-muted-foreground' },\n sync: { label: 'sync', className: 'text-muted-foreground/50' },\n load: { label: 'load', className: 'text-purple-400' },\n error: { label: 'error', className: 'text-red-400' },\n engine: { label: 'eng', className: 'text-cyan-400' },\n custom: { label: 'custom', className: 'text-orange-400' },\n};\n\n// ============================================================================\n// Helpers\n// ============================================================================\n\nfunction getDebugAudioMode(): DebugAudioMode {\n try {\n const v = localStorage.getItem('DEBUG_AUDIO');\n if (v === 'verbose') return 'verbose';\n if (v) return 'on';\n } catch { /* ssr */ }\n return 'off';\n}\n\nfunction formatTs(ts: number): string {\n const d = new Date(ts);\n return `${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}:${String(d.getSeconds()).padStart(2, '0')}.${String(d.getMilliseconds()).padStart(3, '0')}`;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\ninterface AudioDebugPanelProps {\n isActive: boolean;\n}\n\nexport function AudioDebugPanel({ isActive }: AudioDebugPanelProps) {\n const { events, clear, seekRate, syncIntervalMs, kindCounts } = useAudioEventLog(isActive);\n const [debugMode, setDebugMode] = useState<DebugAudioMode>(getDebugAudioMode);\n\n const handleSetDebugAudio = useCallback((mode: DebugAudioMode) => {\n if (mode === 'off') {\n localStorage.removeItem('DEBUG_AUDIO');\n } else {\n localStorage.setItem('DEBUG_AUDIO', mode === 'verbose' ? 'verbose' : '1');\n }\n setDebugMode(mode);\n }, []);\n\n const kindEntries = Object.entries(kindCounts) as [AudioEventKind, number][];\n const activeKinds = kindEntries.filter(([, count]) => count > 0);\n const reversedEvents = [...events].reverse();\n\n return (\n <div className=\"flex flex-col h-full\">\n {/* Metrics bar */}\n <div className=\"flex flex-wrap items-center gap-2 border-b border-border px-3 py-2 text-xs\">\n <span className=\"text-muted-foreground\">\n Sync interval:{' '}\n <span className=\"text-foreground font-mono\">\n {syncIntervalMs !== null ? `${syncIntervalMs.toFixed(1)}ms` : '—'}\n </span>\n </span>\n <span className=\"text-muted-foreground\">\n Seeks/s: <span className=\"text-foreground font-mono\">{seekRate}</span>\n </span>\n <span className=\"text-muted-foreground\">\n Total: <span className=\"text-foreground font-mono\">{events.length}</span>\n </span>\n\n <div className=\"flex gap-1 flex-wrap ml-auto\">\n {activeKinds.map(([kind, count]) => (\n <Badge key={kind} variant=\"outline\" className={cn('text-[10px] px-1 py-0', KIND_STYLES[kind]?.className)}>\n {KIND_STYLES[kind]?.label ?? kind} {count}\n </Badge>\n ))}\n </div>\n\n <Button variant=\"ghost\" size=\"icon\" className=\"h-6 w-6 ml-1\" onClick={clear}>\n <Trash2 className=\"h-3.5 w-3.5\" />\n </Button>\n </div>\n\n {/* DEBUG_AUDIO toggles */}\n <div className=\"flex items-center gap-1.5 border-b border-border px-3 py-1.5\">\n <span className=\"text-[10px] text-muted-foreground mr-1\">DEBUG_AUDIO:</span>\n {DEBUG_MODES.map((mode) => (\n <button\n key={mode}\n type=\"button\"\n className={cn(\n 'text-[10px] px-2 py-0.5 rounded border transition-colors',\n debugMode === mode\n ? 'border-primary bg-primary/10 text-primary'\n : 'border-border hover:bg-muted text-muted-foreground'\n )}\n onClick={() => handleSetDebugAudio(mode)}\n >\n {mode}\n </button>\n ))}\n </div>\n\n {/* Event log */}\n <ScrollArea className=\"flex-1\">\n {reversedEvents.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center py-10 text-muted-foreground\">\n <Radio className=\"h-8 w-8 mb-2 opacity-40\" />\n <p className=\"text-sm\">No audio events yet</p>\n <p className=\"text-xs mt-1\">\n Wire <code className=\"text-xs\">emitAudioEvent()</code> into your audio engine\n </p>\n </div>\n ) : (\n <div className=\"divide-y divide-border/30\">\n {reversedEvents.map((entry) => {\n const style = KIND_STYLES[entry.kind] ?? { label: entry.kind, className: 'text-foreground' };\n return (\n <div key={entry.id} className=\"flex items-start gap-2 px-3 py-1 text-xs\">\n <span className=\"font-mono text-muted-foreground shrink-0 w-[88px]\">{formatTs(entry.ts)}</span>\n <span className={cn('shrink-0 w-12 font-medium', style.className)}>{style.label}</span>\n {entry.trackId && (\n <span className=\"shrink-0 font-mono text-muted-foreground\">{entry.trackId.slice(0, 6)}</span>\n )}\n <span className=\"truncate text-foreground/80\">{entry.msg}</span>\n </div>\n );\n })}\n </div>\n )}\n </ScrollArea>\n </div>\n );\n}\n","'use client';\n\nimport React, { useMemo, useState, useEffect } from 'react';\nimport { installMonitorBridge } from './bridges';\nimport { MONITOR_VERSION } from '@djangocfg/monitor/client';\nimport {\n Button,\n Badge,\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from '@djangocfg/ui-core/components';\nimport { cn } from '@djangocfg/ui-core/lib';\nimport { useDebugErrorCount } from './logger';\nimport {\n X, Bug, Minimize2, Maximize2,\n ScrollText, Radio,\n} from 'lucide-react';\nimport { useDebugStore } from './store/debugStore';\nimport type { DebugTab } from './store/debugStore';\nimport { LogsPanel } from './panels/LogsPanel';\nimport { AudioDebugPanel } from './panels/AudioDebugPanel';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface CustomDebugTab {\n /** Unique id — will be added to DebugTab union at runtime */\n id: string;\n label: string;\n icon: React.ElementType;\n panel: React.ComponentType<{ isActive: boolean }>;\n}\n\nexport interface DebugPanelProps {\n /** Additional app-specific tabs */\n tabs?: CustomDebugTab[];\n position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';\n defaultHeight?: number;\n defaultWidth?: number;\n}\n\n// ============================================================================\n// Built-in tabs\n// ============================================================================\n\nconst BUILTIN_TABS = [\n { id: 'logs', label: 'Logs', icon: ScrollText },\n { id: 'audio', label: 'Audio', icon: Radio },\n] as const;\n\nconst POSITION_CLASSES: Record<NonNullable<DebugPanelProps['position']>, string> = {\n 'bottom-right': 'bottom-4 right-4',\n 'bottom-left': 'bottom-4 left-4',\n 'top-right': 'top-4 right-4',\n 'top-left': 'top-4 left-4',\n};\n\n// ============================================================================\n// Component\n// ============================================================================\n\nexport function DebugPanel({\n tabs: customTabs = [],\n position = 'bottom-left',\n defaultHeight = 480,\n defaultWidth = 560,\n}: DebugPanelProps) {\n const isOpen = useDebugStore((s) => s.isOpen);\n const activeTab = useDebugStore((s) => s.tab);\n const setTab = useDebugStore((s) => s.setTab);\n const close = useDebugStore((s) => s.close);\n const errorCount = useDebugErrorCount();\n\n const [isMinimized, setIsMinimized] = useState(false);\n\n useEffect(() => {\n const unsub = installMonitorBridge();\n return () => unsub?.();\n }, []);\n\n const allTabs = useMemo(() => [\n ...BUILTIN_TABS,\n ...customTabs.map((t) => ({ id: t.id, label: t.label, icon: t.icon })),\n ], [customTabs]);\n\n const panelHeight = isMinimized ? 48 : defaultHeight;\n\n if (!isOpen) return null;\n\n return (\n <div\n className={cn(\n 'fixed z-[100] flex flex-col overflow-hidden rounded-lg border border-border bg-background shadow-xl',\n POSITION_CLASSES[position]\n )}\n style={{ width: defaultWidth, height: panelHeight }}\n >\n {/* Header */}\n <div className=\"flex items-center gap-2 border-b border-border bg-muted/50 px-3 py-2 shrink-0\">\n <Bug className=\"h-4 w-4 text-primary\" />\n <span className=\"text-sm font-medium\">Debug</span>\n <span className=\"text-[10px] text-muted-foreground font-mono\">v{MONITOR_VERSION}</span>\n\n {errorCount > 0 && (\n <Badge variant=\"destructive\" className=\"ml-1 text-[10px]\">{errorCount} errors</Badge>\n )}\n\n {/* Tab bar */}\n {!isMinimized && (\n <div className=\"flex items-center gap-0.5 ml-3\">\n {allTabs.map((tab) => {\n const Icon = tab.icon;\n const isActive = activeTab === tab.id;\n return (\n <button\n key={tab.id}\n type=\"button\"\n onClick={() => setTab(tab.id as DebugTab)}\n className={cn(\n 'flex items-center gap-1.5 px-2 py-0.5 rounded text-xs transition-colors',\n isActive\n ? 'bg-background text-foreground shadow-sm'\n : 'text-muted-foreground hover:text-foreground hover:bg-muted'\n )}\n >\n <Icon className=\"h-3 w-3\" />\n {tab.label}\n </button>\n );\n })}\n </div>\n )}\n\n <div className=\"flex items-center gap-1 ml-auto\">\n <Tooltip>\n <TooltipTrigger asChild>\n <Button variant=\"ghost\" size=\"icon\" className=\"h-6 w-6\" onClick={() => setIsMinimized((v) => !v)}>\n {isMinimized ? <Maximize2 className=\"h-3.5 w-3.5\" /> : <Minimize2 className=\"h-3.5 w-3.5\" />}\n </Button>\n </TooltipTrigger>\n <TooltipContent>{isMinimized ? 'Expand' : 'Minimize'}</TooltipContent>\n </Tooltip>\n <Tooltip>\n <TooltipTrigger asChild>\n <Button variant=\"ghost\" size=\"icon\" className=\"h-6 w-6\" onClick={close}>\n <X className=\"h-3.5 w-3.5\" />\n </Button>\n </TooltipTrigger>\n <TooltipContent>Close</TooltipContent>\n </Tooltip>\n </div>\n </div>\n\n {/* Panel content */}\n {!isMinimized && (\n <div className=\"flex-1 overflow-hidden\">\n {activeTab === 'logs' && <LogsPanel isActive={activeTab === 'logs'} />}\n {activeTab === 'audio' && <AudioDebugPanel isActive={activeTab === 'audio'} />}\n {customTabs.map((tab) => {\n const Panel = tab.panel;\n return (\n <div key={tab.id} className={cn('h-full', activeTab !== tab.id && 'hidden')}>\n <Panel isActive={activeTab === tab.id} />\n </div>\n );\n })}\n </div>\n )}\n </div>\n );\n}\n","'use client';\n\nimport React, { useCallback, useEffect, useRef } from 'react';\nimport { Bug } from 'lucide-react';\nimport {\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from '@djangocfg/ui-core/components';\nimport { cn, isDev } from '@djangocfg/ui-core/lib';\nimport { useDebugMode } from '@djangocfg/monitor/client';\nimport { useDebugStore } from './store/debugStore';\nimport { useDebugShortcut } from './hooks/useDebugShortcut';\nimport { useDebugErrorCount } from './logger';\nimport { DebugPanel } from './DebugPanel';\nimport type { DebugPanelProps } from './DebugPanel';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface DebugButtonProps {\n className?: string;\n /** Props forwarded to DebugPanel */\n panel?: Omit<DebugPanelProps, never>;\n /** Explicitly disable. Default: undefined (auto — visible in dev, hidden in prod, ?debug=1 always works) */\n enabled?: boolean;\n}\n\n// ============================================================================\n// DebugButton\n//\n// Visibility rules (simple):\n// 1. enabled === false AND no ?debug=1 → hidden completely\n// 2. isDev OR ?debug=1 (localStorage) → visible (unlocked)\n// 3. prod without ?debug=1 → invisible click trap (easter egg: 5 clicks)\n// ============================================================================\n\nexport function DebugButton({ className, panel = {}, enabled }: DebugButtonProps) {\n // All hooks called unconditionally (React rules of hooks)\n const isOpen = useDebugStore((s) => s.isOpen);\n const isUnlocked = useDebugStore((s) => s.isUnlocked);\n const unlock = useDebugStore((s) => s.unlock);\n const toggle = useDebugStore((s) => s.toggle);\n const isDebugMode = useDebugMode();\n const errorCount = useDebugErrorCount();\n useDebugShortcut();\n\n // Should this button be visible (unlocked)?\n const shouldUnlock = isDev || isDebugMode;\n\n // eslint-disable-next-line no-console\n if (typeof window !== 'undefined') console.info('[DebugButton]', { isDev, isDebugMode, shouldUnlock, isUnlocked, enabled });\n\n // Auto-unlock in dev or when ?debug=1\n useEffect(() => {\n if (shouldUnlock) unlock('1');\n }, [shouldUnlock, unlock]);\n\n // Hide Next.js dev indicator while panel is open\n useEffect(() => {\n if (typeof document === 'undefined') return;\n const apply = () => {\n document.querySelectorAll<HTMLElement>('nextjs-portal').forEach((el) => {\n el.style.display = isOpen ? 'none' : '';\n });\n };\n apply();\n const observer = new MutationObserver(apply);\n observer.observe(document.body, { childList: true });\n return () => observer.disconnect();\n }, [isOpen]);\n\n // Easter egg: 5 clicks in 2s → unlock\n const clicks = useRef<number[]>([]);\n const handleEasterEgg = useCallback(() => {\n const now = Date.now();\n clicks.current = [...clicks.current.filter((t) => now - t < 2000), now];\n if (clicks.current.length >= 5) {\n clicks.current = [];\n unlock('1');\n toggle();\n }\n }, [unlock, toggle]);\n\n // === Render decision (after all hooks) ===\n\n // Explicitly disabled AND no debug override → don't render at all\n if (enabled === false && !isDebugMode) return null;\n\n // Not unlocked → invisible click trap for easter egg\n if (!isUnlocked) {\n return (\n <div\n className=\"fixed bottom-5 left-5 w-9 h-9 z-[99999] opacity-0 cursor-default\"\n onClick={handleEasterEgg}\n />\n );\n }\n\n // Unlocked → visible debug button\n return (\n <>\n {!isOpen && (\n <div className={cn('fixed bottom-5 z-[99999]', isDev ? 'left-16' : 'left-5')}>\n <Tooltip>\n <TooltipTrigger asChild>\n <button\n type=\"button\"\n className={cn(\n 'relative w-9 h-9 flex items-center justify-center rounded-full',\n 'bg-black/80 backdrop-blur-xl',\n 'shadow-[0_0_0_1px_#171717,inset_0_0_0_1px_hsla(0,0%,100%,0.14),0px_16px_32px_-8px_rgba(0,0,0,0.24)]',\n 'transition-all duration-150 hover:scale-105',\n 'focus:outline-none focus-visible:ring-2 focus-visible:ring-white/50',\n errorCount > 0 && 'bg-red-600/90',\n className,\n )}\n onClick={toggle}\n >\n <Bug className={cn('h-4 w-4', errorCount > 0 ? 'text-white' : 'text-white/80')} />\n {errorCount > 0 && (\n <span className=\"absolute -right-1 -top-1 flex h-4 min-w-4 items-center justify-center rounded-full bg-white text-[10px] font-semibold text-red-600 shadow-sm\">\n {errorCount}\n </span>\n )}\n </button>\n </TooltipTrigger>\n <TooltipContent side=\"top\">Debug Panel <kbd className=\"ml-1 text-[10px] opacity-60\">⌘D</kbd></TooltipContent>\n </Tooltip>\n </div>\n )}\n <DebugPanel {...panel} />\n </>\n );\n}\n","'use client';\n\nimport { useState, useEffect, useRef } from 'react';\n\n// ============================================================================\n// Shallow equal (avoids unnecessary re-renders)\n// ============================================================================\n\nfunction shallowEqual(a: unknown, b: unknown): boolean {\n if (a === b) return true;\n if (typeof a !== 'object' || typeof b !== 'object') return false;\n if (a === null || b === null) return false;\n const keysA = Object.keys(a as object);\n const keysB = Object.keys(b as object);\n if (keysA.length !== keysB.length) return false;\n for (const key of keysA) {\n if ((a as Record<string, unknown>)[key] !== (b as Record<string, unknown>)[key]) return false;\n }\n return true;\n}\n\n// ============================================================================\n// Hook\n// ============================================================================\n\n/**\n * Polling-based external Zustand store snapshot.\n *\n * Reads the store state via `getState()` on an interval — NOT via reactive\n * subscription. This prevents debug panel renders from being triggered by\n * high-frequency store updates and avoids Zustand v5 infinite loop issues\n * (returning new object references from selectors without useShallow).\n *\n * Only polls while `active` is true (panel tab is visible).\n *\n * @param getState A stable function that returns the current store state slice.\n * Use `() => useMyStore.getState()` — the hook ref-stabilizes it.\n * @param intervalMs Poll interval in ms. Default 200ms.\n * @param active Whether to poll. Pass `isActive` from panel props.\n *\n * @example\n * const snap = useStoreSnapshot(\n * () => useTimelineStore.getState(),\n * 200,\n * isActive\n * );\n */\nexport function useStoreSnapshot<T>(\n getState: () => T,\n intervalMs = 200,\n active = true,\n): T {\n const getStateRef = useRef(getState);\n getStateRef.current = getState;\n\n const [snapshot, setSnapshot] = useState<T>(() => getState());\n\n useEffect(() => {\n if (!active) return;\n\n const id = setInterval(() => {\n const next = getStateRef.current();\n setSnapshot((prev) => (shallowEqual(prev, next) ? prev : next));\n }, intervalMs);\n\n return () => clearInterval(id);\n }, [active, intervalMs]);\n\n return snapshot;\n}\n","'use client';\n\nimport React from 'react';\nimport { ScrollArea } from '@djangocfg/ui-core/components';\nimport { LazyJsonTree } from '@djangocfg/ui-tools';\nimport { Database } from 'lucide-react';\nimport { useStoreSnapshot } from '../hooks/useStoreSnapshot';\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface StorePanelProps {\n /** Display label shown above the JSON tree */\n label: string;\n /**\n * Getter for the store state slice to display.\n * Use `() => useMyStore.getState()` — stable function ref is not required,\n * the hook handles stabilization internally.\n */\n getState: () => Record<string, unknown>;\n /**\n * Poll interval in ms. Default 200ms.\n * Use higher values for stores that update very frequently.\n */\n intervalMs?: number;\n /** Only polls when active (panel tab is visible) */\n isActive: boolean;\n}\n\n// ============================================================================\n// Component\n// ============================================================================\n\n/**\n * Generic Zustand store viewer for the debug panel.\n *\n * Uses polling (not reactive subscription) to read external store state.\n * This avoids Zustand v5 infinite loop issues and prevents the debug panel\n * from re-rendering on every store change.\n *\n * @example — in consuming app's custom tab:\n * import { StorePanel } from '@org/debuger';\n * import { useTimelineStore } from '@stores/timelineStore';\n *\n * <StorePanel\n * label=\"Timeline Store\"\n * getState={() => useTimelineStore.getState()}\n * isActive={isActive}\n * />\n */\nexport function StorePanel({ label, getState, intervalMs = 200, isActive }: StorePanelProps) {\n const snapshot = useStoreSnapshot(getState, intervalMs, isActive);\n\n return (\n <div className=\"flex flex-col h-full\">\n <div className=\"flex items-center gap-2 border-b border-border px-3 py-2 shrink-0\">\n <Database className=\"h-3.5 w-3.5 text-muted-foreground\" />\n <span className=\"text-xs font-medium text-muted-foreground\">{label}</span>\n <span className=\"ml-auto text-[10px] text-muted-foreground/60\">\n polling {intervalMs}ms\n </span>\n </div>\n <ScrollArea className=\"flex-1\">\n <div className=\"p-2\">\n <LazyJsonTree data={snapshot} mode=\"full\" />\n </div>\n </ScrollArea>\n </div>\n );\n}\n","'use client';\n\nimport { useState, useEffect, useRef, useCallback } from 'react';\nimport { subscribeCustomEvents } from '../emitters/customEmitter';\nimport type { CustomDebugEvent } from '../emitters/customEmitter';\n\nexport interface CustomLogEntry extends CustomDebugEvent {\n id: string;\n}\n\nconst MAX_EVENTS = 300;\n\n/**\n * Subscribes to custom channel events and maintains a ring-buffer per channel.\n * Pass `channel` to filter — or undefined to receive all channels.\n */\nexport function useCustomEventLog(active: boolean, channel?: string) {\n const [events, setEvents] = useState<CustomLogEntry[]>([]);\n const counterRef = useRef(0);\n\n const clear = useCallback(() => setEvents([]), []);\n\n useEffect(() => {\n if (!active) return;\n\n const unsubscribe = subscribeCustomEvents((event) => {\n if (channel && event.channel !== channel) return;\n const entry: CustomLogEntry = { ...event, id: String(++counterRef.current) };\n setEvents((prev) => {\n const next = [...prev, entry];\n return next.length > MAX_EVENTS ? next.slice(-MAX_EVENTS) : next;\n });\n });\n\n return unsubscribe;\n }, [active, channel]);\n\n return { events, clear };\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@djangocfg/debuger",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.235",
|
|
4
4
|
"description": "Floating debug panel for DjangoCFG — logs, store inspection, monitor bridge, Cmd+D shortcut",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"debug",
|
|
@@ -63,10 +63,10 @@
|
|
|
63
63
|
"react-dom": "^19.1.0",
|
|
64
64
|
"zustand": "^5.0.0",
|
|
65
65
|
"consola": "^3.4.2",
|
|
66
|
-
"@djangocfg/ui-core": "^2.1.
|
|
67
|
-
"@djangocfg/ui-tools": "^2.1.
|
|
66
|
+
"@djangocfg/ui-core": "^2.1.235",
|
|
67
|
+
"@djangocfg/ui-tools": "^2.1.235",
|
|
68
68
|
"@tanstack/react-virtual": "^3.0.0",
|
|
69
|
-
"@djangocfg/monitor": "^2.1.
|
|
69
|
+
"@djangocfg/monitor": "^2.1.235",
|
|
70
70
|
"lucide-react": ">=0.400.0"
|
|
71
71
|
},
|
|
72
72
|
"peerDependenciesMeta": {
|
|
@@ -78,8 +78,8 @@
|
|
|
78
78
|
}
|
|
79
79
|
},
|
|
80
80
|
"devDependencies": {
|
|
81
|
-
"@djangocfg/typescript-config": "^2.1.
|
|
82
|
-
"@djangocfg/monitor": "^2.1.
|
|
81
|
+
"@djangocfg/typescript-config": "^2.1.235",
|
|
82
|
+
"@djangocfg/monitor": "^2.1.235",
|
|
83
83
|
"lucide-react": "^0.545.0",
|
|
84
84
|
"@types/node": "^25.2.3",
|
|
85
85
|
"@types/react": "^19.1.0",
|