@hironytic/anatomist
v0.3.0
Published
A framework for building binary file inspector tools
Readme
Anatomist
A React framework for building binary file inspector tools.
[!WARNING] This library is in early development. The API may change heavily in future versions.
Installation
npm install @hironytic/anatomistRequires react and react-dom >= 19 as peer dependencies.
Setup
Import the default stylesheet once in your app entry point:
import '@hironytic/anatomist/style.css';Quick Start
Drop an <Anatomist> component into your app and supply an onLoad callback. When the user drops a file onto the UI, onLoad receives an Atlas handle that you use to drive the display.
import { Anatomist, SpanListView } from '@hironytic/anatomist';
import type { Atlas, SpanListViewItem } from '@hironytic/anatomist';
import '@hironytic/anatomist/style.css';
function parseFile(atlas: Atlas) {
const items: SpanListViewItem[] = [
{ id: 0, startOffset: 0, endOffset: 4, name: 'Magic bytes', value: '...' },
// ...
];
atlas.setFocusRegion({
range: { startOffset: 0, endOffset: atlas.data.length },
component: SpanListView,
props: { atlas, items },
title: 'File overview',
});
}
export function App() {
return (
<Anatomist
appName="My Inspector"
version="v1.0.0"
description="Drop a binary file to inspect it."
onLoad={parseFile}
/>
);
}How It Works
The framework provides the UI shell — a hex viewer, a right-side detail pane, and browser-style back/forward navigation. Parsing is your responsibility.
- The user drops a file onto the
<Anatomist>component. - Your
onLoadcallback is called with anAtlashandle and the file bytes. - You parse the bytes and call
atlas.setFocusRegion()to populate the hex highlight and the right pane. - Each
setFocusRegioncall appends a navigation history entry. The user can navigate back and forward through the history.
Components
For full prop types, refer to the TypeScript definitions bundled with the package.
| Component | Description |
|---|---|
| <Anatomist> | Root component. Handles file drop, layout, and navigation history. |
| <SpanList> | Field list with keyboard navigation and optional jump buttons. Accepts a focusOnMount boolean prop to automatically focus the list when it mounts. |
| <SpanListView> | SpanList wrapper that wires atlas.setActiveSpan on selection and atlas.setSecondaryRange on jump-button hover automatically. Accepts an atlas prop and SpanListViewItem[] items (which extend SpanListItem with an optional jumpTargetRange). |
| <FocusMessage> | Centered info/error message for the right pane. |
Keyboard Shortcuts
| Context | Key | Action |
|---|---|---|
| <Anatomist> | [ | Navigate history backward |
| <Anatomist> | ] | Navigate history forward |
| <SpanList> | ↑ / k | Move selection up |
| <SpanList> | ↓ / j | Move selection down |
| <SpanList> | Enter | Jump to the selected span's target range |
Atlas API
The Atlas object is passed to your onLoad callback when a file is dropped.
| Member | Description |
|---|---|
| atlas.data | Uint8Array of the dropped file bytes. |
| atlas.setFocusRegion(region) | Push a new focus region. Updates the HexView highlight and the right pane. Appends a navigation history entry. |
| atlas.setActiveSpan(start, end) | Highlight a sub-range within the current focus region in HexView. Offsets are relative to the focus region's startOffset. |
| atlas.setSecondaryRange(range) | Show a secondary range overlay in HexView alongside the primary range. Pass undefined to clear. |
| atlas.showAlert(message) | Show a modal alert dialog with message. Returns a Promise<void> that resolves when the user dismisses it. |
| atlas.showConfirm(message) | Show a modal confirm dialog with message. Returns a Promise<boolean> that resolves to true when the user clicks OK, or false when they click Cancel or press Escape. |
Theming
The default stylesheet adapts to prefers-color-scheme automatically.
To force a specific theme regardless of the OS setting, add a class to any ancestor element:
<div class="anatomist-theme-light">...</div>
<div class="anatomist-theme-dark">...</div>To customize colors, override CSS custom properties on :root:
:root {
/* Typography */
--anatomist-ui-font-family: system-ui, sans-serif;
--anatomist-monospace-font-family: ui-monospace, monospace;
/* HexView */
--anatomist-hex-view-bg: #0a1929;
--anatomist-hex-view-fg: #b8d4ed;
--anatomist-hex-view-header-bg: #0d2035;
--anatomist-hex-view-header-fg: #5c85a8;
--anatomist-hex-view-border-color: #1e3a52;
--anatomist-hex-view-offset-fg: #5ab4e2;
--anatomist-hex-view-active-bg: rgba(90, 180, 226, 0.40);
--anatomist-hex-range-primary-border-color: #5ab4e2;
--anatomist-hex-range-primary-bg: rgba(90, 180, 226, 0.13);
/* SpanList */
--anatomist-span-list-selected-bg: rgba(90, 180, 226, 0.13);
--anatomist-span-list-selected-border: #5ab4e2;
/* App shell */
--anatomist-app-bg: #0a1929;
--anatomist-app-toolbar-bg: #0d2035;
--anatomist-app-toolbar-border-color: #1e3a52;
/* AlertDialog */
--anatomist-dialog-bg: #0d2035;
--anatomist-dialog-accent-color: #5ab4e2;
--anatomist-dialog-border-color: #1e3a52;
--anatomist-dialog-btn-primary-bg: #5ab4e2;
--anatomist-dialog-btn-primary-fg: #0a1929;
}All available variables are documented in src/styles/default.css.
