@mugenlabs/logtape-devtools 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/store.ts","../src/plugin/logtape-devtools-plugin.tsx","../src/plugin/components/log-list.tsx","../src/plugin/theme.ts","../src/plugin/components/log-row.tsx","../src/plugin/icons.tsx","../src/plugin/components/level-badge.tsx","../src/plugin/components/log-detail.tsx","../src/plugin/components/toolbar.tsx","../src/types.ts","../src/plugin/create-logtape-devtools-plugin.tsx","../src/sink.ts"],"sourcesContent":["import type { DevtoolsLogRecord } from \"./types\";\n\ntype Listener = () => void;\n\nexport interface LogStore {\n addRecord(record: DevtoolsLogRecord): void;\n clear(): void;\n getSnapshot(): DevtoolsLogRecord[];\n setMaxSize(size: number): void;\n subscribe(listener: Listener): () => void;\n}\n\nexport function createLogStore(maxSize = 1000): LogStore {\n let records: DevtoolsLogRecord[] = [];\n let max = maxSize;\n const listeners = new Set<Listener>();\n\n function notify() {\n for (const listener of listeners) {\n listener();\n }\n }\n\n return {\n getSnapshot: () => records,\n addRecord: (record) => {\n // Create new array reference for useSyncExternalStore\n records = [...records, record];\n if (records.length > max) {\n records = records.slice(records.length - max);\n }\n notify();\n },\n clear: () => {\n records = [];\n notify();\n },\n subscribe: (listener) => {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n setMaxSize: (size) => {\n max = size;\n if (records.length > max) {\n records = records.slice(records.length - max);\n notify();\n }\n },\n };\n}\n\n/** Default shared store instance used when no custom store is provided */\nexport const defaultLogStore = createLogStore();\n","import { useCallback, useMemo, useState, useSyncExternalStore } from \"react\";\nimport type { LogStore } from \"../store\";\nimport type { DevtoolsLogRecord, LogLevel } from \"../types\";\nimport { LogList } from \"./components/log-list\";\nimport { Toolbar } from \"./components/toolbar\";\nimport { PanelLeftCloseIcon, PanelLeftOpenIcon, PauseIcon, PlayIcon, Trash2Icon } from \"./icons\";\nimport { theme } from \"./theme\";\n\ninterface Props {\n store: LogStore;\n}\n\nexport const LogTapeDevtoolsPlugin = ({ store }: Props) => {\n const allRecords = useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);\n\n const [paused, setPaused] = useState(false);\n const [pausedRecords, setPausedRecords] = useState<DevtoolsLogRecord[]>([]);\n const [levelFilter, setLevelFilter] = useState<Set<LogLevel>>(new Set());\n const [categoryFilter, setCategoryFilter] = useState<string[]>([]);\n const [searchText, setSearchText] = useState(\"\");\n const [expandedId, setExpandedId] = useState<string | null>(null);\n const [sidebarOpen, setSidebarOpen] = useState(true);\n\n const handlePause = useCallback(() => {\n setPaused(true);\n setPausedRecords(store.getSnapshot());\n }, [store]);\n\n const handleResume = useCallback(() => {\n setPaused(false);\n setPausedRecords([]);\n }, []);\n\n const handleClear = useCallback(() => {\n store.clear();\n setPausedRecords([]);\n setExpandedId(null);\n }, [store]);\n\n const records = paused ? pausedRecords : allRecords;\n\n const uniqueCategories = useMemo(() => {\n const seen = new Set<string>();\n for (const r of records) {\n seen.add(r.category.join(\".\"));\n }\n return Array.from(seen).sort();\n }, [records]);\n\n const filteredRecords = useMemo(() => {\n return records.filter((r) => {\n if (levelFilter.size > 0 && !levelFilter.has(r.level)) {\n return false;\n }\n if (categoryFilter.length > 0 && !categoryFilter.includes(r.category.join(\".\"))) {\n return false;\n }\n if (searchText) {\n const term = searchText.toLowerCase();\n if (\n !(\n r.messageText.toLowerCase().includes(term) ||\n r.category.join(\".\").toLowerCase().includes(term)\n )\n ) {\n return false;\n }\n }\n return true;\n });\n }, [records, levelFilter, categoryFilter, searchText]);\n\n return (\n <div\n style={{\n background: theme.colors.background,\n color: theme.colors.textPrimary,\n display: \"flex\",\n flexDirection: \"row\",\n fontFamily: theme.fontFamily.sans,\n height: \"100%\",\n overflow: \"hidden\",\n }}\n >\n <div\n style={{\n borderRight: sidebarOpen ? `1px solid ${theme.colors.border}` : \"none\",\n flexShrink: 0,\n opacity: sidebarOpen ? 1 : 0,\n overflow: \"hidden\",\n transition: \"width 0.2s ease, opacity 0.15s ease\",\n width: sidebarOpen ? \"200px\" : \"0px\",\n }}\n >\n <Toolbar\n categories={uniqueCategories}\n categoryFilter={categoryFilter}\n filteredCount={filteredRecords.length}\n levelFilter={levelFilter}\n onCategoryFilterChange={setCategoryFilter}\n onClear={handleClear}\n onLevelFilterChange={setLevelFilter}\n onPause={handlePause}\n onResume={handleResume}\n onSearchTextChange={setSearchText}\n paused={paused}\n searchText={searchText}\n totalCount={records.length}\n />\n </div>\n\n <div style={{ display: \"flex\", flex: 1, flexDirection: \"column\", overflow: \"hidden\" }}>\n {/* Sidebar toggle bar */}\n <div\n style={{\n alignItems: \"center\",\n borderBottom: `1px solid ${theme.colors.border}`,\n display: \"flex\",\n flexShrink: 0,\n gap: theme.spacing.lg,\n padding: `${theme.spacing.sm} ${theme.spacing.lg}`,\n }}\n >\n <button\n aria-expanded={sidebarOpen}\n data-lt-clear-btn=\"\"\n onClick={() => setSidebarOpen((v) => !v)}\n style={{\n background: \"none\",\n border: \"none\",\n color: theme.colors.textMuted,\n cursor: \"pointer\",\n fontFamily: theme.fontFamily.sans,\n fontSize: theme.fontSize.md,\n padding: `${theme.spacing.xs} ${theme.spacing.sm}`,\n transition: \"color 0.1s\",\n }}\n title={sidebarOpen ? \"Collapse sidebar\" : \"Expand sidebar\"}\n type=\"button\"\n >\n <span style={{ alignItems: \"center\", display: \"inline-flex\", gap: \"6px\" }}>\n {sidebarOpen ? <PanelLeftCloseIcon size={14} /> : <PanelLeftOpenIcon size={14} />}\n {sidebarOpen ? \"Hide controls\" : \"Show controls\"}\n </span>\n </button>\n\n {!sidebarOpen && (\n <>\n <span\n style={{\n color: theme.colors.textMuted,\n fontFamily: theme.fontFamily.mono,\n fontSize: theme.fontSize.sm,\n }}\n >\n {filteredRecords.length === records.length\n ? `${records.length} logs`\n : `${filteredRecords.length} / ${records.length} logs`}\n </span>\n <button\n data-lt-interactive=\"\"\n onClick={paused ? handleResume : handlePause}\n style={{\n background: paused\n ? theme.colors.levels.warning.badge\n : theme.colors.surfaceHover,\n border: `1px solid ${theme.colors.border}`,\n borderRadius: theme.radius.sm,\n color: paused ? theme.colors.white : theme.colors.textPrimary,\n cursor: \"pointer\",\n fontFamily: theme.fontFamily.sans,\n fontSize: theme.fontSize.sm,\n padding: `${theme.spacing.xs} ${theme.spacing.sm}`,\n transition: \"filter 0.1s\",\n }}\n title={paused ? \"Resume\" : \"Pause\"}\n type=\"button\"\n >\n {paused ? <PlayIcon size={12} /> : <PauseIcon size={12} />}\n </button>\n <button\n data-lt-interactive=\"\"\n onClick={handleClear}\n style={{\n background: theme.colors.surfaceHover,\n border: `1px solid ${theme.colors.border}`,\n borderRadius: theme.radius.sm,\n color: theme.colors.textPrimary,\n cursor: \"pointer\",\n fontFamily: theme.fontFamily.sans,\n fontSize: theme.fontSize.sm,\n padding: `${theme.spacing.xs} ${theme.spacing.sm}`,\n transition: \"filter 0.1s\",\n }}\n title=\"Clear\"\n type=\"button\"\n >\n <Trash2Icon size={12} />\n </button>\n </>\n )}\n </div>\n <LogList\n autoScroll={!paused}\n expandedId={expandedId}\n onToggle={setExpandedId}\n records={filteredRecords}\n />\n </div>\n </div>\n );\n};\n","import { useEffect, useRef } from \"react\";\nimport type { DevtoolsLogRecord } from \"../../types\";\nimport { theme } from \"../theme\";\nimport { LogRow } from \"./log-row\";\n\ninterface LogListProps {\n autoScroll: boolean;\n expandedId: string | null;\n onToggle: (id: string | null) => void;\n records: DevtoolsLogRecord[];\n}\n\nexport const LogList = ({ records, expandedId, onToggle, autoScroll }: LogListProps) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const isAtBottomRef = useRef(true);\n\n const recordCount = records.length;\n // biome-ignore lint/correctness/useExhaustiveDependencies: recordCount triggers scroll on new records\n useEffect(() => {\n const el = containerRef.current;\n if (!(el && autoScroll && isAtBottomRef.current)) {\n return;\n }\n el.scrollTop = el.scrollHeight;\n }, [autoScroll, recordCount]);\n\n const handleScroll = () => {\n const el = containerRef.current;\n if (!el) {\n return;\n }\n // Consider \"at bottom\" if within 40px of the end\n isAtBottomRef.current = el.scrollHeight - el.scrollTop - el.clientHeight < 40;\n };\n\n if (records.length === 0) {\n return (\n <div\n data-testid=\"log-list-empty\"\n style={{\n alignItems: \"center\",\n color: theme.colors.textMuted,\n display: \"flex\",\n flex: 1,\n fontSize: theme.fontSize.lg,\n justifyContent: \"center\",\n }}\n >\n No logs yet\n </div>\n );\n }\n\n return (\n <div\n data-testid=\"log-list\"\n onScroll={handleScroll}\n ref={containerRef}\n style={{\n flex: 1,\n overflow: \"auto\",\n scrollbarColor: `${theme.colors.scrollbar} transparent`,\n scrollbarWidth: \"thin\",\n }}\n >\n {records.map((record) => (\n <LogRow\n expanded={expandedId === record.id}\n key={record.id}\n onToggle={onToggle}\n record={record}\n />\n ))}\n </div>\n );\n};\n","export const theme = {\n colors: {\n background: \"#1e1e1e\",\n surface: \"#1a1a1a\",\n surfaceHover: \"#2a2a2a\",\n surfaceSelected: \"#2a2a3a\",\n border: \"#333\",\n borderInput: \"#444\",\n borderFocus: \"#6366f1\",\n\n textPrimary: \"#e0e0e0\",\n textSecondary: \"#888\",\n textMuted: \"#666\",\n textDimmed: \"#555\",\n white: \"#fff\",\n\n accent: \"#6366f1\",\n accentHover: \"#818cf8\",\n\n levels: {\n trace: { bg: \"#1a1a2e\", color: \"#8888bb\", badge: \"#5555aa\" },\n debug: { bg: \"#1a2a1a\", color: \"#88bb88\", badge: \"#55aa55\" },\n info: { bg: \"#1a2a3a\", color: \"#60a5fa\", badge: \"#3b82f6\" },\n warning: { bg: \"#2a2a1a\", color: \"#facc15\", badge: \"#eab308\" },\n error: { bg: \"#2a1a1a\", color: \"#ef4444\", badge: \"#dc2626\" },\n fatal: { bg: \"#3a0a0a\", color: \"#ff6b6b\", badge: \"#b91c1c\" },\n },\n\n scrollbar: \"#444\",\n scrollbarHover: \"#555\",\n },\n\n fontFamily: {\n mono: 'ui-monospace, \"Cascadia Code\", \"Source Code Pro\", Menlo, Consolas, monospace',\n sans: 'system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif',\n },\n\n fontSize: {\n xs: \"9px\",\n sm: \"10px\",\n md: \"11px\",\n base: \"12px\",\n lg: \"13px\",\n },\n\n radius: {\n sm: \"3px\",\n md: \"4px\",\n lg: \"6px\",\n pill: \"10px\",\n },\n\n spacing: {\n xs: \"2px\",\n sm: \"4px\",\n md: \"6px\",\n lg: \"8px\",\n xl: \"12px\",\n xxl: \"16px\",\n },\n} as const;\n\nexport type LogLevelColors = (typeof theme.colors.levels)[keyof typeof theme.colors.levels];\n","import { useCallback } from \"react\";\nimport type { DevtoolsLogRecord } from \"../../types\";\nimport { ChevronRightIcon } from \"../icons\";\nimport { theme } from \"../theme\";\nimport { LevelBadge } from \"./level-badge\";\nimport { LogDetail } from \"./log-detail\";\n\nfunction formatTime(ts: number): string {\n const d = new Date(ts);\n return d.toLocaleTimeString(undefined, {\n hour12: false,\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n });\n}\n\ninterface LogRowProps {\n expanded: boolean;\n onToggle: (id: string | null) => void;\n record: DevtoolsLogRecord;\n}\n\nexport const LogRow = ({ record, expanded, onToggle }: LogRowProps) => {\n const levelColors = theme.colors.levels[record.level];\n\n const handleClick = useCallback(() => {\n onToggle(expanded ? null : record.id);\n }, [expanded, onToggle, record.id]);\n\n return (\n <div>\n <button\n aria-expanded={expanded}\n data-lt-interactive=\"\"\n data-testid=\"log-row\"\n onClick={handleClick}\n style={{\n alignItems: \"center\",\n background: expanded ? levelColors.bg : \"transparent\",\n border: \"none\",\n borderBottom: `1px solid ${theme.colors.border}`,\n cursor: \"pointer\",\n display: \"flex\",\n gap: theme.spacing.lg,\n padding: `${theme.spacing.md} ${theme.spacing.xl}`,\n textAlign: \"left\",\n transition: \"background 0.1s, filter 0.1s\",\n width: \"100%\",\n }}\n type=\"button\"\n >\n {/* Timestamp */}\n <span\n style={{\n color: theme.colors.textDimmed,\n flexShrink: 0,\n fontFamily: theme.fontFamily.mono,\n fontSize: theme.fontSize.md,\n }}\n >\n {formatTime(record.timestamp)}\n </span>\n\n {/* Level badge */}\n <LevelBadge level={record.level} />\n\n {/* Category */}\n <span\n style={{\n color: theme.colors.accent,\n flexShrink: 0,\n fontFamily: theme.fontFamily.mono,\n fontSize: theme.fontSize.md,\n maxWidth: \"180px\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }}\n >\n {record.category.join(\".\")}\n </span>\n\n {/* Message */}\n <span\n style={{\n color: theme.colors.textPrimary,\n flex: 1,\n fontSize: theme.fontSize.base,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }}\n >\n {record.messageText}\n </span>\n\n {/* Caller (right-aligned) */}\n {record.caller && (\n <span\n style={{\n color: theme.colors.textDimmed,\n flexShrink: 0,\n fontFamily: theme.fontFamily.mono,\n fontSize: theme.fontSize.sm,\n maxWidth: \"200px\",\n opacity: 0.7,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n }}\n >\n {record.caller}\n </span>\n )}\n\n {/* Expand indicator */}\n <span\n style={{\n color: theme.colors.textDimmed,\n display: \"flex\",\n flexShrink: 0,\n transform: expanded ? \"rotate(90deg)\" : \"rotate(0deg)\",\n transition: \"transform 0.15s\",\n }}\n >\n <ChevronRightIcon size={12} />\n </span>\n </button>\n\n {expanded && <LogDetail record={record} />}\n </div>\n );\n};\n","/**\n * Inline SVG icons based on Lucide (https://lucide.dev) — ISC License.\n * Using inline SVGs avoids adding lucide-react as a runtime dependency.\n */\n\ninterface IconProps {\n color?: string;\n size?: number;\n style?: React.CSSProperties;\n}\n\nconst defaults = { size: 14, color: \"currentColor\" } as const;\n\nconst Svg = ({\n size = defaults.size,\n color = defaults.color,\n style,\n children,\n}: IconProps & { children: React.ReactNode }) => (\n <svg\n aria-hidden=\"true\"\n fill=\"none\"\n height={size}\n stroke={color}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n style={style}\n viewBox=\"0 0 24 24\"\n width={size}\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n {children}\n </svg>\n);\n\nexport const PlayIcon = (props: IconProps) => (\n <Svg {...props}>\n <path d=\"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\" />\n </Svg>\n);\n\nexport const PauseIcon = (props: IconProps) => (\n <Svg {...props}>\n <rect height={18} rx={1} width={5} x={14} y={3} />\n <rect height={18} rx={1} width={5} x={5} y={3} />\n </Svg>\n);\n\nexport const XIcon = (props: IconProps) => (\n <Svg {...props}>\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </Svg>\n);\n\nexport const CheckIcon = (props: IconProps) => (\n <Svg {...props}>\n <path d=\"M20 6 9 17l-5-5\" />\n </Svg>\n);\n\nexport const ChevronRightIcon = (props: IconProps) => (\n <Svg {...props}>\n <path d=\"m9 18 6-6-6-6\" />\n </Svg>\n);\n\nexport const PanelLeftCloseIcon = (props: IconProps) => (\n <Svg {...props}>\n <rect height={18} rx={2} width={18} x={3} y={3} />\n <path d=\"M9 3v18\" />\n <path d=\"m16 15-3-3 3-3\" />\n </Svg>\n);\n\nexport const PanelLeftOpenIcon = (props: IconProps) => (\n <Svg {...props}>\n <rect height={18} rx={2} width={18} x={3} y={3} />\n <path d=\"M9 3v18\" />\n <path d=\"m14 9 3 3-3 3\" />\n </Svg>\n);\n\nexport const Trash2Icon = (props: IconProps) => (\n <Svg {...props}>\n <path d=\"M10 11v6\" />\n <path d=\"M14 11v6\" />\n <path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6\" />\n <path d=\"M3 6h18\" />\n <path d=\"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\" />\n </Svg>\n);\n","import type { LogLevel } from \"../../types\";\nimport { theme } from \"../theme\";\n\nconst LEVEL_LABELS: Record<LogLevel, string> = {\n trace: \"TRC\",\n debug: \"DBG\",\n info: \"INF\",\n warning: \"WRN\",\n error: \"ERR\",\n fatal: \"FTL\",\n};\n\nexport const LevelBadge = ({ level }: { level: LogLevel }) => {\n const colors = theme.colors.levels[level];\n\n return (\n <span\n style={{\n background: colors.badge,\n borderRadius: theme.radius.sm,\n color: theme.colors.white,\n display: \"inline-block\",\n fontFamily: theme.fontFamily.mono,\n fontSize: theme.fontSize.sm,\n fontWeight: 600,\n lineHeight: 1,\n minWidth: \"28px\",\n padding: `${theme.spacing.xs} ${theme.spacing.sm}`,\n textAlign: \"center\",\n textTransform: \"uppercase\",\n }}\n >\n {LEVEL_LABELS[level]}\n </span>\n );\n};\n","import type { DevtoolsLogRecord } from \"../../types\";\nimport { theme } from \"../theme\";\n\nfunction formatTimestamp(ts: number): string {\n const d = new Date(ts);\n return d.toLocaleTimeString(undefined, {\n hour12: false,\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n });\n}\n\nfunction safeStringify(value: unknown, indent = 2): string {\n try {\n return JSON.stringify(value, null, indent);\n } catch {\n return String(value);\n }\n}\n\nconst DetailRow = ({ label, children }: { label: string; children: React.ReactNode }) => (\n <div style={{ display: \"flex\", gap: theme.spacing.lg, marginBottom: theme.spacing.md }}>\n <span\n style={{\n color: theme.colors.textMuted,\n flexShrink: 0,\n fontSize: theme.fontSize.md,\n minWidth: \"72px\",\n textAlign: \"right\",\n }}\n >\n {label}\n </span>\n <span style={{ fontSize: theme.fontSize.base, wordBreak: \"break-all\" }}>{children}</span>\n </div>\n);\n\nexport const LogDetail = ({ record }: { record: DevtoolsLogRecord }) => {\n const levelColors = theme.colors.levels[record.level];\n const hasProperties = Object.keys(record.properties).length > 0;\n\n return (\n <div\n data-testid=\"log-detail\"\n style={{\n background: levelColors.bg,\n borderTop: `1px solid ${theme.colors.border}`,\n padding: `${theme.spacing.lg} ${theme.spacing.xl}`,\n }}\n >\n <DetailRow label=\"Time\">{formatTimestamp(record.timestamp)}</DetailRow>\n <DetailRow label=\"Level\">\n <span style={{ color: levelColors.color, fontWeight: 600 }}>{record.level}</span>\n </DetailRow>\n <DetailRow label=\"Category\">\n <span style={{ color: theme.colors.accent, fontFamily: theme.fontFamily.mono }}>\n {record.category.join(\".\")}\n </span>\n </DetailRow>\n {record.caller && (\n <DetailRow label=\"Caller\">\n <span style={{ color: theme.colors.textSecondary, fontFamily: theme.fontFamily.mono }}>\n {record.caller}\n </span>\n </DetailRow>\n )}\n <DetailRow label=\"Message\">\n <span style={{ color: theme.colors.textPrimary }}>{record.messageText}</span>\n </DetailRow>\n\n {hasProperties && (\n <DetailRow label=\"Data\">\n <pre\n style={{\n background: \"rgba(0,0,0,0.3)\",\n borderRadius: theme.radius.md,\n color: theme.colors.textPrimary,\n fontFamily: theme.fontFamily.mono,\n fontSize: theme.fontSize.md,\n margin: 0,\n maxHeight: \"200px\",\n overflow: \"auto\",\n padding: theme.spacing.lg,\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-all\",\n }}\n >\n {safeStringify(record.properties)}\n </pre>\n </DetailRow>\n )}\n </div>\n );\n};\n","import { Combobox } from \"@base-ui-components/react/combobox\";\nimport { Popover } from \"@base-ui-components/react/popover\";\nimport { Debouncer } from \"@tanstack/pacer\";\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { LOG_LEVELS, type LogLevel } from \"../../types\";\nimport { CheckIcon, PauseIcon, PlayIcon, Trash2Icon, XIcon } from \"../icons\";\nimport { theme } from \"../theme\";\n\ninterface ToolbarProps {\n categories: string[];\n categoryFilter: string[];\n filteredCount: number;\n levelFilter: Set<LogLevel>;\n onCategoryFilterChange: (value: string[]) => void;\n onClear: () => void;\n onLevelFilterChange: (levels: Set<LogLevel>) => void;\n onPause: () => void;\n onResume: () => void;\n onSearchTextChange: (value: string) => void;\n paused: boolean;\n searchText: string;\n totalCount: number;\n}\n\n// Inject hover styles once (scoped via data attribute to avoid leaking)\nconst HOVER_STYLE_ID = \"logtape-devtools-hover\";\nfunction useHoverStyles() {\n useEffect(() => {\n if (document.getElementById(HOVER_STYLE_ID)) {\n return;\n }\n const style = document.createElement(\"style\");\n style.id = HOVER_STYLE_ID;\n style.textContent = `\n [data-lt-interactive]:hover {\n filter: brightness(1.25);\n }\n [data-lt-interactive]:active {\n filter: brightness(0.9);\n }\n [data-lt-clear-btn]:hover {\n color: ${theme.colors.textPrimary} !important;\n }\n [data-lt-chip-remove]:hover {\n opacity: 1 !important;\n color: ${theme.colors.white} !important;\n }\n `;\n document.head.appendChild(style);\n }, []);\n}\n\nconst buttonStyle = {\n background: theme.colors.surfaceHover,\n border: `1px solid ${theme.colors.border}`,\n borderRadius: theme.radius.md,\n color: theme.colors.textPrimary,\n cursor: \"pointer\",\n fontFamily: theme.fontFamily.sans,\n fontSize: theme.fontSize.md,\n padding: `${theme.spacing.sm} ${theme.spacing.lg}`,\n transition: \"filter 0.1s, background 0.1s, border-color 0.1s\",\n width: \"100%\",\n} as const;\n\nconst inputStyle = {\n background: theme.colors.surface,\n border: `1px solid ${theme.colors.borderInput}`,\n borderRadius: theme.radius.md,\n color: theme.colors.textPrimary,\n fontFamily: theme.fontFamily.sans,\n fontSize: theme.fontSize.md,\n outline: \"none\",\n padding: `${theme.spacing.sm} ${theme.spacing.lg}`,\n transition: \"border-color 0.15s\",\n width: \"100%\",\n} as const;\n\nconst sectionLabelStyle = {\n color: theme.colors.textMuted,\n fontSize: \"9px\",\n fontWeight: 600,\n letterSpacing: \"0.05em\",\n textTransform: \"uppercase\",\n} as const;\n\nconst LevelToggle = ({\n level,\n active,\n onToggle,\n}: {\n level: LogLevel;\n active: boolean;\n onToggle: (level: LogLevel) => void;\n}) => {\n const colors = theme.colors.levels[level];\n const handleClick = useCallback(() => onToggle(level), [level, onToggle]);\n\n return (\n <button\n aria-pressed={active}\n data-lt-interactive=\"\"\n data-testid={`level-toggle-${level}`}\n onClick={handleClick}\n style={{\n background: active ? colors.badge : \"transparent\",\n border: `1px solid ${active ? colors.badge : theme.colors.border}`,\n borderRadius: theme.radius.sm,\n color: active ? theme.colors.white : colors.color,\n cursor: \"pointer\",\n fontFamily: theme.fontFamily.mono,\n fontSize: theme.fontSize.sm,\n fontWeight: 600,\n lineHeight: 1,\n minWidth: \"30px\",\n opacity: active ? 1 : 0.5,\n padding: \"3px 0\",\n textAlign: \"center\" as const,\n transition: \"all 0.15s\",\n }}\n title={`Filter ${level} logs`}\n type=\"button\"\n >\n {level.slice(0, 3).toUpperCase()}\n </button>\n );\n};\n\nexport const Toolbar = ({\n paused,\n onPause,\n onResume,\n onClear,\n levelFilter,\n onLevelFilterChange,\n categories,\n categoryFilter,\n onCategoryFilterChange,\n searchText,\n onSearchTextChange,\n totalCount,\n filteredCount,\n}: ToolbarProps) => {\n useHoverStyles();\n\n const [localSearch, setLocalSearch] = useState(searchText);\n const debouncedSearch = useMemo(\n () => new Debouncer(onSearchTextChange, { wait: 200 }),\n [onSearchTextChange]\n );\n\n const handleSearchChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const value = e.target.value;\n setLocalSearch(value);\n debouncedSearch.maybeExecute(value);\n },\n [debouncedSearch]\n );\n\n // Sync local state when parent clears search\n useEffect(() => {\n if (searchText === \"\" && localSearch !== \"\") {\n setLocalSearch(\"\");\n }\n }, [searchText, localSearch]);\n\n const handleLevelToggle = useCallback(\n (level: LogLevel) => {\n const next = new Set(levelFilter);\n if (next.has(level)) {\n next.delete(level);\n } else {\n next.add(level);\n }\n onLevelFilterChange(next);\n },\n [levelFilter, onLevelFilterChange]\n );\n\n return (\n <div\n data-testid=\"toolbar\"\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n flexShrink: 0,\n gap: theme.spacing.xl,\n height: \"100%\",\n minWidth: \"200px\",\n overflow: \"auto\",\n padding: `${theme.spacing.lg} ${theme.spacing.xl}`,\n }}\n >\n {/* Log count */}\n <div style={{ textAlign: \"center\" }}>\n <span\n style={{\n color: theme.colors.textPrimary,\n fontFamily: theme.fontFamily.mono,\n fontSize: theme.fontSize.lg,\n fontWeight: 600,\n }}\n >\n {filteredCount === totalCount ? `${totalCount}` : `${filteredCount} / ${totalCount}`}\n </span>\n <div style={{ color: theme.colors.textMuted, fontSize: theme.fontSize.sm }}>logs</div>\n </div>\n\n {/* Actions */}\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: theme.spacing.sm }}>\n <div style={sectionLabelStyle}>Actions</div>\n <button\n data-lt-interactive=\"\"\n onClick={paused ? onResume : onPause}\n style={{\n ...buttonStyle,\n background: paused ? theme.colors.levels.warning.badge : buttonStyle.background,\n color: paused ? theme.colors.white : buttonStyle.color,\n }}\n title={paused ? \"Resume live updates\" : \"Pause live updates\"}\n type=\"button\"\n >\n <span style={{ alignItems: \"center\", display: \"inline-flex\", gap: \"6px\" }}>\n {paused ? <PlayIcon size={12} /> : <PauseIcon size={12} />}\n {paused ? \"Resume\" : \"Pause\"}\n </span>\n </button>\n\n <button\n data-lt-interactive=\"\"\n onClick={onClear}\n style={buttonStyle}\n title=\"Clear all logs\"\n type=\"button\"\n >\n <span style={{ alignItems: \"center\", display: \"inline-flex\", gap: \"6px\" }}>\n <Trash2Icon size={12} />\n Clear\n </span>\n </button>\n </div>\n\n {/* Level filters */}\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: theme.spacing.sm }}>\n <div style={{ alignItems: \"center\", display: \"flex\", justifyContent: \"space-between\" }}>\n <div style={sectionLabelStyle}>Levels</div>\n {levelFilter.size > 0 && (\n <button\n data-lt-clear-btn=\"\"\n onClick={() => onLevelFilterChange(new Set())}\n style={{\n background: \"none\",\n border: \"none\",\n color: theme.colors.textMuted,\n cursor: \"pointer\",\n fontSize: \"9px\",\n padding: 0,\n transition: \"color 0.1s\",\n }}\n title=\"Show all levels\"\n type=\"button\"\n >\n clear\n </button>\n )}\n </div>\n <div\n style={{\n display: \"grid\",\n gap: theme.spacing.xs,\n gridTemplateColumns: \"repeat(3, 1fr)\",\n }}\n >\n {LOG_LEVELS.map((level) => (\n <LevelToggle\n active={levelFilter.size === 0 || levelFilter.has(level)}\n key={level}\n level={level}\n onToggle={handleLevelToggle}\n />\n ))}\n </div>\n </div>\n\n {/* Category filter (multi-select combobox) */}\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: theme.spacing.sm }}>\n <div style={{ alignItems: \"center\", display: \"flex\", justifyContent: \"space-between\" }}>\n <div style={sectionLabelStyle}>Category</div>\n {categoryFilter.length > 0 && (\n <button\n data-lt-clear-btn=\"\"\n onClick={() => onCategoryFilterChange([])}\n style={{\n background: \"none\",\n border: \"none\",\n color: theme.colors.textMuted,\n cursor: \"pointer\",\n fontSize: \"9px\",\n padding: 0,\n transition: \"color 0.1s\",\n }}\n title=\"Clear all categories\"\n type=\"button\"\n >\n clear\n </button>\n )}\n </div>\n {categories.length === 0 ? (\n <Popover.Root>\n <Popover.Trigger\n delay={300}\n nativeButton={false}\n openOnHover\n render={\n <div\n data-testid=\"category-input\"\n style={{\n ...inputStyle,\n color: theme.colors.textMuted,\n cursor: \"not-allowed\",\n opacity: 0.5,\n }}\n >\n Category…\n </div>\n }\n />\n <Popover.Portal>\n <Popover.Positioner sideOffset={6} style={{ zIndex: 999_999 }}>\n <Popover.Popup\n style={{\n background: theme.colors.surface,\n border: `1px solid ${theme.colors.border}`,\n borderRadius: theme.radius.md,\n boxShadow: \"0 8px 24px rgba(0,0,0,0.5)\",\n fontSize: theme.fontSize.sm,\n maxWidth: \"200px\",\n padding: `${theme.spacing.sm} ${theme.spacing.lg}`,\n }}\n >\n <p style={{ color: theme.colors.textMuted, lineHeight: 1.4, margin: 0 }}>\n Waiting for logs to populate available categories.\n </p>\n </Popover.Popup>\n </Popover.Positioner>\n </Popover.Portal>\n </Popover.Root>\n ) : (\n <Combobox.Root\n items={categories}\n multiple\n onValueChange={onCategoryFilterChange}\n value={categoryFilter}\n >\n <div\n style={{\n background: theme.colors.surface,\n border: `1px solid ${theme.colors.borderInput}`,\n borderRadius: theme.radius.md,\n display: \"flex\",\n flexWrap: \"wrap\",\n gap: \"3px\",\n minHeight: \"28px\",\n padding: \"3px\",\n transition: \"border-color 0.15s\",\n }}\n >\n {categoryFilter.map((cat) => (\n <span\n key={cat}\n style={{\n alignItems: \"center\",\n background: \"rgba(99, 102, 241, 0.15)\",\n border: \"1px solid rgba(99, 102, 241, 0.3)\",\n borderRadius: theme.radius.sm,\n color: theme.colors.accentHover,\n display: \"inline-flex\",\n fontFamily: theme.fontFamily.mono,\n fontSize: \"9px\",\n gap: \"3px\",\n lineHeight: 1,\n padding: \"1px 4px\",\n }}\n >\n {cat}\n <button\n data-lt-chip-remove=\"\"\n onClick={() => onCategoryFilterChange(categoryFilter.filter((c) => c !== cat))}\n style={{\n background: \"none\",\n border: \"none\",\n color: theme.colors.textMuted,\n cursor: \"pointer\",\n fontSize: \"7px\",\n lineHeight: 1,\n opacity: 0.7,\n padding: 0,\n transition: \"color 0.1s, opacity 0.1s\",\n }}\n title={`Remove ${cat}`}\n type=\"button\"\n >\n <XIcon size={7} />\n </button>\n </span>\n ))}\n <Combobox.Input\n data-testid=\"category-input\"\n placeholder={categoryFilter.length === 0 ? \"Category…\" : \"\"}\n style={{\n background: \"transparent\",\n border: \"none\",\n color: theme.colors.textPrimary,\n flex: 1,\n fontFamily: theme.fontFamily.sans,\n fontSize: theme.fontSize.md,\n minWidth: \"40px\",\n outline: \"none\",\n padding: `${theme.spacing.xs} ${theme.spacing.sm}`,\n }}\n />\n </div>\n <Combobox.Portal>\n <Combobox.Positioner style={{ zIndex: 999_999 }}>\n <Combobox.Popup\n style={{\n background: theme.colors.surface,\n border: `1px solid ${theme.colors.border}`,\n borderRadius: theme.radius.md,\n boxShadow: \"0 8px 24px rgba(0,0,0,0.5)\",\n maxHeight: \"200px\",\n overflow: \"auto\",\n padding: theme.spacing.xs,\n }}\n >\n <Combobox.List>\n {(item, index) => (\n <Combobox.Item\n index={index}\n key={String(item)}\n style={{\n alignItems: \"center\",\n borderRadius: theme.radius.sm,\n color: theme.colors.textPrimary,\n cursor: \"pointer\",\n display: \"flex\",\n fontFamily: theme.fontFamily.mono,\n fontSize: theme.fontSize.md,\n gap: theme.spacing.sm,\n justifyContent: \"space-between\",\n padding: `${theme.spacing.sm} ${theme.spacing.lg}`,\n transition: \"background 0.1s\",\n }}\n value={item}\n >\n <span style={{ flex: 1, overflow: \"hidden\", textOverflow: \"ellipsis\" }}>\n {String(item)}\n </span>\n <Combobox.ItemIndicator>\n <CheckIcon color={theme.colors.accent} size={14} />\n </Combobox.ItemIndicator>\n </Combobox.Item>\n )}\n </Combobox.List>\n </Combobox.Popup>\n </Combobox.Positioner>\n </Combobox.Portal>\n </Combobox.Root>\n )}\n </div>\n\n {/* Text search */}\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: theme.spacing.sm }}>\n <div style={sectionLabelStyle}>Search</div>\n <input\n data-testid=\"search-input\"\n onChange={handleSearchChange}\n placeholder=\"Search…\"\n style={inputStyle}\n type=\"text\"\n value={localSearch}\n />\n </div>\n </div>\n );\n};\n","export type LogLevel = \"trace\" | \"debug\" | \"info\" | \"warning\" | \"error\" | \"fatal\";\n\nexport const LOG_LEVELS: LogLevel[] = [\"trace\", \"debug\", \"info\", \"warning\", \"error\", \"fatal\"];\n\nexport interface DevtoolsLogRecord {\n /** Source location of the log call (only present when `experimentalCaptureStackTrace` is enabled). */\n caller?: string;\n category: string[];\n id: string;\n level: LogLevel;\n message: unknown[];\n messageText: string;\n properties: Record<string, unknown>;\n timestamp: number;\n}\n","import { defaultLogStore, type LogStore } from \"../store\";\nimport { LogTapeDevtoolsPlugin } from \"./logtape-devtools-plugin\";\n\nexport interface LogTapeDevtoolsPluginOptions {\n /** Whether to open the devtools panel by default. Default: true */\n defaultOpen?: boolean;\n /** Plugin display name. Default: \"LogTape\" */\n name?: string;\n /** Custom log store instance. Must match the store passed to createDevtoolsSink. */\n store?: LogStore;\n}\n\n/**\n * Creates a TanStack DevTools plugin config object for LogTape.\n *\n * Usage:\n * ```tsx\n * import { TanStackDevtools } from \"@tanstack/react-devtools\";\n * import { createLogTapeDevtoolsPlugin } from \"@mugenlabs/logtape-devtools\";\n *\n * <TanStackDevtools plugins={[createLogTapeDevtoolsPlugin()]} />\n * ```\n */\nexport const createLogTapeDevtoolsPlugin = (options?: LogTapeDevtoolsPluginOptions) => ({\n defaultOpen: options?.defaultOpen ?? true,\n id: \"logtape-devtools-plugin\",\n name: options?.name ?? \"LogTape\",\n render: <LogTapeDevtoolsPlugin store={options?.store ?? defaultLogStore} />,\n});\n","import type { LogRecord, Sink } from \"@logtape/logtape\";\nimport { defaultLogStore, type LogStore } from \"./store\";\nimport type { DevtoolsLogRecord, LogLevel } from \"./types\";\n\nlet counter = 0;\n\nfunction renderMessage(message: readonly unknown[]): string {\n return message\n .map((part) => {\n if (typeof part === \"string\") {\n return part;\n }\n if (part === null || part === undefined) {\n return String(part);\n }\n try {\n return JSON.stringify(part);\n } catch {\n return String(part);\n }\n })\n .join(\"\");\n}\n\nfunction safeCloneProperties(properties: Record<string, unknown>): Record<string, unknown> {\n try {\n return JSON.parse(JSON.stringify(properties));\n } catch {\n // Fallback: shallow copy with stringified values for non-serializable entries\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(properties)) {\n try {\n result[key] = JSON.parse(JSON.stringify(value));\n } catch {\n result[key] = String(value);\n }\n }\n return result;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Stack trace parser — extracts the caller frame from `new Error().stack`\n// ---------------------------------------------------------------------------\n\n// V8 (Chrome/Node/Edge): \" at functionName (file:line:col)\"\nconst v8FrameRe = /at\\s+(?:.*?\\s+\\()?(.+?):(\\d+):(\\d+)\\)?$/;\n// SpiderMonkey (Firefox) / JSC (Safari): \"functionName@file:line:col\"\nconst smFrameRe = /(?:^|@)(.+?):(\\d+):(\\d+)$/;\n\nfunction captureCallerInfo(): string | undefined {\n // biome-ignore lint/suspicious/useErrorMessage: we only need the stack trace, not the message\n const stack = new Error().stack;\n if (!stack) {\n return undefined;\n }\n\n const lines = stack.split(\"\\n\");\n\n for (const line of lines) {\n const trimmed = line.trim();\n\n // Skip empty lines and the \"Error\" header\n if (!trimmed || trimmed === \"Error\") {\n continue;\n }\n\n // Skip frames from logtape internals (both @logtape/logtape and @mugenlabs/logtape-devtools)\n if (/logtape/i.test(trimmed)) {\n continue;\n }\n\n // Try V8 format first, then SpiderMonkey/JSC\n const match = v8FrameRe.exec(trimmed) ?? smFrameRe.exec(trimmed);\n if (!match) {\n continue;\n }\n\n const [, filePath, lineNo, colNo] = match;\n\n // Extract just the filename from the full path/URL\n const fileName =\n filePath\n .replace(/[?#].*$/, \"\")\n .split(\"/\")\n .pop() ?? filePath;\n\n return `${fileName}:${lineNo}:${colNo}`;\n }\n\n return undefined;\n}\n\nfunction normalizeRecord(record: LogRecord, captureStack: boolean): DevtoolsLogRecord {\n const normalized: DevtoolsLogRecord = {\n id: `log-${++counter}-${record.timestamp}`,\n timestamp: record.timestamp,\n level: record.level as LogLevel,\n category: [...record.category],\n message: [...record.message],\n messageText: renderMessage(record.message),\n properties: safeCloneProperties(record.properties),\n };\n\n if (captureStack) {\n const caller = captureCallerInfo();\n if (caller) {\n normalized.caller = caller;\n }\n }\n\n return normalized;\n}\n\nfunction isProductionEnv(): boolean {\n try {\n // Bundlers (Vite, webpack, etc.) statically replace this at build time\n if (typeof process !== \"undefined\" && process.env?.NODE_ENV === \"production\") {\n return true;\n }\n } catch {\n // process may not exist in browser environments\n }\n return false;\n}\n\nexport interface DevtoolsSinkOptions {\n /**\n * Capture the source location of each log call via stack trace parsing.\n *\n * **Experimental / dev-only** — relies on `new Error().stack` which is\n * engine-dependent. Automatically disabled in production builds (when\n * `process.env.NODE_ENV === \"production\"`) because minified bundles\n * produce meaningless file/line references. Note that source maps do not\n * help here — browsers do not apply source maps to `Error.stack`.\n *\n * Set `forceStackTrace` to `true` to override the production guard — useful\n * when your production build ships unminified code.\n *\n * @default true\n */\n experimentalCaptureStackTrace?: boolean;\n /**\n * Force stack trace capture even in production builds.\n * Only has an effect when `experimentalCaptureStackTrace` is `true`.\n *\n * @default false\n */\n forceStackTrace?: boolean;\n /** Custom log store instance. Defaults to the shared store. */\n store?: LogStore;\n}\n\n/**\n * Creates a LogTape sink that forwards log records to the devtools panel.\n *\n * Usage:\n * ```ts\n * import { configure } from \"@logtape/logtape\";\n * import { createDevtoolsSink } from \"@mugenlabs/logtape-devtools\";\n *\n * await configure({\n * sinks: { devtools: createDevtoolsSink() },\n * loggers: [\n * { category: [\"app\"], lowestLevel: \"debug\", sinks: [\"devtools\"] },\n * ],\n * });\n * ```\n */\nexport function createDevtoolsSink(options?: DevtoolsSinkOptions): Sink {\n const store = options?.store ?? defaultLogStore;\n const wantsStack = options?.experimentalCaptureStackTrace ?? true;\n const captureStack = wantsStack && (options?.forceStackTrace || !isProductionEnv());\n\n return (record: LogRecord) => {\n try {\n const normalized = normalizeRecord(record, captureStack);\n store.addRecord(normalized);\n } catch {\n // Fail silently — devtools should never break the application\n }\n };\n}\n"],"mappings":";AAYO,SAAS,eAAe,UAAU,KAAgB;AACvD,MAAI,UAA+B,CAAC;AACpC,MAAI,MAAM;AACV,QAAM,YAAY,oBAAI,IAAc;AAEpC,WAAS,SAAS;AAChB,eAAW,YAAY,WAAW;AAChC,eAAS;AAAA,IACX;AAAA,EACF;AAEA,SAAO;AAAA,IACL,aAAa,MAAM;AAAA,IACnB,WAAW,CAAC,WAAW;AAErB,gBAAU,CAAC,GAAG,SAAS,MAAM;AAC7B,UAAI,QAAQ,SAAS,KAAK;AACxB,kBAAU,QAAQ,MAAM,QAAQ,SAAS,GAAG;AAAA,MAC9C;AACA,aAAO;AAAA,IACT;AAAA,IACA,OAAO,MAAM;AACX,gBAAU,CAAC;AACX,aAAO;AAAA,IACT;AAAA,IACA,WAAW,CAAC,aAAa;AACvB,gBAAU,IAAI,QAAQ;AACtB,aAAO,MAAM;AACX,kBAAU,OAAO,QAAQ;AAAA,MAC3B;AAAA,IACF;AAAA,IACA,YAAY,CAAC,SAAS;AACpB,YAAM;AACN,UAAI,QAAQ,SAAS,KAAK;AACxB,kBAAU,QAAQ,MAAM,QAAQ,SAAS,GAAG;AAC5C,eAAO;AAAA,MACT;AAAA,IACF;AAAA,EACF;AACF;AAGO,IAAM,kBAAkB,eAAe;;;ACtD9C,SAAS,eAAAA,cAAa,WAAAC,UAAS,YAAAC,WAAU,4BAA4B;;;ACArE,SAAS,WAAW,cAAc;;;ACA3B,IAAM,QAAQ;AAAA,EACnB,QAAQ;AAAA,IACN,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,cAAc;AAAA,IACd,iBAAiB;AAAA,IACjB,QAAQ;AAAA,IACR,aAAa;AAAA,IACb,aAAa;AAAA,IAEb,aAAa;AAAA,IACb,eAAe;AAAA,IACf,WAAW;AAAA,IACX,YAAY;AAAA,IACZ,OAAO;AAAA,IAEP,QAAQ;AAAA,IACR,aAAa;AAAA,IAEb,QAAQ;AAAA,MACN,OAAO,EAAE,IAAI,WAAW,OAAO,WAAW,OAAO,UAAU;AAAA,MAC3D,OAAO,EAAE,IAAI,WAAW,OAAO,WAAW,OAAO,UAAU;AAAA,MAC3D,MAAM,EAAE,IAAI,WAAW,OAAO,WAAW,OAAO,UAAU;AAAA,MAC1D,SAAS,EAAE,IAAI,WAAW,OAAO,WAAW,OAAO,UAAU;AAAA,MAC7D,OAAO,EAAE,IAAI,WAAW,OAAO,WAAW,OAAO,UAAU;AAAA,MAC3D,OAAO,EAAE,IAAI,WAAW,OAAO,WAAW,OAAO,UAAU;AAAA,IAC7D;AAAA,IAEA,WAAW;AAAA,IACX,gBAAgB;AAAA,EAClB;AAAA,EAEA,YAAY;AAAA,IACV,MAAM;AAAA,IACN,MAAM;AAAA,EACR;AAAA,EAEA,UAAU;AAAA,IACR,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,MAAM;AAAA,IACN,IAAI;AAAA,EACN;AAAA,EAEA,QAAQ;AAAA,IACN,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,MAAM;AAAA,EACR;AAAA,EAEA,SAAS;AAAA,IACP,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,KAAK;AAAA,EACP;AACF;;;AC5DA,SAAS,mBAAmB;;;ACmB1B,cAwBA,YAxBA;AARF,IAAM,WAAW,EAAE,MAAM,IAAI,OAAO,eAAe;AAEnD,IAAM,MAAM,CAAC;AAAA,EACX,OAAO,SAAS;AAAA,EAChB,QAAQ,SAAS;AAAA,EACjB;AAAA,EACA;AACF,MACE;AAAA,EAAC;AAAA;AAAA,IACC,eAAY;AAAA,IACZ,MAAK;AAAA,IACL,QAAQ;AAAA,IACR,QAAQ;AAAA,IACR,eAAc;AAAA,IACd,gBAAe;AAAA,IACf,aAAa;AAAA,IACb;AAAA,IACA,SAAQ;AAAA,IACR,OAAO;AAAA,IACP,OAAM;AAAA,IAEL;AAAA;AACH;AAGK,IAAM,WAAW,CAAC,UACvB,oBAAC,OAAK,GAAG,OACP,8BAAC,UAAK,GAAE,sFAAqF,GAC/F;AAGK,IAAM,YAAY,CAAC,UACxB,qBAAC,OAAK,GAAG,OACP;AAAA,sBAAC,UAAK,QAAQ,IAAI,IAAI,GAAG,OAAO,GAAG,GAAG,IAAI,GAAG,GAAG;AAAA,EAChD,oBAAC,UAAK,QAAQ,IAAI,IAAI,GAAG,OAAO,GAAG,GAAG,GAAG,GAAG,GAAG;AAAA,GACjD;AAGK,IAAM,QAAQ,CAAC,UACpB,qBAAC,OAAK,GAAG,OACP;AAAA,sBAAC,UAAK,GAAE,cAAa;AAAA,EACrB,oBAAC,UAAK,GAAE,cAAa;AAAA,GACvB;AAGK,IAAM,YAAY,CAAC,UACxB,oBAAC,OAAK,GAAG,OACP,8BAAC,UAAK,GAAE,mBAAkB,GAC5B;AAGK,IAAM,mBAAmB,CAAC,UAC/B,oBAAC,OAAK,GAAG,OACP,8BAAC,UAAK,GAAE,iBAAgB,GAC1B;AAGK,IAAM,qBAAqB,CAAC,UACjC,qBAAC,OAAK,GAAG,OACP;AAAA,sBAAC,UAAK,QAAQ,IAAI,IAAI,GAAG,OAAO,IAAI,GAAG,GAAG,GAAG,GAAG;AAAA,EAChD,oBAAC,UAAK,GAAE,WAAU;AAAA,EAClB,oBAAC,UAAK,GAAE,kBAAiB;AAAA,GAC3B;AAGK,IAAM,oBAAoB,CAAC,UAChC,qBAAC,OAAK,GAAG,OACP;AAAA,sBAAC,UAAK,QAAQ,IAAI,IAAI,GAAG,OAAO,IAAI,GAAG,GAAG,GAAG,GAAG;AAAA,EAChD,oBAAC,UAAK,GAAE,WAAU;AAAA,EAClB,oBAAC,UAAK,GAAE,iBAAgB;AAAA,GAC1B;AAGK,IAAM,aAAa,CAAC,UACzB,qBAAC,OAAK,GAAG,OACP;AAAA,sBAAC,UAAK,GAAE,YAAW;AAAA,EACnB,oBAAC,UAAK,GAAE,YAAW;AAAA,EACnB,oBAAC,UAAK,GAAE,4CAA2C;AAAA,EACnD,oBAAC,UAAK,GAAE,WAAU;AAAA,EAClB,oBAAC,UAAK,GAAE,0CAAyC;AAAA,GACnD;;;AC3EE,gBAAAC,YAAA;AAbJ,IAAM,eAAyC;AAAA,EAC7C,OAAO;AAAA,EACP,OAAO;AAAA,EACP,MAAM;AAAA,EACN,SAAS;AAAA,EACT,OAAO;AAAA,EACP,OAAO;AACT;AAEO,IAAM,aAAa,CAAC,EAAE,MAAM,MAA2B;AAC5D,QAAM,SAAS,MAAM,OAAO,OAAO,KAAK;AAExC,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,QACL,YAAY,OAAO;AAAA,QACnB,cAAc,MAAM,OAAO;AAAA,QAC3B,OAAO,MAAM,OAAO;AAAA,QACpB,SAAS;AAAA,QACT,YAAY,MAAM,WAAW;AAAA,QAC7B,UAAU,MAAM,SAAS;AAAA,QACzB,YAAY;AAAA,QACZ,YAAY;AAAA,QACZ,UAAU;AAAA,QACV,SAAS,GAAG,MAAM,QAAQ,EAAE,IAAI,MAAM,QAAQ,EAAE;AAAA,QAChD,WAAW;AAAA,QACX,eAAe;AAAA,MACjB;AAAA,MAEC,uBAAa,KAAK;AAAA;AAAA,EACrB;AAEJ;;;ACbE,SACE,OAAAC,MADF,QAAAC,aAAA;AAnBF,SAAS,gBAAgB,IAAoB;AAC3C,QAAM,IAAI,IAAI,KAAK,EAAE;AACrB,SAAO,EAAE,mBAAmB,QAAW;AAAA,IACrC,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV,CAAC;AACH;AAEA,SAAS,cAAc,OAAgB,SAAS,GAAW;AACzD,MAAI;AACF,WAAO,KAAK,UAAU,OAAO,MAAM,MAAM;AAAA,EAC3C,QAAQ;AACN,WAAO,OAAO,KAAK;AAAA,EACrB;AACF;AAEA,IAAM,YAAY,CAAC,EAAE,OAAO,SAAS,MACnC,gBAAAA,MAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,KAAK,MAAM,QAAQ,IAAI,cAAc,MAAM,QAAQ,GAAG,GACnF;AAAA,kBAAAD;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,QACL,OAAO,MAAM,OAAO;AAAA,QACpB,YAAY;AAAA,QACZ,UAAU,MAAM,SAAS;AAAA,QACzB,UAAU;AAAA,QACV,WAAW;AAAA,MACb;AAAA,MAEC;AAAA;AAAA,EACH;AAAA,EACA,gBAAAA,KAAC,UAAK,OAAO,EAAE,UAAU,MAAM,SAAS,MAAM,WAAW,YAAY,GAAI,UAAS;AAAA,GACpF;AAGK,IAAM,YAAY,CAAC,EAAE,OAAO,MAAqC;AACtE,QAAM,cAAc,MAAM,OAAO,OAAO,OAAO,KAAK;AACpD,QAAM,gBAAgB,OAAO,KAAK,OAAO,UAAU,EAAE,SAAS;AAE9D,SACE,gBAAAC;AAAA,IAAC;AAAA;AAAA,MACC,eAAY;AAAA,MACZ,OAAO;AAAA,QACL,YAAY,YAAY;AAAA,QACxB,WAAW,aAAa,MAAM,OAAO,MAAM;AAAA,QAC3C,SAAS,GAAG,MAAM,QAAQ,EAAE,IAAI,MAAM,QAAQ,EAAE;AAAA,MAClD;AAAA,MAEA;AAAA,wBAAAD,KAAC,aAAU,OAAM,QAAQ,0BAAgB,OAAO,SAAS,GAAE;AAAA,QAC3D,gBAAAA,KAAC,aAAU,OAAM,SACf,0BAAAA,KAAC,UAAK,OAAO,EAAE,OAAO,YAAY,OAAO,YAAY,IAAI,GAAI,iBAAO,OAAM,GAC5E;AAAA,QACA,gBAAAA,KAAC,aAAU,OAAM,YACf,0BAAAA,KAAC,UAAK,OAAO,EAAE,OAAO,MAAM,OAAO,QAAQ,YAAY,MAAM,WAAW,KAAK,GAC1E,iBAAO,SAAS,KAAK,GAAG,GAC3B,GACF;AAAA,QACC,OAAO,UACN,gBAAAA,KAAC,aAAU,OAAM,UACf,0BAAAA,KAAC,UAAK,OAAO,EAAE,OAAO,MAAM,OAAO,eAAe,YAAY,MAAM,WAAW,KAAK,GACjF,iBAAO,QACV,GACF;AAAA,QAEF,gBAAAA,KAAC,aAAU,OAAM,WACf,0BAAAA,KAAC,UAAK,OAAO,EAAE,OAAO,MAAM,OAAO,YAAY,GAAI,iBAAO,aAAY,GACxE;AAAA,QAEC,iBACC,gBAAAA,KAAC,aAAU,OAAM,QACf,0BAAAA;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,cACL,YAAY;AAAA,cACZ,cAAc,MAAM,OAAO;AAAA,cAC3B,OAAO,MAAM,OAAO;AAAA,cACpB,YAAY,MAAM,WAAW;AAAA,cAC7B,UAAU,MAAM,SAAS;AAAA,cACzB,QAAQ;AAAA,cACR,WAAW;AAAA,cACX,UAAU;AAAA,cACV,SAAS,MAAM,QAAQ;AAAA,cACvB,YAAY;AAAA,cACZ,WAAW;AAAA,YACb;AAAA,YAEC,wBAAc,OAAO,UAAU;AAAA;AAAA,QAClC,GACF;AAAA;AAAA;AAAA,EAEJ;AAEJ;;;AH9DM,SAqBE,OAAAE,MArBF,QAAAC,aAAA;AAzBN,SAAS,WAAW,IAAoB;AACtC,QAAM,IAAI,IAAI,KAAK,EAAE;AACrB,SAAO,EAAE,mBAAmB,QAAW;AAAA,IACrC,QAAQ;AAAA,IACR,MAAM;AAAA,IACN,QAAQ;AAAA,IACR,QAAQ;AAAA,EACV,CAAC;AACH;AAQO,IAAM,SAAS,CAAC,EAAE,QAAQ,UAAU,SAAS,MAAmB;AACrE,QAAM,cAAc,MAAM,OAAO,OAAO,OAAO,KAAK;AAEpD,QAAM,cAAc,YAAY,MAAM;AACpC,aAAS,WAAW,OAAO,OAAO,EAAE;AAAA,EACtC,GAAG,CAAC,UAAU,UAAU,OAAO,EAAE,CAAC;AAElC,SACE,gBAAAA,MAAC,SACC;AAAA,oBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,iBAAe;AAAA,QACf,uBAAoB;AAAA,QACpB,eAAY;AAAA,QACZ,SAAS;AAAA,QACT,OAAO;AAAA,UACL,YAAY;AAAA,UACZ,YAAY,WAAW,YAAY,KAAK;AAAA,UACxC,QAAQ;AAAA,UACR,cAAc,aAAa,MAAM,OAAO,MAAM;AAAA,UAC9C,QAAQ;AAAA,UACR,SAAS;AAAA,UACT,KAAK,MAAM,QAAQ;AAAA,UACnB,SAAS,GAAG,MAAM,QAAQ,EAAE,IAAI,MAAM,QAAQ,EAAE;AAAA,UAChD,WAAW;AAAA,UACX,YAAY;AAAA,UACZ,OAAO;AAAA,QACT;AAAA,QACA,MAAK;AAAA,QAGL;AAAA,0BAAAD;AAAA,YAAC;AAAA;AAAA,cACC,OAAO;AAAA,gBACL,OAAO,MAAM,OAAO;AAAA,gBACpB,YAAY;AAAA,gBACZ,YAAY,MAAM,WAAW;AAAA,gBAC7B,UAAU,MAAM,SAAS;AAAA,cAC3B;AAAA,cAEC,qBAAW,OAAO,SAAS;AAAA;AAAA,UAC9B;AAAA,UAGA,gBAAAA,KAAC,cAAW,OAAO,OAAO,OAAO;AAAA,UAGjC,gBAAAA;AAAA,YAAC;AAAA;AAAA,cACC,OAAO;AAAA,gBACL,OAAO,MAAM,OAAO;AAAA,gBACpB,YAAY;AAAA,gBACZ,YAAY,MAAM,WAAW;AAAA,gBAC7B,UAAU,MAAM,SAAS;AAAA,gBACzB,UAAU;AAAA,gBACV,UAAU;AAAA,gBACV,cAAc;AAAA,gBACd,YAAY;AAAA,cACd;AAAA,cAEC,iBAAO,SAAS,KAAK,GAAG;AAAA;AAAA,UAC3B;AAAA,UAGA,gBAAAA;AAAA,YAAC;AAAA;AAAA,cACC,OAAO;AAAA,gBACL,OAAO,MAAM,OAAO;AAAA,gBACpB,MAAM;AAAA,gBACN,UAAU,MAAM,SAAS;AAAA,gBACzB,UAAU;AAAA,gBACV,cAAc;AAAA,gBACd,YAAY;AAAA,cACd;AAAA,cAEC,iBAAO;AAAA;AAAA,UACV;AAAA,UAGC,OAAO,UACN,gBAAAA;AAAA,YAAC;AAAA;AAAA,cACC,OAAO;AAAA,gBACL,OAAO,MAAM,OAAO;AAAA,gBACpB,YAAY;AAAA,gBACZ,YAAY,MAAM,WAAW;AAAA,gBAC7B,UAAU,MAAM,SAAS;AAAA,gBACzB,UAAU;AAAA,gBACV,SAAS;AAAA,gBACT,UAAU;AAAA,gBACV,cAAc;AAAA,gBACd,YAAY;AAAA,cACd;AAAA,cAEC,iBAAO;AAAA;AAAA,UACV;AAAA,UAIF,gBAAAA;AAAA,YAAC;AAAA;AAAA,cACC,OAAO;AAAA,gBACL,OAAO,MAAM,OAAO;AAAA,gBACpB,SAAS;AAAA,gBACT,YAAY;AAAA,gBACZ,WAAW,WAAW,kBAAkB;AAAA,gBACxC,YAAY;AAAA,cACd;AAAA,cAEA,0BAAAA,KAAC,oBAAiB,MAAM,IAAI;AAAA;AAAA,UAC9B;AAAA;AAAA;AAAA,IACF;AAAA,IAEC,YAAY,gBAAAA,KAAC,aAAU,QAAgB;AAAA,KAC1C;AAEJ;;;AFhGM,gBAAAE,YAAA;AAzBC,IAAM,UAAU,CAAC,EAAE,SAAS,YAAY,UAAU,WAAW,MAAoB;AACtF,QAAM,eAAe,OAAuB,IAAI;AAChD,QAAM,gBAAgB,OAAO,IAAI;AAEjC,QAAM,cAAc,QAAQ;AAE5B,YAAU,MAAM;AACd,UAAM,KAAK,aAAa;AACxB,QAAI,EAAE,MAAM,cAAc,cAAc,UAAU;AAChD;AAAA,IACF;AACA,OAAG,YAAY,GAAG;AAAA,EACpB,GAAG,CAAC,YAAY,WAAW,CAAC;AAE5B,QAAM,eAAe,MAAM;AACzB,UAAM,KAAK,aAAa;AACxB,QAAI,CAAC,IAAI;AACP;AAAA,IACF;AAEA,kBAAc,UAAU,GAAG,eAAe,GAAG,YAAY,GAAG,eAAe;AAAA,EAC7E;AAEA,MAAI,QAAQ,WAAW,GAAG;AACxB,WACE,gBAAAA;AAAA,MAAC;AAAA;AAAA,QACC,eAAY;AAAA,QACZ,OAAO;AAAA,UACL,YAAY;AAAA,UACZ,OAAO,MAAM,OAAO;AAAA,UACpB,SAAS;AAAA,UACT,MAAM;AAAA,UACN,UAAU,MAAM,SAAS;AAAA,UACzB,gBAAgB;AAAA,QAClB;AAAA,QACD;AAAA;AAAA,IAED;AAAA,EAEJ;AAEA,SACE,gBAAAA;AAAA,IAAC;AAAA;AAAA,MACC,eAAY;AAAA,MACZ,UAAU;AAAA,MACV,KAAK;AAAA,MACL,OAAO;AAAA,QACL,MAAM;AAAA,QACN,UAAU;AAAA,QACV,gBAAgB,GAAG,MAAM,OAAO,SAAS;AAAA,QACzC,gBAAgB;AAAA,MAClB;AAAA,MAEC,kBAAQ,IAAI,CAAC,WACZ,gBAAAA;AAAA,QAAC;AAAA;AAAA,UACC,UAAU,eAAe,OAAO;AAAA,UAEhC;AAAA,UACA;AAAA;AAAA,QAFK,OAAO;AAAA,MAGd,CACD;AAAA;AAAA,EACH;AAEJ;;;AM3EA,SAAS,gBAAgB;AACzB,SAAS,eAAe;AACxB,SAAS,iBAAiB;AAC1B,SAAS,eAAAC,cAAa,aAAAC,YAAW,SAAS,gBAAgB;;;ACDnD,IAAM,aAAyB,CAAC,SAAS,SAAS,QAAQ,WAAW,SAAS,OAAO;;;ADiGxF,gBAAAC,MAgGE,QAAAC,aAhGF;AA1EJ,IAAM,iBAAiB;AACvB,SAAS,iBAAiB;AACxB,EAAAC,WAAU,MAAM;AACd,QAAI,SAAS,eAAe,cAAc,GAAG;AAC3C;AAAA,IACF;AACA,UAAM,QAAQ,SAAS,cAAc,OAAO;AAC5C,UAAM,KAAK;AACX,UAAM,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAQP,MAAM,OAAO,WAAW;AAAA;AAAA;AAAA;AAAA,iBAIxB,MAAM,OAAO,KAAK;AAAA;AAAA;AAG/B,aAAS,KAAK,YAAY,KAAK;AAAA,EACjC,GAAG,CAAC,CAAC;AACP;AAEA,IAAM,cAAc;AAAA,EAClB,YAAY,MAAM,OAAO;AAAA,EACzB,QAAQ,aAAa,MAAM,OAAO,MAAM;AAAA,EACxC,cAAc,MAAM,OAAO;AAAA,EAC3B,OAAO,MAAM,OAAO;AAAA,EACpB,QAAQ;AAAA,EACR,YAAY,MAAM,WAAW;AAAA,EAC7B,UAAU,MAAM,SAAS;AAAA,EACzB,SAAS,GAAG,MAAM,QAAQ,EAAE,IAAI,MAAM,QAAQ,EAAE;AAAA,EAChD,YAAY;AAAA,EACZ,OAAO;AACT;AAEA,IAAM,aAAa;AAAA,EACjB,YAAY,MAAM,OAAO;AAAA,EACzB,QAAQ,aAAa,MAAM,OAAO,WAAW;AAAA,EAC7C,cAAc,MAAM,OAAO;AAAA,EAC3B,OAAO,MAAM,OAAO;AAAA,EACpB,YAAY,MAAM,WAAW;AAAA,EAC7B,UAAU,MAAM,SAAS;AAAA,EACzB,SAAS;AAAA,EACT,SAAS,GAAG,MAAM,QAAQ,EAAE,IAAI,MAAM,QAAQ,EAAE;AAAA,EAChD,YAAY;AAAA,EACZ,OAAO;AACT;AAEA,IAAM,oBAAoB;AAAA,EACxB,OAAO,MAAM,OAAO;AAAA,EACpB,UAAU;AAAA,EACV,YAAY;AAAA,EACZ,eAAe;AAAA,EACf,eAAe;AACjB;AAEA,IAAM,cAAc,CAAC;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AACF,MAIM;AACJ,QAAM,SAAS,MAAM,OAAO,OAAO,KAAK;AACxC,QAAM,cAAcC,aAAY,MAAM,SAAS,KAAK,GAAG,CAAC,OAAO,QAAQ,CAAC;AAExE,SACE,gBAAAH;AAAA,IAAC;AAAA;AAAA,MACC,gBAAc;AAAA,MACd,uBAAoB;AAAA,MACpB,eAAa,gBAAgB,KAAK;AAAA,MAClC,SAAS;AAAA,MACT,OAAO;AAAA,QACL,YAAY,SAAS,OAAO,QAAQ;AAAA,QACpC,QAAQ,aAAa,SAAS,OAAO,QAAQ,MAAM,OAAO,MAAM;AAAA,QAChE,cAAc,MAAM,OAAO;AAAA,QAC3B,OAAO,SAAS,MAAM,OAAO,QAAQ,OAAO;AAAA,QAC5C,QAAQ;AAAA,QACR,YAAY,MAAM,WAAW;AAAA,QAC7B,UAAU,MAAM,SAAS;AAAA,QACzB,YAAY;AAAA,QACZ,YAAY;AAAA,QACZ,UAAU;AAAA,QACV,SAAS,SAAS,IAAI;AAAA,QACtB,SAAS;AAAA,QACT,WAAW;AAAA,QACX,YAAY;AAAA,MACd;AAAA,MACA,OAAO,UAAU,KAAK;AAAA,MACtB,MAAK;AAAA,MAEJ,gBAAM,MAAM,GAAG,CAAC,EAAE,YAAY;AAAA;AAAA,EACjC;AAEJ;AAEO,IAAM,UAAU,CAAC;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAoB;AAClB,iBAAe;AAEf,QAAM,CAAC,aAAa,cAAc,IAAI,SAAS,UAAU;AACzD,QAAM,kBAAkB;AAAA,IACtB,MAAM,IAAI,UAAU,oBAAoB,EAAE,MAAM,IAAI,CAAC;AAAA,IACrD,CAAC,kBAAkB;AAAA,EACrB;AAEA,QAAM,qBAAqBG;AAAA,IACzB,CAAC,MAA2C;AAC1C,YAAM,QAAQ,EAAE,OAAO;AACvB,qBAAe,KAAK;AACpB,sBAAgB,aAAa,KAAK;AAAA,IACpC;AAAA,IACA,CAAC,eAAe;AAAA,EAClB;AAGA,EAAAD,WAAU,MAAM;AACd,QAAI,eAAe,MAAM,gBAAgB,IAAI;AAC3C,qBAAe,EAAE;AAAA,IACnB;AAAA,EACF,GAAG,CAAC,YAAY,WAAW,CAAC;AAE5B,QAAM,oBAAoBC;AAAA,IACxB,CAAC,UAAoB;AACnB,YAAM,OAAO,IAAI,IAAI,WAAW;AAChC,UAAI,KAAK,IAAI,KAAK,GAAG;AACnB,aAAK,OAAO,KAAK;AAAA,MACnB,OAAO;AACL,aAAK,IAAI,KAAK;AAAA,MAChB;AACA,0BAAoB,IAAI;AAAA,IAC1B;AAAA,IACA,CAAC,aAAa,mBAAmB;AAAA,EACnC;AAEA,SACE,gBAAAF;AAAA,IAAC;AAAA;AAAA,MACC,eAAY;AAAA,MACZ,OAAO;AAAA,QACL,SAAS;AAAA,QACT,eAAe;AAAA,QACf,YAAY;AAAA,QACZ,KAAK,MAAM,QAAQ;AAAA,QACnB,QAAQ;AAAA,QACR,UAAU;AAAA,QACV,UAAU;AAAA,QACV,SAAS,GAAG,MAAM,QAAQ,EAAE,IAAI,MAAM,QAAQ,EAAE;AAAA,MAClD;AAAA,MAGA;AAAA,wBAAAA,MAAC,SAAI,OAAO,EAAE,WAAW,SAAS,GAChC;AAAA,0BAAAD;AAAA,YAAC;AAAA;AAAA,cACC,OAAO;AAAA,gBACL,OAAO,MAAM,OAAO;AAAA,gBACpB,YAAY,MAAM,WAAW;AAAA,gBAC7B,UAAU,MAAM,SAAS;AAAA,gBACzB,YAAY;AAAA,cACd;AAAA,cAEC,4BAAkB,aAAa,GAAG,UAAU,KAAK,GAAG,aAAa,MAAM,UAAU;AAAA;AAAA,UACpF;AAAA,UACA,gBAAAA,KAAC,SAAI,OAAO,EAAE,OAAO,MAAM,OAAO,WAAW,UAAU,MAAM,SAAS,GAAG,GAAG,kBAAI;AAAA,WAClF;AAAA,QAGA,gBAAAC,MAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,eAAe,UAAU,KAAK,MAAM,QAAQ,GAAG,GAC5E;AAAA,0BAAAD,KAAC,SAAI,OAAO,mBAAmB,qBAAO;AAAA,UACtC,gBAAAA;AAAA,YAAC;AAAA;AAAA,cACC,uBAAoB;AAAA,cACpB,SAAS,SAAS,WAAW;AAAA,cAC7B,OAAO;AAAA,gBACL,GAAG;AAAA,gBACH,YAAY,SAAS,MAAM,OAAO,OAAO,QAAQ,QAAQ,YAAY;AAAA,gBACrE,OAAO,SAAS,MAAM,OAAO,QAAQ,YAAY;AAAA,cACnD;AAAA,cACA,OAAO,SAAS,wBAAwB;AAAA,cACxC,MAAK;AAAA,cAEL,0BAAAC,MAAC,UAAK,OAAO,EAAE,YAAY,UAAU,SAAS,eAAe,KAAK,MAAM,GACrE;AAAA,yBAAS,gBAAAD,KAAC,YAAS,MAAM,IAAI,IAAK,gBAAAA,KAAC,aAAU,MAAM,IAAI;AAAA,gBACvD,SAAS,WAAW;AAAA,iBACvB;AAAA;AAAA,UACF;AAAA,UAEA,gBAAAA;AAAA,YAAC;AAAA;AAAA,cACC,uBAAoB;AAAA,cACpB,SAAS;AAAA,cACT,OAAO;AAAA,cACP,OAAM;AAAA,cACN,MAAK;AAAA,cAEL,0BAAAC,MAAC,UAAK,OAAO,EAAE,YAAY,UAAU,SAAS,eAAe,KAAK,MAAM,GACtE;AAAA,gCAAAD,KAAC,cAAW,MAAM,IAAI;AAAA,gBAAE;AAAA,iBAE1B;AAAA;AAAA,UACF;AAAA,WACF;AAAA,QAGA,gBAAAC,MAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,eAAe,UAAU,KAAK,MAAM,QAAQ,GAAG,GAC5E;AAAA,0BAAAA,MAAC,SAAI,OAAO,EAAE,YAAY,UAAU,SAAS,QAAQ,gBAAgB,gBAAgB,GACnF;AAAA,4BAAAD,KAAC,SAAI,OAAO,mBAAmB,oBAAM;AAAA,YACpC,YAAY,OAAO,KAClB,gBAAAA;AAAA,cAAC;AAAA;AAAA,gBACC,qBAAkB;AAAA,gBAClB,SAAS,MAAM,oBAAoB,oBAAI,IAAI,CAAC;AAAA,gBAC5C,OAAO;AAAA,kBACL,YAAY;AAAA,kBACZ,QAAQ;AAAA,kBACR,OAAO,MAAM,OAAO;AAAA,kBACpB,QAAQ;AAAA,kBACR,UAAU;AAAA,kBACV,SAAS;AAAA,kBACT,YAAY;AAAA,gBACd;AAAA,gBACA,OAAM;AAAA,gBACN,MAAK;AAAA,gBACN;AAAA;AAAA,YAED;AAAA,aAEJ;AAAA,UACA,gBAAAA;AAAA,YAAC;AAAA;AAAA,cACC,OAAO;AAAA,gBACL,SAAS;AAAA,gBACT,KAAK,MAAM,QAAQ;AAAA,gBACnB,qBAAqB;AAAA,cACvB;AAAA,cAEC,qBAAW,IAAI,CAAC,UACf,gBAAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,QAAQ,YAAY,SAAS,KAAK,YAAY,IAAI,KAAK;AAAA,kBAEvD;AAAA,kBACA,UAAU;AAAA;AAAA,gBAFL;AAAA,cAGP,CACD;AAAA;AAAA,UACH;AAAA,WACF;AAAA,QAGA,gBAAAC,MAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,eAAe,UAAU,KAAK,MAAM,QAAQ,GAAG,GAC5E;AAAA,0BAAAA,MAAC,SAAI,OAAO,EAAE,YAAY,UAAU,SAAS,QAAQ,gBAAgB,gBAAgB,GACnF;AAAA,4BAAAD,KAAC,SAAI,OAAO,mBAAmB,sBAAQ;AAAA,YACtC,eAAe,SAAS,KACvB,gBAAAA;AAAA,cAAC;AAAA;AAAA,gBACC,qBAAkB;AAAA,gBAClB,SAAS,MAAM,uBAAuB,CAAC,CAAC;AAAA,gBACxC,OAAO;AAAA,kBACL,YAAY;AAAA,kBACZ,QAAQ;AAAA,kBACR,OAAO,MAAM,OAAO;AAAA,kBACpB,QAAQ;AAAA,kBACR,UAAU;AAAA,kBACV,SAAS;AAAA,kBACT,YAAY;AAAA,gBACd;AAAA,gBACA,OAAM;AAAA,gBACN,MAAK;AAAA,gBACN;AAAA;AAAA,YAED;AAAA,aAEJ;AAAA,UACC,WAAW,WAAW,IACrB,gBAAAC,MAAC,QAAQ,MAAR,EACC;AAAA,4BAAAD;AAAA,cAAC,QAAQ;AAAA,cAAR;AAAA,gBACC,OAAO;AAAA,gBACP,cAAc;AAAA,gBACd,aAAW;AAAA,gBACX,QACE,gBAAAA;AAAA,kBAAC;AAAA;AAAA,oBACC,eAAY;AAAA,oBACZ,OAAO;AAAA,sBACL,GAAG;AAAA,sBACH,OAAO,MAAM,OAAO;AAAA,sBACpB,QAAQ;AAAA,sBACR,SAAS;AAAA,oBACX;AAAA,oBACD;AAAA;AAAA,gBAED;AAAA;AAAA,YAEJ;AAAA,YACA,gBAAAA,KAAC,QAAQ,QAAR,EACC,0BAAAA,KAAC,QAAQ,YAAR,EAAmB,YAAY,GAAG,OAAO,EAAE,QAAQ,OAAQ,GAC1D,0BAAAA;AAAA,cAAC,QAAQ;AAAA,cAAR;AAAA,gBACC,OAAO;AAAA,kBACL,YAAY,MAAM,OAAO;AAAA,kBACzB,QAAQ,aAAa,MAAM,OAAO,MAAM;AAAA,kBACxC,cAAc,MAAM,OAAO;AAAA,kBAC3B,WAAW;AAAA,kBACX,UAAU,MAAM,SAAS;AAAA,kBACzB,UAAU;AAAA,kBACV,SAAS,GAAG,MAAM,QAAQ,EAAE,IAAI,MAAM,QAAQ,EAAE;AAAA,gBAClD;AAAA,gBAEA,0BAAAA,KAAC,OAAE,OAAO,EAAE,OAAO,MAAM,OAAO,WAAW,YAAY,KAAK,QAAQ,EAAE,GAAG,gEAEzE;AAAA;AAAA,YACF,GACF,GACF;AAAA,aACF,IAEA,gBAAAC;AAAA,YAAC,SAAS;AAAA,YAAT;AAAA,cACC,OAAO;AAAA,cACP,UAAQ;AAAA,cACR,eAAe;AAAA,cACf,OAAO;AAAA,cAEP;AAAA,gCAAAA;AAAA,kBAAC;AAAA;AAAA,oBACC,OAAO;AAAA,sBACL,YAAY,MAAM,OAAO;AAAA,sBACzB,QAAQ,aAAa,MAAM,OAAO,WAAW;AAAA,sBAC7C,cAAc,MAAM,OAAO;AAAA,sBAC3B,SAAS;AAAA,sBACT,UAAU;AAAA,sBACV,KAAK;AAAA,sBACL,WAAW;AAAA,sBACX,SAAS;AAAA,sBACT,YAAY;AAAA,oBACd;AAAA,oBAEC;AAAA,qCAAe,IAAI,CAAC,QACnB,gBAAAA;AAAA,wBAAC;AAAA;AAAA,0BAEC,OAAO;AAAA,4BACL,YAAY;AAAA,4BACZ,YAAY;AAAA,4BACZ,QAAQ;AAAA,4BACR,cAAc,MAAM,OAAO;AAAA,4BAC3B,OAAO,MAAM,OAAO;AAAA,4BACpB,SAAS;AAAA,4BACT,YAAY,MAAM,WAAW;AAAA,4BAC7B,UAAU;AAAA,4BACV,KAAK;AAAA,4BACL,YAAY;AAAA,4BACZ,SAAS;AAAA,0BACX;AAAA,0BAEC;AAAA;AAAA,4BACD,gBAAAD;AAAA,8BAAC;AAAA;AAAA,gCACC,uBAAoB;AAAA,gCACpB,SAAS,MAAM,uBAAuB,eAAe,OAAO,CAAC,MAAM,MAAM,GAAG,CAAC;AAAA,gCAC7E,OAAO;AAAA,kCACL,YAAY;AAAA,kCACZ,QAAQ;AAAA,kCACR,OAAO,MAAM,OAAO;AAAA,kCACpB,QAAQ;AAAA,kCACR,UAAU;AAAA,kCACV,YAAY;AAAA,kCACZ,SAAS;AAAA,kCACT,SAAS;AAAA,kCACT,YAAY;AAAA,gCACd;AAAA,gCACA,OAAO,UAAU,GAAG;AAAA,gCACpB,MAAK;AAAA,gCAEL,0BAAAA,KAAC,SAAM,MAAM,GAAG;AAAA;AAAA,4BAClB;AAAA;AAAA;AAAA,wBAlCK;AAAA,sBAmCP,CACD;AAAA,sBACD,gBAAAA;AAAA,wBAAC,SAAS;AAAA,wBAAT;AAAA,0BACC,eAAY;AAAA,0BACZ,aAAa,eAAe,WAAW,IAAI,mBAAc;AAAA,0BACzD,OAAO;AAAA,4BACL,YAAY;AAAA,4BACZ,QAAQ;AAAA,4BACR,OAAO,MAAM,OAAO;AAAA,4BACpB,MAAM;AAAA,4BACN,YAAY,MAAM,WAAW;AAAA,4BAC7B,UAAU,MAAM,SAAS;AAAA,4BACzB,UAAU;AAAA,4BACV,SAAS;AAAA,4BACT,SAAS,GAAG,MAAM,QAAQ,EAAE,IAAI,MAAM,QAAQ,EAAE;AAAA,0BAClD;AAAA;AAAA,sBACF;AAAA;AAAA;AAAA,gBACF;AAAA,gBACA,gBAAAA,KAAC,SAAS,QAAT,EACC,0BAAAA,KAAC,SAAS,YAAT,EAAoB,OAAO,EAAE,QAAQ,OAAQ,GAC5C,0BAAAA;AAAA,kBAAC,SAAS;AAAA,kBAAT;AAAA,oBACC,OAAO;AAAA,sBACL,YAAY,MAAM,OAAO;AAAA,sBACzB,QAAQ,aAAa,MAAM,OAAO,MAAM;AAAA,sBACxC,cAAc,MAAM,OAAO;AAAA,sBAC3B,WAAW;AAAA,sBACX,WAAW;AAAA,sBACX,UAAU;AAAA,sBACV,SAAS,MAAM,QAAQ;AAAA,oBACzB;AAAA,oBAEA,0BAAAA,KAAC,SAAS,MAAT,EACE,WAAC,MAAM,UACN,gBAAAC;AAAA,sBAAC,SAAS;AAAA,sBAAT;AAAA,wBACC;AAAA,wBAEA,OAAO;AAAA,0BACL,YAAY;AAAA,0BACZ,cAAc,MAAM,OAAO;AAAA,0BAC3B,OAAO,MAAM,OAAO;AAAA,0BACpB,QAAQ;AAAA,0BACR,SAAS;AAAA,0BACT,YAAY,MAAM,WAAW;AAAA,0BAC7B,UAAU,MAAM,SAAS;AAAA,0BACzB,KAAK,MAAM,QAAQ;AAAA,0BACnB,gBAAgB;AAAA,0BAChB,SAAS,GAAG,MAAM,QAAQ,EAAE,IAAI,MAAM,QAAQ,EAAE;AAAA,0BAChD,YAAY;AAAA,wBACd;AAAA,wBACA,OAAO;AAAA,wBAEP;AAAA,0CAAAD,KAAC,UAAK,OAAO,EAAE,MAAM,GAAG,UAAU,UAAU,cAAc,WAAW,GAClE,iBAAO,IAAI,GACd;AAAA,0BACA,gBAAAA,KAAC,SAAS,eAAT,EACC,0BAAAA,KAAC,aAAU,OAAO,MAAM,OAAO,QAAQ,MAAM,IAAI,GACnD;AAAA;AAAA;AAAA,sBArBK,OAAO,IAAI;AAAA,oBAsBlB,GAEJ;AAAA;AAAA,gBACF,GACF,GACF;AAAA;AAAA;AAAA,UACF;AAAA,WAEJ;AAAA,QAGA,gBAAAC,MAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,eAAe,UAAU,KAAK,MAAM,QAAQ,GAAG,GAC5E;AAAA,0BAAAD,KAAC,SAAI,OAAO,mBAAmB,oBAAM;AAAA,UACrC,gBAAAA;AAAA,YAAC;AAAA;AAAA,cACC,eAAY;AAAA,cACZ,UAAU;AAAA,cACV,aAAY;AAAA,cACZ,OAAO;AAAA,cACP,MAAK;AAAA,cACL,OAAO;AAAA;AAAA,UACT;AAAA,WACF;AAAA;AAAA;AAAA,EACF;AAEJ;;;APzYQ,SAqDI,UArDJ,OAAAI,MA8CI,QAAAC,aA9CJ;AAlFD,IAAM,wBAAwB,CAAC,EAAE,MAAM,MAAa;AACzD,QAAM,aAAa,qBAAqB,MAAM,WAAW,MAAM,aAAa,MAAM,WAAW;AAE7F,QAAM,CAAC,QAAQ,SAAS,IAAIC,UAAS,KAAK;AAC1C,QAAM,CAAC,eAAe,gBAAgB,IAAIA,UAA8B,CAAC,CAAC;AAC1E,QAAM,CAAC,aAAa,cAAc,IAAIA,UAAwB,oBAAI,IAAI,CAAC;AACvE,QAAM,CAAC,gBAAgB,iBAAiB,IAAIA,UAAmB,CAAC,CAAC;AACjE,QAAM,CAAC,YAAY,aAAa,IAAIA,UAAS,EAAE;AAC/C,QAAM,CAAC,YAAY,aAAa,IAAIA,UAAwB,IAAI;AAChE,QAAM,CAAC,aAAa,cAAc,IAAIA,UAAS,IAAI;AAEnD,QAAM,cAAcC,aAAY,MAAM;AACpC,cAAU,IAAI;AACd,qBAAiB,MAAM,YAAY,CAAC;AAAA,EACtC,GAAG,CAAC,KAAK,CAAC;AAEV,QAAM,eAAeA,aAAY,MAAM;AACrC,cAAU,KAAK;AACf,qBAAiB,CAAC,CAAC;AAAA,EACrB,GAAG,CAAC,CAAC;AAEL,QAAM,cAAcA,aAAY,MAAM;AACpC,UAAM,MAAM;AACZ,qBAAiB,CAAC,CAAC;AACnB,kBAAc,IAAI;AAAA,EACpB,GAAG,CAAC,KAAK,CAAC;AAEV,QAAM,UAAU,SAAS,gBAAgB;AAEzC,QAAM,mBAAmBC,SAAQ,MAAM;AACrC,UAAM,OAAO,oBAAI,IAAY;AAC7B,eAAW,KAAK,SAAS;AACvB,WAAK,IAAI,EAAE,SAAS,KAAK,GAAG,CAAC;AAAA,IAC/B;AACA,WAAO,MAAM,KAAK,IAAI,EAAE,KAAK;AAAA,EAC/B,GAAG,CAAC,OAAO,CAAC;AAEZ,QAAM,kBAAkBA,SAAQ,MAAM;AACpC,WAAO,QAAQ,OAAO,CAAC,MAAM;AAC3B,UAAI,YAAY,OAAO,KAAK,CAAC,YAAY,IAAI,EAAE,KAAK,GAAG;AACrD,eAAO;AAAA,MACT;AACA,UAAI,eAAe,SAAS,KAAK,CAAC,eAAe,SAAS,EAAE,SAAS,KAAK,GAAG,CAAC,GAAG;AAC/E,eAAO;AAAA,MACT;AACA,UAAI,YAAY;AACd,cAAM,OAAO,WAAW,YAAY;AACpC,YACE,EACE,EAAE,YAAY,YAAY,EAAE,SAAS,IAAI,KACzC,EAAE,SAAS,KAAK,GAAG,EAAE,YAAY,EAAE,SAAS,IAAI,IAElD;AACA,iBAAO;AAAA,QACT;AAAA,MACF;AACA,aAAO;AAAA,IACT,CAAC;AAAA,EACH,GAAG,CAAC,SAAS,aAAa,gBAAgB,UAAU,CAAC;AAErD,SACE,gBAAAH;AAAA,IAAC;AAAA;AAAA,MACC,OAAO;AAAA,QACL,YAAY,MAAM,OAAO;AAAA,QACzB,OAAO,MAAM,OAAO;AAAA,QACpB,SAAS;AAAA,QACT,eAAe;AAAA,QACf,YAAY,MAAM,WAAW;AAAA,QAC7B,QAAQ;AAAA,QACR,UAAU;AAAA,MACZ;AAAA,MAEA;AAAA,wBAAAD;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,cACL,aAAa,cAAc,aAAa,MAAM,OAAO,MAAM,KAAK;AAAA,cAChE,YAAY;AAAA,cACZ,SAAS,cAAc,IAAI;AAAA,cAC3B,UAAU;AAAA,cACV,YAAY;AAAA,cACZ,OAAO,cAAc,UAAU;AAAA,YACjC;AAAA,YAEA,0BAAAA;AAAA,cAAC;AAAA;AAAA,gBACC,YAAY;AAAA,gBACZ;AAAA,gBACA,eAAe,gBAAgB;AAAA,gBAC/B;AAAA,gBACA,wBAAwB;AAAA,gBACxB,SAAS;AAAA,gBACT,qBAAqB;AAAA,gBACrB,SAAS;AAAA,gBACT,UAAU;AAAA,gBACV,oBAAoB;AAAA,gBACpB;AAAA,gBACA;AAAA,gBACA,YAAY,QAAQ;AAAA;AAAA,YACtB;AAAA;AAAA,QACF;AAAA,QAEA,gBAAAC,MAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,MAAM,GAAG,eAAe,UAAU,UAAU,SAAS,GAElF;AAAA,0BAAAA;AAAA,YAAC;AAAA;AAAA,cACC,OAAO;AAAA,gBACL,YAAY;AAAA,gBACZ,cAAc,aAAa,MAAM,OAAO,MAAM;AAAA,gBAC9C,SAAS;AAAA,gBACT,YAAY;AAAA,gBACZ,KAAK,MAAM,QAAQ;AAAA,gBACnB,SAAS,GAAG,MAAM,QAAQ,EAAE,IAAI,MAAM,QAAQ,EAAE;AAAA,cAClD;AAAA,cAEA;AAAA,gCAAAD;AAAA,kBAAC;AAAA;AAAA,oBACC,iBAAe;AAAA,oBACf,qBAAkB;AAAA,oBAClB,SAAS,MAAM,eAAe,CAAC,MAAM,CAAC,CAAC;AAAA,oBACvC,OAAO;AAAA,sBACL,YAAY;AAAA,sBACZ,QAAQ;AAAA,sBACR,OAAO,MAAM,OAAO;AAAA,sBACpB,QAAQ;AAAA,sBACR,YAAY,MAAM,WAAW;AAAA,sBAC7B,UAAU,MAAM,SAAS;AAAA,sBACzB,SAAS,GAAG,MAAM,QAAQ,EAAE,IAAI,MAAM,QAAQ,EAAE;AAAA,sBAChD,YAAY;AAAA,oBACd;AAAA,oBACA,OAAO,cAAc,qBAAqB;AAAA,oBAC1C,MAAK;AAAA,oBAEL,0BAAAC,MAAC,UAAK,OAAO,EAAE,YAAY,UAAU,SAAS,eAAe,KAAK,MAAM,GACrE;AAAA,oCAAc,gBAAAD,KAAC,sBAAmB,MAAM,IAAI,IAAK,gBAAAA,KAAC,qBAAkB,MAAM,IAAI;AAAA,sBAC9E,cAAc,kBAAkB;AAAA,uBACnC;AAAA;AAAA,gBACF;AAAA,gBAEC,CAAC,eACA,gBAAAC,MAAA,YACE;AAAA,kCAAAD;AAAA,oBAAC;AAAA;AAAA,sBACC,OAAO;AAAA,wBACL,OAAO,MAAM,OAAO;AAAA,wBACpB,YAAY,MAAM,WAAW;AAAA,wBAC7B,UAAU,MAAM,SAAS;AAAA,sBAC3B;AAAA,sBAEC,0BAAgB,WAAW,QAAQ,SAChC,GAAG,QAAQ,MAAM,UACjB,GAAG,gBAAgB,MAAM,MAAM,QAAQ,MAAM;AAAA;AAAA,kBACnD;AAAA,kBACA,gBAAAA;AAAA,oBAAC;AAAA;AAAA,sBACC,uBAAoB;AAAA,sBACpB,SAAS,SAAS,eAAe;AAAA,sBACjC,OAAO;AAAA,wBACL,YAAY,SACR,MAAM,OAAO,OAAO,QAAQ,QAC5B,MAAM,OAAO;AAAA,wBACjB,QAAQ,aAAa,MAAM,OAAO,MAAM;AAAA,wBACxC,cAAc,MAAM,OAAO;AAAA,wBAC3B,OAAO,SAAS,MAAM,OAAO,QAAQ,MAAM,OAAO;AAAA,wBAClD,QAAQ;AAAA,wBACR,YAAY,MAAM,WAAW;AAAA,wBAC7B,UAAU,MAAM,SAAS;AAAA,wBACzB,SAAS,GAAG,MAAM,QAAQ,EAAE,IAAI,MAAM,QAAQ,EAAE;AAAA,wBAChD,YAAY;AAAA,sBACd;AAAA,sBACA,OAAO,SAAS,WAAW;AAAA,sBAC3B,MAAK;AAAA,sBAEJ,mBAAS,gBAAAA,KAAC,YAAS,MAAM,IAAI,IAAK,gBAAAA,KAAC,aAAU,MAAM,IAAI;AAAA;AAAA,kBAC1D;AAAA,kBACA,gBAAAA;AAAA,oBAAC;AAAA;AAAA,sBACC,uBAAoB;AAAA,sBACpB,SAAS;AAAA,sBACT,OAAO;AAAA,wBACL,YAAY,MAAM,OAAO;AAAA,wBACzB,QAAQ,aAAa,MAAM,OAAO,MAAM;AAAA,wBACxC,cAAc,MAAM,OAAO;AAAA,wBAC3B,OAAO,MAAM,OAAO;AAAA,wBACpB,QAAQ;AAAA,wBACR,YAAY,MAAM,WAAW;AAAA,wBAC7B,UAAU,MAAM,SAAS;AAAA,wBACzB,SAAS,GAAG,MAAM,QAAQ,EAAE,IAAI,MAAM,QAAQ,EAAE;AAAA,wBAChD,YAAY;AAAA,sBACd;AAAA,sBACA,OAAM;AAAA,sBACN,MAAK;AAAA,sBAEL,0BAAAA,KAAC,cAAW,MAAM,IAAI;AAAA;AAAA,kBACxB;AAAA,mBACF;AAAA;AAAA;AAAA,UAEJ;AAAA,UACA,gBAAAA;AAAA,YAAC;AAAA;AAAA,cACC,YAAY,CAAC;AAAA,cACb;AAAA,cACA,UAAU;AAAA,cACV,SAAS;AAAA;AAAA,UACX;AAAA,WACF;AAAA;AAAA;AAAA,EACF;AAEJ;;;ASxLU,gBAAAK,YAAA;AAJH,IAAM,8BAA8B,CAAC,aAA4C;AAAA,EACtF,aAAa,SAAS,eAAe;AAAA,EACrC,IAAI;AAAA,EACJ,MAAM,SAAS,QAAQ;AAAA,EACvB,QAAQ,gBAAAA,KAAC,yBAAsB,OAAO,SAAS,SAAS,iBAAiB;AAC3E;;;ACxBA,IAAI,UAAU;AAEd,SAAS,cAAc,SAAqC;AAC1D,SAAO,QACJ,IAAI,CAAC,SAAS;AACb,QAAI,OAAO,SAAS,UAAU;AAC5B,aAAO;AAAA,IACT;AACA,QAAI,SAAS,QAAQ,SAAS,QAAW;AACvC,aAAO,OAAO,IAAI;AAAA,IACpB;AACA,QAAI;AACF,aAAO,KAAK,UAAU,IAAI;AAAA,IAC5B,QAAQ;AACN,aAAO,OAAO,IAAI;AAAA,IACpB;AAAA,EACF,CAAC,EACA,KAAK,EAAE;AACZ;AAEA,SAAS,oBAAoB,YAA8D;AACzF,MAAI;AACF,WAAO,KAAK,MAAM,KAAK,UAAU,UAAU,CAAC;AAAA,EAC9C,QAAQ;AAEN,UAAM,SAAkC,CAAC;AACzC,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,UAAU,GAAG;AACrD,UAAI;AACF,eAAO,GAAG,IAAI,KAAK,MAAM,KAAK,UAAU,KAAK,CAAC;AAAA,MAChD,QAAQ;AACN,eAAO,GAAG,IAAI,OAAO,KAAK;AAAA,MAC5B;AAAA,IACF;AACA,WAAO;AAAA,EACT;AACF;AAOA,IAAM,YAAY;AAElB,IAAM,YAAY;AAElB,SAAS,oBAAwC;AAE/C,QAAM,QAAQ,IAAI,MAAM,EAAE;AAC1B,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AAEA,QAAM,QAAQ,MAAM,MAAM,IAAI;AAE9B,aAAW,QAAQ,OAAO;AACxB,UAAM,UAAU,KAAK,KAAK;AAG1B,QAAI,CAAC,WAAW,YAAY,SAAS;AACnC;AAAA,IACF;AAGA,QAAI,WAAW,KAAK,OAAO,GAAG;AAC5B;AAAA,IACF;AAGA,UAAM,QAAQ,UAAU,KAAK,OAAO,KAAK,UAAU,KAAK,OAAO;AAC/D,QAAI,CAAC,OAAO;AACV;AAAA,IACF;AAEA,UAAM,CAAC,EAAE,UAAU,QAAQ,KAAK,IAAI;AAGpC,UAAM,WACJ,SACG,QAAQ,WAAW,EAAE,EACrB,MAAM,GAAG,EACT,IAAI,KAAK;AAEd,WAAO,GAAG,QAAQ,IAAI,MAAM,IAAI,KAAK;AAAA,EACvC;AAEA,SAAO;AACT;AAEA,SAAS,gBAAgB,QAAmB,cAA0C;AACpF,QAAM,aAAgC;AAAA,IACpC,IAAI,OAAO,EAAE,OAAO,IAAI,OAAO,SAAS;AAAA,IACxC,WAAW,OAAO;AAAA,IAClB,OAAO,OAAO;AAAA,IACd,UAAU,CAAC,GAAG,OAAO,QAAQ;AAAA,IAC7B,SAAS,CAAC,GAAG,OAAO,OAAO;AAAA,IAC3B,aAAa,cAAc,OAAO,OAAO;AAAA,IACzC,YAAY,oBAAoB,OAAO,UAAU;AAAA,EACnD;AAEA,MAAI,cAAc;AAChB,UAAM,SAAS,kBAAkB;AACjC,QAAI,QAAQ;AACV,iBAAW,SAAS;AAAA,IACtB;AAAA,EACF;AAEA,SAAO;AACT;AAEA,SAAS,kBAA2B;AAClC,MAAI;AAEF,QAAI,OAAO,YAAY,eAAe,QAAQ,KAAK,aAAa,cAAc;AAC5E,aAAO;AAAA,IACT;AAAA,EACF,QAAQ;AAAA,EAER;AACA,SAAO;AACT;AA6CO,SAAS,mBAAmB,SAAqC;AACtE,QAAM,QAAQ,SAAS,SAAS;AAChC,QAAM,aAAa,SAAS,iCAAiC;AAC7D,QAAM,eAAe,eAAe,SAAS,mBAAmB,CAAC,gBAAgB;AAEjF,SAAO,CAAC,WAAsB;AAC5B,QAAI;AACF,YAAM,aAAa,gBAAgB,QAAQ,YAAY;AACvD,YAAM,UAAU,UAAU;AAAA,IAC5B,QAAQ;AAAA,IAER;AAAA,EACF;AACF;","names":["useCallback","useMemo","useState","jsx","jsx","jsxs","jsx","jsxs","jsx","useCallback","useEffect","jsx","jsxs","useEffect","useCallback","jsx","jsxs","useState","useCallback","useMemo","jsx"]}
1
+ {"version":3,"sources":["../src/plugin/logtape-devtools-plugin.tsx","../src/plugin/components/log-list.tsx","../src/plugin/theme.ts","../src/plugin/components/log-row.tsx","../src/plugin/format.ts","../src/plugin/icons.tsx","../src/plugin/components/level-badge.tsx","../src/plugin/components/log-detail.tsx","../src/plugin/components/toolbar.tsx","../src/plugin/create-logtape-devtools-plugin.tsx","../src/create-logtape-devtools.ts"],"sourcesContent":["import { useCallback, useMemo, useState, useSyncExternalStore } from \"react\";\nimport type { LogStore } from \"../store\";\nimport type { DevtoolsLogRecord, LogLevel } from \"../types\";\nimport { LogList } from \"./components/log-list\";\nimport { Toolbar } from \"./components/toolbar\";\nimport { PanelLeftCloseIcon, PanelLeftOpenIcon, PauseIcon, PlayIcon, Trash2Icon } from \"./icons\";\nimport { theme } from \"./theme\";\n\ninterface Props {\n store: LogStore;\n}\n\nconst rootStyle = {\n background: theme.colors.background,\n color: theme.colors.textPrimary,\n display: \"flex\",\n flexDirection: \"row\",\n fontFamily: theme.fontFamily.sans,\n height: \"100%\",\n overflow: \"hidden\",\n} as const;\n\nconst sidebarStyle = {\n flexShrink: 0,\n overflow: \"hidden\",\n transition: \"width 0.2s ease, opacity 0.15s ease\",\n} as const;\n\nconst mainStyle = {\n display: \"flex\",\n flex: 1,\n flexDirection: \"column\",\n overflow: \"hidden\",\n} as const;\n\nconst topBarStyle = {\n alignItems: \"center\",\n borderBottom: `1px solid ${theme.colors.border}`,\n display: \"flex\",\n flexShrink: 0,\n gap: theme.spacing.lg,\n padding: `${theme.spacing.sm} ${theme.spacing.lg}`,\n} as const;\n\nconst sidebarToggleStyle = {\n background: \"none\",\n border: \"none\",\n color: theme.colors.textMuted,\n cursor: \"pointer\",\n fontFamily: theme.fontFamily.sans,\n fontSize: theme.fontSize.md,\n padding: `${theme.spacing.xs} ${theme.spacing.sm}`,\n transition: \"color 0.1s\",\n} as const;\n\nconst iconLabelStyle = { alignItems: \"center\", display: \"inline-flex\", gap: \"6px\" } as const;\n\nconst countStyle = {\n color: theme.colors.textMuted,\n fontFamily: theme.fontFamily.mono,\n fontSize: theme.fontSize.sm,\n} as const;\n\nconst compactButtonStyle = {\n background: theme.colors.surfaceHover,\n border: `1px solid ${theme.colors.border}`,\n borderRadius: theme.radius.sm,\n color: theme.colors.textPrimary,\n cursor: \"pointer\",\n fontFamily: theme.fontFamily.sans,\n fontSize: theme.fontSize.sm,\n padding: `${theme.spacing.xs} ${theme.spacing.sm}`,\n transition: \"filter 0.1s\",\n} as const;\n\nexport const LogTapeDevtoolsPlugin = ({ store }: Props) => {\n const allRecords = useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);\n\n const [paused, setPaused] = useState(false);\n const [pausedRecords, setPausedRecords] = useState<DevtoolsLogRecord[]>([]);\n const [levelFilter, setLevelFilter] = useState<Set<LogLevel>>(new Set());\n const [categoryFilter, setCategoryFilter] = useState<string[]>([]);\n const [searchText, setSearchText] = useState(\"\");\n const [expandedId, setExpandedId] = useState<string | null>(null);\n const [sidebarOpen, setSidebarOpen] = useState(true);\n\n const handlePause = useCallback(() => {\n setPaused(true);\n setPausedRecords(store.getSnapshot());\n }, [store]);\n\n const handleResume = useCallback(() => {\n setPaused(false);\n setPausedRecords([]);\n }, []);\n\n const handleClear = useCallback(() => {\n store.clear();\n setPausedRecords([]);\n setExpandedId(null);\n }, [store]);\n\n const records = paused ? pausedRecords : allRecords;\n\n const uniqueCategories = useMemo(() => {\n const seen = new Set<string>();\n for (const r of records) {\n seen.add(r.category.join(\".\"));\n }\n return Array.from(seen).sort();\n }, [records]);\n\n const filteredRecords = useMemo(() => {\n return records.filter((r) => {\n if (levelFilter.size > 0 && !levelFilter.has(r.level)) {\n return false;\n }\n if (categoryFilter.length > 0 && !categoryFilter.includes(r.category.join(\".\"))) {\n return false;\n }\n if (searchText) {\n const term = searchText.toLowerCase();\n if (\n !(\n r.messageText.toLowerCase().includes(term) ||\n r.category.join(\".\").toLowerCase().includes(term)\n )\n ) {\n return false;\n }\n }\n return true;\n });\n }, [records, levelFilter, categoryFilter, searchText]);\n\n return (\n <div style={rootStyle}>\n <div\n style={{\n ...sidebarStyle,\n borderRight: sidebarOpen ? `1px solid ${theme.colors.border}` : \"none\",\n opacity: sidebarOpen ? 1 : 0,\n width: sidebarOpen ? \"200px\" : \"0px\",\n }}\n >\n <Toolbar\n categories={uniqueCategories}\n categoryFilter={categoryFilter}\n filteredCount={filteredRecords.length}\n levelFilter={levelFilter}\n onCategoryFilterChange={setCategoryFilter}\n onClear={handleClear}\n onLevelFilterChange={setLevelFilter}\n onPause={handlePause}\n onResume={handleResume}\n onSearchTextChange={setSearchText}\n paused={paused}\n totalCount={records.length}\n />\n </div>\n\n <div style={mainStyle}>\n {/* Sidebar toggle bar */}\n <div style={topBarStyle}>\n <button\n aria-expanded={sidebarOpen}\n data-lt-clear-btn=\"\"\n onClick={() => setSidebarOpen((v) => !v)}\n style={sidebarToggleStyle}\n title={sidebarOpen ? \"Collapse sidebar\" : \"Expand sidebar\"}\n type=\"button\"\n >\n <span style={iconLabelStyle}>\n {sidebarOpen ? <PanelLeftCloseIcon size={14} /> : <PanelLeftOpenIcon size={14} />}\n {sidebarOpen ? \"Hide controls\" : \"Show controls\"}\n </span>\n </button>\n\n {!sidebarOpen && (\n <>\n <span style={countStyle}>\n {filteredRecords.length === records.length\n ? `${records.length} logs`\n : `${filteredRecords.length} / ${records.length} logs`}\n </span>\n <button\n data-lt-interactive=\"\"\n onClick={paused ? handleResume : handlePause}\n style={{\n ...compactButtonStyle,\n background: paused\n ? theme.colors.levels.warning.badge\n : compactButtonStyle.background,\n color: paused ? theme.colors.white : compactButtonStyle.color,\n }}\n title={paused ? \"Resume\" : \"Pause\"}\n type=\"button\"\n >\n {paused ? <PlayIcon size={12} /> : <PauseIcon size={12} />}\n </button>\n <button\n data-lt-interactive=\"\"\n onClick={handleClear}\n style={compactButtonStyle}\n title=\"Clear\"\n type=\"button\"\n >\n <Trash2Icon size={12} />\n </button>\n </>\n )}\n </div>\n <LogList\n autoScroll={!paused}\n expandedId={expandedId}\n onToggle={setExpandedId}\n records={filteredRecords}\n />\n </div>\n </div>\n );\n};\n","import { useVirtualizer } from \"@tanstack/react-virtual\";\nimport { useCallback, useEffect, useRef } from \"react\";\nimport type { DevtoolsLogRecord } from \"../../types\";\nimport { theme } from \"../theme\";\nimport { LogRow } from \"./log-row\";\n\ninterface LogListProps {\n autoScroll: boolean;\n expandedId: string | null;\n onToggle: (id: string | null) => void;\n records: DevtoolsLogRecord[];\n}\n\n/** Collapsed row height — rows are measured after mount, this is only the seed. */\nconst ESTIMATED_ROW_HEIGHT = 28;\nconst OVERSCAN = 10;\n/** Distance from the bottom (px) still considered \"stuck to the bottom\". */\nconst STICK_THRESHOLD = 40;\n\nconst emptyStyle = {\n alignItems: \"center\",\n color: theme.colors.textMuted,\n display: \"flex\",\n flex: 1,\n fontSize: theme.fontSize.lg,\n justifyContent: \"center\",\n} as const;\n\nconst containerStyle = {\n flex: 1,\n overflow: \"auto\",\n scrollbarColor: `${theme.colors.scrollbar} transparent`,\n scrollbarWidth: \"thin\",\n} as const;\n\nexport const LogList = ({ records, expandedId, onToggle, autoScroll }: LogListProps) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const isAtBottomRef = useRef(true);\n\n const virtualizer = useVirtualizer({\n count: records.length,\n estimateSize: () => ESTIMATED_ROW_HEIGHT,\n getItemKey: (index) => records[index].id,\n getScrollElement: () => containerRef.current,\n overscan: OVERSCAN,\n });\n\n const recordCount = records.length;\n useEffect(() => {\n if (recordCount === 0 || !(autoScroll && isAtBottomRef.current)) {\n return;\n }\n virtualizer.scrollToIndex(recordCount - 1, { align: \"end\" });\n }, [autoScroll, recordCount, virtualizer]);\n\n const handleScroll = useCallback(() => {\n const el = containerRef.current;\n if (!el) {\n return;\n }\n isAtBottomRef.current = el.scrollHeight - el.scrollTop - el.clientHeight < STICK_THRESHOLD;\n }, []);\n\n if (records.length === 0) {\n return (\n <div data-testid=\"log-list-empty\" style={emptyStyle}>\n No logs yet\n </div>\n );\n }\n\n const virtualItems = virtualizer.getVirtualItems();\n\n return (\n <div data-testid=\"log-list\" onScroll={handleScroll} ref={containerRef} style={containerStyle}>\n {/* Spacer sized to the full list, with only the visible window rendered */}\n <div\n style={{\n height: `${virtualizer.getTotalSize()}px`,\n position: \"relative\",\n width: \"100%\",\n }}\n >\n <div\n style={{\n left: 0,\n position: \"absolute\",\n top: 0,\n transform: `translateY(${virtualItems[0]?.start ?? 0}px)`,\n width: \"100%\",\n }}\n >\n {virtualItems.map((virtualItem) => {\n const record = records[virtualItem.index];\n return (\n <div\n data-index={virtualItem.index}\n key={virtualItem.key}\n ref={virtualizer.measureElement}\n >\n <LogRow expanded={expandedId === record.id} onToggle={onToggle} record={record} />\n </div>\n );\n })}\n </div>\n </div>\n </div>\n );\n};\n","export const theme = {\n colors: {\n background: \"#1e1e1e\",\n surface: \"#1a1a1a\",\n surfaceHover: \"#2a2a2a\",\n surfaceSelected: \"#2a2a3a\",\n border: \"#333\",\n borderInput: \"#444\",\n borderFocus: \"#6366f1\",\n\n textPrimary: \"#e0e0e0\",\n textSecondary: \"#888\",\n textMuted: \"#666\",\n textDimmed: \"#555\",\n white: \"#fff\",\n\n accent: \"#6366f1\",\n accentHover: \"#818cf8\",\n\n levels: {\n trace: { bg: \"#1a1a2e\", color: \"#8888bb\", badge: \"#5555aa\" },\n debug: { bg: \"#1a2a1a\", color: \"#88bb88\", badge: \"#55aa55\" },\n info: { bg: \"#1a2a3a\", color: \"#60a5fa\", badge: \"#3b82f6\" },\n warning: { bg: \"#2a2a1a\", color: \"#facc15\", badge: \"#eab308\" },\n error: { bg: \"#2a1a1a\", color: \"#ef4444\", badge: \"#dc2626\" },\n fatal: { bg: \"#3a0a0a\", color: \"#ff6b6b\", badge: \"#b91c1c\" },\n },\n\n scrollbar: \"#444\",\n scrollbarHover: \"#555\",\n },\n\n fontFamily: {\n mono: 'ui-monospace, \"Cascadia Code\", \"Source Code Pro\", Menlo, Consolas, monospace',\n sans: 'system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif',\n },\n\n fontSize: {\n xs: \"9px\",\n sm: \"10px\",\n md: \"11px\",\n base: \"12px\",\n lg: \"13px\",\n },\n\n radius: {\n sm: \"3px\",\n md: \"4px\",\n lg: \"6px\",\n pill: \"10px\",\n },\n\n spacing: {\n xs: \"2px\",\n sm: \"4px\",\n md: \"6px\",\n lg: \"8px\",\n xl: \"12px\",\n xxl: \"16px\",\n },\n} as const;\n\nexport type LogLevelColors = (typeof theme.colors.levels)[keyof typeof theme.colors.levels];\n","import { useCallback } from \"react\";\nimport type { DevtoolsLogRecord } from \"../../types\";\nimport { formatTime } from \"../format\";\nimport { ChevronRightIcon } from \"../icons\";\nimport { theme } from \"../theme\";\nimport { LevelBadge } from \"./level-badge\";\nimport { LogDetail } from \"./log-detail\";\n\ninterface LogRowProps {\n expanded: boolean;\n onToggle: (id: string | null) => void;\n record: DevtoolsLogRecord;\n}\n\nconst rowStyle = {\n alignItems: \"center\",\n border: \"none\",\n borderBottom: `1px solid ${theme.colors.border}`,\n cursor: \"pointer\",\n display: \"flex\",\n gap: theme.spacing.lg,\n padding: `${theme.spacing.md} ${theme.spacing.xl}`,\n textAlign: \"left\",\n transition: \"background 0.1s, filter 0.1s\",\n width: \"100%\",\n} as const;\n\nconst timestampStyle = {\n color: theme.colors.textDimmed,\n flexShrink: 0,\n fontFamily: theme.fontFamily.mono,\n fontSize: theme.fontSize.md,\n} as const;\n\nconst categoryStyle = {\n color: theme.colors.accent,\n flexShrink: 0,\n fontFamily: theme.fontFamily.mono,\n fontSize: theme.fontSize.md,\n maxWidth: \"180px\",\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n} as const;\n\nconst messageStyle = {\n color: theme.colors.textPrimary,\n flex: 1,\n fontSize: theme.fontSize.base,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n} as const;\n\nconst callerStyle = {\n color: theme.colors.textDimmed,\n flexShrink: 0,\n fontFamily: theme.fontFamily.mono,\n fontSize: theme.fontSize.sm,\n maxWidth: \"200px\",\n opacity: 0.7,\n overflow: \"hidden\",\n textOverflow: \"ellipsis\",\n whiteSpace: \"nowrap\",\n} as const;\n\nconst chevronStyle = {\n color: theme.colors.textDimmed,\n display: \"flex\",\n flexShrink: 0,\n transition: \"transform 0.15s\",\n} as const;\n\nexport const LogRow = ({ record, expanded, onToggle }: LogRowProps) => {\n const levelColors = theme.colors.levels[record.level];\n\n const handleClick = useCallback(() => {\n onToggle(expanded ? null : record.id);\n }, [expanded, onToggle, record.id]);\n\n return (\n <div>\n <button\n aria-expanded={expanded}\n data-lt-interactive=\"\"\n data-testid=\"log-row\"\n onClick={handleClick}\n style={{ ...rowStyle, background: expanded ? levelColors.bg : \"transparent\" }}\n type=\"button\"\n >\n {/* Timestamp */}\n <span style={timestampStyle}>{formatTime(record.timestamp)}</span>\n\n {/* Level badge */}\n <LevelBadge level={record.level} />\n\n {/* Category */}\n <span style={categoryStyle}>{record.category.join(\".\")}</span>\n\n {/* Message */}\n <span style={messageStyle}>{record.messageText}</span>\n\n {/* Caller (right-aligned) */}\n {record.caller && <span style={callerStyle}>{record.caller}</span>}\n\n {/* Expand indicator */}\n <span style={{ ...chevronStyle, transform: expanded ? \"rotate(90deg)\" : \"rotate(0deg)\" }}>\n <ChevronRightIcon size={12} />\n </span>\n </button>\n\n {expanded && <LogDetail record={record} />}\n </div>\n );\n};\n","/** Formats a timestamp as a 24-hour `HH:MM:SS` local time string. */\nexport function formatTime(ts: number): string {\n const d = new Date(ts);\n return d.toLocaleTimeString(undefined, {\n hour12: false,\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n });\n}\n","/**\n * Inline SVG icons based on Lucide (https://lucide.dev) — ISC License.\n * Using inline SVGs avoids adding lucide-react as a runtime dependency.\n */\n\ninterface IconProps {\n color?: string;\n size?: number;\n style?: React.CSSProperties;\n}\n\nconst defaults = { size: 14, color: \"currentColor\" } as const;\n\nconst Svg = ({\n size = defaults.size,\n color = defaults.color,\n style,\n children,\n}: IconProps & { children: React.ReactNode }) => (\n <svg\n aria-hidden=\"true\"\n fill=\"none\"\n height={size}\n stroke={color}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n strokeWidth={2}\n style={style}\n viewBox=\"0 0 24 24\"\n width={size}\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n {children}\n </svg>\n);\n\nexport const PlayIcon = (props: IconProps) => (\n <Svg {...props}>\n <path d=\"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\" />\n </Svg>\n);\n\nexport const PauseIcon = (props: IconProps) => (\n <Svg {...props}>\n <rect height={18} rx={1} width={5} x={14} y={3} />\n <rect height={18} rx={1} width={5} x={5} y={3} />\n </Svg>\n);\n\nexport const XIcon = (props: IconProps) => (\n <Svg {...props}>\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </Svg>\n);\n\nexport const CheckIcon = (props: IconProps) => (\n <Svg {...props}>\n <path d=\"M20 6 9 17l-5-5\" />\n </Svg>\n);\n\nexport const ChevronRightIcon = (props: IconProps) => (\n <Svg {...props}>\n <path d=\"m9 18 6-6-6-6\" />\n </Svg>\n);\n\nexport const PanelLeftCloseIcon = (props: IconProps) => (\n <Svg {...props}>\n <rect height={18} rx={2} width={18} x={3} y={3} />\n <path d=\"M9 3v18\" />\n <path d=\"m16 15-3-3 3-3\" />\n </Svg>\n);\n\nexport const PanelLeftOpenIcon = (props: IconProps) => (\n <Svg {...props}>\n <rect height={18} rx={2} width={18} x={3} y={3} />\n <path d=\"M9 3v18\" />\n <path d=\"m14 9 3 3-3 3\" />\n </Svg>\n);\n\nexport const Trash2Icon = (props: IconProps) => (\n <Svg {...props}>\n <path d=\"M10 11v6\" />\n <path d=\"M14 11v6\" />\n <path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6\" />\n <path d=\"M3 6h18\" />\n <path d=\"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\" />\n </Svg>\n);\n","import type { LogLevel } from \"../../types\";\nimport { theme } from \"../theme\";\n\nconst LEVEL_LABELS: Record<LogLevel, string> = {\n trace: \"TRC\",\n debug: \"DBG\",\n info: \"INF\",\n warning: \"WRN\",\n error: \"ERR\",\n fatal: \"FTL\",\n};\n\nexport const LevelBadge = ({ level }: { level: LogLevel }) => {\n const colors = theme.colors.levels[level];\n\n return (\n <span\n style={{\n background: colors.badge,\n borderRadius: theme.radius.sm,\n color: theme.colors.white,\n display: \"inline-block\",\n fontFamily: theme.fontFamily.mono,\n fontSize: theme.fontSize.sm,\n fontWeight: 600,\n lineHeight: 1,\n minWidth: \"28px\",\n padding: `${theme.spacing.xs} ${theme.spacing.sm}`,\n textAlign: \"center\",\n textTransform: \"uppercase\",\n }}\n >\n {LEVEL_LABELS[level]}\n </span>\n );\n};\n","import { safeStringify } from \"../../safe-json\";\nimport type { DevtoolsLogRecord } from \"../../types\";\nimport { formatTime } from \"../format\";\nimport { theme } from \"../theme\";\n\nconst detailRowStyle = {\n display: \"flex\",\n gap: theme.spacing.lg,\n marginBottom: theme.spacing.md,\n} as const;\n\nconst detailLabelStyle = {\n color: theme.colors.textMuted,\n flexShrink: 0,\n fontSize: theme.fontSize.md,\n minWidth: \"72px\",\n textAlign: \"right\",\n} as const;\n\nconst detailValueStyle = {\n fontSize: theme.fontSize.base,\n wordBreak: \"break-all\",\n} as const;\n\nconst containerStyle = {\n borderTop: `1px solid ${theme.colors.border}`,\n padding: `${theme.spacing.lg} ${theme.spacing.xl}`,\n} as const;\n\nconst categoryStyle = {\n color: theme.colors.accent,\n fontFamily: theme.fontFamily.mono,\n} as const;\n\nconst callerStyle = {\n color: theme.colors.textSecondary,\n fontFamily: theme.fontFamily.mono,\n} as const;\n\nconst messageStyle = { color: theme.colors.textPrimary } as const;\n\nconst propertiesStyle = {\n background: \"rgba(0,0,0,0.3)\",\n borderRadius: theme.radius.md,\n color: theme.colors.textPrimary,\n fontFamily: theme.fontFamily.mono,\n fontSize: theme.fontSize.md,\n margin: 0,\n maxHeight: \"200px\",\n overflow: \"auto\",\n padding: theme.spacing.lg,\n whiteSpace: \"pre-wrap\",\n wordBreak: \"break-all\",\n} as const;\n\nconst DetailRow = ({ label, children }: { label: string; children: React.ReactNode }) => (\n <div style={detailRowStyle}>\n <span style={detailLabelStyle}>{label}</span>\n <span style={detailValueStyle}>{children}</span>\n </div>\n);\n\nexport const LogDetail = ({ record }: { record: DevtoolsLogRecord }) => {\n const levelColors = theme.colors.levels[record.level];\n const hasProperties = Object.keys(record.properties).length > 0;\n\n return (\n <div data-testid=\"log-detail\" style={{ ...containerStyle, background: levelColors.bg }}>\n <DetailRow label=\"Time\">{formatTime(record.timestamp)}</DetailRow>\n <DetailRow label=\"Level\">\n <span style={{ color: levelColors.color, fontWeight: 600 }}>{record.level}</span>\n </DetailRow>\n <DetailRow label=\"Category\">\n <span style={categoryStyle}>{record.category.join(\".\")}</span>\n </DetailRow>\n {record.caller && (\n <DetailRow label=\"Caller\">\n <span style={callerStyle}>{record.caller}</span>\n </DetailRow>\n )}\n <DetailRow label=\"Message\">\n <span style={messageStyle}>{record.messageText}</span>\n </DetailRow>\n\n {hasProperties && (\n <DetailRow label=\"Data\">\n <pre style={propertiesStyle}>{safeStringify(record.properties, 2)}</pre>\n </DetailRow>\n )}\n </div>\n );\n};\n","import { Combobox } from \"@base-ui-components/react/combobox\";\nimport { Popover } from \"@base-ui-components/react/popover\";\nimport { Debouncer } from \"@tanstack/pacer\";\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { LOG_LEVELS, type LogLevel } from \"../../types\";\nimport { CheckIcon, PauseIcon, PlayIcon, Trash2Icon, XIcon } from \"../icons\";\nimport { theme } from \"../theme\";\n\ninterface ToolbarProps {\n categories: string[];\n categoryFilter: string[];\n filteredCount: number;\n levelFilter: Set<LogLevel>;\n onCategoryFilterChange: (value: string[]) => void;\n onClear: () => void;\n onLevelFilterChange: (levels: Set<LogLevel>) => void;\n onPause: () => void;\n onResume: () => void;\n /** Called with the debounced search term. The toolbar owns the input value. */\n onSearchTextChange: (value: string) => void;\n paused: boolean;\n totalCount: number;\n}\n\n// Inject hover styles once (scoped via data attribute to avoid leaking)\nconst HOVER_STYLE_ID = \"logtape-devtools-hover\";\nfunction useHoverStyles() {\n useEffect(() => {\n if (document.getElementById(HOVER_STYLE_ID)) {\n return;\n }\n const style = document.createElement(\"style\");\n style.id = HOVER_STYLE_ID;\n style.textContent = `\n [data-lt-interactive]:hover {\n filter: brightness(1.25);\n }\n [data-lt-interactive]:active {\n filter: brightness(0.9);\n }\n [data-lt-clear-btn]:hover {\n color: ${theme.colors.textPrimary} !important;\n }\n [data-lt-chip-remove]:hover {\n opacity: 1 !important;\n color: ${theme.colors.white} !important;\n }\n `;\n document.head.appendChild(style);\n }, []);\n}\n\nconst buttonStyle = {\n background: theme.colors.surfaceHover,\n border: `1px solid ${theme.colors.border}`,\n borderRadius: theme.radius.md,\n color: theme.colors.textPrimary,\n cursor: \"pointer\",\n fontFamily: theme.fontFamily.sans,\n fontSize: theme.fontSize.md,\n padding: `${theme.spacing.sm} ${theme.spacing.lg}`,\n transition: \"filter 0.1s, background 0.1s, border-color 0.1s\",\n width: \"100%\",\n} as const;\n\nconst inputStyle = {\n background: theme.colors.surface,\n border: `1px solid ${theme.colors.borderInput}`,\n borderRadius: theme.radius.md,\n color: theme.colors.textPrimary,\n fontFamily: theme.fontFamily.sans,\n fontSize: theme.fontSize.md,\n outline: \"none\",\n padding: `${theme.spacing.sm} ${theme.spacing.lg}`,\n transition: \"border-color 0.15s\",\n width: \"100%\",\n} as const;\n\nconst sectionLabelStyle = {\n color: theme.colors.textMuted,\n fontSize: \"9px\",\n fontWeight: 600,\n letterSpacing: \"0.05em\",\n textTransform: \"uppercase\",\n} as const;\n\nconst LevelToggle = ({\n level,\n active,\n onToggle,\n}: {\n level: LogLevel;\n active: boolean;\n onToggle: (level: LogLevel) => void;\n}) => {\n const colors = theme.colors.levels[level];\n const handleClick = useCallback(() => onToggle(level), [level, onToggle]);\n\n return (\n <button\n aria-pressed={active}\n data-lt-interactive=\"\"\n data-testid={`level-toggle-${level}`}\n onClick={handleClick}\n style={{\n background: active ? colors.badge : \"transparent\",\n border: `1px solid ${active ? colors.badge : theme.colors.border}`,\n borderRadius: theme.radius.sm,\n color: active ? theme.colors.white : colors.color,\n cursor: \"pointer\",\n fontFamily: theme.fontFamily.mono,\n fontSize: theme.fontSize.sm,\n fontWeight: 600,\n lineHeight: 1,\n minWidth: \"30px\",\n opacity: active ? 1 : 0.5,\n padding: \"3px 0\",\n textAlign: \"center\" as const,\n transition: \"all 0.15s\",\n }}\n title={`Filter ${level} logs`}\n type=\"button\"\n >\n {level.slice(0, 3).toUpperCase()}\n </button>\n );\n};\n\nexport const Toolbar = ({\n paused,\n onPause,\n onResume,\n onClear,\n levelFilter,\n onLevelFilterChange,\n categories,\n categoryFilter,\n onCategoryFilterChange,\n onSearchTextChange,\n totalCount,\n filteredCount,\n}: ToolbarProps) => {\n useHoverStyles();\n\n // The toolbar is the single source of truth for the search input; the parent\n // only ever receives the debounced value.\n const [search, setSearch] = useState(\"\");\n const debouncedSearch = useMemo(\n () => new Debouncer(onSearchTextChange, { wait: 200 }),\n [onSearchTextChange]\n );\n\n useEffect(() => () => debouncedSearch.cancel(), [debouncedSearch]);\n\n const handleSearchChange = useCallback(\n (e: React.ChangeEvent<HTMLInputElement>) => {\n const value = e.target.value;\n setSearch(value);\n debouncedSearch.maybeExecute(value);\n },\n [debouncedSearch]\n );\n\n const handleLevelToggle = useCallback(\n (level: LogLevel) => {\n const next = new Set(levelFilter);\n if (next.has(level)) {\n next.delete(level);\n } else {\n next.add(level);\n }\n onLevelFilterChange(next);\n },\n [levelFilter, onLevelFilterChange]\n );\n\n return (\n <div\n data-testid=\"toolbar\"\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n flexShrink: 0,\n gap: theme.spacing.xl,\n height: \"100%\",\n minWidth: \"200px\",\n overflow: \"auto\",\n padding: `${theme.spacing.lg} ${theme.spacing.xl}`,\n }}\n >\n {/* Log count */}\n <div style={{ textAlign: \"center\" }}>\n <span\n style={{\n color: theme.colors.textPrimary,\n fontFamily: theme.fontFamily.mono,\n fontSize: theme.fontSize.lg,\n fontWeight: 600,\n }}\n >\n {filteredCount === totalCount ? `${totalCount}` : `${filteredCount} / ${totalCount}`}\n </span>\n <div style={{ color: theme.colors.textMuted, fontSize: theme.fontSize.sm }}>logs</div>\n </div>\n\n {/* Actions */}\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: theme.spacing.sm }}>\n <div style={sectionLabelStyle}>Actions</div>\n <button\n data-lt-interactive=\"\"\n onClick={paused ? onResume : onPause}\n style={{\n ...buttonStyle,\n background: paused ? theme.colors.levels.warning.badge : buttonStyle.background,\n color: paused ? theme.colors.white : buttonStyle.color,\n }}\n title={paused ? \"Resume live updates\" : \"Pause live updates\"}\n type=\"button\"\n >\n <span style={{ alignItems: \"center\", display: \"inline-flex\", gap: \"6px\" }}>\n {paused ? <PlayIcon size={12} /> : <PauseIcon size={12} />}\n {paused ? \"Resume\" : \"Pause\"}\n </span>\n </button>\n\n <button\n data-lt-interactive=\"\"\n onClick={onClear}\n style={buttonStyle}\n title=\"Clear all logs\"\n type=\"button\"\n >\n <span style={{ alignItems: \"center\", display: \"inline-flex\", gap: \"6px\" }}>\n <Trash2Icon size={12} />\n Clear\n </span>\n </button>\n </div>\n\n {/* Level filters */}\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: theme.spacing.sm }}>\n <div style={{ alignItems: \"center\", display: \"flex\", justifyContent: \"space-between\" }}>\n <div style={sectionLabelStyle}>Levels</div>\n {levelFilter.size > 0 && (\n <button\n data-lt-clear-btn=\"\"\n onClick={() => onLevelFilterChange(new Set())}\n style={{\n background: \"none\",\n border: \"none\",\n color: theme.colors.textMuted,\n cursor: \"pointer\",\n fontSize: \"9px\",\n padding: 0,\n transition: \"color 0.1s\",\n }}\n title=\"Show all levels\"\n type=\"button\"\n >\n clear\n </button>\n )}\n </div>\n <div\n style={{\n display: \"grid\",\n gap: theme.spacing.xs,\n gridTemplateColumns: \"repeat(3, 1fr)\",\n }}\n >\n {LOG_LEVELS.map((level) => (\n <LevelToggle\n active={levelFilter.size === 0 || levelFilter.has(level)}\n key={level}\n level={level}\n onToggle={handleLevelToggle}\n />\n ))}\n </div>\n </div>\n\n {/* Category filter (multi-select combobox) */}\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: theme.spacing.sm }}>\n <div style={{ alignItems: \"center\", display: \"flex\", justifyContent: \"space-between\" }}>\n <div style={sectionLabelStyle}>Category</div>\n {categoryFilter.length > 0 && (\n <button\n data-lt-clear-btn=\"\"\n onClick={() => onCategoryFilterChange([])}\n style={{\n background: \"none\",\n border: \"none\",\n color: theme.colors.textMuted,\n cursor: \"pointer\",\n fontSize: \"9px\",\n padding: 0,\n transition: \"color 0.1s\",\n }}\n title=\"Clear all categories\"\n type=\"button\"\n >\n clear\n </button>\n )}\n </div>\n {categories.length === 0 ? (\n <Popover.Root>\n <Popover.Trigger\n delay={300}\n nativeButton={false}\n openOnHover\n render={\n <div\n data-testid=\"category-input\"\n style={{\n ...inputStyle,\n color: theme.colors.textMuted,\n cursor: \"not-allowed\",\n opacity: 0.5,\n }}\n >\n Category…\n </div>\n }\n />\n <Popover.Portal>\n <Popover.Positioner sideOffset={6} style={{ zIndex: 999_999 }}>\n <Popover.Popup\n style={{\n background: theme.colors.surface,\n border: `1px solid ${theme.colors.border}`,\n borderRadius: theme.radius.md,\n boxShadow: \"0 8px 24px rgba(0,0,0,0.5)\",\n fontSize: theme.fontSize.sm,\n maxWidth: \"200px\",\n padding: `${theme.spacing.sm} ${theme.spacing.lg}`,\n }}\n >\n <p style={{ color: theme.colors.textMuted, lineHeight: 1.4, margin: 0 }}>\n Waiting for logs to populate available categories.\n </p>\n </Popover.Popup>\n </Popover.Positioner>\n </Popover.Portal>\n </Popover.Root>\n ) : (\n <Combobox.Root\n items={categories}\n multiple\n onValueChange={onCategoryFilterChange}\n value={categoryFilter}\n >\n <div\n style={{\n background: theme.colors.surface,\n border: `1px solid ${theme.colors.borderInput}`,\n borderRadius: theme.radius.md,\n display: \"flex\",\n flexWrap: \"wrap\",\n gap: \"3px\",\n minHeight: \"28px\",\n padding: \"3px\",\n transition: \"border-color 0.15s\",\n }}\n >\n {categoryFilter.map((cat) => (\n <span\n key={cat}\n style={{\n alignItems: \"center\",\n background: \"rgba(99, 102, 241, 0.15)\",\n border: \"1px solid rgba(99, 102, 241, 0.3)\",\n borderRadius: theme.radius.sm,\n color: theme.colors.accentHover,\n display: \"inline-flex\",\n fontFamily: theme.fontFamily.mono,\n fontSize: \"9px\",\n gap: \"3px\",\n lineHeight: 1,\n padding: \"1px 4px\",\n }}\n >\n {cat}\n <button\n data-lt-chip-remove=\"\"\n onClick={() => onCategoryFilterChange(categoryFilter.filter((c) => c !== cat))}\n style={{\n background: \"none\",\n border: \"none\",\n color: theme.colors.textMuted,\n cursor: \"pointer\",\n fontSize: \"7px\",\n lineHeight: 1,\n opacity: 0.7,\n padding: 0,\n transition: \"color 0.1s, opacity 0.1s\",\n }}\n title={`Remove ${cat}`}\n type=\"button\"\n >\n <XIcon size={7} />\n </button>\n </span>\n ))}\n <Combobox.Input\n data-testid=\"category-input\"\n placeholder={categoryFilter.length === 0 ? \"Category…\" : \"\"}\n style={{\n background: \"transparent\",\n border: \"none\",\n color: theme.colors.textPrimary,\n flex: 1,\n fontFamily: theme.fontFamily.sans,\n fontSize: theme.fontSize.md,\n minWidth: \"40px\",\n outline: \"none\",\n padding: `${theme.spacing.xs} ${theme.spacing.sm}`,\n }}\n />\n </div>\n <Combobox.Portal>\n <Combobox.Positioner style={{ zIndex: 999_999 }}>\n <Combobox.Popup\n style={{\n background: theme.colors.surface,\n border: `1px solid ${theme.colors.border}`,\n borderRadius: theme.radius.md,\n boxShadow: \"0 8px 24px rgba(0,0,0,0.5)\",\n maxHeight: \"200px\",\n overflow: \"auto\",\n padding: theme.spacing.xs,\n }}\n >\n <Combobox.List>\n {(item, index) => (\n <Combobox.Item\n index={index}\n key={String(item)}\n style={{\n alignItems: \"center\",\n borderRadius: theme.radius.sm,\n color: theme.colors.textPrimary,\n cursor: \"pointer\",\n display: \"flex\",\n fontFamily: theme.fontFamily.mono,\n fontSize: theme.fontSize.md,\n gap: theme.spacing.sm,\n justifyContent: \"space-between\",\n padding: `${theme.spacing.sm} ${theme.spacing.lg}`,\n transition: \"background 0.1s\",\n }}\n value={item}\n >\n <span style={{ flex: 1, overflow: \"hidden\", textOverflow: \"ellipsis\" }}>\n {String(item)}\n </span>\n <Combobox.ItemIndicator>\n <CheckIcon color={theme.colors.accent} size={14} />\n </Combobox.ItemIndicator>\n </Combobox.Item>\n )}\n </Combobox.List>\n </Combobox.Popup>\n </Combobox.Positioner>\n </Combobox.Portal>\n </Combobox.Root>\n )}\n </div>\n\n {/* Text search */}\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: theme.spacing.sm }}>\n <div style={sectionLabelStyle}>Search</div>\n <input\n data-testid=\"search-input\"\n onChange={handleSearchChange}\n placeholder=\"Search…\"\n style={inputStyle}\n type=\"text\"\n value={search}\n />\n </div>\n </div>\n );\n};\n","import { defaultLogStore, type LogStore } from \"../store\";\nimport { LogTapeDevtoolsPlugin } from \"./logtape-devtools-plugin\";\n\nexport interface LogTapeDevtoolsPluginOptions {\n /** Whether to open the devtools panel by default. Default: true */\n defaultOpen?: boolean;\n /** Plugin display name. Default: \"LogTape\" */\n name?: string;\n /** Custom log store instance. Must match the store passed to createDevtoolsSink. */\n store?: LogStore;\n}\n\n/**\n * Creates a TanStack DevTools plugin config object for LogTape.\n *\n * Usage:\n * ```tsx\n * import { TanStackDevtools } from \"@tanstack/react-devtools\";\n * import { createLogTapeDevtoolsPlugin } from \"@mugenlabs/logtape-devtools\";\n *\n * <TanStackDevtools plugins={[createLogTapeDevtoolsPlugin()]} />\n * ```\n */\nexport const createLogTapeDevtoolsPlugin = (options?: LogTapeDevtoolsPluginOptions) => ({\n defaultOpen: options?.defaultOpen ?? true,\n id: \"logtape-devtools-plugin\",\n name: options?.name ?? \"LogTape\",\n render: <LogTapeDevtoolsPlugin store={options?.store ?? defaultLogStore} />,\n});\n","import {\n createLogTapeDevtoolsPlugin,\n type LogTapeDevtoolsPluginOptions,\n} from \"./plugin/create-logtape-devtools-plugin\";\nimport { createDevtoolsSink, type DevtoolsSinkOptions } from \"./sink\";\nimport { defaultLogStore, type LogStore } from \"./store\";\n\n/** Options for {@link createLogTapeDevtools}. */\nexport interface CreateLogTapeDevtoolsOptions {\n /** Plugin options, minus `store` — the shared store is wired automatically. */\n plugin?: Omit<LogTapeDevtoolsPluginOptions, \"store\">;\n /** Sink options, minus `store` — the shared store is wired automatically. */\n sink?: Omit<DevtoolsSinkOptions, \"store\">;\n /** Store shared by the sink and the plugin. Defaults to the shared store. */\n store?: LogStore;\n}\n\n/**\n * Creates a LogTape sink and its matching TanStack DevTools plugin, both wired\n * to the same store.\n *\n * Use this instead of calling `createDevtoolsSink` and\n * `createLogTapeDevtoolsPlugin` separately when you do not need to hold on to\n * the store yourself.\n *\n * ```tsx\n * import { configure, getLogger } from \"@logtape/logtape\";\n * import { TanStackDevtools } from \"@tanstack/react-devtools\";\n * import { createLogTapeDevtools } from \"@mugenlabs/logtape-devtools\";\n *\n * const { sink, plugin } = createLogTapeDevtools();\n *\n * await configure({\n * sinks: { devtools: sink },\n * loggers: [{ category: [], lowestLevel: \"trace\", sinks: [\"devtools\"] }],\n * });\n *\n * function App() {\n * return <TanStackDevtools plugins={[plugin]} />;\n * }\n * ```\n */\nexport function createLogTapeDevtools(options?: CreateLogTapeDevtoolsOptions) {\n const store = options?.store ?? defaultLogStore;\n\n return {\n plugin: createLogTapeDevtoolsPlugin({ ...options?.plugin, store }),\n sink: createDevtoolsSink({ ...options?.sink, store }),\n };\n}\n"],"mappings":"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","names":["useCallback","useMemo","useState","useCallback","jsx","jsx","jsxs","jsx","jsxs","categoryStyle","messageStyle","callerStyle","jsx","containerStyle","useCallback","useCallback","useEffect","jsx","jsxs","useEffect","useCallback","jsx","jsxs","useState","useCallback","useMemo","jsx"]}
package/dist/sink.d.ts ADDED
@@ -0,0 +1,130 @@
1
+ import { Sink } from '@logtape/logtape';
2
+
3
+ /** Severity levels supported by LogTape, ordered from least to most severe. */
4
+ type LogLevel = "trace" | "debug" | "info" | "warning" | "error" | "fatal";
5
+ /** Every {@link LogLevel}, ordered from least to most severe. */
6
+ declare const LOG_LEVELS: LogLevel[];
7
+ /** A LogTape record normalized for display in the devtools panel. */
8
+ interface DevtoolsLogRecord {
9
+ /** Source location of the log call (only present when `captureStackTrace` is enabled). */
10
+ caller?: string;
11
+ /** Logger category path, e.g. `["app", "auth"]`. */
12
+ category: string[];
13
+ /** Unique identifier, stable for the lifetime of the record. */
14
+ id: string;
15
+ /** Severity of the record. */
16
+ level: LogLevel;
17
+ /** Raw message parts, alternating literals and interpolated values. */
18
+ message: unknown[];
19
+ /** Message parts rendered into a single searchable string. */
20
+ messageText: string;
21
+ /** Structured properties attached to the log call, deep-cloned for safety. */
22
+ properties: Record<string, unknown>;
23
+ /** Creation time in milliseconds since the Unix epoch. */
24
+ timestamp: number;
25
+ }
26
+
27
+ type Listener = () => void;
28
+ /**
29
+ * Reactive log record container backing the devtools panel.
30
+ *
31
+ * Records are kept in a fixed-capacity ring buffer so appending is O(1); the
32
+ * array returned by {@link LogStore.getSnapshot} is rebuilt lazily at most once
33
+ * per mutation batch. Listener notifications are coalesced into a microtask, so
34
+ * a synchronous burst of {@link LogStore.addRecord} calls results in a single
35
+ * notification.
36
+ */
37
+ interface LogStore {
38
+ /** Appends a record, evicting the oldest one when the max size is reached. */
39
+ addRecord(record: DevtoolsLogRecord): void;
40
+ /** Removes every record and notifies subscribers. */
41
+ clear(): void;
42
+ /**
43
+ * Returns the current records, oldest first.
44
+ *
45
+ * The reference is stable until the store changes, which makes it safe to use
46
+ * with `useSyncExternalStore`.
47
+ */
48
+ getSnapshot(): DevtoolsLogRecord[];
49
+ /**
50
+ * Whether anything is currently subscribed to the store.
51
+ *
52
+ * Used by the sink to skip expensive work (such as stack trace capture) while
53
+ * no devtools panel is mounted.
54
+ */
55
+ hasListeners(): boolean;
56
+ /** Updates the maximum number of retained records, trimming if needed. */
57
+ setMaxSize(size: number): void;
58
+ /** Registers a change listener. Returns an unsubscribe function. */
59
+ subscribe(listener: Listener): () => void;
60
+ }
61
+ /** Options for {@link createLogStore}. */
62
+ interface LogStoreOptions {
63
+ /**
64
+ * Maximum number of log records to retain. Older records are evicted first.
65
+ *
66
+ * @default 1000
67
+ */
68
+ maxRecords?: number;
69
+ }
70
+ /**
71
+ * Creates an isolated log store.
72
+ *
73
+ * Pass the same instance to `createDevtoolsSink` and
74
+ * `createLogTapeDevtoolsPlugin` to keep the sink and the panel in sync.
75
+ *
76
+ * ```ts
77
+ * const store = createLogStore({ maxRecords: 5000 });
78
+ * ```
79
+ */
80
+ declare function createLogStore(options?: LogStoreOptions): LogStore;
81
+ /** Default shared store instance used when no custom store is provided */
82
+ declare const defaultLogStore: LogStore;
83
+
84
+ /** Options for {@link createDevtoolsSink}. */
85
+ interface DevtoolsSinkOptions {
86
+ /**
87
+ * Capture the source location of each log call via stack trace parsing.
88
+ *
89
+ * Relies on `new Error().stack`, which is engine-dependent. Automatically
90
+ * disabled in production builds (when `process.env.NODE_ENV === "production"`)
91
+ * because minified bundles produce meaningless file/line references. Note that
92
+ * source maps do not help here — browsers do not apply source maps to
93
+ * `Error.stack`.
94
+ *
95
+ * Also skipped while no devtools panel is mounted (the store has no
96
+ * subscribers), unless `forceStackTrace` is `true`.
97
+ *
98
+ * @experimental
99
+ * @default true
100
+ */
101
+ captureStackTrace?: boolean;
102
+ /**
103
+ * Force stack trace capture even in production builds and while the panel is
104
+ * closed. Only has an effect when `captureStackTrace` is `true`.
105
+ *
106
+ * @default false
107
+ */
108
+ forceStackTrace?: boolean;
109
+ /** Custom log store instance. Defaults to the shared store. */
110
+ store?: LogStore;
111
+ }
112
+ /**
113
+ * Creates a LogTape sink that forwards log records to the devtools panel.
114
+ *
115
+ * Usage:
116
+ * ```ts
117
+ * import { configure } from "@logtape/logtape";
118
+ * import { createDevtoolsSink } from "@mugenlabs/logtape-devtools";
119
+ *
120
+ * await configure({
121
+ * sinks: { devtools: createDevtoolsSink() },
122
+ * loggers: [
123
+ * { category: ["app"], lowestLevel: "debug", sinks: ["devtools"] },
124
+ * ],
125
+ * });
126
+ * ```
127
+ */
128
+ declare function createDevtoolsSink(options?: DevtoolsSinkOptions): Sink;
129
+
130
+ export { type DevtoolsLogRecord, type DevtoolsSinkOptions, LOG_LEVELS, type LogLevel, type LogStore, type LogStoreOptions, createDevtoolsSink, createLogStore, defaultLogStore };
package/dist/sink.mjs ADDED
@@ -0,0 +1,13 @@
1
+ import {
2
+ LOG_LEVELS,
3
+ createDevtoolsSink,
4
+ createLogStore,
5
+ defaultLogStore
6
+ } from "./chunk-CYXOBB6A.mjs";
7
+ export {
8
+ LOG_LEVELS,
9
+ createDevtoolsSink,
10
+ createLogStore,
11
+ defaultLogStore
12
+ };
13
+ //# sourceMappingURL=sink.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
package/package.json CHANGED
@@ -1,16 +1,20 @@
1
1
  {
2
2
  "name": "@mugenlabs/logtape-devtools",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "A TanStack DevTools plugin for inspecting LogTape logs in the browser",
5
5
  "keywords": [
6
6
  "logtape",
7
7
  "devtools",
8
8
  "logging",
9
+ "logger",
10
+ "observability",
11
+ "structured-logging",
9
12
  "tanstack",
13
+ "tanstack-devtools",
10
14
  "react",
11
15
  "debugging"
12
16
  ],
13
- "homepage": "https://github.com/mugenlabs-dev/logtape-devtools",
17
+ "homepage": "https://logtape-devtools.mugenlabs.dev",
14
18
  "bugs": {
15
19
  "url": "https://github.com/mugenlabs-dev/logtape-devtools/issues"
16
20
  },
@@ -22,7 +26,8 @@
22
26
  "directory": "packages/core"
23
27
  },
24
28
  "files": [
25
- "dist"
29
+ "dist",
30
+ "assets"
26
31
  ],
27
32
  "type": "module",
28
33
  "sideEffects": false,
@@ -32,7 +37,12 @@
32
37
  ".": {
33
38
  "types": "./dist/index.d.ts",
34
39
  "import": "./dist/index.mjs"
35
- }
40
+ },
41
+ "./sink": {
42
+ "types": "./dist/sink.d.ts",
43
+ "import": "./dist/sink.mjs"
44
+ },
45
+ "./package.json": "./package.json"
36
46
  },
37
47
  "publishConfig": {
38
48
  "access": "public",
@@ -41,6 +51,7 @@
41
51
  "devDependencies": {
42
52
  "@logtape/logtape": "^2.0.4",
43
53
  "@storybook/react": "^10.2.19",
54
+ "@tanstack/react-devtools": "^0.9.6",
44
55
  "@storybook/react-vite": "^10.2.19",
45
56
  "react": "^19.0.0",
46
57
  "react-dom": "^19.0.0",
@@ -48,15 +59,22 @@
48
59
  },
49
60
  "peerDependencies": {
50
61
  "@logtape/logtape": ">=2.0.0",
62
+ "@tanstack/react-devtools": ">=0.9.0",
51
63
  "react": "^18.0.0 || ^19.0.0",
52
64
  "react-dom": "^18.0.0 || ^19.0.0"
53
65
  },
66
+ "peerDependenciesMeta": {
67
+ "@tanstack/react-devtools": {
68
+ "optional": true
69
+ }
70
+ },
54
71
  "engines": {
55
72
  "node": ">=18.0.0"
56
73
  },
57
74
  "dependencies": {
58
75
  "@base-ui-components/react": "^1.0.0-rc.0",
59
- "@tanstack/pacer": "^0.19.0"
76
+ "@tanstack/pacer": "^0.19.0",
77
+ "@tanstack/react-virtual": "^3.14.8"
60
78
  },
61
79
  "scripts": {
62
80
  "build": "tsup",