@zendir/ui 0.7.0 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"HexViewer.js","names":[],"sources":["../../../../src/react/core/widgets/HexViewer.tsx"],"sourcesContent":["/**\r\n * @zendir/ui - HexViewer Component\r\n *\r\n * Displays raw binary data in a hex viewer format for telemetry packet analysis.\r\n * Shows offset, hex bytes, and ASCII representation side by side.\r\n *\r\n * Features:\r\n * - Hex + ASCII view with configurable bytes per row (8, 16, 32)\r\n * - Byte highlighting with custom colors (for field boundaries, errors, etc.)\r\n * - Click-to-select bytes and ranges\r\n * - Search by hex pattern or ASCII string\r\n * - Offset display in hex or decimal\r\n * - Live data streaming support (auto-scroll)\r\n * - Copy selection as hex, decimal, or ASCII\r\n * - Byte grouping (1, 2, 4, 8)\r\n * - Endianness toggle for multi-byte interpretation\r\n * - Status bar showing cursor position, selection info, data interpretation\r\n *\r\n * Astro UX Compliance:\r\n * - Dark theme with monospace font\r\n * - Status colors for highlighting\r\n * - Accessible keyboard navigation\r\n *\r\n * @example\r\n * ```tsx\r\n * <HexViewer\r\n * data={new Uint8Array([0x48, 0x65, 0x6C, 0x6C, 0x6F])}\r\n * bytesPerRow={16}\r\n * highlights={[{ start: 0, end: 4, color: '#4CAF50', label: 'Header' }]}\r\n * />\r\n * ```\r\n */\r\n\r\nimport React, {\r\n useState,\r\n useRef,\r\n useCallback,\r\n useMemo,\r\n useEffect,\r\n memo,\r\n} from \"react\";\r\nimport { useTheme } from \"../../theme\";\r\n\r\n// =============================================================================\r\n// Types\r\n// =============================================================================\r\n\r\nexport interface HexHighlight {\r\n /** Start byte offset (inclusive) */\r\n start: number;\r\n /** End byte offset (inclusive) */\r\n end: number;\r\n /** Highlight color (CSS color) */\r\n color: string;\r\n /** Optional label for the highlight region */\r\n label?: string;\r\n}\r\n\r\n/**\r\n * Named region for structural packet analysis (e.g., CCSDS Primary Header,\r\n * Secondary Header, User Data). Regions provide persistent background color\r\n * and a legend entry, unlike transient highlights.\r\n */\r\nexport interface HexRegion {\r\n /** Start byte offset (inclusive) */\r\n start: number;\r\n /** End byte offset (exclusive) */\r\n end: number;\r\n /** Region display name (e.g., \"Primary Header\") */\r\n label: string;\r\n /** Background fill color (CSS rgba recommended) */\r\n color: string;\r\n /** Border/accent color for the region */\r\n borderColor?: string;\r\n}\r\n\r\n/**\r\n * A decoded field within the packet payload for the fields table.\r\n * Enables cross-highlighting: hover a field row → highlight its bytes,\r\n * hover hex bytes → highlight the corresponding field row.\r\n */\r\nexport interface DecodedField {\r\n /** Field name */\r\n name: string;\r\n /** Decoded value (displayed via toString) */\r\n value: string | number | boolean | null;\r\n /** Engineering units (e.g., \"°C\", \"V\", \"rpm\") */\r\n unit?: string;\r\n /** Byte offset within the packet where this field starts */\r\n byteOffset?: number;\r\n /** Size in bits */\r\n sizeBits?: number;\r\n /** Optional description / tooltip */\r\n description?: string;\r\n}\r\n\r\n/**\r\n * Packet header key-value pairs shown in a collapsible summary panel.\r\n * Supports CCSDS-style primary + secondary header display.\r\n */\r\nexport interface PacketHeaderEntry {\r\n /** Label (e.g., \"APID\", \"Sequence Count\", \"Spacecraft ID\") */\r\n label: string;\r\n /** Value */\r\n value: string | number;\r\n /** Render value in monospace font */\r\n mono?: boolean;\r\n}\r\n\r\n/** Pre-defined region color palette for space packet headers */\r\nexport const REGION_COLORS = {\r\n primary: \"rgba(96, 165, 250, 0.15)\",\r\n secondary: \"rgba(168, 85, 247, 0.15)\",\r\n tertiary: \"rgba(251, 191, 36, 0.15)\",\r\n userData: \"rgba(34, 197, 94, 0.15)\",\r\n error: \"rgba(255, 56, 56, 0.15)\",\r\n} as const;\r\n\r\nexport const REGION_BORDER_COLORS = {\r\n primary: \"rgba(96, 165, 250, 0.5)\",\r\n secondary: \"rgba(168, 85, 247, 0.5)\",\r\n tertiary: \"rgba(251, 191, 36, 0.5)\",\r\n userData: \"rgba(34, 197, 94, 0.5)\",\r\n error: \"rgba(255, 56, 56, 0.5)\",\r\n} as const;\r\n\r\nexport type ByteGrouping = 1 | 2 | 4 | 8;\r\nexport type OffsetBase = \"hex\" | \"decimal\";\r\nexport type Endianness = \"big\" | \"little\";\r\n\r\nexport interface HexViewerProps {\r\n /** Binary data to display */\r\n data: Uint8Array | number[];\r\n /** Bytes per row (default: 16) */\r\n bytesPerRow?: 8 | 16 | 32;\r\n /** Byte grouping for hex display (default: 1) */\r\n byteGrouping?: ByteGrouping;\r\n /** Offset display base (default: 'hex') */\r\n offsetBase?: OffsetBase;\r\n /** Highlighted byte regions (transient, e.g., search results or field hover) */\r\n highlights?: HexHighlight[];\r\n /** Named structural regions (persistent background, e.g., Primary/Secondary Header) */\r\n regions?: HexRegion[];\r\n /** Decoded fields for the fields table (cross-highlights with hex bytes) */\r\n decodedFields?: DecodedField[];\r\n /** Packet header entries for the summary panel */\r\n packetHeaders?: PacketHeaderEntry[];\r\n /** External hover highlight range (for cross-component linking) */\r\n externalHighlight?: { start: number; end: number } | null;\r\n /** Whether to show the ASCII column (default: true) */\r\n showAscii?: boolean;\r\n /** Whether to show the offset column (default: true) */\r\n showOffset?: boolean;\r\n /** Whether to show the status/info bar (default: true) */\r\n showStatusBar?: boolean;\r\n /** Whether to show the search bar (default: true) */\r\n showSearch?: boolean;\r\n /** Whether to show the toolbar (default: true) */\r\n showToolbar?: boolean;\r\n /** Whether to show the decoded fields table (default: true if decodedFields provided) */\r\n showFieldsTable?: boolean;\r\n /** Whether to show the packet header summary (default: true if packetHeaders provided) */\r\n showHeaderSummary?: boolean;\r\n /**\r\n * Height of the viewer (default: 400).\r\n * When constrained, HexViewer enables outer scroll fallback so expanded\r\n * panels (headers/decoded fields) never trap lower sections.\r\n */\r\n height?: number | string;\r\n /** Title for the viewer */\r\n title?: string;\r\n /** Whether data is streaming (auto-scroll to bottom) */\r\n streaming?: boolean;\r\n /** Endianness for multi-byte interpretation (default: 'big') */\r\n endianness?: Endianness;\r\n /** Called when byte selection changes */\r\n onSelectionChange?: (start: number, end: number) => void;\r\n /** Called when a byte is clicked */\r\n onByteClick?: (offset: number, value: number) => void;\r\n /** Called when hovering a byte (for external cross-highlighting) */\r\n onByteHover?: (byteIndex: number) => void;\r\n /** Called when mouse leaves hex area */\r\n onByteLeave?: () => void;\r\n /** CSS class name */\r\n className?: string;\r\n /** Show outer container border (default: true). Set false when embedded inside a Container/card. */\r\n bordered?: boolean;\r\n /** Custom style overrides for the outer container */\r\n style?: React.CSSProperties;\r\n}\r\n\r\n// =============================================================================\r\n// Helpers\r\n// =============================================================================\r\n\r\nfunction toUint8Array(data: Uint8Array | number[]): Uint8Array {\r\n return data instanceof Uint8Array ? data : new Uint8Array(data);\r\n}\r\n\r\nfunction byteToHex(byte: number): string {\r\n return byte.toString(16).padStart(2, \"0\").toUpperCase();\r\n}\r\n\r\nfunction byteToAscii(byte: number): string {\r\n return byte >= 0x20 && byte <= 0x7e ? String.fromCharCode(byte) : \".\";\r\n}\r\n\r\nfunction formatOffset(\r\n offset: number,\r\n base: OffsetBase,\r\n totalBytes: number,\r\n): string {\r\n if (base === \"hex\") {\r\n const width = Math.max(\r\n 4,\r\n Math.ceil(Math.log2(Math.max(totalBytes, 1)) / 4) * 1,\r\n );\r\n return offset.toString(16).padStart(Math.max(width, 4), \"0\").toUpperCase();\r\n }\r\n const width = Math.max(4, totalBytes.toString().length);\r\n return offset.toString().padStart(width, \" \");\r\n}\r\n\r\nfunction interpretBytes(\r\n data: Uint8Array,\r\n offset: number,\r\n endianness: Endianness,\r\n): {\r\n u8: number;\r\n i8: number;\r\n u16?: number;\r\n i16?: number;\r\n u32?: number;\r\n i32?: number;\r\n f32?: number;\r\n f64?: number;\r\n} {\r\n const result: ReturnType<typeof interpretBytes> = {\r\n u8: data[offset],\r\n i8: data[offset] > 127 ? data[offset] - 256 : data[offset],\r\n };\r\n\r\n if (offset + 1 < data.length) {\r\n const view = new DataView(\r\n data.buffer,\r\n data.byteOffset + offset,\r\n Math.min(8, data.length - offset),\r\n );\r\n const be = endianness === \"big\";\r\n result.u16 = view.getUint16(0, !be);\r\n result.i16 = view.getInt16(0, !be);\r\n if (offset + 3 < data.length) {\r\n result.u32 = view.getUint32(0, !be);\r\n result.i32 = view.getInt32(0, !be);\r\n result.f32 = view.getFloat32(0, !be);\r\n }\r\n if (offset + 7 < data.length) {\r\n result.f64 = view.getFloat64(0, !be);\r\n }\r\n }\r\n return result;\r\n}\r\n\r\nconst HEX_ROW_HEIGHT = 22;\r\nconst HEX_OVERSCAN_ROWS = 16;\r\nconst MAX_RENDERED_SEARCH_HIGHLIGHTS = 400;\r\n\r\n// =============================================================================\r\n// Sub-components\r\n// =============================================================================\r\n\r\nconst HexRow = memo(function HexRow({\r\n offset,\r\n bytes,\r\n bytesPerRow,\r\n byteGrouping,\r\n offsetBase,\r\n totalBytes,\r\n showAscii,\r\n showOffset,\r\n highlights,\r\n regions,\r\n effectiveHighlight,\r\n selectedStart,\r\n selectedEnd,\r\n cursorOffset,\r\n onByteMouseDown,\r\n onByteMouseEnter,\r\n onByteClick,\r\n handleByteHoverInternal,\r\n handleByteLeaveInternal,\r\n tokens,\r\n}: {\r\n offset: number;\r\n bytes: Uint8Array;\r\n bytesPerRow: number;\r\n byteGrouping: ByteGrouping;\r\n offsetBase: OffsetBase;\r\n totalBytes: number;\r\n showAscii: boolean;\r\n showOffset: boolean;\r\n highlights: HexHighlight[];\r\n regions: HexRegion[];\r\n effectiveHighlight: { start: number; end: number } | null | undefined;\r\n selectedStart: number;\r\n selectedEnd: number;\r\n cursorOffset: number;\r\n onByteMouseDown: (idx: number) => void;\r\n onByteMouseEnter: (idx: number) => void;\r\n onByteClick: (idx: number) => void;\r\n handleByteHoverInternal: (idx: number) => void;\r\n handleByteLeaveInternal: () => void;\r\n tokens: ReturnType<typeof useTheme>[\"tokens\"];\r\n}) {\r\n const hexCells: React.ReactNode[] = [];\r\n const asciiCells: React.ReactNode[] = [];\r\n\r\n for (let i = 0; i < bytesPerRow; i++) {\r\n const byteIdx = offset + i;\r\n const isValid = i < bytes.length;\r\n const byte = isValid ? bytes[i] : 0;\r\n\r\n // Determine highlight color (priority: selection > cross-highlight > search highlight > region)\r\n let bgColor = \"transparent\";\r\n let fgColor = tokens.colors.text.primary;\r\n let borderBottom = \"2px solid transparent\";\r\n const isSelected =\r\n byteIdx >= Math.min(selectedStart, selectedEnd) &&\r\n byteIdx <= Math.max(selectedStart, selectedEnd) &&\r\n selectedStart >= 0;\r\n const isCursor = byteIdx === cursorOffset;\r\n\r\n // 1. Region background (lowest priority — always visible unless overridden)\r\n let regionColor: string | null = null;\r\n for (let r = 0; r < regions.length; r++) {\r\n const region = regions[r];\r\n if (byteIdx < region.start) break;\r\n if (byteIdx >= region.start && byteIdx < region.end) {\r\n regionColor = region.color;\r\n break;\r\n }\r\n }\r\n if (regionColor) {\r\n bgColor = regionColor;\r\n }\r\n\r\n // 2. Search highlights\r\n for (const h of highlights) {\r\n if (byteIdx >= h.start && byteIdx <= h.end) {\r\n bgColor = `${h.color}33`;\r\n fgColor = h.color;\r\n break;\r\n }\r\n }\r\n\r\n // 3. Cross-highlight from field hover or external\r\n if (\r\n effectiveHighlight &&\r\n byteIdx >= effectiveHighlight.start &&\r\n byteIdx < effectiveHighlight.end\r\n ) {\r\n bgColor = `${tokens.colors.status.caution}4D`;\r\n borderBottom = `2px solid ${tokens.colors.status.caution}`;\r\n }\r\n\r\n // 4. Selection (highest priority)\r\n if (isSelected) {\r\n bgColor = `${tokens.colors.interactive.default}4D`;\r\n fgColor = tokens.colors.interactive.default;\r\n }\r\n\r\n // Add grouping space\r\n const needsGroupSpace = i > 0 && i % byteGrouping === 0;\r\n\r\n hexCells.push(\r\n <span\r\n key={`hex-${i}`}\r\n role=\"button\"\r\n tabIndex={isValid ? 0 : -1}\r\n onMouseDown={() => isValid && onByteMouseDown(byteIdx)}\r\n onMouseEnter={() => {\r\n isValid && onByteMouseEnter(byteIdx);\r\n isValid && handleByteHoverInternal(byteIdx);\r\n }}\r\n onMouseLeave={() => isValid && handleByteLeaveInternal()}\r\n onClick={() => isValid && onByteClick(byteIdx)}\r\n onKeyDown={(e) => {\r\n if (isValid && (e.key === \"Enter\" || e.key === \" \")) {\r\n e.preventDefault();\r\n onByteClick(byteIdx);\r\n }\r\n }}\r\n style={{\r\n padding: \"0 2px\",\r\n marginLeft: needsGroupSpace ? 6 : 0,\r\n background: bgColor,\r\n color: isValid ? fgColor : `${tokens.colors.text.muted}26`,\r\n cursor: isValid ? \"pointer\" : \"default\",\r\n borderBottom: isCursor\r\n ? `2px solid ${tokens.colors.status.normal}`\r\n : borderBottom,\r\n borderRadius: tokens.borderRadius.sm,\r\n userSelect: \"none\",\r\n transition: \"background 0.1s ease\",\r\n // The two-space filler in a partial final row must keep its full\r\n // two-character width — collapsed whitespace shrinks the pad cells\r\n // and shifts the ASCII column out of alignment on the last line.\r\n whiteSpace: \"pre\",\r\n }}\r\n >\r\n {isValid ? byteToHex(byte) : \" \"}\r\n </span>,\r\n );\r\n\r\n if (showAscii) {\r\n asciiCells.push(\r\n <span\r\n key={`ascii-${i}`}\r\n role=\"button\"\r\n tabIndex={isValid ? 0 : -1}\r\n onMouseDown={() => isValid && onByteMouseDown(byteIdx)}\r\n onMouseEnter={() => {\r\n isValid && onByteMouseEnter(byteIdx);\r\n isValid && handleByteHoverInternal(byteIdx);\r\n }}\r\n onMouseLeave={() => isValid && handleByteLeaveInternal()}\r\n onClick={() => isValid && onByteClick(byteIdx)}\r\n onKeyDown={(e) => {\r\n if (isValid && (e.key === \"Enter\" || e.key === \" \")) {\r\n e.preventDefault();\r\n onByteClick(byteIdx);\r\n }\r\n }}\r\n style={{\r\n background: bgColor,\r\n color: isValid\r\n ? byte >= 0x20 && byte <= 0x7e\r\n ? fgColor\r\n : `${tokens.colors.text.muted}33`\r\n : \"transparent\",\r\n cursor: isValid ? \"pointer\" : \"default\",\r\n borderBottom: isCursor\r\n ? `2px solid ${tokens.colors.status.normal}`\r\n : borderBottom,\r\n borderRadius: tokens.borderRadius.sm,\r\n userSelect: \"none\",\r\n width: 8,\r\n textAlign: \"center\" as const,\r\n }}\r\n >\r\n {isValid ? byteToAscii(byte) : \" \"}\r\n </span>,\r\n );\r\n }\r\n }\r\n\r\n return (\r\n <div\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n height: HEX_ROW_HEIGHT,\r\n lineHeight: `${HEX_ROW_HEIGHT}px`,\r\n }}\r\n >\r\n {showOffset && (\r\n <span\r\n style={{\r\n color: tokens.colors.text.muted,\r\n marginRight: 12,\r\n minWidth: 60,\r\n textAlign: \"right\",\r\n }}\r\n >\r\n {formatOffset(offset, offsetBase, totalBytes)}\r\n </span>\r\n )}\r\n <span\r\n style={{\r\n display: \"flex\",\r\n gap: 1,\r\n marginRight: showAscii ? 16 : 0,\r\n letterSpacing: \"0.5px\",\r\n }}\r\n >\r\n {hexCells}\r\n </span>\r\n {showAscii && (\r\n <>\r\n <span\r\n style={{ color: `${tokens.colors.border.muted}`, marginRight: 8 }}\r\n >\r\n │\r\n </span>\r\n <span style={{ display: \"flex\", letterSpacing: \"1px\" }}>\r\n {asciiCells}\r\n </span>\r\n </>\r\n )}\r\n </div>\r\n );\r\n});\r\n\r\n// =============================================================================\r\n// Main Component\r\n// =============================================================================\r\n\r\nexport function HexViewer({\r\n data: rawData,\r\n bytesPerRow = 16,\r\n byteGrouping = 1,\r\n offsetBase = \"hex\",\r\n highlights = [],\r\n regions = [],\r\n decodedFields,\r\n packetHeaders,\r\n externalHighlight,\r\n showAscii = true,\r\n showOffset = true,\r\n showStatusBar = true,\r\n showSearch = true,\r\n showToolbar = true,\r\n showFieldsTable,\r\n showHeaderSummary,\r\n height = 400,\r\n title,\r\n streaming = false,\r\n endianness = \"big\",\r\n onSelectionChange,\r\n onByteClick,\r\n onByteHover,\r\n onByteLeave,\r\n className = \"\",\r\n bordered = true,\r\n style: styleProp,\r\n}: HexViewerProps): React.ReactElement {\r\n const { tokens } = useTheme();\r\n const data = useMemo(() => toUint8Array(rawData), [rawData]);\r\n const [hoveredFieldIdx, setHoveredFieldIdx] = useState<number | null>(null);\r\n const [fieldHighlight, setFieldHighlight] = useState<{\r\n start: number;\r\n end: number;\r\n } | null>(null);\r\n const [showHeaders, setShowHeaders] = useState(true);\r\n const [showFields, setShowFields] = useState(true);\r\n\r\n const sortedRegions = useMemo(\r\n () => [...regions].sort((a, b) => a.start - b.start),\r\n [regions],\r\n );\r\n\r\n // Build field byte ranges for cross-highlighting\r\n const fieldByteRanges = useMemo(() => {\r\n if (!decodedFields) return [];\r\n return decodedFields.map((f) => ({\r\n start: f.byteOffset ?? 0,\r\n end: (f.byteOffset ?? 0) + Math.ceil((f.sizeBits ?? 0) / 8),\r\n name: f.name,\r\n }));\r\n }, [decodedFields]);\r\n\r\n // Cross-highlight: field hover → byte highlight\r\n const handleFieldHover = useCallback(\r\n (fieldIdx: number) => {\r\n setHoveredFieldIdx(fieldIdx);\r\n const range = fieldByteRanges[fieldIdx];\r\n if (range && range.end > range.start) setFieldHighlight(range);\r\n },\r\n [fieldByteRanges],\r\n );\r\n\r\n const handleFieldLeave = useCallback(() => {\r\n setHoveredFieldIdx(null);\r\n setFieldHighlight(null);\r\n }, []);\r\n\r\n // Cross-highlight: byte hover → field highlight\r\n const handleByteHoverInternal = useCallback(\r\n (byteIdx: number) => {\r\n onByteHover?.(byteIdx);\r\n const fi = fieldByteRanges.findIndex(\r\n (r) => byteIdx >= r.start && byteIdx < r.end,\r\n );\r\n if (fi >= 0) {\r\n setHoveredFieldIdx(fi);\r\n setFieldHighlight(fieldByteRanges[fi]);\r\n } else {\r\n setHoveredFieldIdx(null);\r\n setFieldHighlight({ start: byteIdx, end: byteIdx + 1 });\r\n }\r\n },\r\n [fieldByteRanges, onByteHover],\r\n );\r\n\r\n const handleByteLeaveInternal = useCallback(() => {\r\n onByteLeave?.();\r\n setHoveredFieldIdx(null);\r\n setFieldHighlight(null);\r\n }, [onByteLeave]);\r\n\r\n // Merge field highlight + external highlight into effective highlights\r\n const effectiveHighlight = externalHighlight || fieldHighlight;\r\n\r\n const shouldShowFieldsTable =\r\n showFieldsTable ?? (decodedFields && decodedFields.length > 0);\r\n const shouldShowHeaderSummary =\r\n showHeaderSummary ?? (packetHeaders && packetHeaders.length > 0);\r\n const scrollRef = useRef<HTMLDivElement>(null);\r\n const hasConstrainedHeight = useMemo(() => {\r\n if (height === undefined || height === null) return false;\r\n if (typeof height === \"string\")\r\n return height.trim().toLowerCase() !== \"auto\";\r\n return true;\r\n }, [height]);\r\n const decodedFieldsMaxHeight = useMemo(() => {\r\n if (typeof height === \"number\") {\r\n // Keep decoded fields useful but avoid starving the hex grid.\r\n return Math.min(220, Math.max(120, Math.floor(height * 0.32)));\r\n }\r\n return 200;\r\n }, [height]);\r\n\r\n const [cursorOffset, setCursorOffset] = useState(-1);\r\n const [selectStart, setSelectStart] = useState(-1);\r\n const [selectEnd, setSelectEnd] = useState(-1);\r\n const [isDragging, setIsDragging] = useState(false);\r\n const [searchQuery, setSearchQuery] = useState(\"\");\r\n const [searchType, setSearchType] = useState<\"hex\" | \"ascii\">(\"hex\");\r\n const [searchResults, setSearchResults] = useState<number[]>([]);\r\n const [currentSearchIdx, setCurrentSearchIdx] = useState(-1);\r\n const [localBytesPerRow, setLocalBytesPerRow] = useState(bytesPerRow);\r\n const [localGrouping, setLocalGrouping] = useState(byteGrouping);\r\n const [localOffsetBase, setLocalOffsetBase] = useState(offsetBase);\r\n const [localEndianness, setLocalEndianness] = useState(endianness);\r\n const [localShowAscii, setLocalShowAscii] = useState(showAscii);\r\n const [scrollTop, setScrollTop] = useState(0);\r\n const [viewportHeight, setViewportHeight] = useState(160);\r\n\r\n // Auto-scroll when streaming\r\n useEffect(() => {\r\n if (streaming && scrollRef.current) {\r\n scrollRef.current.scrollTop = scrollRef.current.scrollHeight;\r\n }\r\n }, [data, streaming]);\r\n\r\n useEffect(() => {\r\n const el = scrollRef.current;\r\n if (!el) return undefined;\r\n\r\n const updateViewportHeight = () => {\r\n setViewportHeight(Math.max(120, el.clientHeight || 160));\r\n };\r\n\r\n updateViewportHeight();\r\n if (typeof ResizeObserver !== \"undefined\") {\r\n const observer = new ResizeObserver(updateViewportHeight);\r\n observer.observe(el);\r\n return () => observer.disconnect();\r\n }\r\n\r\n window.addEventListener(\"resize\", updateViewportHeight);\r\n return () => window.removeEventListener(\"resize\", updateViewportHeight);\r\n }, []);\r\n\r\n const totalRows = Math.max(1, Math.ceil(data.length / localBytesPerRow));\r\n const startRow = Math.max(\r\n 0,\r\n Math.floor(scrollTop / HEX_ROW_HEIGHT) - HEX_OVERSCAN_ROWS,\r\n );\r\n const visibleRowCount =\r\n Math.ceil(viewportHeight / HEX_ROW_HEIGHT) + HEX_OVERSCAN_ROWS * 2;\r\n const endRow = Math.min(totalRows, startRow + visibleRowCount);\r\n const virtualRows = useMemo(() => {\r\n const result: { offset: number; bytes: Uint8Array }[] = [];\r\n for (let row = startRow; row < endRow; row++) {\r\n const offset = row * localBytesPerRow;\r\n const bytes = data.subarray(\r\n offset,\r\n Math.min(data.length, offset + localBytesPerRow),\r\n );\r\n result.push({ offset, bytes });\r\n }\r\n if (result.length === 0) {\r\n result.push({ offset: 0, bytes: new Uint8Array(0) });\r\n }\r\n return result;\r\n }, [data, localBytesPerRow, startRow, endRow]);\r\n\r\n // Search\r\n const doSearch = useCallback(() => {\r\n if (!searchQuery.trim()) {\r\n setSearchResults([]);\r\n setCurrentSearchIdx(-1);\r\n return;\r\n }\r\n\r\n const results: number[] = [];\r\n if (searchType === \"hex\") {\r\n const hexStr = searchQuery.replace(/\\s+/g, \"\");\r\n if (hexStr.length % 2 !== 0 || !/^[0-9a-fA-F]+$/.test(hexStr)) return;\r\n const searchBytes = new Uint8Array(hexStr.length / 2);\r\n for (let i = 0; i < searchBytes.length; i++) {\r\n searchBytes[i] = parseInt(hexStr.slice(i * 2, i * 2 + 2), 16);\r\n }\r\n for (let i = 0; i <= data.length - searchBytes.length; i++) {\r\n let match = true;\r\n for (let j = 0; j < searchBytes.length; j++) {\r\n if (data[i + j] !== searchBytes[j]) {\r\n match = false;\r\n break;\r\n }\r\n }\r\n if (match) results.push(i);\r\n }\r\n } else {\r\n const encoder = new TextEncoder();\r\n const searchBytes = encoder.encode(searchQuery);\r\n for (let i = 0; i <= data.length - searchBytes.length; i++) {\r\n let match = true;\r\n for (let j = 0; j < searchBytes.length; j++) {\r\n if (data[i + j] !== searchBytes[j]) {\r\n match = false;\r\n break;\r\n }\r\n }\r\n if (match) results.push(i);\r\n }\r\n }\r\n setSearchResults(results);\r\n setCurrentSearchIdx(results.length > 0 ? 0 : -1);\r\n if (results.length > 0) {\r\n setCursorOffset(results[0]);\r\n if (scrollRef.current) {\r\n const rowIdx = Math.floor(results[0] / localBytesPerRow);\r\n scrollRef.current.scrollTop = Math.max(\r\n 0,\r\n rowIdx * HEX_ROW_HEIGHT - 100,\r\n );\r\n }\r\n }\r\n }, [searchQuery, searchType, data, localBytesPerRow]);\r\n\r\n const scrollToOffset = useCallback(\r\n (offset: number) => {\r\n if (!scrollRef.current) return;\r\n const rowIdx = Math.floor(offset / localBytesPerRow);\r\n scrollRef.current.scrollTop = Math.max(0, rowIdx * HEX_ROW_HEIGHT - 100);\r\n },\r\n [localBytesPerRow],\r\n );\r\n\r\n const handleHexScroll = useCallback(\r\n (event: React.UIEvent<HTMLDivElement>) => {\r\n setScrollTop(event.currentTarget.scrollTop);\r\n },\r\n [],\r\n );\r\n\r\n const nextSearchResult = useCallback(() => {\r\n if (searchResults.length === 0) return;\r\n const nextIdx = (currentSearchIdx + 1) % searchResults.length;\r\n setCurrentSearchIdx(nextIdx);\r\n setCursorOffset(searchResults[nextIdx]);\r\n scrollToOffset(searchResults[nextIdx]);\r\n }, [searchResults, currentSearchIdx, scrollToOffset]);\r\n\r\n const prevSearchResult = useCallback(() => {\r\n if (searchResults.length === 0) return;\r\n const prevIdx =\r\n (currentSearchIdx - 1 + searchResults.length) % searchResults.length;\r\n setCurrentSearchIdx(prevIdx);\r\n setCursorOffset(searchResults[prevIdx]);\r\n scrollToOffset(searchResults[prevIdx]);\r\n }, [searchResults, currentSearchIdx, scrollToOffset]);\r\n\r\n // Selection handlers\r\n const handleByteMouseDown = useCallback((idx: number) => {\r\n setSelectStart(idx);\r\n setSelectEnd(idx);\r\n setCursorOffset(idx);\r\n setIsDragging(true);\r\n }, []);\r\n\r\n const handleByteMouseEnter = useCallback(\r\n (idx: number) => {\r\n if (isDragging) {\r\n setSelectEnd(idx);\r\n }\r\n },\r\n [isDragging],\r\n );\r\n\r\n const handleMouseUp = useCallback(() => {\r\n if (isDragging) {\r\n setIsDragging(false);\r\n if (onSelectionChange && selectStart >= 0 && selectEnd >= 0) {\r\n onSelectionChange(\r\n Math.min(selectStart, selectEnd),\r\n Math.max(selectStart, selectEnd),\r\n );\r\n }\r\n }\r\n }, [isDragging, selectStart, selectEnd, onSelectionChange]);\r\n\r\n useEffect(() => {\r\n window.addEventListener(\"mouseup\", handleMouseUp);\r\n return () => window.removeEventListener(\"mouseup\", handleMouseUp);\r\n }, [handleMouseUp]);\r\n\r\n const handleByteClickCb = useCallback(\r\n (idx: number) => {\r\n setCursorOffset(idx);\r\n if (onByteClick) {\r\n onByteClick(idx, data[idx]);\r\n }\r\n },\r\n [data, onByteClick],\r\n );\r\n\r\n // Copy selection\r\n const copySelection = useCallback(\r\n (format: \"hex\" | \"decimal\" | \"ascii\") => {\r\n if (selectStart < 0 || selectEnd < 0) return;\r\n const start = Math.min(selectStart, selectEnd);\r\n const end = Math.max(selectStart, selectEnd);\r\n const selected = data.slice(start, end + 1);\r\n\r\n let text: string;\r\n if (format === \"hex\") {\r\n text = Array.from(selected)\r\n .map((b) => byteToHex(b))\r\n .join(\" \");\r\n } else if (format === \"decimal\") {\r\n text = Array.from(selected).join(\", \");\r\n } else {\r\n text = Array.from(selected)\r\n .map((b) => byteToAscii(b))\r\n .join(\"\");\r\n }\r\n navigator.clipboard?.writeText(text);\r\n },\r\n [data, selectStart, selectEnd],\r\n );\r\n\r\n // Interpretation of cursor byte\r\n const interpretation = useMemo(() => {\r\n if (cursorOffset < 0 || cursorOffset >= data.length) return null;\r\n return interpretBytes(data, cursorOffset, localEndianness);\r\n }, [data, cursorOffset, localEndianness]);\r\n\r\n const renderedSearchResultEntries = useMemo(() => {\r\n if (searchResults.length <= MAX_RENDERED_SEARCH_HIGHLIGHTS) {\r\n return searchResults.map((pos, idx) => ({ pos, idx }));\r\n }\r\n\r\n const halfWindow = Math.floor(MAX_RENDERED_SEARCH_HIGHLIGHTS / 2);\r\n const anchor = currentSearchIdx >= 0 ? currentSearchIdx : 0;\r\n const start = Math.max(0, anchor - halfWindow);\r\n const end = Math.min(\r\n searchResults.length,\r\n start + MAX_RENDERED_SEARCH_HIGHLIGHTS,\r\n );\r\n const adjustedStart = Math.max(0, end - MAX_RENDERED_SEARCH_HIGHLIGHTS);\r\n\r\n return searchResults\r\n .slice(adjustedStart, end)\r\n .map((pos, i) => ({ pos, idx: adjustedStart + i }));\r\n }, [searchResults, currentSearchIdx]);\r\n\r\n // Search highlights\r\n const allHighlights = useMemo(() => {\r\n const h = [...highlights];\r\n const searchLen =\r\n searchType === \"hex\"\r\n ? searchQuery.replace(/\\s+/g, \"\").length / 2\r\n : searchQuery.length;\r\n renderedSearchResultEntries.forEach(({ pos, idx }) => {\r\n h.push({\r\n start: pos,\r\n end: pos + Math.max(0, searchLen - 1),\r\n color:\r\n idx === currentSearchIdx\r\n ? tokens.colors.status.serious\r\n : tokens.colors.status.caution,\r\n label: `Search match ${idx + 1}`,\r\n });\r\n });\r\n return h;\r\n }, [\r\n highlights,\r\n renderedSearchResultEntries,\r\n currentSearchIdx,\r\n searchQuery,\r\n searchType,\r\n tokens,\r\n ]);\r\n\r\n const containerStyle: React.CSSProperties = {\r\n fontFamily: tokens.typography.fontFamily.mono,\r\n fontSize: 13,\r\n lineHeight: \"22px\",\r\n background: tokens.colors.background.base,\r\n border: bordered ? `1px solid ${tokens.colors.border.muted}` : \"none\",\r\n borderRadius: tokens.borderRadius.lg,\r\n overflowX: \"hidden\",\r\n overflowY: hasConstrainedHeight ? \"auto\" : \"visible\",\r\n display: \"flex\",\r\n flexDirection: \"column\",\r\n minHeight: 0,\r\n height: hasConstrainedHeight ? height : undefined,\r\n color: tokens.colors.text.primary,\r\n ...styleProp,\r\n };\r\n\r\n return (\r\n <div className={`hex-viewer ${className}`} style={containerStyle}>\r\n {/* Sticky header: title bar + toolbar stay pinned while content scrolls */}\r\n <div\r\n style={{\r\n position: \"sticky\",\r\n top: 0,\r\n zIndex: 10,\r\n background: tokens.colors.background.surface,\r\n flexShrink: 0,\r\n }}\r\n >\r\n {/* Title bar */}\r\n {title && (\r\n <div\r\n style={{\r\n padding: `${tokens.spacing.sm} ${tokens.spacing.smd}`,\r\n borderBottom: `1px solid ${tokens.colors.border.muted}`,\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"space-between\",\r\n }}\r\n >\r\n <span\r\n style={{\r\n fontWeight: tokens.typography.fontWeight.medium,\r\n fontSize: tokens.typography.fontSize.base,\r\n fontFamily: tokens.typography.fontFamily.primary,\r\n }}\r\n >\r\n {title}\r\n </span>\r\n <span\r\n style={{\r\n fontSize: tokens.typography.fontSize.sm,\r\n color: tokens.colors.text.muted,\r\n }}\r\n >\r\n {data.length.toLocaleString()} bytes\r\n </span>\r\n </div>\r\n )}\r\n\r\n {/* Toolbar */}\r\n {showToolbar && (\r\n <div\r\n role=\"toolbar\"\r\n aria-label=\"Hex viewer controls\"\r\n style={{\r\n padding: `${tokens.spacing.sm} ${tokens.spacing.smd}`,\r\n borderBottom: `1px solid ${tokens.colors.border.muted}`,\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: tokens.spacing.sm,\r\n flexWrap: \"wrap\",\r\n fontSize: tokens.typography.fontSize.sm,\r\n }}\r\n >\r\n <label\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: 4,\r\n color: tokens.colors.text.muted,\r\n }}\r\n >\r\n Bytes/Row:\r\n <select\r\n aria-label=\"Bytes per row\"\r\n value={localBytesPerRow}\r\n onChange={(e) =>\r\n setLocalBytesPerRow(Number(e.target.value) as 8 | 16 | 32)\r\n }\r\n style={{\r\n background: tokens.colors.background.base,\r\n color: tokens.colors.text.primary,\r\n border: `1px solid ${tokens.colors.border.muted}`,\r\n borderRadius: tokens.borderRadius.md,\r\n padding: \"2px 4px\",\r\n fontSize: 11,\r\n }}\r\n >\r\n <option value={8}>8</option>\r\n <option value={16}>16</option>\r\n <option value={32}>32</option>\r\n </select>\r\n </label>\r\n <label\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: 4,\r\n color: tokens.colors.text.muted,\r\n }}\r\n >\r\n Group:\r\n <select\r\n aria-label=\"Byte grouping\"\r\n value={localGrouping}\r\n onChange={(e) =>\r\n setLocalGrouping(Number(e.target.value) as ByteGrouping)\r\n }\r\n style={{\r\n background: tokens.colors.background.base,\r\n color: tokens.colors.text.primary,\r\n border: `1px solid ${tokens.colors.border.muted}`,\r\n borderRadius: tokens.borderRadius.md,\r\n padding: \"2px 4px\",\r\n fontSize: 11,\r\n }}\r\n >\r\n <option value={1}>1</option>\r\n <option value={2}>2</option>\r\n <option value={4}>4</option>\r\n <option value={8}>8</option>\r\n </select>\r\n </label>\r\n <label\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: 4,\r\n color: tokens.colors.text.muted,\r\n }}\r\n >\r\n Offset:\r\n <select\r\n aria-label=\"Offset format\"\r\n value={localOffsetBase}\r\n onChange={(e) =>\r\n setLocalOffsetBase(e.target.value as OffsetBase)\r\n }\r\n style={{\r\n background: tokens.colors.background.base,\r\n color: tokens.colors.text.primary,\r\n border: `1px solid ${tokens.colors.border.muted}`,\r\n borderRadius: tokens.borderRadius.md,\r\n padding: \"2px 4px\",\r\n fontSize: 11,\r\n }}\r\n >\r\n <option value=\"hex\">Hex</option>\r\n <option value=\"decimal\">Dec</option>\r\n </select>\r\n </label>\r\n <label\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: 4,\r\n color: tokens.colors.text.muted,\r\n }}\r\n >\r\n Endian:\r\n <select\r\n aria-label=\"Endianness\"\r\n value={localEndianness}\r\n onChange={(e) =>\r\n setLocalEndianness(e.target.value as Endianness)\r\n }\r\n style={{\r\n background: tokens.colors.background.base,\r\n color: tokens.colors.text.primary,\r\n border: `1px solid ${tokens.colors.border.muted}`,\r\n borderRadius: tokens.borderRadius.md,\r\n padding: \"2px 4px\",\r\n fontSize: 11,\r\n }}\r\n >\r\n <option value=\"big\">Big</option>\r\n <option value=\"little\">Little</option>\r\n </select>\r\n </label>\r\n <label\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: 4,\r\n color: tokens.colors.text.muted,\r\n cursor: \"pointer\",\r\n }}\r\n >\r\n <input\r\n type=\"checkbox\"\r\n checked={localShowAscii}\r\n onChange={(e) => setLocalShowAscii(e.target.checked)}\r\n style={{ accentColor: tokens.colors.interactive.default }}\r\n />\r\n ASCII\r\n </label>\r\n <div style={{ flex: 1 }} />\r\n {selectStart >= 0 && selectEnd >= 0 && (\r\n <div style={{ display: \"flex\", gap: 4 }}>\r\n {([\"hex\", \"decimal\", \"ascii\"] as const).map((fmt) => (\r\n <button\r\n key={fmt}\r\n onClick={() => copySelection(fmt)}\r\n style={{\r\n background: tokens.colors.background.base,\r\n color: tokens.colors.text.secondary,\r\n border: `1px solid ${tokens.colors.border.muted}`,\r\n borderRadius: tokens.borderRadius.md,\r\n padding: \"2px 8px\",\r\n fontSize: 10,\r\n cursor: \"pointer\",\r\n }}\r\n >\r\n Copy {fmt}\r\n </button>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* Search bar */}\r\n {showSearch && (\r\n <div\r\n role=\"search\"\r\n style={{\r\n padding: `${tokens.spacing.sm} ${tokens.spacing.smd}`,\r\n borderBottom: `1px solid ${tokens.colors.border.muted}`,\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: tokens.spacing.sm,\r\n }}\r\n >\r\n <label\r\n htmlFor=\"hex-search-type\"\r\n style={{\r\n position: \"absolute\",\r\n width: 1,\r\n height: 1,\r\n padding: 0,\r\n margin: -1,\r\n overflow: \"hidden\",\r\n clip: \"rect(0, 0, 0, 0)\",\r\n border: 0,\r\n }}\r\n >\r\n Search type\r\n </label>\r\n <select\r\n id=\"hex-search-type\"\r\n value={searchType}\r\n onChange={(e) => setSearchType(e.target.value as \"hex\" | \"ascii\")}\r\n style={{\r\n background: tokens.colors.background.base,\r\n color: tokens.colors.text.primary,\r\n border: `1px solid ${tokens.colors.border.muted}`,\r\n borderRadius: tokens.borderRadius.md,\r\n padding: `${tokens.spacing.xs} ${tokens.spacing.sm}`,\r\n fontSize: tokens.typography.fontSize.sm,\r\n }}\r\n >\r\n <option value=\"hex\">Hex</option>\r\n <option value=\"ascii\">ASCII</option>\r\n </select>\r\n <input\r\n type=\"text\"\r\n value={searchQuery}\r\n onChange={(e) => setSearchQuery(e.target.value)}\r\n onKeyDown={(e) => {\r\n if (e.key === \"Enter\") doSearch();\r\n }}\r\n placeholder={\r\n searchType === \"hex\" ? \"e.g. 48 65 6C 6C 6F\" : \"Search ASCII...\"\r\n }\r\n aria-label=\"Search hex data\"\r\n style={{\r\n flex: 1,\r\n background: tokens.colors.background.base,\r\n color: tokens.colors.text.primary,\r\n border: `1px solid ${tokens.colors.border.muted}`,\r\n borderRadius: tokens.borderRadius.md,\r\n padding: `${tokens.spacing.xs} ${tokens.spacing.sm}`,\r\n fontSize: tokens.typography.fontSize.sm,\r\n outline: \"none\",\r\n fontFamily: \"inherit\",\r\n }}\r\n />\r\n <button\r\n onClick={doSearch}\r\n aria-label=\"Find matches\"\r\n style={{\r\n background: tokens.colors.interactive.default,\r\n color: tokens.colors.text.inverse,\r\n border: \"none\",\r\n borderRadius: tokens.borderRadius.md,\r\n padding: `${tokens.spacing.xs} ${tokens.spacing.smd}`,\r\n fontSize: tokens.typography.fontSize.sm,\r\n cursor: \"pointer\",\r\n fontWeight: tokens.typography.fontWeight.medium,\r\n }}\r\n >\r\n Find\r\n </button>\r\n {searchResults.length > 0 && (\r\n <>\r\n <span\r\n style={{\r\n fontSize: tokens.typography.fontSize.sm,\r\n color: tokens.colors.text.muted,\r\n }}\r\n aria-live=\"polite\"\r\n >\r\n {currentSearchIdx + 1}/{searchResults.length}\r\n </span>\r\n <button\r\n onClick={prevSearchResult}\r\n aria-label=\"Previous match\"\r\n style={{\r\n background: \"none\",\r\n border: \"none\",\r\n color: tokens.colors.text.secondary,\r\n cursor: \"pointer\",\r\n fontSize: tokens.typography.fontSize.base,\r\n padding: tokens.spacing.xs,\r\n }}\r\n >\r\n &#x25B2;\r\n </button>\r\n <button\r\n onClick={nextSearchResult}\r\n aria-label=\"Next match\"\r\n style={{\r\n background: \"none\",\r\n border: \"none\",\r\n color: tokens.colors.text.secondary,\r\n cursor: \"pointer\",\r\n fontSize: tokens.typography.fontSize.base,\r\n padding: tokens.spacing.xs,\r\n }}\r\n >\r\n &#x25BC;\r\n </button>\r\n </>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n {/* end sticky header */}\r\n\r\n {/* Packet Header Summary (collapsible) */}\r\n {shouldShowHeaderSummary && packetHeaders && packetHeaders.length > 0 && (\r\n <div style={{ flexShrink: 0 }}>\r\n <div\r\n role=\"button\"\r\n tabIndex={0}\r\n aria-expanded={showHeaders}\r\n aria-label=\"Toggle packet headers\"\r\n onClick={() => setShowHeaders(!showHeaders)}\r\n onKeyDown={(e) => {\r\n if (e.key === \"Enter\" || e.key === \" \") {\r\n e.preventDefault();\r\n setShowHeaders(!showHeaders);\r\n }\r\n }}\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: tokens.spacing.sm,\r\n padding: `${tokens.spacing.sm} ${tokens.spacing.smd}`,\r\n background: tokens.colors.background.surface,\r\n cursor: \"pointer\",\r\n borderBottom: `1px solid ${tokens.colors.border.muted}`,\r\n userSelect: \"none\",\r\n }}\r\n >\r\n <span\r\n aria-hidden=\"true\"\r\n style={{\r\n fontSize: tokens.typography.fontSize.micro,\r\n color: tokens.colors.text.muted,\r\n transition: \"transform 150ms ease\",\r\n transform: showHeaders ? \"rotate(0deg)\" : \"rotate(-90deg)\",\r\n }}\r\n >\r\n {\"\\u25BC\"}\r\n </span>\r\n <span\r\n style={{\r\n fontSize: tokens.typography.fontSize.sm,\r\n color: tokens.colors.text.secondary,\r\n fontWeight: tokens.typography.fontWeight.medium,\r\n }}\r\n >\r\n Packet Headers\r\n </span>\r\n </div>\r\n {showHeaders && (\r\n <div\r\n style={{\r\n padding: `${tokens.spacing.sm} ${tokens.spacing.smd}`,\r\n borderBottom: `1px solid ${tokens.colors.border.muted}`,\r\n background: tokens.colors.background.base,\r\n }}\r\n >\r\n <div\r\n style={{\r\n display: \"grid\",\r\n gridTemplateColumns: \"auto 1fr\",\r\n gap: `${tokens.spacing.xxs} ${tokens.spacing.md}`,\r\n fontSize: tokens.typography.fontSize.sm,\r\n lineHeight: tokens.typography.lineHeight.tight,\r\n }}\r\n >\r\n {packetHeaders.map((entry, i) => (\r\n <React.Fragment key={i}>\r\n <span style={{ color: tokens.colors.text.muted }}>\r\n {entry.label}\r\n </span>\r\n <span\r\n style={{\r\n color: tokens.colors.text.primary,\r\n fontWeight: tokens.typography.fontWeight.medium,\r\n fontFamily: entry.mono\r\n ? tokens.typography.fontFamily.mono\r\n : \"inherit\",\r\n }}\r\n >\r\n {entry.value}\r\n </span>\r\n </React.Fragment>\r\n ))}\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* Decoded Fields Table (collapsible) */}\r\n {shouldShowFieldsTable && decodedFields && decodedFields.length > 0 && (\r\n <div style={{ flexShrink: 0 }}>\r\n <div\r\n role=\"button\"\r\n tabIndex={0}\r\n aria-expanded={showFields}\r\n aria-label=\"Toggle decoded fields\"\r\n onClick={() => setShowFields(!showFields)}\r\n onKeyDown={(e) => {\r\n if (e.key === \"Enter\" || e.key === \" \") {\r\n e.preventDefault();\r\n setShowFields(!showFields);\r\n }\r\n }}\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: tokens.spacing.sm,\r\n padding: `${tokens.spacing.sm} ${tokens.spacing.smd}`,\r\n background: tokens.colors.background.surface,\r\n cursor: \"pointer\",\r\n borderBottom: `1px solid ${tokens.colors.border.muted}`,\r\n userSelect: \"none\",\r\n }}\r\n >\r\n <span\r\n aria-hidden=\"true\"\r\n style={{\r\n fontSize: tokens.typography.fontSize.micro,\r\n color: tokens.colors.text.muted,\r\n transition: \"transform 150ms ease\",\r\n transform: showFields ? \"rotate(0deg)\" : \"rotate(-90deg)\",\r\n }}\r\n >\r\n {\"\\u25BC\"}\r\n </span>\r\n <span\r\n style={{\r\n fontSize: tokens.typography.fontSize.sm,\r\n color: tokens.colors.text.secondary,\r\n fontWeight: tokens.typography.fontWeight.medium,\r\n }}\r\n >\r\n Decoded Fields ({decodedFields.length})\r\n </span>\r\n </div>\r\n {showFields && (\r\n <div\r\n role=\"table\"\r\n aria-label=\"Decoded packet fields\"\r\n style={{\r\n borderBottom: `1px solid ${tokens.colors.border.muted}`,\r\n maxHeight: decodedFieldsMaxHeight,\r\n overflowY: \"auto\",\r\n }}\r\n >\r\n {/* Fields table header */}\r\n <div\r\n role=\"row\"\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n padding: `${tokens.spacing.xs} ${tokens.spacing.smd}`,\r\n borderBottom: `1px solid ${tokens.colors.border.muted}`,\r\n gap: tokens.spacing.sm,\r\n position: \"sticky\",\r\n top: 0,\r\n background: tokens.colors.background.surface,\r\n zIndex: 1,\r\n }}\r\n >\r\n <span\r\n role=\"columnheader\"\r\n style={{\r\n flex: 2,\r\n fontSize: tokens.typography.fontSize.xxs,\r\n color: tokens.colors.text.muted,\r\n textTransform: \"uppercase\",\r\n letterSpacing: \"0.5px\",\r\n }}\r\n >\r\n Field\r\n </span>\r\n <span\r\n role=\"columnheader\"\r\n style={{\r\n flex: 2,\r\n fontSize: tokens.typography.fontSize.xxs,\r\n color: tokens.colors.text.muted,\r\n textTransform: \"uppercase\",\r\n letterSpacing: \"0.5px\",\r\n textAlign: \"right\",\r\n }}\r\n >\r\n Value\r\n </span>\r\n <span\r\n role=\"columnheader\"\r\n style={{\r\n flex: 1,\r\n fontSize: tokens.typography.fontSize.xxs,\r\n color: tokens.colors.text.muted,\r\n textTransform: \"uppercase\",\r\n letterSpacing: \"0.5px\",\r\n textAlign: \"right\",\r\n }}\r\n >\r\n Unit\r\n </span>\r\n <span\r\n role=\"columnheader\"\r\n style={{\r\n flex: 1,\r\n fontSize: tokens.typography.fontSize.xxs,\r\n color: tokens.colors.text.muted,\r\n textTransform: \"uppercase\",\r\n letterSpacing: \"0.5px\",\r\n textAlign: \"right\",\r\n }}\r\n >\r\n Offset\r\n </span>\r\n <span\r\n role=\"columnheader\"\r\n style={{\r\n flex: 1,\r\n fontSize: tokens.typography.fontSize.xxs,\r\n color: tokens.colors.text.muted,\r\n textTransform: \"uppercase\",\r\n letterSpacing: \"0.5px\",\r\n textAlign: \"right\",\r\n }}\r\n >\r\n Size\r\n </span>\r\n </div>\r\n {/* Field rows */}\r\n {decodedFields.map((field, fi) => {\r\n const isHovered = hoveredFieldIdx === fi;\r\n return (\r\n <div\r\n key={fi}\r\n onMouseEnter={() => handleFieldHover(fi)}\r\n onMouseLeave={handleFieldLeave}\r\n title={field.description}\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n padding: `3px ${tokens.spacing.smd}`,\r\n gap: tokens.spacing.sm,\r\n background: isHovered\r\n ? `${tokens.colors.status.caution}14`\r\n : fi % 2 === 0\r\n ? tokens.colors.background.base\r\n : \"transparent\",\r\n transition: \"background 0.15s ease\",\r\n cursor: \"default\",\r\n minHeight: tokens.elementSize.sm,\r\n }}\r\n >\r\n <span\r\n role=\"cell\"\r\n style={{\r\n flex: 2,\r\n fontSize: tokens.typography.fontSize.sm,\r\n color: tokens.colors.text.secondary,\r\n overflow: \"hidden\",\r\n textOverflow: \"ellipsis\",\r\n whiteSpace: \"nowrap\",\r\n }}\r\n >\r\n {field.name}\r\n </span>\r\n <span\r\n role=\"cell\"\r\n style={{\r\n flex: 2,\r\n fontSize: tokens.typography.fontSize.sm,\r\n color: tokens.colors.text.primary,\r\n fontWeight: tokens.typography.fontWeight.medium,\r\n fontFamily: tokens.typography.fontFamily.mono,\r\n textAlign: \"right\",\r\n }}\r\n >\r\n {field.value === null || field.value === undefined\r\n ? \"\\u2014\"\r\n : String(field.value)}\r\n </span>\r\n <span\r\n role=\"cell\"\r\n style={{\r\n flex: 1,\r\n fontSize: tokens.typography.fontSize.xxs,\r\n color: tokens.colors.text.muted,\r\n textAlign: \"right\",\r\n }}\r\n >\r\n {field.unit || \"\"}\r\n </span>\r\n <span\r\n role=\"cell\"\r\n style={{\r\n flex: 1,\r\n fontSize: tokens.typography.fontSize.xxs,\r\n color: tokens.colors.text.muted,\r\n textAlign: \"right\",\r\n fontFamily: tokens.typography.fontFamily.mono,\r\n }}\r\n >\r\n {field.byteOffset !== undefined ? field.byteOffset : \"\"}\r\n </span>\r\n <span\r\n role=\"cell\"\r\n style={{\r\n flex: 1,\r\n fontSize: tokens.typography.fontSize.xxs,\r\n color: tokens.colors.text.muted,\r\n textAlign: \"right\",\r\n fontFamily: tokens.typography.fontFamily.mono,\r\n }}\r\n >\r\n {field.sizeBits ? `${field.sizeBits}b` : \"\"}\r\n </span>\r\n </div>\r\n );\r\n })}\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* Region legend */}\r\n {regions.length > 0 && (\r\n <div\r\n role=\"group\"\r\n aria-label=\"Packet structure regions\"\r\n style={{\r\n padding: `${tokens.spacing.xs} ${tokens.spacing.smd}`,\r\n borderBottom: `1px solid ${tokens.colors.border.muted}`,\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: tokens.spacing.smd,\r\n flexWrap: \"wrap\",\r\n fontSize: tokens.typography.fontSize.xxs,\r\n background: tokens.colors.background.surface,\r\n }}\r\n >\r\n {regions.map((r, i) => (\r\n <span\r\n key={i}\r\n style={{\r\n display: \"inline-flex\",\r\n alignItems: \"center\",\r\n gap: tokens.spacing.xs,\r\n }}\r\n >\r\n <span\r\n aria-hidden=\"true\"\r\n style={{\r\n display: \"inline-block\",\r\n width: 10,\r\n height: 10,\r\n borderRadius: tokens.borderRadius.sm,\r\n background: r.color,\r\n border: `1px solid ${r.borderColor || \"transparent\"}`,\r\n }}\r\n />\r\n <span style={{ color: tokens.colors.text.muted }}>\r\n {r.label} ({r.end - r.start}B)\r\n </span>\r\n </span>\r\n ))}\r\n </div>\r\n )}\r\n\r\n {/* Column headers */}\r\n <div\r\n role=\"row\"\r\n aria-label=\"Column headers\"\r\n style={{\r\n padding: `${tokens.spacing.xs} ${tokens.spacing.smd}`,\r\n borderBottom: `1px solid ${tokens.colors.border.muted}`,\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n fontSize: tokens.typography.fontSize.xxs,\r\n color: tokens.colors.text.muted,\r\n textTransform: \"uppercase\",\r\n letterSpacing: \"0.5px\",\r\n fontWeight: tokens.typography.fontWeight.medium,\r\n background: tokens.colors.background.surface,\r\n }}\r\n >\r\n {showOffset && (\r\n <span\r\n style={{\r\n marginRight: tokens.spacing.smd,\r\n minWidth: 60,\r\n textAlign: \"right\",\r\n }}\r\n >\r\n Offset\r\n </span>\r\n )}\r\n <span style={{ flex: 1 }}>Hex</span>\r\n {localShowAscii && (\r\n <>\r\n <span\r\n aria-hidden=\"true\"\r\n style={{\r\n color: `${tokens.colors.border.muted}`,\r\n marginRight: tokens.spacing.sm,\r\n }}\r\n >\r\n |\r\n </span>\r\n <span>ASCII</span>\r\n </>\r\n )}\r\n </div>\r\n\r\n {/* Hex content */}\r\n <div\r\n ref={scrollRef}\r\n role=\"grid\"\r\n aria-label=\"Hex data\"\r\n tabIndex={0}\r\n onScroll={handleHexScroll}\r\n style={{\r\n flex: \"1 1 160px\",\r\n minHeight: 160,\r\n overflow: \"auto\",\r\n padding: `${tokens.spacing.xs} ${tokens.spacing.smd}`,\r\n }}\r\n >\r\n <div\r\n style={{ height: totalRows * HEX_ROW_HEIGHT, position: \"relative\" }}\r\n >\r\n <div\r\n style={{\r\n position: \"absolute\",\r\n top: startRow * HEX_ROW_HEIGHT,\r\n left: 0,\r\n right: 0,\r\n }}\r\n >\r\n {virtualRows.map((row) => (\r\n <HexRow\r\n key={row.offset}\r\n offset={row.offset}\r\n bytes={row.bytes}\r\n bytesPerRow={localBytesPerRow}\r\n byteGrouping={localGrouping}\r\n offsetBase={localOffsetBase}\r\n totalBytes={data.length}\r\n showAscii={localShowAscii}\r\n showOffset={showOffset}\r\n highlights={allHighlights}\r\n regions={sortedRegions}\r\n effectiveHighlight={effectiveHighlight}\r\n selectedStart={selectStart}\r\n selectedEnd={selectEnd}\r\n cursorOffset={cursorOffset}\r\n onByteMouseDown={handleByteMouseDown}\r\n onByteMouseEnter={handleByteMouseEnter}\r\n onByteClick={handleByteClickCb}\r\n handleByteHoverInternal={handleByteHoverInternal}\r\n handleByteLeaveInternal={handleByteLeaveInternal}\r\n tokens={tokens}\r\n />\r\n ))}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* Highlight legend */}\r\n {highlights.length > 0 && (\r\n <div\r\n role=\"group\"\r\n aria-label=\"Search highlights\"\r\n style={{\r\n padding: `${tokens.spacing.xs} ${tokens.spacing.smd}`,\r\n borderTop: `1px solid ${tokens.colors.border.muted}`,\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: tokens.spacing.smd,\r\n flexWrap: \"wrap\",\r\n fontSize: tokens.typography.fontSize.xxs,\r\n background: tokens.colors.background.surface,\r\n }}\r\n >\r\n {highlights\r\n .filter((h) => h.label)\r\n .map((h, i) => (\r\n <span\r\n key={i}\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: tokens.spacing.xs,\r\n }}\r\n >\r\n <span\r\n aria-hidden=\"true\"\r\n style={{\r\n width: 10,\r\n height: 10,\r\n borderRadius: tokens.borderRadius.sm,\r\n background: h.color,\r\n display: \"inline-block\",\r\n }}\r\n />\r\n <span style={{ color: tokens.colors.text.muted }}>\r\n {h.label} (0x{h.start.toString(16)}-0x{h.end.toString(16)})\r\n </span>\r\n </span>\r\n ))}\r\n </div>\r\n )}\r\n\r\n {/* Status bar */}\r\n {showStatusBar && (\r\n <div\r\n role=\"status\"\r\n aria-live=\"polite\"\r\n style={{\r\n padding: `${tokens.spacing.sm} ${tokens.spacing.smd}`,\r\n borderTop: `1px solid ${tokens.colors.border.muted}`,\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: tokens.spacing.md,\r\n fontSize: tokens.typography.fontSize.sm,\r\n background: tokens.colors.background.surface,\r\n color: tokens.colors.text.muted,\r\n flexWrap: \"wrap\",\r\n }}\r\n >\r\n <span>Size: {data.length.toLocaleString()} bytes</span>\r\n {cursorOffset >= 0 && cursorOffset < data.length && (\r\n <>\r\n <span>\r\n Offset: 0x{cursorOffset.toString(16).toUpperCase()} (\r\n {cursorOffset})\r\n </span>\r\n <span>\r\n Value: 0x{byteToHex(data[cursorOffset])} ({data[cursorOffset]})\r\n </span>\r\n </>\r\n )}\r\n {selectStart >= 0 && selectEnd >= 0 && selectStart !== selectEnd && (\r\n <span>\r\n Selection: {Math.abs(selectEnd - selectStart) + 1} bytes (0x\r\n {Math.min(selectStart, selectEnd).toString(16).toUpperCase()}-0x\r\n {Math.max(selectStart, selectEnd).toString(16).toUpperCase()})\r\n </span>\r\n )}\r\n {interpretation && (\r\n <span\r\n style={{\r\n display: \"flex\",\r\n gap: tokens.spacing.sm,\r\n color: tokens.colors.text.secondary,\r\n }}\r\n >\r\n <span>U8: {interpretation.u8}</span>\r\n <span>I8: {interpretation.i8}</span>\r\n {interpretation.u16 !== undefined && (\r\n <span>U16: {interpretation.u16}</span>\r\n )}\r\n {interpretation.u32 !== undefined && (\r\n <span>U32: {interpretation.u32}</span>\r\n )}\r\n {interpretation.f32 !== undefined && (\r\n <span>F32: {interpretation.f32.toFixed(6)}</span>\r\n )}\r\n </span>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\nexport default HexViewer;\r\n"],"mappings":"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"}
1
+ {"version":3,"file":"HexViewer.js","names":[],"sources":["../../../../src/react/core/widgets/HexViewer.tsx"],"sourcesContent":["/**\r\n * @zendir/ui - HexViewer Component\r\n *\r\n * Displays raw binary data in a hex viewer format for telemetry packet analysis.\r\n * Shows offset, hex bytes, and ASCII representation side by side.\r\n *\r\n * Features:\r\n * - Hex + ASCII view with configurable bytes per row (8, 16, 32)\r\n * - Byte highlighting with custom colors (for field boundaries, errors, etc.)\r\n * - Click-to-select bytes and ranges\r\n * - Search by hex pattern or ASCII string\r\n * - Offset display in hex or decimal\r\n * - Live data streaming support (auto-scroll)\r\n * - Copy selection as hex, decimal, or ASCII\r\n * - Byte grouping (1, 2, 4, 8)\r\n * - Endianness toggle for multi-byte interpretation\r\n * - Status bar showing cursor position, selection info, data interpretation\r\n *\r\n * Astro UX Compliance:\r\n * - Dark theme with monospace font\r\n * - Status colors for highlighting\r\n * - Accessible keyboard navigation\r\n *\r\n * @example\r\n * ```tsx\r\n * <HexViewer\r\n * data={new Uint8Array([0x48, 0x65, 0x6C, 0x6C, 0x6F])}\r\n * bytesPerRow={16}\r\n * highlights={[{ start: 0, end: 4, color: '#4CAF50', label: 'Header' }]}\r\n * />\r\n * ```\r\n */\r\n\r\nimport React, {\r\n useState,\r\n useRef,\r\n useCallback,\r\n useMemo,\r\n useEffect,\r\n memo,\r\n} from \"react\";\r\nimport { useTheme } from \"../../theme\";\r\n\r\n// =============================================================================\r\n// Types\r\n// =============================================================================\r\n\r\nexport interface HexHighlight {\r\n /** Start byte offset (inclusive) */\r\n start: number;\r\n /** End byte offset (inclusive) */\r\n end: number;\r\n /** Highlight color (CSS color) */\r\n color: string;\r\n /** Optional label for the highlight region */\r\n label?: string;\r\n}\r\n\r\n/**\r\n * Named region for structural packet analysis (e.g., CCSDS Primary Header,\r\n * Secondary Header, User Data). Regions provide persistent background color\r\n * and a legend entry, unlike transient highlights.\r\n */\r\nexport interface HexRegion {\r\n /** Start byte offset (inclusive) */\r\n start: number;\r\n /** End byte offset (exclusive) */\r\n end: number;\r\n /** Region display name (e.g., \"Primary Header\") */\r\n label: string;\r\n /** Background fill color (CSS rgba recommended) */\r\n color: string;\r\n /** Border/accent color for the region */\r\n borderColor?: string;\r\n}\r\n\r\n/**\r\n * A decoded field within the packet payload for the fields table.\r\n * Enables cross-highlighting: hover a field row → highlight its bytes,\r\n * hover hex bytes → highlight the corresponding field row.\r\n */\r\nexport interface DecodedField {\r\n /** Field name */\r\n name: string;\r\n /** Decoded value (displayed via toString) */\r\n value: string | number | boolean | null;\r\n /** Engineering units (e.g., \"°C\", \"V\", \"rpm\") */\r\n unit?: string;\r\n /** Byte offset within the packet where this field starts */\r\n byteOffset?: number;\r\n /** Size in bits */\r\n sizeBits?: number;\r\n /** Optional description / tooltip */\r\n description?: string;\r\n}\r\n\r\n/**\r\n * Packet header key-value pairs shown in a collapsible summary panel.\r\n * Supports CCSDS-style primary + secondary header display.\r\n */\r\nexport interface PacketHeaderEntry {\r\n /** Label (e.g., \"APID\", \"Sequence Count\", \"Spacecraft ID\") */\r\n label: string;\r\n /** Value */\r\n value: string | number;\r\n /** Render value in monospace font */\r\n mono?: boolean;\r\n}\r\n\r\n/** Pre-defined region color palette for space packet headers */\r\nexport const REGION_COLORS = {\r\n primary: \"rgba(96, 165, 250, 0.15)\",\r\n secondary: \"rgba(168, 85, 247, 0.15)\",\r\n tertiary: \"rgba(251, 191, 36, 0.15)\",\r\n userData: \"rgba(34, 197, 94, 0.15)\",\r\n error: \"rgba(255, 56, 56, 0.15)\",\r\n} as const;\r\n\r\nexport const REGION_BORDER_COLORS = {\r\n primary: \"rgba(96, 165, 250, 0.5)\",\r\n secondary: \"rgba(168, 85, 247, 0.5)\",\r\n tertiary: \"rgba(251, 191, 36, 0.5)\",\r\n userData: \"rgba(34, 197, 94, 0.5)\",\r\n error: \"rgba(255, 56, 56, 0.5)\",\r\n} as const;\r\n\r\nexport type ByteGrouping = 1 | 2 | 4 | 8;\r\nexport type OffsetBase = \"hex\" | \"decimal\";\r\nexport type Endianness = \"big\" | \"little\";\r\n\r\nexport interface HexViewerProps {\r\n /** Binary data to display */\r\n data: Uint8Array | number[];\r\n /** Bytes per row (default: 16) */\r\n bytesPerRow?: 8 | 16 | 32;\r\n /** Byte grouping for hex display (default: 1) */\r\n byteGrouping?: ByteGrouping;\r\n /** Offset display base (default: 'hex') */\r\n offsetBase?: OffsetBase;\r\n /** Highlighted byte regions (transient, e.g., search results or field hover) */\r\n highlights?: HexHighlight[];\r\n /** Named structural regions (persistent background, e.g., Primary/Secondary Header) */\r\n regions?: HexRegion[];\r\n /** Decoded fields for the fields table (cross-highlights with hex bytes) */\r\n decodedFields?: DecodedField[];\r\n /** Packet header entries for the summary panel */\r\n packetHeaders?: PacketHeaderEntry[];\r\n /** External hover highlight range (for cross-component linking) */\r\n externalHighlight?: { start: number; end: number } | null;\r\n /** Whether to show the ASCII column (default: true) */\r\n showAscii?: boolean;\r\n /** Whether to show the offset column (default: true) */\r\n showOffset?: boolean;\r\n /** Whether to show the status/info bar (default: true) */\r\n showStatusBar?: boolean;\r\n /** Whether to show the search bar (default: true) */\r\n showSearch?: boolean;\r\n /** Whether to show the toolbar (default: true) */\r\n showToolbar?: boolean;\r\n /** Whether to show the decoded fields table (default: true if decodedFields provided) */\r\n showFieldsTable?: boolean;\r\n /** Whether to show the packet header summary (default: true if packetHeaders provided) */\r\n showHeaderSummary?: boolean;\r\n /**\r\n * Height of the viewer (default: 400).\r\n * When constrained, HexViewer enables outer scroll fallback so expanded\r\n * panels (headers/decoded fields) never trap lower sections.\r\n */\r\n height?: number | string;\r\n /** Title for the viewer */\r\n title?: string;\r\n /** Whether data is streaming (auto-scroll to bottom) */\r\n streaming?: boolean;\r\n /** Endianness for multi-byte interpretation (default: 'big') */\r\n endianness?: Endianness;\r\n /** Called when byte selection changes */\r\n onSelectionChange?: (start: number, end: number) => void;\r\n /** Called when a byte is clicked */\r\n onByteClick?: (offset: number, value: number) => void;\r\n /** Called when hovering a byte (for external cross-highlighting) */\r\n onByteHover?: (byteIndex: number) => void;\r\n /** Called when mouse leaves hex area */\r\n onByteLeave?: () => void;\r\n /** CSS class name */\r\n className?: string;\r\n /** Show outer container border (default: true). Set false when embedded inside a Container/card. */\r\n bordered?: boolean;\r\n /** Custom style overrides for the outer container */\r\n style?: React.CSSProperties;\r\n}\r\n\r\n// =============================================================================\r\n// Helpers\r\n// =============================================================================\r\n\r\nfunction toUint8Array(data: Uint8Array | number[]): Uint8Array {\r\n return data instanceof Uint8Array ? data : new Uint8Array(data);\r\n}\r\n\r\nfunction byteToHex(byte: number): string {\r\n return byte.toString(16).padStart(2, \"0\").toUpperCase();\r\n}\r\n\r\nfunction byteToAscii(byte: number): string {\r\n return byte >= 0x20 && byte <= 0x7e ? String.fromCharCode(byte) : \".\";\r\n}\r\n\r\nfunction formatOffset(\r\n offset: number,\r\n base: OffsetBase,\r\n totalBytes: number,\r\n): string {\r\n if (base === \"hex\") {\r\n const width = Math.max(\r\n 4,\r\n Math.ceil(Math.log2(Math.max(totalBytes, 1)) / 4) * 1,\r\n );\r\n return offset.toString(16).padStart(Math.max(width, 4), \"0\").toUpperCase();\r\n }\r\n const width = Math.max(4, totalBytes.toString().length);\r\n return offset.toString().padStart(width, \" \");\r\n}\r\n\r\nfunction interpretBytes(\r\n data: Uint8Array,\r\n offset: number,\r\n endianness: Endianness,\r\n): {\r\n u8: number;\r\n i8: number;\r\n u16?: number;\r\n i16?: number;\r\n u32?: number;\r\n i32?: number;\r\n f32?: number;\r\n f64?: number;\r\n} {\r\n const result: ReturnType<typeof interpretBytes> = {\r\n u8: data[offset],\r\n i8: data[offset] > 127 ? data[offset] - 256 : data[offset],\r\n };\r\n\r\n if (offset + 1 < data.length) {\r\n const view = new DataView(\r\n data.buffer,\r\n data.byteOffset + offset,\r\n Math.min(8, data.length - offset),\r\n );\r\n const be = endianness === \"big\";\r\n result.u16 = view.getUint16(0, !be);\r\n result.i16 = view.getInt16(0, !be);\r\n if (offset + 3 < data.length) {\r\n result.u32 = view.getUint32(0, !be);\r\n result.i32 = view.getInt32(0, !be);\r\n result.f32 = view.getFloat32(0, !be);\r\n }\r\n if (offset + 7 < data.length) {\r\n result.f64 = view.getFloat64(0, !be);\r\n }\r\n }\r\n return result;\r\n}\r\n\r\nconst HEX_ROW_HEIGHT = 22;\r\nconst HEX_OVERSCAN_ROWS = 16;\r\nconst MAX_RENDERED_SEARCH_HIGHLIGHTS = 400;\r\n\r\n// =============================================================================\r\n// Sub-components\r\n// =============================================================================\r\n\r\nconst HexRow = memo(function HexRow({\r\n offset,\r\n bytes,\r\n bytesPerRow,\r\n byteGrouping,\r\n offsetBase,\r\n totalBytes,\r\n showAscii,\r\n showOffset,\r\n highlights,\r\n regions,\r\n effectiveHighlight,\r\n selectedStart,\r\n selectedEnd,\r\n cursorOffset,\r\n onByteMouseDown,\r\n onByteMouseEnter,\r\n onByteClick,\r\n handleByteHoverInternal,\r\n handleByteLeaveInternal,\r\n tokens,\r\n}: {\r\n offset: number;\r\n bytes: Uint8Array;\r\n bytesPerRow: number;\r\n byteGrouping: ByteGrouping;\r\n offsetBase: OffsetBase;\r\n totalBytes: number;\r\n showAscii: boolean;\r\n showOffset: boolean;\r\n highlights: HexHighlight[];\r\n regions: HexRegion[];\r\n effectiveHighlight: { start: number; end: number } | null | undefined;\r\n selectedStart: number;\r\n selectedEnd: number;\r\n cursorOffset: number;\r\n onByteMouseDown: (idx: number) => void;\r\n onByteMouseEnter: (idx: number) => void;\r\n onByteClick: (idx: number) => void;\r\n handleByteHoverInternal: (idx: number) => void;\r\n handleByteLeaveInternal: () => void;\r\n tokens: ReturnType<typeof useTheme>[\"tokens\"];\r\n}) {\r\n const hexCells: React.ReactNode[] = [];\r\n const asciiCells: React.ReactNode[] = [];\r\n\r\n for (let i = 0; i < bytesPerRow; i++) {\r\n const byteIdx = offset + i;\r\n const isValid = i < bytes.length;\r\n const byte = isValid ? bytes[i] : 0;\r\n\r\n // Determine highlight color (priority: selection > cross-highlight > search highlight > region)\r\n let bgColor = \"transparent\";\r\n let fgColor = tokens.colors.text.primary;\r\n let borderBottom = \"2px solid transparent\";\r\n const isSelected =\r\n byteIdx >= Math.min(selectedStart, selectedEnd) &&\r\n byteIdx <= Math.max(selectedStart, selectedEnd) &&\r\n selectedStart >= 0;\r\n const isCursor = byteIdx === cursorOffset;\r\n\r\n // 1. Region background (lowest priority — always visible unless overridden)\r\n let regionColor: string | null = null;\r\n for (let r = 0; r < regions.length; r++) {\r\n const region = regions[r];\r\n if (byteIdx < region.start) break;\r\n if (byteIdx >= region.start && byteIdx < region.end) {\r\n regionColor = region.color;\r\n break;\r\n }\r\n }\r\n if (regionColor) {\r\n bgColor = regionColor;\r\n }\r\n\r\n // 2. Search highlights\r\n for (const h of highlights) {\r\n if (byteIdx >= h.start && byteIdx <= h.end) {\r\n bgColor = `${h.color}33`;\r\n fgColor = h.color;\r\n break;\r\n }\r\n }\r\n\r\n // 3. Cross-highlight from field hover or external\r\n if (\r\n effectiveHighlight &&\r\n byteIdx >= effectiveHighlight.start &&\r\n byteIdx < effectiveHighlight.end\r\n ) {\r\n bgColor = `${tokens.colors.status.caution}4D`;\r\n borderBottom = `2px solid ${tokens.colors.status.caution}`;\r\n }\r\n\r\n // 4. Selection (highest priority)\r\n if (isSelected) {\r\n bgColor = `${tokens.colors.interactive.default}4D`;\r\n fgColor = tokens.colors.interactive.default;\r\n }\r\n\r\n // Add grouping space\r\n const needsGroupSpace = i > 0 && i % byteGrouping === 0;\r\n\r\n hexCells.push(\r\n <span\r\n key={`hex-${i}`}\r\n role=\"button\"\r\n tabIndex={isValid ? 0 : -1}\r\n onMouseDown={() => isValid && onByteMouseDown(byteIdx)}\r\n onMouseEnter={() => {\r\n isValid && onByteMouseEnter(byteIdx);\r\n isValid && handleByteHoverInternal(byteIdx);\r\n }}\r\n onMouseLeave={() => isValid && handleByteLeaveInternal()}\r\n onClick={() => isValid && onByteClick(byteIdx)}\r\n onKeyDown={(e) => {\r\n if (isValid && (e.key === \"Enter\" || e.key === \" \")) {\r\n e.preventDefault();\r\n onByteClick(byteIdx);\r\n }\r\n }}\r\n style={{\r\n padding: \"0 2px\",\r\n marginLeft: needsGroupSpace ? 6 : 0,\r\n flexShrink: 0,\r\n background: bgColor,\r\n color: isValid ? fgColor : `${tokens.colors.text.muted}26`,\r\n cursor: isValid ? \"pointer\" : \"default\",\r\n borderBottom: isCursor\r\n ? `2px solid ${tokens.colors.status.normal}`\r\n : borderBottom,\r\n borderRadius: tokens.borderRadius.sm,\r\n userSelect: \"none\",\r\n transition: \"background 0.1s ease\",\r\n // The two-space filler in a partial final row must keep its full\r\n // two-character width — collapsed whitespace shrinks the pad cells\r\n // and shifts the ASCII column out of alignment on the last line.\r\n whiteSpace: \"pre\",\r\n }}\r\n >\r\n {isValid ? byteToHex(byte) : \" \"}\r\n </span>,\r\n );\r\n\r\n if (showAscii) {\r\n asciiCells.push(\r\n <span\r\n key={`ascii-${i}`}\r\n role=\"button\"\r\n tabIndex={isValid ? 0 : -1}\r\n onMouseDown={() => isValid && onByteMouseDown(byteIdx)}\r\n onMouseEnter={() => {\r\n isValid && onByteMouseEnter(byteIdx);\r\n isValid && handleByteHoverInternal(byteIdx);\r\n }}\r\n onMouseLeave={() => isValid && handleByteLeaveInternal()}\r\n onClick={() => isValid && onByteClick(byteIdx)}\r\n onKeyDown={(e) => {\r\n if (isValid && (e.key === \"Enter\" || e.key === \" \")) {\r\n e.preventDefault();\r\n onByteClick(byteIdx);\r\n }\r\n }}\r\n style={{\r\n background: bgColor,\r\n color: isValid\r\n ? byte >= 0x20 && byte <= 0x7e\r\n ? fgColor\r\n : `${tokens.colors.text.muted}33`\r\n : \"transparent\",\r\n cursor: isValid ? \"pointer\" : \"default\",\r\n borderBottom: isCursor\r\n ? `2px solid ${tokens.colors.status.normal}`\r\n : borderBottom,\r\n borderRadius: tokens.borderRadius.sm,\r\n userSelect: \"none\",\r\n width: 8,\r\n flexShrink: 0,\r\n textAlign: \"center\" as const,\r\n }}\r\n >\r\n {isValid ? byteToAscii(byte) : \" \"}\r\n </span>,\r\n );\r\n }\r\n }\r\n\r\n return (\r\n <div\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n height: HEX_ROW_HEIGHT,\r\n lineHeight: `${HEX_ROW_HEIGHT}px`,\r\n // Hex rows are a fixed-width grid. Sizing to content rather than to\r\n // the container keeps the ASCII column at full width in a narrow\r\n // panel, where shrink-to-fit would squeeze it down to one character.\r\n width: \"max-content\",\r\n }}\r\n >\r\n {showOffset && (\r\n <span\r\n style={{\r\n color: tokens.colors.text.muted,\r\n marginRight: 12,\r\n minWidth: 60,\r\n flexShrink: 0,\r\n textAlign: \"right\",\r\n }}\r\n >\r\n {formatOffset(offset, offsetBase, totalBytes)}\r\n </span>\r\n )}\r\n <span\r\n style={{\r\n display: \"flex\",\r\n gap: 1,\r\n marginRight: showAscii ? 16 : 0,\r\n flexShrink: 0,\r\n letterSpacing: \"0.5px\",\r\n }}\r\n >\r\n {hexCells}\r\n </span>\r\n {showAscii && (\r\n <>\r\n <span\r\n style={{\r\n color: `${tokens.colors.border.muted}`,\r\n marginRight: 8,\r\n flexShrink: 0,\r\n }}\r\n >\r\n │\r\n </span>\r\n <span\r\n style={{ display: \"flex\", flexShrink: 0, letterSpacing: \"1px\" }}\r\n >\r\n {asciiCells}\r\n </span>\r\n </>\r\n )}\r\n </div>\r\n );\r\n});\r\n\r\n// =============================================================================\r\n// Main Component\r\n// =============================================================================\r\n\r\nexport function HexViewer({\r\n data: rawData,\r\n bytesPerRow = 16,\r\n byteGrouping = 1,\r\n offsetBase = \"hex\",\r\n highlights = [],\r\n regions = [],\r\n decodedFields,\r\n packetHeaders,\r\n externalHighlight,\r\n showAscii = true,\r\n showOffset = true,\r\n showStatusBar = true,\r\n showSearch = true,\r\n showToolbar = true,\r\n showFieldsTable,\r\n showHeaderSummary,\r\n height = 400,\r\n title,\r\n streaming = false,\r\n endianness = \"big\",\r\n onSelectionChange,\r\n onByteClick,\r\n onByteHover,\r\n onByteLeave,\r\n className = \"\",\r\n bordered = true,\r\n style: styleProp,\r\n}: HexViewerProps): React.ReactElement {\r\n const { tokens } = useTheme();\r\n const data = useMemo(() => toUint8Array(rawData), [rawData]);\r\n const [hoveredFieldIdx, setHoveredFieldIdx] = useState<number | null>(null);\r\n const [fieldHighlight, setFieldHighlight] = useState<{\r\n start: number;\r\n end: number;\r\n } | null>(null);\r\n const [showHeaders, setShowHeaders] = useState(true);\r\n const [showFields, setShowFields] = useState(true);\r\n\r\n const sortedRegions = useMemo(\r\n () => [...regions].sort((a, b) => a.start - b.start),\r\n [regions],\r\n );\r\n\r\n // Build field byte ranges for cross-highlighting\r\n const fieldByteRanges = useMemo(() => {\r\n if (!decodedFields) return [];\r\n return decodedFields.map((f) => ({\r\n start: f.byteOffset ?? 0,\r\n end: (f.byteOffset ?? 0) + Math.ceil((f.sizeBits ?? 0) / 8),\r\n name: f.name,\r\n }));\r\n }, [decodedFields]);\r\n\r\n // Cross-highlight: field hover → byte highlight\r\n const handleFieldHover = useCallback(\r\n (fieldIdx: number) => {\r\n setHoveredFieldIdx(fieldIdx);\r\n const range = fieldByteRanges[fieldIdx];\r\n if (range && range.end > range.start) setFieldHighlight(range);\r\n },\r\n [fieldByteRanges],\r\n );\r\n\r\n const handleFieldLeave = useCallback(() => {\r\n setHoveredFieldIdx(null);\r\n setFieldHighlight(null);\r\n }, []);\r\n\r\n // Cross-highlight: byte hover → field highlight\r\n const handleByteHoverInternal = useCallback(\r\n (byteIdx: number) => {\r\n onByteHover?.(byteIdx);\r\n const fi = fieldByteRanges.findIndex(\r\n (r) => byteIdx >= r.start && byteIdx < r.end,\r\n );\r\n if (fi >= 0) {\r\n setHoveredFieldIdx(fi);\r\n setFieldHighlight(fieldByteRanges[fi]);\r\n } else {\r\n setHoveredFieldIdx(null);\r\n setFieldHighlight({ start: byteIdx, end: byteIdx + 1 });\r\n }\r\n },\r\n [fieldByteRanges, onByteHover],\r\n );\r\n\r\n const handleByteLeaveInternal = useCallback(() => {\r\n onByteLeave?.();\r\n setHoveredFieldIdx(null);\r\n setFieldHighlight(null);\r\n }, [onByteLeave]);\r\n\r\n // Merge field highlight + external highlight into effective highlights\r\n const effectiveHighlight = externalHighlight || fieldHighlight;\r\n\r\n const shouldShowFieldsTable =\r\n showFieldsTable ?? (decodedFields && decodedFields.length > 0);\r\n const shouldShowHeaderSummary =\r\n showHeaderSummary ?? (packetHeaders && packetHeaders.length > 0);\r\n const scrollRef = useRef<HTMLDivElement>(null);\r\n const hasConstrainedHeight = useMemo(() => {\r\n if (height === undefined || height === null) return false;\r\n if (typeof height === \"string\")\r\n return height.trim().toLowerCase() !== \"auto\";\r\n return true;\r\n }, [height]);\r\n const decodedFieldsMaxHeight = useMemo(() => {\r\n if (typeof height === \"number\") {\r\n // Keep decoded fields useful but avoid starving the hex grid.\r\n return Math.min(220, Math.max(120, Math.floor(height * 0.32)));\r\n }\r\n return 200;\r\n }, [height]);\r\n\r\n const [cursorOffset, setCursorOffset] = useState(-1);\r\n const [selectStart, setSelectStart] = useState(-1);\r\n const [selectEnd, setSelectEnd] = useState(-1);\r\n const [isDragging, setIsDragging] = useState(false);\r\n const [searchQuery, setSearchQuery] = useState(\"\");\r\n const [searchType, setSearchType] = useState<\"hex\" | \"ascii\">(\"hex\");\r\n const [searchResults, setSearchResults] = useState<number[]>([]);\r\n const [currentSearchIdx, setCurrentSearchIdx] = useState(-1);\r\n const [localBytesPerRow, setLocalBytesPerRow] = useState(bytesPerRow);\r\n const [localGrouping, setLocalGrouping] = useState(byteGrouping);\r\n const [localOffsetBase, setLocalOffsetBase] = useState(offsetBase);\r\n const [localEndianness, setLocalEndianness] = useState(endianness);\r\n const [localShowAscii, setLocalShowAscii] = useState(showAscii);\r\n const [scrollTop, setScrollTop] = useState(0);\r\n const [scrollLeft, setScrollLeft] = useState(0);\r\n const [viewportHeight, setViewportHeight] = useState(160);\r\n\r\n // Auto-scroll when streaming\r\n useEffect(() => {\r\n if (streaming && scrollRef.current) {\r\n scrollRef.current.scrollTop = scrollRef.current.scrollHeight;\r\n }\r\n }, [data, streaming]);\r\n\r\n useEffect(() => {\r\n const el = scrollRef.current;\r\n if (!el) return undefined;\r\n\r\n const updateViewportHeight = () => {\r\n setViewportHeight(Math.max(120, el.clientHeight || 160));\r\n };\r\n\r\n updateViewportHeight();\r\n if (typeof ResizeObserver !== \"undefined\") {\r\n const observer = new ResizeObserver(updateViewportHeight);\r\n observer.observe(el);\r\n return () => observer.disconnect();\r\n }\r\n\r\n window.addEventListener(\"resize\", updateViewportHeight);\r\n return () => window.removeEventListener(\"resize\", updateViewportHeight);\r\n }, []);\r\n\r\n const totalRows = Math.max(1, Math.ceil(data.length / localBytesPerRow));\r\n const startRow = Math.max(\r\n 0,\r\n Math.floor(scrollTop / HEX_ROW_HEIGHT) - HEX_OVERSCAN_ROWS,\r\n );\r\n const visibleRowCount =\r\n Math.ceil(viewportHeight / HEX_ROW_HEIGHT) + HEX_OVERSCAN_ROWS * 2;\r\n const endRow = Math.min(totalRows, startRow + visibleRowCount);\r\n const virtualRows = useMemo(() => {\r\n const result: { offset: number; bytes: Uint8Array }[] = [];\r\n for (let row = startRow; row < endRow; row++) {\r\n const offset = row * localBytesPerRow;\r\n const bytes = data.subarray(\r\n offset,\r\n Math.min(data.length, offset + localBytesPerRow),\r\n );\r\n result.push({ offset, bytes });\r\n }\r\n if (result.length === 0) {\r\n result.push({ offset: 0, bytes: new Uint8Array(0) });\r\n }\r\n return result;\r\n }, [data, localBytesPerRow, startRow, endRow]);\r\n\r\n // Search\r\n const doSearch = useCallback(() => {\r\n if (!searchQuery.trim()) {\r\n setSearchResults([]);\r\n setCurrentSearchIdx(-1);\r\n return;\r\n }\r\n\r\n const results: number[] = [];\r\n if (searchType === \"hex\") {\r\n const hexStr = searchQuery.replace(/\\s+/g, \"\");\r\n if (hexStr.length % 2 !== 0 || !/^[0-9a-fA-F]+$/.test(hexStr)) return;\r\n const searchBytes = new Uint8Array(hexStr.length / 2);\r\n for (let i = 0; i < searchBytes.length; i++) {\r\n searchBytes[i] = parseInt(hexStr.slice(i * 2, i * 2 + 2), 16);\r\n }\r\n for (let i = 0; i <= data.length - searchBytes.length; i++) {\r\n let match = true;\r\n for (let j = 0; j < searchBytes.length; j++) {\r\n if (data[i + j] !== searchBytes[j]) {\r\n match = false;\r\n break;\r\n }\r\n }\r\n if (match) results.push(i);\r\n }\r\n } else {\r\n const encoder = new TextEncoder();\r\n const searchBytes = encoder.encode(searchQuery);\r\n for (let i = 0; i <= data.length - searchBytes.length; i++) {\r\n let match = true;\r\n for (let j = 0; j < searchBytes.length; j++) {\r\n if (data[i + j] !== searchBytes[j]) {\r\n match = false;\r\n break;\r\n }\r\n }\r\n if (match) results.push(i);\r\n }\r\n }\r\n setSearchResults(results);\r\n setCurrentSearchIdx(results.length > 0 ? 0 : -1);\r\n if (results.length > 0) {\r\n setCursorOffset(results[0]);\r\n if (scrollRef.current) {\r\n const rowIdx = Math.floor(results[0] / localBytesPerRow);\r\n scrollRef.current.scrollTop = Math.max(\r\n 0,\r\n rowIdx * HEX_ROW_HEIGHT - 100,\r\n );\r\n }\r\n }\r\n }, [searchQuery, searchType, data, localBytesPerRow]);\r\n\r\n const scrollToOffset = useCallback(\r\n (offset: number) => {\r\n if (!scrollRef.current) return;\r\n const rowIdx = Math.floor(offset / localBytesPerRow);\r\n scrollRef.current.scrollTop = Math.max(0, rowIdx * HEX_ROW_HEIGHT - 100);\r\n },\r\n [localBytesPerRow],\r\n );\r\n\r\n const handleHexScroll = useCallback(\r\n (event: React.UIEvent<HTMLDivElement>) => {\r\n setScrollTop(event.currentTarget.scrollTop);\r\n setScrollLeft(event.currentTarget.scrollLeft);\r\n },\r\n [],\r\n );\r\n\r\n const nextSearchResult = useCallback(() => {\r\n if (searchResults.length === 0) return;\r\n const nextIdx = (currentSearchIdx + 1) % searchResults.length;\r\n setCurrentSearchIdx(nextIdx);\r\n setCursorOffset(searchResults[nextIdx]);\r\n scrollToOffset(searchResults[nextIdx]);\r\n }, [searchResults, currentSearchIdx, scrollToOffset]);\r\n\r\n const prevSearchResult = useCallback(() => {\r\n if (searchResults.length === 0) return;\r\n const prevIdx =\r\n (currentSearchIdx - 1 + searchResults.length) % searchResults.length;\r\n setCurrentSearchIdx(prevIdx);\r\n setCursorOffset(searchResults[prevIdx]);\r\n scrollToOffset(searchResults[prevIdx]);\r\n }, [searchResults, currentSearchIdx, scrollToOffset]);\r\n\r\n // Selection handlers\r\n const handleByteMouseDown = useCallback((idx: number) => {\r\n setSelectStart(idx);\r\n setSelectEnd(idx);\r\n setCursorOffset(idx);\r\n setIsDragging(true);\r\n }, []);\r\n\r\n const handleByteMouseEnter = useCallback(\r\n (idx: number) => {\r\n if (isDragging) {\r\n setSelectEnd(idx);\r\n }\r\n },\r\n [isDragging],\r\n );\r\n\r\n const handleMouseUp = useCallback(() => {\r\n if (isDragging) {\r\n setIsDragging(false);\r\n if (onSelectionChange && selectStart >= 0 && selectEnd >= 0) {\r\n onSelectionChange(\r\n Math.min(selectStart, selectEnd),\r\n Math.max(selectStart, selectEnd),\r\n );\r\n }\r\n }\r\n }, [isDragging, selectStart, selectEnd, onSelectionChange]);\r\n\r\n useEffect(() => {\r\n window.addEventListener(\"mouseup\", handleMouseUp);\r\n return () => window.removeEventListener(\"mouseup\", handleMouseUp);\r\n }, [handleMouseUp]);\r\n\r\n const handleByteClickCb = useCallback(\r\n (idx: number) => {\r\n setCursorOffset(idx);\r\n if (onByteClick) {\r\n onByteClick(idx, data[idx]);\r\n }\r\n },\r\n [data, onByteClick],\r\n );\r\n\r\n // Copy selection\r\n const copySelection = useCallback(\r\n (format: \"hex\" | \"decimal\" | \"ascii\") => {\r\n if (selectStart < 0 || selectEnd < 0) return;\r\n const start = Math.min(selectStart, selectEnd);\r\n const end = Math.max(selectStart, selectEnd);\r\n const selected = data.slice(start, end + 1);\r\n\r\n let text: string;\r\n if (format === \"hex\") {\r\n text = Array.from(selected)\r\n .map((b) => byteToHex(b))\r\n .join(\" \");\r\n } else if (format === \"decimal\") {\r\n text = Array.from(selected).join(\", \");\r\n } else {\r\n text = Array.from(selected)\r\n .map((b) => byteToAscii(b))\r\n .join(\"\");\r\n }\r\n navigator.clipboard?.writeText(text);\r\n },\r\n [data, selectStart, selectEnd],\r\n );\r\n\r\n // Interpretation of cursor byte\r\n const interpretation = useMemo(() => {\r\n if (cursorOffset < 0 || cursorOffset >= data.length) return null;\r\n return interpretBytes(data, cursorOffset, localEndianness);\r\n }, [data, cursorOffset, localEndianness]);\r\n\r\n const renderedSearchResultEntries = useMemo(() => {\r\n if (searchResults.length <= MAX_RENDERED_SEARCH_HIGHLIGHTS) {\r\n return searchResults.map((pos, idx) => ({ pos, idx }));\r\n }\r\n\r\n const halfWindow = Math.floor(MAX_RENDERED_SEARCH_HIGHLIGHTS / 2);\r\n const anchor = currentSearchIdx >= 0 ? currentSearchIdx : 0;\r\n const start = Math.max(0, anchor - halfWindow);\r\n const end = Math.min(\r\n searchResults.length,\r\n start + MAX_RENDERED_SEARCH_HIGHLIGHTS,\r\n );\r\n const adjustedStart = Math.max(0, end - MAX_RENDERED_SEARCH_HIGHLIGHTS);\r\n\r\n return searchResults\r\n .slice(adjustedStart, end)\r\n .map((pos, i) => ({ pos, idx: adjustedStart + i }));\r\n }, [searchResults, currentSearchIdx]);\r\n\r\n // Search highlights\r\n const allHighlights = useMemo(() => {\r\n const h = [...highlights];\r\n const searchLen =\r\n searchType === \"hex\"\r\n ? searchQuery.replace(/\\s+/g, \"\").length / 2\r\n : searchQuery.length;\r\n renderedSearchResultEntries.forEach(({ pos, idx }) => {\r\n h.push({\r\n start: pos,\r\n end: pos + Math.max(0, searchLen - 1),\r\n color:\r\n idx === currentSearchIdx\r\n ? tokens.colors.status.serious\r\n : tokens.colors.status.caution,\r\n label: `Search match ${idx + 1}`,\r\n });\r\n });\r\n return h;\r\n }, [\r\n highlights,\r\n renderedSearchResultEntries,\r\n currentSearchIdx,\r\n searchQuery,\r\n searchType,\r\n tokens,\r\n ]);\r\n\r\n const containerStyle: React.CSSProperties = {\r\n fontFamily: tokens.typography.fontFamily.mono,\r\n fontSize: 13,\r\n lineHeight: \"22px\",\r\n background: tokens.colors.background.base,\r\n border: bordered ? `1px solid ${tokens.colors.border.muted}` : \"none\",\r\n borderRadius: tokens.borderRadius.lg,\r\n overflowX: \"hidden\",\r\n overflowY: hasConstrainedHeight ? \"auto\" : \"visible\",\r\n display: \"flex\",\r\n flexDirection: \"column\",\r\n minHeight: 0,\r\n height: hasConstrainedHeight ? height : undefined,\r\n color: tokens.colors.text.primary,\r\n ...styleProp,\r\n };\r\n\r\n return (\r\n <div className={`hex-viewer ${className}`} style={containerStyle}>\r\n {/* Sticky header: title bar + toolbar stay pinned while content scrolls */}\r\n <div\r\n style={{\r\n position: \"sticky\",\r\n top: 0,\r\n zIndex: 10,\r\n background: tokens.colors.background.surface,\r\n flexShrink: 0,\r\n }}\r\n >\r\n {/* Title bar */}\r\n {title && (\r\n <div\r\n style={{\r\n padding: `${tokens.spacing.sm} ${tokens.spacing.smd}`,\r\n borderBottom: `1px solid ${tokens.colors.border.muted}`,\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"space-between\",\r\n }}\r\n >\r\n <span\r\n style={{\r\n fontWeight: tokens.typography.fontWeight.medium,\r\n fontSize: tokens.typography.fontSize.base,\r\n fontFamily: tokens.typography.fontFamily.primary,\r\n }}\r\n >\r\n {title}\r\n </span>\r\n <span\r\n style={{\r\n fontSize: tokens.typography.fontSize.sm,\r\n color: tokens.colors.text.muted,\r\n }}\r\n >\r\n {data.length.toLocaleString()} bytes\r\n </span>\r\n </div>\r\n )}\r\n\r\n {/* Toolbar */}\r\n {showToolbar && (\r\n <div\r\n role=\"toolbar\"\r\n aria-label=\"Hex viewer controls\"\r\n style={{\r\n padding: `${tokens.spacing.sm} ${tokens.spacing.smd}`,\r\n borderBottom: `1px solid ${tokens.colors.border.muted}`,\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: tokens.spacing.sm,\r\n flexWrap: \"wrap\",\r\n fontSize: tokens.typography.fontSize.sm,\r\n }}\r\n >\r\n <label\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: 4,\r\n color: tokens.colors.text.muted,\r\n }}\r\n >\r\n Bytes/Row:\r\n <select\r\n aria-label=\"Bytes per row\"\r\n value={localBytesPerRow}\r\n onChange={(e) =>\r\n setLocalBytesPerRow(Number(e.target.value) as 8 | 16 | 32)\r\n }\r\n style={{\r\n background: tokens.colors.background.base,\r\n color: tokens.colors.text.primary,\r\n border: `1px solid ${tokens.colors.border.muted}`,\r\n borderRadius: tokens.borderRadius.md,\r\n padding: \"2px 4px\",\r\n fontSize: 11,\r\n }}\r\n >\r\n <option value={8}>8</option>\r\n <option value={16}>16</option>\r\n <option value={32}>32</option>\r\n </select>\r\n </label>\r\n <label\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: 4,\r\n color: tokens.colors.text.muted,\r\n }}\r\n >\r\n Group:\r\n <select\r\n aria-label=\"Byte grouping\"\r\n value={localGrouping}\r\n onChange={(e) =>\r\n setLocalGrouping(Number(e.target.value) as ByteGrouping)\r\n }\r\n style={{\r\n background: tokens.colors.background.base,\r\n color: tokens.colors.text.primary,\r\n border: `1px solid ${tokens.colors.border.muted}`,\r\n borderRadius: tokens.borderRadius.md,\r\n padding: \"2px 4px\",\r\n fontSize: 11,\r\n }}\r\n >\r\n <option value={1}>1</option>\r\n <option value={2}>2</option>\r\n <option value={4}>4</option>\r\n <option value={8}>8</option>\r\n </select>\r\n </label>\r\n <label\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: 4,\r\n color: tokens.colors.text.muted,\r\n }}\r\n >\r\n Offset:\r\n <select\r\n aria-label=\"Offset format\"\r\n value={localOffsetBase}\r\n onChange={(e) =>\r\n setLocalOffsetBase(e.target.value as OffsetBase)\r\n }\r\n style={{\r\n background: tokens.colors.background.base,\r\n color: tokens.colors.text.primary,\r\n border: `1px solid ${tokens.colors.border.muted}`,\r\n borderRadius: tokens.borderRadius.md,\r\n padding: \"2px 4px\",\r\n fontSize: 11,\r\n }}\r\n >\r\n <option value=\"hex\">Hex</option>\r\n <option value=\"decimal\">Dec</option>\r\n </select>\r\n </label>\r\n <label\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: 4,\r\n color: tokens.colors.text.muted,\r\n }}\r\n >\r\n Endian:\r\n <select\r\n aria-label=\"Endianness\"\r\n value={localEndianness}\r\n onChange={(e) =>\r\n setLocalEndianness(e.target.value as Endianness)\r\n }\r\n style={{\r\n background: tokens.colors.background.base,\r\n color: tokens.colors.text.primary,\r\n border: `1px solid ${tokens.colors.border.muted}`,\r\n borderRadius: tokens.borderRadius.md,\r\n padding: \"2px 4px\",\r\n fontSize: 11,\r\n }}\r\n >\r\n <option value=\"big\">Big</option>\r\n <option value=\"little\">Little</option>\r\n </select>\r\n </label>\r\n <label\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: 4,\r\n color: tokens.colors.text.muted,\r\n cursor: \"pointer\",\r\n }}\r\n >\r\n <input\r\n type=\"checkbox\"\r\n checked={localShowAscii}\r\n onChange={(e) => setLocalShowAscii(e.target.checked)}\r\n style={{ accentColor: tokens.colors.interactive.default }}\r\n />\r\n ASCII\r\n </label>\r\n <div style={{ flex: 1 }} />\r\n {selectStart >= 0 && selectEnd >= 0 && (\r\n <div style={{ display: \"flex\", gap: 4 }}>\r\n {([\"hex\", \"decimal\", \"ascii\"] as const).map((fmt) => (\r\n <button\r\n key={fmt}\r\n onClick={() => copySelection(fmt)}\r\n style={{\r\n background: tokens.colors.background.base,\r\n color: tokens.colors.text.secondary,\r\n border: `1px solid ${tokens.colors.border.muted}`,\r\n borderRadius: tokens.borderRadius.md,\r\n padding: \"2px 8px\",\r\n fontSize: 10,\r\n cursor: \"pointer\",\r\n }}\r\n >\r\n Copy {fmt}\r\n </button>\r\n ))}\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* Search bar */}\r\n {showSearch && (\r\n <div\r\n role=\"search\"\r\n style={{\r\n padding: `${tokens.spacing.sm} ${tokens.spacing.smd}`,\r\n borderBottom: `1px solid ${tokens.colors.border.muted}`,\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: tokens.spacing.sm,\r\n }}\r\n >\r\n <label\r\n htmlFor=\"hex-search-type\"\r\n style={{\r\n position: \"absolute\",\r\n width: 1,\r\n height: 1,\r\n padding: 0,\r\n margin: -1,\r\n overflow: \"hidden\",\r\n clip: \"rect(0, 0, 0, 0)\",\r\n border: 0,\r\n }}\r\n >\r\n Search type\r\n </label>\r\n <select\r\n id=\"hex-search-type\"\r\n value={searchType}\r\n onChange={(e) => setSearchType(e.target.value as \"hex\" | \"ascii\")}\r\n style={{\r\n background: tokens.colors.background.base,\r\n color: tokens.colors.text.primary,\r\n border: `1px solid ${tokens.colors.border.muted}`,\r\n borderRadius: tokens.borderRadius.md,\r\n padding: `${tokens.spacing.xs} ${tokens.spacing.sm}`,\r\n fontSize: tokens.typography.fontSize.sm,\r\n }}\r\n >\r\n <option value=\"hex\">Hex</option>\r\n <option value=\"ascii\">ASCII</option>\r\n </select>\r\n <input\r\n type=\"text\"\r\n value={searchQuery}\r\n onChange={(e) => setSearchQuery(e.target.value)}\r\n onKeyDown={(e) => {\r\n if (e.key === \"Enter\") doSearch();\r\n }}\r\n placeholder={\r\n searchType === \"hex\" ? \"e.g. 48 65 6C 6C 6F\" : \"Search ASCII...\"\r\n }\r\n aria-label=\"Search hex data\"\r\n style={{\r\n flex: 1,\r\n background: tokens.colors.background.base,\r\n color: tokens.colors.text.primary,\r\n border: `1px solid ${tokens.colors.border.muted}`,\r\n borderRadius: tokens.borderRadius.md,\r\n padding: `${tokens.spacing.xs} ${tokens.spacing.sm}`,\r\n fontSize: tokens.typography.fontSize.sm,\r\n outline: \"none\",\r\n fontFamily: \"inherit\",\r\n }}\r\n />\r\n <button\r\n onClick={doSearch}\r\n aria-label=\"Find matches\"\r\n style={{\r\n background: tokens.colors.interactive.default,\r\n color: tokens.colors.text.inverse,\r\n border: \"none\",\r\n borderRadius: tokens.borderRadius.md,\r\n padding: `${tokens.spacing.xs} ${tokens.spacing.smd}`,\r\n fontSize: tokens.typography.fontSize.sm,\r\n cursor: \"pointer\",\r\n fontWeight: tokens.typography.fontWeight.medium,\r\n }}\r\n >\r\n Find\r\n </button>\r\n {searchResults.length > 0 && (\r\n <>\r\n <span\r\n style={{\r\n fontSize: tokens.typography.fontSize.sm,\r\n color: tokens.colors.text.muted,\r\n }}\r\n aria-live=\"polite\"\r\n >\r\n {currentSearchIdx + 1}/{searchResults.length}\r\n </span>\r\n <button\r\n onClick={prevSearchResult}\r\n aria-label=\"Previous match\"\r\n style={{\r\n background: \"none\",\r\n border: \"none\",\r\n color: tokens.colors.text.secondary,\r\n cursor: \"pointer\",\r\n fontSize: tokens.typography.fontSize.base,\r\n padding: tokens.spacing.xs,\r\n }}\r\n >\r\n &#x25B2;\r\n </button>\r\n <button\r\n onClick={nextSearchResult}\r\n aria-label=\"Next match\"\r\n style={{\r\n background: \"none\",\r\n border: \"none\",\r\n color: tokens.colors.text.secondary,\r\n cursor: \"pointer\",\r\n fontSize: tokens.typography.fontSize.base,\r\n padding: tokens.spacing.xs,\r\n }}\r\n >\r\n &#x25BC;\r\n </button>\r\n </>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n {/* end sticky header */}\r\n\r\n {/* Packet Header Summary (collapsible) */}\r\n {shouldShowHeaderSummary && packetHeaders && packetHeaders.length > 0 && (\r\n <div style={{ flexShrink: 0 }}>\r\n <div\r\n role=\"button\"\r\n tabIndex={0}\r\n aria-expanded={showHeaders}\r\n aria-label=\"Toggle packet headers\"\r\n onClick={() => setShowHeaders(!showHeaders)}\r\n onKeyDown={(e) => {\r\n if (e.key === \"Enter\" || e.key === \" \") {\r\n e.preventDefault();\r\n setShowHeaders(!showHeaders);\r\n }\r\n }}\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: tokens.spacing.sm,\r\n padding: `${tokens.spacing.sm} ${tokens.spacing.smd}`,\r\n background: tokens.colors.background.surface,\r\n cursor: \"pointer\",\r\n borderBottom: `1px solid ${tokens.colors.border.muted}`,\r\n userSelect: \"none\",\r\n }}\r\n >\r\n <span\r\n aria-hidden=\"true\"\r\n style={{\r\n fontSize: tokens.typography.fontSize.micro,\r\n color: tokens.colors.text.muted,\r\n transition: \"transform 150ms ease\",\r\n transform: showHeaders ? \"rotate(0deg)\" : \"rotate(-90deg)\",\r\n }}\r\n >\r\n {\"\\u25BC\"}\r\n </span>\r\n <span\r\n style={{\r\n fontSize: tokens.typography.fontSize.sm,\r\n color: tokens.colors.text.secondary,\r\n fontWeight: tokens.typography.fontWeight.medium,\r\n }}\r\n >\r\n Packet Headers\r\n </span>\r\n </div>\r\n {showHeaders && (\r\n <div\r\n style={{\r\n padding: `${tokens.spacing.sm} ${tokens.spacing.smd}`,\r\n borderBottom: `1px solid ${tokens.colors.border.muted}`,\r\n background: tokens.colors.background.base,\r\n }}\r\n >\r\n <div\r\n style={{\r\n display: \"grid\",\r\n gridTemplateColumns: \"auto 1fr\",\r\n gap: `${tokens.spacing.xxs} ${tokens.spacing.md}`,\r\n fontSize: tokens.typography.fontSize.sm,\r\n lineHeight: tokens.typography.lineHeight.tight,\r\n }}\r\n >\r\n {packetHeaders.map((entry, i) => (\r\n <React.Fragment key={i}>\r\n <span style={{ color: tokens.colors.text.muted }}>\r\n {entry.label}\r\n </span>\r\n <span\r\n style={{\r\n color: tokens.colors.text.primary,\r\n fontWeight: tokens.typography.fontWeight.medium,\r\n fontFamily: entry.mono\r\n ? tokens.typography.fontFamily.mono\r\n : \"inherit\",\r\n }}\r\n >\r\n {entry.value}\r\n </span>\r\n </React.Fragment>\r\n ))}\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* Decoded Fields Table (collapsible) */}\r\n {shouldShowFieldsTable && decodedFields && decodedFields.length > 0 && (\r\n <div style={{ flexShrink: 0 }}>\r\n <div\r\n role=\"button\"\r\n tabIndex={0}\r\n aria-expanded={showFields}\r\n aria-label=\"Toggle decoded fields\"\r\n onClick={() => setShowFields(!showFields)}\r\n onKeyDown={(e) => {\r\n if (e.key === \"Enter\" || e.key === \" \") {\r\n e.preventDefault();\r\n setShowFields(!showFields);\r\n }\r\n }}\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: tokens.spacing.sm,\r\n padding: `${tokens.spacing.sm} ${tokens.spacing.smd}`,\r\n background: tokens.colors.background.surface,\r\n cursor: \"pointer\",\r\n borderBottom: `1px solid ${tokens.colors.border.muted}`,\r\n userSelect: \"none\",\r\n }}\r\n >\r\n <span\r\n aria-hidden=\"true\"\r\n style={{\r\n fontSize: tokens.typography.fontSize.micro,\r\n color: tokens.colors.text.muted,\r\n transition: \"transform 150ms ease\",\r\n transform: showFields ? \"rotate(0deg)\" : \"rotate(-90deg)\",\r\n }}\r\n >\r\n {\"\\u25BC\"}\r\n </span>\r\n <span\r\n style={{\r\n fontSize: tokens.typography.fontSize.sm,\r\n color: tokens.colors.text.secondary,\r\n fontWeight: tokens.typography.fontWeight.medium,\r\n }}\r\n >\r\n Decoded Fields ({decodedFields.length})\r\n </span>\r\n </div>\r\n {showFields && (\r\n <div\r\n role=\"table\"\r\n aria-label=\"Decoded packet fields\"\r\n style={{\r\n borderBottom: `1px solid ${tokens.colors.border.muted}`,\r\n maxHeight: decodedFieldsMaxHeight,\r\n overflowY: \"auto\",\r\n }}\r\n >\r\n {/* Fields table header */}\r\n <div\r\n role=\"row\"\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n padding: `${tokens.spacing.xs} ${tokens.spacing.smd}`,\r\n borderBottom: `1px solid ${tokens.colors.border.muted}`,\r\n gap: tokens.spacing.sm,\r\n position: \"sticky\",\r\n top: 0,\r\n background: tokens.colors.background.surface,\r\n zIndex: 1,\r\n }}\r\n >\r\n <span\r\n role=\"columnheader\"\r\n style={{\r\n flex: 2,\r\n fontSize: tokens.typography.fontSize.xxs,\r\n color: tokens.colors.text.muted,\r\n textTransform: \"uppercase\",\r\n letterSpacing: \"0.5px\",\r\n }}\r\n >\r\n Field\r\n </span>\r\n <span\r\n role=\"columnheader\"\r\n style={{\r\n flex: 2,\r\n fontSize: tokens.typography.fontSize.xxs,\r\n color: tokens.colors.text.muted,\r\n textTransform: \"uppercase\",\r\n letterSpacing: \"0.5px\",\r\n textAlign: \"right\",\r\n }}\r\n >\r\n Value\r\n </span>\r\n <span\r\n role=\"columnheader\"\r\n style={{\r\n flex: 1,\r\n fontSize: tokens.typography.fontSize.xxs,\r\n color: tokens.colors.text.muted,\r\n textTransform: \"uppercase\",\r\n letterSpacing: \"0.5px\",\r\n textAlign: \"right\",\r\n }}\r\n >\r\n Unit\r\n </span>\r\n <span\r\n role=\"columnheader\"\r\n style={{\r\n flex: 1,\r\n fontSize: tokens.typography.fontSize.xxs,\r\n color: tokens.colors.text.muted,\r\n textTransform: \"uppercase\",\r\n letterSpacing: \"0.5px\",\r\n textAlign: \"right\",\r\n }}\r\n >\r\n Offset\r\n </span>\r\n <span\r\n role=\"columnheader\"\r\n style={{\r\n flex: 1,\r\n fontSize: tokens.typography.fontSize.xxs,\r\n color: tokens.colors.text.muted,\r\n textTransform: \"uppercase\",\r\n letterSpacing: \"0.5px\",\r\n textAlign: \"right\",\r\n }}\r\n >\r\n Size\r\n </span>\r\n </div>\r\n {/* Field rows */}\r\n {decodedFields.map((field, fi) => {\r\n const isHovered = hoveredFieldIdx === fi;\r\n return (\r\n <div\r\n key={fi}\r\n onMouseEnter={() => handleFieldHover(fi)}\r\n onMouseLeave={handleFieldLeave}\r\n title={field.description}\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n padding: `3px ${tokens.spacing.smd}`,\r\n gap: tokens.spacing.sm,\r\n background: isHovered\r\n ? `${tokens.colors.status.caution}14`\r\n : fi % 2 === 0\r\n ? tokens.colors.background.base\r\n : \"transparent\",\r\n transition: \"background 0.15s ease\",\r\n cursor: \"default\",\r\n minHeight: tokens.elementSize.sm,\r\n }}\r\n >\r\n <span\r\n role=\"cell\"\r\n style={{\r\n flex: 2,\r\n fontSize: tokens.typography.fontSize.sm,\r\n color: tokens.colors.text.secondary,\r\n overflow: \"hidden\",\r\n textOverflow: \"ellipsis\",\r\n whiteSpace: \"nowrap\",\r\n }}\r\n >\r\n {field.name}\r\n </span>\r\n <span\r\n role=\"cell\"\r\n style={{\r\n flex: 2,\r\n fontSize: tokens.typography.fontSize.sm,\r\n color: tokens.colors.text.primary,\r\n fontWeight: tokens.typography.fontWeight.medium,\r\n fontFamily: tokens.typography.fontFamily.mono,\r\n textAlign: \"right\",\r\n }}\r\n >\r\n {field.value === null || field.value === undefined\r\n ? \"\\u2014\"\r\n : String(field.value)}\r\n </span>\r\n <span\r\n role=\"cell\"\r\n style={{\r\n flex: 1,\r\n fontSize: tokens.typography.fontSize.xxs,\r\n color: tokens.colors.text.muted,\r\n textAlign: \"right\",\r\n }}\r\n >\r\n {field.unit || \"\"}\r\n </span>\r\n <span\r\n role=\"cell\"\r\n style={{\r\n flex: 1,\r\n fontSize: tokens.typography.fontSize.xxs,\r\n color: tokens.colors.text.muted,\r\n textAlign: \"right\",\r\n fontFamily: tokens.typography.fontFamily.mono,\r\n }}\r\n >\r\n {field.byteOffset !== undefined ? field.byteOffset : \"\"}\r\n </span>\r\n <span\r\n role=\"cell\"\r\n style={{\r\n flex: 1,\r\n fontSize: tokens.typography.fontSize.xxs,\r\n color: tokens.colors.text.muted,\r\n textAlign: \"right\",\r\n fontFamily: tokens.typography.fontFamily.mono,\r\n }}\r\n >\r\n {field.sizeBits ? `${field.sizeBits}b` : \"\"}\r\n </span>\r\n </div>\r\n );\r\n })}\r\n </div>\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* Region legend */}\r\n {regions.length > 0 && (\r\n <div\r\n role=\"group\"\r\n aria-label=\"Packet structure regions\"\r\n style={{\r\n padding: `${tokens.spacing.xs} ${tokens.spacing.smd}`,\r\n borderBottom: `1px solid ${tokens.colors.border.muted}`,\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: tokens.spacing.smd,\r\n flexWrap: \"wrap\",\r\n fontSize: tokens.typography.fontSize.xxs,\r\n background: tokens.colors.background.surface,\r\n }}\r\n >\r\n {regions.map((r, i) => (\r\n <span\r\n key={i}\r\n style={{\r\n display: \"inline-flex\",\r\n alignItems: \"center\",\r\n gap: tokens.spacing.xs,\r\n }}\r\n >\r\n <span\r\n aria-hidden=\"true\"\r\n style={{\r\n display: \"inline-block\",\r\n width: 10,\r\n height: 10,\r\n borderRadius: tokens.borderRadius.sm,\r\n background: r.color,\r\n border: `1px solid ${r.borderColor || \"transparent\"}`,\r\n }}\r\n />\r\n <span style={{ color: tokens.colors.text.muted }}>\r\n {r.label} ({r.end - r.start}B)\r\n </span>\r\n </span>\r\n ))}\r\n </div>\r\n )}\r\n\r\n {/* Column headers */}\r\n <div\r\n role=\"row\"\r\n aria-label=\"Column headers\"\r\n style={{\r\n padding: `${tokens.spacing.xs} ${tokens.spacing.smd}`,\r\n borderBottom: `1px solid ${tokens.colors.border.muted}`,\r\n fontSize: tokens.typography.fontSize.xxs,\r\n color: tokens.colors.text.muted,\r\n textTransform: \"uppercase\",\r\n letterSpacing: \"0.5px\",\r\n fontWeight: tokens.typography.fontWeight.medium,\r\n background: tokens.colors.background.surface,\r\n // Clip rather than scroll: the grid below owns the scrollbar, and the\r\n // labels are kept in step with it by the offset applied inside.\r\n overflow: \"hidden\",\r\n }}\r\n >\r\n <div\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n // Track the grid's horizontal scroll so each label stays over the\r\n // column it names once a narrow panel scrolls the rows sideways.\r\n transform: `translateX(${-scrollLeft}px)`,\r\n }}\r\n >\r\n {showOffset && (\r\n <span\r\n style={{\r\n marginRight: tokens.spacing.smd,\r\n minWidth: 60,\r\n flexShrink: 0,\r\n textAlign: \"right\",\r\n }}\r\n >\r\n Offset\r\n </span>\r\n )}\r\n <span style={{ flex: 1 }}>Hex</span>\r\n {localShowAscii && (\r\n <>\r\n <span\r\n aria-hidden=\"true\"\r\n style={{\r\n color: `${tokens.colors.border.muted}`,\r\n marginRight: tokens.spacing.sm,\r\n flexShrink: 0,\r\n }}\r\n >\r\n |\r\n </span>\r\n <span style={{ flexShrink: 0 }}>ASCII</span>\r\n </>\r\n )}\r\n </div>\r\n </div>\r\n\r\n {/* Hex content */}\r\n <div\r\n ref={scrollRef}\r\n role=\"grid\"\r\n aria-label=\"Hex data\"\r\n tabIndex={0}\r\n onScroll={handleHexScroll}\r\n style={{\r\n flex: \"1 1 160px\",\r\n minHeight: 160,\r\n overflow: \"auto\",\r\n padding: `${tokens.spacing.xs} ${tokens.spacing.smd}`,\r\n }}\r\n >\r\n <div\r\n style={{ height: totalRows * HEX_ROW_HEIGHT, position: \"relative\" }}\r\n >\r\n <div\r\n style={{\r\n position: \"absolute\",\r\n top: startRow * HEX_ROW_HEIGHT,\r\n left: 0,\r\n // `right: 0` capped rows at the visible width, so a row wider\r\n // than the panel was clipped instead of becoming scrollable.\r\n minWidth: \"100%\",\r\n }}\r\n >\r\n {virtualRows.map((row) => (\r\n <HexRow\r\n key={row.offset}\r\n offset={row.offset}\r\n bytes={row.bytes}\r\n bytesPerRow={localBytesPerRow}\r\n byteGrouping={localGrouping}\r\n offsetBase={localOffsetBase}\r\n totalBytes={data.length}\r\n showAscii={localShowAscii}\r\n showOffset={showOffset}\r\n highlights={allHighlights}\r\n regions={sortedRegions}\r\n effectiveHighlight={effectiveHighlight}\r\n selectedStart={selectStart}\r\n selectedEnd={selectEnd}\r\n cursorOffset={cursorOffset}\r\n onByteMouseDown={handleByteMouseDown}\r\n onByteMouseEnter={handleByteMouseEnter}\r\n onByteClick={handleByteClickCb}\r\n handleByteHoverInternal={handleByteHoverInternal}\r\n handleByteLeaveInternal={handleByteLeaveInternal}\r\n tokens={tokens}\r\n />\r\n ))}\r\n </div>\r\n </div>\r\n </div>\r\n\r\n {/* Highlight legend */}\r\n {highlights.length > 0 && (\r\n <div\r\n role=\"group\"\r\n aria-label=\"Search highlights\"\r\n style={{\r\n padding: `${tokens.spacing.xs} ${tokens.spacing.smd}`,\r\n borderTop: `1px solid ${tokens.colors.border.muted}`,\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: tokens.spacing.smd,\r\n flexWrap: \"wrap\",\r\n fontSize: tokens.typography.fontSize.xxs,\r\n background: tokens.colors.background.surface,\r\n }}\r\n >\r\n {highlights\r\n .filter((h) => h.label)\r\n .map((h, i) => (\r\n <span\r\n key={i}\r\n style={{\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: tokens.spacing.xs,\r\n }}\r\n >\r\n <span\r\n aria-hidden=\"true\"\r\n style={{\r\n width: 10,\r\n height: 10,\r\n borderRadius: tokens.borderRadius.sm,\r\n background: h.color,\r\n display: \"inline-block\",\r\n }}\r\n />\r\n <span style={{ color: tokens.colors.text.muted }}>\r\n {h.label} (0x{h.start.toString(16)}-0x{h.end.toString(16)})\r\n </span>\r\n </span>\r\n ))}\r\n </div>\r\n )}\r\n\r\n {/* Status bar */}\r\n {showStatusBar && (\r\n <div\r\n role=\"status\"\r\n aria-live=\"polite\"\r\n style={{\r\n padding: `${tokens.spacing.sm} ${tokens.spacing.smd}`,\r\n borderTop: `1px solid ${tokens.colors.border.muted}`,\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n gap: tokens.spacing.md,\r\n fontSize: tokens.typography.fontSize.sm,\r\n background: tokens.colors.background.surface,\r\n color: tokens.colors.text.muted,\r\n flexWrap: \"wrap\",\r\n }}\r\n >\r\n <span>Size: {data.length.toLocaleString()} bytes</span>\r\n {cursorOffset >= 0 && cursorOffset < data.length && (\r\n <>\r\n <span>\r\n Offset: 0x{cursorOffset.toString(16).toUpperCase()} (\r\n {cursorOffset})\r\n </span>\r\n <span>\r\n Value: 0x{byteToHex(data[cursorOffset])} ({data[cursorOffset]})\r\n </span>\r\n </>\r\n )}\r\n {selectStart >= 0 && selectEnd >= 0 && selectStart !== selectEnd && (\r\n <span>\r\n Selection: {Math.abs(selectEnd - selectStart) + 1} bytes (0x\r\n {Math.min(selectStart, selectEnd).toString(16).toUpperCase()}-0x\r\n {Math.max(selectStart, selectEnd).toString(16).toUpperCase()})\r\n </span>\r\n )}\r\n {interpretation && (\r\n <span\r\n style={{\r\n display: \"flex\",\r\n gap: tokens.spacing.sm,\r\n color: tokens.colors.text.secondary,\r\n }}\r\n >\r\n <span>U8: {interpretation.u8}</span>\r\n <span>I8: {interpretation.i8}</span>\r\n {interpretation.u16 !== undefined && (\r\n <span>U16: {interpretation.u16}</span>\r\n )}\r\n {interpretation.u32 !== undefined && (\r\n <span>U32: {interpretation.u32}</span>\r\n )}\r\n {interpretation.f32 !== undefined && (\r\n <span>F32: {interpretation.f32.toFixed(6)}</span>\r\n )}\r\n </span>\r\n )}\r\n </div>\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\nexport default HexViewer;\r\n"],"mappings":"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"}
package/dist/react.js CHANGED
@@ -82,7 +82,7 @@ import { PowerOverviewChart, generateSamplePowerData } from "./react/charts/unif
82
82
  import { useChartStream, useWebSocketStream } from "./react/charts/unified/useChartStream.js";
83
83
  import { dispatchToGroup, exportGroupAsCSV, exportGroupAsImages, getGroupCharts, hideGroupTooltip, resetGroupZoom, showGroupTooltip, syncZoomRange, useChartSync } from "./react/charts/unified/sync.js";
84
84
  import { GroundTrackMap } from "./react/charts/GroundTrackMap.js";
85
- import { CARTO_ATTRIBUTION, ESRI_WORLD_IMAGERY_ATTRIBUTION, OSM_ATTRIBUTION, TILE_PRESETS, getBasemapAttribution } from "./react/charts/groundTrackMapLeafletTiles.js";
85
+ import { CANVAS_LABEL_TILES, CARTO_ATTRIBUTION, ESRI_CANVAS_ATTRIBUTION, ESRI_WORLD_IMAGERY_ATTRIBUTION, OSM_ATTRIBUTION, TILE_PRESETS, getBasemapAttribution } from "./react/charts/groundTrackMapLeafletTiles.js";
86
86
  import { ObjectInventoryPanel, recommendedFlyDistance } from "./react/panels/ObjectInventoryPanel.js";
87
87
  import { LayerControlPanel } from "./react/panels/LayerControlPanel.js";
88
88
  import { PLANETS, auToKm, estimateOrbitalPeriod, estimateOrbitalVelocity, getPlanet, normalizePlanetName } from "./react/types.js";
@@ -97,4 +97,4 @@ import { LinkBudgetCard } from "./react/visualizations/LinkBudgetCard.js";
97
97
  import { ThermalHeatmapCard } from "./react/visualizations/ThermalHeatmapCard.js";
98
98
  import { PropulsionCard } from "./react/visualizations/PropulsionCard.js";
99
99
  import { SensorFootprintCard } from "./react/visualizations/SensorFootprintCard.js";
100
- export { ASTRO_DATA_VIZ_COLORS, AccessCard, ActivityPlanner, AntennaPattern3DChart, AppBar, AreaChart, AstroChart, AttitudeChart, AttitudeHistory3DChart, BREAKPOINTS, Badge, Bar3DChart, BarChart, Body1, Body2, Body3, Box, BoxPlotChart, BubbleChart, Button, CARD_ACCENT_COLORS, CARTO_ATTRIBUTION, CATEGORY_ICONS, CATEGORY_LABELS, CHAT_RESPONSE_JSON_PROMPT, CHAT_RESPONSE_MCP_TOOL, CHAT_RESPONSE_TOOL_SCHEMA, CHAT_RESPONSE_YAML_PROMPT, CHAT_STATUS_RULES_PROMPT, CandlestickChart, Capture, CardAccentProvider, CardHeader, CategoryPalette, CategoryProvider, Center, ChatPanel, Checkbox, ClassificationBanner, ColorPickerPanel, CommandBuilder, Compact, ConfirmDialog, ConfirmProvider, ConjunctionAssessment3DChart, ConjunctionChart, ConnectionForm, ConstellationCoverageChart, ContactWindowChart, Container, CopyButton, DataTable, DataTableRowDetail, DataText, DataValue, DataValueGroup, Dialog, Display1, Display2, DisplaySettingsProvider, Divider, DonutChart, DopplerTrackChart, DualAxisChart, ESRI_WORLD_IMAGERY_ATTRIBUTION, EclipseTimelineChart, EclipseTimerCard, ErrorBoundary, FONT_FAMILY_MONO, FONT_FAMILY_PRIMARY, FONT_WEIGHTS, FileExplorer, Flex, GLASS_COLOR_OVERLAYS, GLASS_TINTS, GaugeChart, GlassCard, GlobalStatusBar, GraphChart, Grid, GroundTrackMap, H1, H2, H3, H4, H5, H6, HStack, HeaderIconWithStatus, HeatmapChart, HeliocentricOrbitPlot, HexViewer, HistogramChart, Icon, ImageFrame, ImageGallery, ImagePanel, Input, Label, LaunchCorridor3DChart, LayerControlPanel, LimitsBar, LineChart, Lines3DChart, LinkBudgetCard, LinkBudgetChart, LinkMarginChart, LogViewer, Logo, ManeuverBudgetChart, Menu, MessageStream, Micro, MiniSimulationControls, MissionCalendar, MissionClock, MonitoringIcon, Mono, NavBallCard, Notification, NumberInput, OFFICIAL_ASTRO_DATA_VIZ_COLORS, OSM_ATTRIBUTION, ObjectInventoryPanel, OrbitCard, OrbitChart, PLANETS, PRESET_COLORS, PROPERTY_PRESETS, PacketViewer, Pagination, ParallelChart, PieChart, PinInput, Popover, PowerChart, PowerOverviewChart, Progress, PropulsionCard, REGION_BORDER_COLORS, REGION_COLORS, RadarChart, RoseDiagram, SIDENAV_HEADER_LOGO_SLOT_HEIGHT_PX, SPACE_SYSTEM_COLORS, STATUS_COLORS, SankeyChart, Scatter3DChart, ScatterChart, Select, SensorFootprintCard, SideNav, SidePanel, SimulationControls, SimulationControlsWithClock, Skeleton3D, SkeletonBox, SkeletonCard, SkeletonChart, SkeletonCircle, SkeletonText, SpacecraftCard, Spacer, SpectrumChart, SphericalRadar3DChart, Stack, StackedAreaChart, StackedBarChart, StatusIndicator, SubsystemGauge, SunburstChart, Surface3DChart, TILE_PRESETS, Tabs, TelemetryCard, TelemetryStreamCard, ThemeProvider, ThermalHeatmapCard, ThermalHeatmapChart, TimeSeriesChart, UnifiedTimeline as Timeline, ToastProvider, Toggle, Tooltip, TransferOrbit3DChart, TreemapChart, Typography, VStack, WaterfallChart, ZENDIR_BRAND_COLORS, ZenSpace3D, addAlpha, auToKm, calculateAxisBounds, clamp, classNames, createAreaGradient, createAstroEChartsTheme, createChatResponseParser, createPropertyConfig, decodeImage, deriveBatteryStatus, deriveStatus, dispatchToGroup, ecefEulerXyzToHpr, ecefMetersToSdkPosition, estimateOrbitalPeriod, estimateOrbitalVelocity, exportGroupAsCSV, exportGroupAsImages, focusRingStyle, formatAltitude, formatCoordinate, formatCountdown, formatDataRate, formatDecibels, formatDegrees, formatDistance, formatDuration, formatFrequency, formatLatLon, formatNumber, formatPercentage, formatPower, formatPropertyLabel, formatPropertyValue, formatTabular, formatTemperature, formatTime, formatTimeLabel, formatUTC, formatValueWithUnit, formatVelocity, generateAttitudeData, generateConjunctionEvents, generateConstellationCoverage, generateContactWindows, generateDopplerData, generateEclipseTimeline, generateHeliocentricOrbits, generatePowerData, generateSamplePowerData, generateSpectrum, generateWaterfallData, getAccentColorOptions, getBasemapAttribution, getEffectiveCompactMode, getGroupCharts, getIconNames, getPaletteForDataType, getPlanet, getPropertiesByCategory, getPropertyConfig, getSeriesColor, getStatusColor, getStatusFromValue, getStatusSeverity, getSystemAccentColor, getWorstStatus, hideGroupTooltip, isStatusLevel, isValidIconName, isValidNumber, lerp, loadCapturePlaceholderImage, mapRange, normalizePlanetName, normalizeStatus, parseChatResponse, parseMcpToolResult, recommendedFlyDistance, resetGroupZoom, resolveResponsive, resolveSpacing, safeAccentText, safeNumber, showGroupTooltip, syncZoomRange, tabularNumsStyle, transitions, useBreakpoint, useCapture, useCardAccent, useCategoryPalette, useCategoryPaletteRequired, useChartStream, useChartSync, useCompactMode, useConfirm, useCopyToClipboard, useDisplaySettings, useDisplaySettingsOptional, useScrollbarStyles, useSimulationScene, useTheme, useThemeTokens, useToast, useToastManager, useWebSocketStream, withErrorBoundary, withNullSafety };
100
+ export { ASTRO_DATA_VIZ_COLORS, AccessCard, ActivityPlanner, AntennaPattern3DChart, AppBar, AreaChart, AstroChart, AttitudeChart, AttitudeHistory3DChart, BREAKPOINTS, Badge, Bar3DChart, BarChart, Body1, Body2, Body3, Box, BoxPlotChart, BubbleChart, Button, CANVAS_LABEL_TILES, CARD_ACCENT_COLORS, CARTO_ATTRIBUTION, CATEGORY_ICONS, CATEGORY_LABELS, CHAT_RESPONSE_JSON_PROMPT, CHAT_RESPONSE_MCP_TOOL, CHAT_RESPONSE_TOOL_SCHEMA, CHAT_RESPONSE_YAML_PROMPT, CHAT_STATUS_RULES_PROMPT, CandlestickChart, Capture, CardAccentProvider, CardHeader, CategoryPalette, CategoryProvider, Center, ChatPanel, Checkbox, ClassificationBanner, ColorPickerPanel, CommandBuilder, Compact, ConfirmDialog, ConfirmProvider, ConjunctionAssessment3DChart, ConjunctionChart, ConnectionForm, ConstellationCoverageChart, ContactWindowChart, Container, CopyButton, DataTable, DataTableRowDetail, DataText, DataValue, DataValueGroup, Dialog, Display1, Display2, DisplaySettingsProvider, Divider, DonutChart, DopplerTrackChart, DualAxisChart, ESRI_CANVAS_ATTRIBUTION, ESRI_WORLD_IMAGERY_ATTRIBUTION, EclipseTimelineChart, EclipseTimerCard, ErrorBoundary, FONT_FAMILY_MONO, FONT_FAMILY_PRIMARY, FONT_WEIGHTS, FileExplorer, Flex, GLASS_COLOR_OVERLAYS, GLASS_TINTS, GaugeChart, GlassCard, GlobalStatusBar, GraphChart, Grid, GroundTrackMap, H1, H2, H3, H4, H5, H6, HStack, HeaderIconWithStatus, HeatmapChart, HeliocentricOrbitPlot, HexViewer, HistogramChart, Icon, ImageFrame, ImageGallery, ImagePanel, Input, Label, LaunchCorridor3DChart, LayerControlPanel, LimitsBar, LineChart, Lines3DChart, LinkBudgetCard, LinkBudgetChart, LinkMarginChart, LogViewer, Logo, ManeuverBudgetChart, Menu, MessageStream, Micro, MiniSimulationControls, MissionCalendar, MissionClock, MonitoringIcon, Mono, NavBallCard, Notification, NumberInput, OFFICIAL_ASTRO_DATA_VIZ_COLORS, OSM_ATTRIBUTION, ObjectInventoryPanel, OrbitCard, OrbitChart, PLANETS, PRESET_COLORS, PROPERTY_PRESETS, PacketViewer, Pagination, ParallelChart, PieChart, PinInput, Popover, PowerChart, PowerOverviewChart, Progress, PropulsionCard, REGION_BORDER_COLORS, REGION_COLORS, RadarChart, RoseDiagram, SIDENAV_HEADER_LOGO_SLOT_HEIGHT_PX, SPACE_SYSTEM_COLORS, STATUS_COLORS, SankeyChart, Scatter3DChart, ScatterChart, Select, SensorFootprintCard, SideNav, SidePanel, SimulationControls, SimulationControlsWithClock, Skeleton3D, SkeletonBox, SkeletonCard, SkeletonChart, SkeletonCircle, SkeletonText, SpacecraftCard, Spacer, SpectrumChart, SphericalRadar3DChart, Stack, StackedAreaChart, StackedBarChart, StatusIndicator, SubsystemGauge, SunburstChart, Surface3DChart, TILE_PRESETS, Tabs, TelemetryCard, TelemetryStreamCard, ThemeProvider, ThermalHeatmapCard, ThermalHeatmapChart, TimeSeriesChart, UnifiedTimeline as Timeline, ToastProvider, Toggle, Tooltip, TransferOrbit3DChart, TreemapChart, Typography, VStack, WaterfallChart, ZENDIR_BRAND_COLORS, ZenSpace3D, addAlpha, auToKm, calculateAxisBounds, clamp, classNames, createAreaGradient, createAstroEChartsTheme, createChatResponseParser, createPropertyConfig, decodeImage, deriveBatteryStatus, deriveStatus, dispatchToGroup, ecefEulerXyzToHpr, ecefMetersToSdkPosition, estimateOrbitalPeriod, estimateOrbitalVelocity, exportGroupAsCSV, exportGroupAsImages, focusRingStyle, formatAltitude, formatCoordinate, formatCountdown, formatDataRate, formatDecibels, formatDegrees, formatDistance, formatDuration, formatFrequency, formatLatLon, formatNumber, formatPercentage, formatPower, formatPropertyLabel, formatPropertyValue, formatTabular, formatTemperature, formatTime, formatTimeLabel, formatUTC, formatValueWithUnit, formatVelocity, generateAttitudeData, generateConjunctionEvents, generateConstellationCoverage, generateContactWindows, generateDopplerData, generateEclipseTimeline, generateHeliocentricOrbits, generatePowerData, generateSamplePowerData, generateSpectrum, generateWaterfallData, getAccentColorOptions, getBasemapAttribution, getEffectiveCompactMode, getGroupCharts, getIconNames, getPaletteForDataType, getPlanet, getPropertiesByCategory, getPropertyConfig, getSeriesColor, getStatusColor, getStatusFromValue, getStatusSeverity, getSystemAccentColor, getWorstStatus, hideGroupTooltip, isStatusLevel, isValidIconName, isValidNumber, lerp, loadCapturePlaceholderImage, mapRange, normalizePlanetName, normalizeStatus, parseChatResponse, parseMcpToolResult, recommendedFlyDistance, resetGroupZoom, resolveResponsive, resolveSpacing, safeAccentText, safeNumber, showGroupTooltip, syncZoomRange, tabularNumsStyle, transitions, useBreakpoint, useCapture, useCardAccent, useCategoryPalette, useCategoryPaletteRequired, useChartStream, useChartSync, useCompactMode, useConfirm, useCopyToClipboard, useDisplaySettings, useDisplaySettingsOptional, useScrollbarStyles, useSimulationScene, useTheme, useThemeTokens, useToast, useToastManager, useWebSocketStream, withErrorBoundary, withNullSafety };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zendir/ui",
3
- "version": "0.7.0",
3
+ "version": "0.7.1",
4
4
  "description": "React UI components for space operations, built on the Astro UX Design System",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",