vuehex 0.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.txt +23 -0
- package/README.md +397 -0
- package/dist/index.js +1419 -0
- package/dist/screenshot001.png +0 -0
- package/dist/screenshot002.png +0 -0
- package/dist/styles.css +1 -0
- package/dist/styles.js +0 -0
- package/package.json +80 -0
package/LICENSE.txt
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) Vincent Vollers
|
|
4
|
+
|
|
5
|
+
All rights reserved.
|
|
6
|
+
|
|
7
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
9
|
+
in the Software without restriction, including without limitation the rights
|
|
10
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
11
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
12
|
+
furnished to do so, subject to the following conditions:
|
|
13
|
+
|
|
14
|
+
The above copyright notice and this permission notice shall be included in all
|
|
15
|
+
copies or substantial portions of the Software.
|
|
16
|
+
|
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
19
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
20
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
21
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
22
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
23
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,397 @@
|
|
|
1
|
+
# VueHex
|
|
2
|
+
|
|
3
|
+
VueHex is a fast, virtualized hex viewer component for Vue 3. It can be used both for cleanly displaying binary data and for efficiently viewing very large datasets.
|
|
4
|
+
|
|
5
|
+
* No dependencies
|
|
6
|
+
* Small package (~64KB minimized / ~15KB zipped)
|
|
7
|
+
* Render local and remote data
|
|
8
|
+
* Can handle extremely large data sizes
|
|
9
|
+
* Very flexible and themeable, can be as simple or as complicated as you wish
|
|
10
|
+
|
|
11
|
+

|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install vuehex
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Optionally register the plugin once to make the `<VueHex>` component available everywhere and load the bundled styles:
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
import { createApp } from "vue";
|
|
23
|
+
import VueHex from "vuehex";
|
|
24
|
+
import "vuehex/styles";
|
|
25
|
+
|
|
26
|
+
import App from "./App.vue";
|
|
27
|
+
|
|
28
|
+
const app = createApp(App);
|
|
29
|
+
app.use(VueHex);
|
|
30
|
+
app.mount("#app");
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Quick start
|
|
34
|
+
|
|
35
|
+
It can be as simple as this
|
|
36
|
+
|
|
37
|
+
```vue
|
|
38
|
+
<template>
|
|
39
|
+
<VueHex
|
|
40
|
+
v-model="windowData"
|
|
41
|
+
/>
|
|
42
|
+
</template>
|
|
43
|
+
|
|
44
|
+
<script setup lang="ts">
|
|
45
|
+
import { ref } from "vue";
|
|
46
|
+
|
|
47
|
+
const backingFile = crypto.getRandomValues(new Uint8Array(2 ** 20));
|
|
48
|
+
const windowData = ref(backingFile.slice(0, 16 * 48));
|
|
49
|
+
</script>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Props
|
|
53
|
+
|
|
54
|
+
| Prop | Default | Description |
|
|
55
|
+
|------|---------|-------------|
|
|
56
|
+
| `dataMode` / `data-mode` | `auto` | Data handling mode: `auto`, `buffer`, or `window`. |
|
|
57
|
+
| `expandToContent` / `expand-to-content` | `false` | Disables internal scrolling/virtualization and expands the component height to fit the full buffer (expects the full data in `v-model`). |
|
|
58
|
+
| `totalSize` | `modelValue.length` | Total bytes available. |
|
|
59
|
+
| `bytesPerRow` | `16` | Number of bytes to display per row. |
|
|
60
|
+
| `uppercase` | `false` | Whether to display hex values in uppercase. |
|
|
61
|
+
| `nonPrintableChar` | `'.'` | Character to display for non-printable bytes in ASCII column. |
|
|
62
|
+
| `isPrintable` / `renderAscii` | — | Functions to customize ASCII rendering. |
|
|
63
|
+
| `theme` | — | Color theme: `'dark'`, `'light'`, `'terminal'`, `'sunset'`, or `'auto'`. Omit to follow `prefers-color-scheme` between dark and light. |
|
|
64
|
+
| `cellClassForByte` | — | Function `(payload: { kind: 'hex' \| 'ascii'; index: number; byte: number }) => string \| string[] \| void` for custom highlighting. |
|
|
65
|
+
| `getSelectionData` | — | Function `(selectionStart: number, selectionEnd: number) => Uint8Array` used for clipboard copy (required when using virtual windows; auto-implemented in full-data mode). |
|
|
66
|
+
| `overscan` | `2` | Number of extra rows to render above and below the viewport. |
|
|
67
|
+
| `showChunkNavigator` + `chunkNavigatorPlacement` | — | Enable and configure the optional chunk navigator UI. |
|
|
68
|
+
| `statusbar` | `null` | Status bar placement: `'top'`, `'bottom'`, or `null` to hide. Shows byte info on hover and selection details. |
|
|
69
|
+
| `statusbarLayout` | — | Configuration object controlling which items appear in the status bar and their placement (`left`, `middle`, `right` sections). |
|
|
70
|
+
| `cursor` | `false` | Enable keyboard/click cursor navigation. Navigate with arrow keys when focused or click bytes to move cursor. |
|
|
71
|
+
|
|
72
|
+
## Models
|
|
73
|
+
|
|
74
|
+
VueHex uses Vue 3's `defineModel` for two-way data binding. These support `v-model` syntax:
|
|
75
|
+
|
|
76
|
+
| Model | Type | Default | Description |
|
|
77
|
+
|-------|------|---------|-------------|
|
|
78
|
+
| `v-model` (modelValue) | `Uint8Array` | `new Uint8Array(0)` | The currently visible data buffer. In buffer mode, this is the entire dataset; in window mode, this is the current slice. |
|
|
79
|
+
| `v-model:windowOffset` | `number` | `0` | Absolute byte offset of the current window. Automatically updates when scrolling, and scrolls the viewer when changed externally. Use for two-way sync of scroll position. |
|
|
80
|
+
| `v-model:cursorLocation` | `number \| null` | `null` | Current cursor position (absolute byte index). Only active when `cursor` prop is `true`. Automatically updates when navigating with keyboard/mouse. |
|
|
81
|
+
|
|
82
|
+
## Events
|
|
83
|
+
|
|
84
|
+
VueHex emits several events to enable interactive features:
|
|
85
|
+
|
|
86
|
+
| Event | Payload | Description |
|
|
87
|
+
|-------|---------|-------------|
|
|
88
|
+
| `updateVirtualData` | `{ offset: number, length: number }` | Emitted when the component needs more data in windowed mode. Load the requested byte range and update `v-model` with the new data. |
|
|
89
|
+
| `byte-click` | `{ index: number, byte: number, kind: 'hex' \| 'ascii' }` | Emitted when a user clicks on a specific byte cell. `index` is the absolute byte position, `byte` is the value (0-255), and `kind` indicates whether the hex or ASCII column was clicked. |
|
|
90
|
+
| `selection-change` | `{ start: number \| null, end: number \| null, length: number }` | Emitted when the selection range changes. `start` and `end` are absolute byte positions (inclusive), or `null` if nothing is selected. `length` is the number of selected bytes. |
|
|
91
|
+
| `row-hover-on` / `row-hover-off` | `{ offset: number }` | Emitted when hovering over/leaving a row. |
|
|
92
|
+
| `hex-hover-on` / `hex-hover-off` | `{ index: number, byte: number }` | Emitted when hovering over/leaving a hex cell. |
|
|
93
|
+
| `ascii-hover-on` / `ascii-hover-off` | `{ index: number, byte: number }` | Emitted when hovering over/leaving an ASCII cell. |
|
|
94
|
+
|
|
95
|
+
## Styling options
|
|
96
|
+
|
|
97
|
+
1. Import `vuehex/styles` for the default look.
|
|
98
|
+
2. Pass `theme="dark" | "light" | "terminal" | "sunset" | "auto"` to toggle bundled palettes explicitly (or skip the prop entirely to stick with OS detection).
|
|
99
|
+
3. Roll your own styles targeting the emitted class names (`.vuehex`, `.vuehex-byte`, `.vuehex-ascii-char`, etc.). The default sheet sets `.vuehex { height: 100%; }`, so remember to give the wrapper a concrete height.
|
|
100
|
+
|
|
101
|
+
## How VueHex handles large datasets
|
|
102
|
+
|
|
103
|
+
### Technique 1/3 : Virtual Scrolling
|
|
104
|
+
|
|
105
|
+
Instead of rendering **all** rows in the DOM, which works fine for small files but quickly becomes unusable for large datasets. A 1 MB file with 16 bytes per row produces over 65,000 DOM nodes. A 100 MB file? 6.5 million nodes. Browsers slow to a crawl when manipulating or even keeping these trees in memory.
|
|
106
|
+
|
|
107
|
+
VueHex solves this with optimized **virtual scrolling**:
|
|
108
|
+
|
|
109
|
+
1. **Calculate the full height** – VueHex computes how tall the entire table *would* be if every row were rendered (e.g., 65,000 rows × 24px = 1,560,000px).
|
|
110
|
+
2. **Create a container of that height** – The scroll container's inner wrapper is sized to the full calculated height, so the scrollbar represents the entire dataset.
|
|
111
|
+
3. **Render only visible rows** – As you scroll, VueHex calculates which rows are currently in the viewport (plus a small overscan buffer above/below) and renders **only** those rows.
|
|
112
|
+
4. **Translate the table** – The rendered slice is positioned at the correct scroll offset using CSS `transform: translateY()` so it appears in the right place as you scroll.
|
|
113
|
+
|
|
114
|
+
**Result:** Instead of 65,000 DOM nodes for a 1 MB file, VueHex renders ~50 rows (what fits on your screen + overscan). Scrolling through a 100 MB file feels instant because the browser only ever manages a tiny fraction of the data.
|
|
115
|
+
|
|
116
|
+
### Technique 2/3 : Chunking
|
|
117
|
+
|
|
118
|
+
The above technique works very well, but unfortunately it has a limit. Browsers impose limits on element dimensions to prevent rendering engine crashes. Most modern browsers cap `max-height` at around **33,554,432 pixels** (Chrome/Edge) or **17,895,698 pixels** (Firefox). Once your calculated scroll container height exceeds this limit, virtualization breaks—the scrollbar becomes inaccurate, and you can't reach data beyond the cap.
|
|
119
|
+
|
|
120
|
+
For a hex viewer with 16 bytes per row and 24px row height:
|
|
121
|
+
- **Firefox limit:** ~746,000 rows = ~11.4 MB of data
|
|
122
|
+
- **Chrome limit:** ~1.4 million rows = ~21.4 MB of data
|
|
123
|
+
|
|
124
|
+
Files larger than these thresholds need **chunking**:
|
|
125
|
+
|
|
126
|
+
1. **Divide the dataset into chunks** – VueHex splits the file into manageable pieces (e.g., 20,000 rows per chunk).
|
|
127
|
+
2. **Render one chunk at a time** – The scroll container only represents the *current chunk*, keeping its height safely below browser limits.
|
|
128
|
+
3. **Provide chunk navigation** – Users click through chunks via the optional chunk navigator UI, and VueHex resets the scroll position and loads the next slice of data.
|
|
129
|
+
|
|
130
|
+
**Why this matters:**
|
|
131
|
+
- Without chunking, a 100 MB file would require a scroll container **416 million pixels tall**—far beyond any browser's rendering capabilities.
|
|
132
|
+
- With chunking (e.g., 10,000 rows per chunk = 240,000px per chunk), the same file becomes 6,400 navigable chunks, each comfortably under browser limits.
|
|
133
|
+
|
|
134
|
+
**When chunking activates:**
|
|
135
|
+
- VueHex automatically enables chunking when the calculated container height would exceed 8,000,000 pixels (a safe default below browser caps).
|
|
136
|
+
- You can disable chunking by setting `expand-to-content` (which removes virtualization entirely)
|
|
137
|
+
|
|
138
|
+
### Technique 3/3 : Virtual Data
|
|
139
|
+
|
|
140
|
+
Even with virtualization and chunking, loading a 40 GB file entirely into memory isn't practical. VueHex supports **windowed data mode**, where:
|
|
141
|
+
|
|
142
|
+
1. Your application keeps the full file in a storage backend.
|
|
143
|
+
2. You provide VueHex with only the **currently needed slice** via `v-model` (e.g., 100 KB around the visible rows).
|
|
144
|
+
3. When VueHex needs different bytes (because the user scrolled or jumped to a new chunk), it emits `updateVirtualData` with `{ offset, length }`.
|
|
145
|
+
4. Your application fetches the requested slice and updates `v-model` asynchronously.
|
|
146
|
+
|
|
147
|
+
**Result:** VueHex can display terabyte-scale files while keeping browser memory usage under a few megabytes.
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## Data modes
|
|
152
|
+
|
|
153
|
+
### Virtual data mode
|
|
154
|
+
|
|
155
|
+
When VueHex needs different bytes it emits `updateVirtualData` with `{ offset, length }`. The component keeps rendering whatever you provide through `v-model` until you feed it a new slice. That means you can back the viewer with disk I/O, HTTP range requests, IndexedDB, or any other storage you control.
|
|
156
|
+
|
|
157
|
+
You can use `v-model:window-offset` for two-way binding of the current offset. This automatically:
|
|
158
|
+
- Updates the parent when the user scrolls to new data
|
|
159
|
+
- Scrolls the viewer when you change the offset programmatically
|
|
160
|
+
|
|
161
|
+
```vue
|
|
162
|
+
<template>
|
|
163
|
+
<VueHex
|
|
164
|
+
v-model="windowData"
|
|
165
|
+
v-model:window-offset="windowOffset"
|
|
166
|
+
:total-size="fileSize"
|
|
167
|
+
data-mode="window"
|
|
168
|
+
@updateVirtualData="loadWindow"
|
|
169
|
+
/>
|
|
170
|
+
</template>
|
|
171
|
+
|
|
172
|
+
<script setup>
|
|
173
|
+
const windowData = ref(new Uint8Array());
|
|
174
|
+
const windowOffset = ref(0);
|
|
175
|
+
|
|
176
|
+
async function loadWindow({ offset, length }) {
|
|
177
|
+
const data = await fetchBytesFromSource(offset, length);
|
|
178
|
+
windowData.value = data;
|
|
179
|
+
// windowOffset will be automatically updated by the component
|
|
180
|
+
}
|
|
181
|
+
</script>
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Alternatively, manually sync the offset when handling `updateVirtualData`:
|
|
185
|
+
|
|
186
|
+
```vue
|
|
187
|
+
<template>
|
|
188
|
+
<VueHex
|
|
189
|
+
v-model="windowData"
|
|
190
|
+
:window-offset="windowOffset"
|
|
191
|
+
:total-size="fileSize"
|
|
192
|
+
@updateVirtualData="loadWindow"
|
|
193
|
+
/>
|
|
194
|
+
</template>
|
|
195
|
+
|
|
196
|
+
<script setup>
|
|
197
|
+
async function loadWindow({ offset, length }) {
|
|
198
|
+
windowOffset.value = offset; // Manual sync
|
|
199
|
+
windowData.value = await fetchBytesFromSource(offset, length);
|
|
200
|
+
}
|
|
201
|
+
</script>
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Full data mode
|
|
205
|
+
|
|
206
|
+
If you already have the entire `Uint8Array`, you can skip the virtual data handshake entirely. Set `data-mode="buffer"` (or omit it entirely) and point `v-model` at the whole buffer.
|
|
207
|
+
|
|
208
|
+
```vue
|
|
209
|
+
<VueHex v-model="entireFile" />
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
For large datasets you'll probably still want to use the virtual data mode.
|
|
213
|
+
|
|
214
|
+
### Expand-to-content mode
|
|
215
|
+
|
|
216
|
+
If you don't want VueHex to create its own scroll container, enable `expand-to-content`. In this mode the component grows to fit the rendered rows, so scrolling happens in the parent/page instead.
|
|
217
|
+
|
|
218
|
+
- No internal scrolling
|
|
219
|
+
- No virtualization / window requests
|
|
220
|
+
- `v-model` must contain the full `Uint8Array`
|
|
221
|
+
|
|
222
|
+
```vue
|
|
223
|
+
<VueHex v-model="entireFile" expand-to-content :bytes-per-row="16" />
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
This is useful for docs pages or print-style layouts, but avoid it for very large buffers.
|
|
227
|
+
|
|
228
|
+
### Asynchronous providers
|
|
229
|
+
|
|
230
|
+
Responding to `updateVirtualData` can be asynchronous—just update `windowOffset` and `windowData` when the bytes arrive:
|
|
231
|
+
|
|
232
|
+
```ts
|
|
233
|
+
async function handleUpdateVirtualData(request: VueHexWindowRequest) {
|
|
234
|
+
const response = await fetch(
|
|
235
|
+
`/api/blob?offset=${request.offset}&length=${request.length}`,
|
|
236
|
+
);
|
|
237
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
238
|
+
windowOffset.value = request.offset;
|
|
239
|
+
windowData.value = new Uint8Array(arrayBuffer);
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
## Storybook workspace
|
|
244
|
+
|
|
245
|
+
Run Storybook to explore prebuilt demos:
|
|
246
|
+
|
|
247
|
+
```bash
|
|
248
|
+
npm run storybook
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
The static build lives in `storybook-static/` when you run `npm run storybook:build`.
|
|
252
|
+
|
|
253
|
+
## Viewport sizing
|
|
254
|
+
|
|
255
|
+
VueHex virtualizes DOM rows, so make sure the component has a bounded height. Set `height`, `max-height`, or place it inside a flex/grid cell with a defined size. Without a viewport the table expands indefinitely and virtualization is effectively disabled.
|
|
256
|
+
|
|
257
|
+
## Imperative scrolling
|
|
258
|
+
|
|
259
|
+
Call `scrollToByte` through a template ref to jump to absolute offsets:
|
|
260
|
+
|
|
261
|
+
```vue
|
|
262
|
+
<VueHex ref="viewer" v-model="windowData" ... />
|
|
263
|
+
|
|
264
|
+
const viewer = ref<InstanceType<typeof VueHex> | null>(null);
|
|
265
|
+
viewer.value?.scrollToByte(0x1f400);
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
## Hover events
|
|
269
|
+
|
|
270
|
+
VueHex emits enter/leave events for rows, hex cells, and ASCII cells so you can power tooltips or side panels:
|
|
271
|
+
|
|
272
|
+
- `row-hover-on` / `row-hover-off` – `{ offset }`
|
|
273
|
+
- `hex-hover-on` / `hex-hover-off` – `{ index, byte }`
|
|
274
|
+
- `ascii-hover-on` / `ascii-hover-off` – `{ index, byte }`
|
|
275
|
+
|
|
276
|
+
```vue
|
|
277
|
+
<VueHex
|
|
278
|
+
v-model="windowData"
|
|
279
|
+
v-model:window-offset="windowOffset"
|
|
280
|
+
@hex-hover-on="handleHexEnter"
|
|
281
|
+
@hex-hover-off="handleHexLeave"
|
|
282
|
+
/>
|
|
283
|
+
|
|
284
|
+
function handleHexEnter(payload: { index: number; byte: number }) {
|
|
285
|
+
tooltip.open({ byteOffset: payload.index, value: payload.byte });
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
function handleHexLeave() {
|
|
289
|
+
tooltip.close();
|
|
290
|
+
}
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
## ASCII rendering overrides
|
|
294
|
+
|
|
295
|
+
The ASCII pane renders characters in the standard printable range (`0x20`–`0x7E`) by default. Override the behaviour with `is-printable` and `render-ascii` props:
|
|
296
|
+
|
|
297
|
+
```vue
|
|
298
|
+
<VueHex
|
|
299
|
+
v-model="windowData"
|
|
300
|
+
:is-printable="(byte) => byte >= 0x30 && byte <= 0x39"
|
|
301
|
+
:render-ascii="(byte) => `${String.fromCharCode(byte)}`"
|
|
302
|
+
/>
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
VueHex also exports `VUE_HEX_ASCII_PRESETS` (`standard`, `latin1`, `visibleWhitespace`) if you want a drop-in configuration.
|
|
306
|
+
|
|
307
|
+
## Chunk Navigator Customization
|
|
308
|
+
|
|
309
|
+
When using the chunk navigator (`show-chunk-navigator` prop), you can customize how the navigator header and chunk items are rendered using slots:
|
|
310
|
+
|
|
311
|
+
### chunk-navigator-header
|
|
312
|
+
|
|
313
|
+
Customize the chunk navigator header with access to the chunks list and active index:
|
|
314
|
+
|
|
315
|
+
```vue
|
|
316
|
+
<VueHex
|
|
317
|
+
v-model="windowData"
|
|
318
|
+
show-chunk-navigator
|
|
319
|
+
chunk-navigator-placement="right"
|
|
320
|
+
>
|
|
321
|
+
<template #chunk-navigator-header="{ chunks, activeIndex }">
|
|
322
|
+
<div class="custom-header">
|
|
323
|
+
<h3>File Chunks</h3>
|
|
324
|
+
<p>{{ chunks.length }} total | Active: {{ activeIndex + 1 }}</p>
|
|
325
|
+
</div>
|
|
326
|
+
</template>
|
|
327
|
+
</VueHex>
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
**Slot props:**
|
|
331
|
+
- `chunks`: Array of all chunk descriptors
|
|
332
|
+
- `activeIndex`: Index of the currently active chunk
|
|
333
|
+
|
|
334
|
+
### chunk-navigator-item
|
|
335
|
+
|
|
336
|
+
Customize individual chunk items with access to chunk data and active state:
|
|
337
|
+
|
|
338
|
+
```vue
|
|
339
|
+
<VueHex
|
|
340
|
+
v-model="windowData"
|
|
341
|
+
show-chunk-navigator
|
|
342
|
+
chunk-navigator-placement="right"
|
|
343
|
+
>
|
|
344
|
+
<template #chunk-navigator-item="{ chunk, active, select }">
|
|
345
|
+
<div :class="{ 'my-chunk': true, 'active': active }">
|
|
346
|
+
<strong>{{ chunk.label }}</strong>
|
|
347
|
+
<span>{{ chunk.range }}</span>
|
|
348
|
+
<button @click="select">Jump</button>
|
|
349
|
+
</div>
|
|
350
|
+
</template>
|
|
351
|
+
</VueHex>
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
**Slot props:**
|
|
355
|
+
- `chunk`: Object with `{ index: number, label: string, range: string }`
|
|
356
|
+
- `active`: Boolean indicating if this is the currently active chunk
|
|
357
|
+
- `select`: Function to programmatically select this chunk
|
|
358
|
+
|
|
359
|
+
Both slots are optional. If not provided, VueHex uses the default chunk navigator appearance.
|
|
360
|
+
|
|
361
|
+
## Status Bar Slots
|
|
362
|
+
|
|
363
|
+
When using the status bar (`statusbar="top"` or `statusbar="bottom"`), you can provide custom content via slots. Use the `statusbarLayout` prop with the `"slot"` component name to control where your custom content appears.
|
|
364
|
+
|
|
365
|
+
### Available slots
|
|
366
|
+
|
|
367
|
+
- `#statusbar-left` - Content for the left section
|
|
368
|
+
- `#statusbar-middle` - Content for the middle section
|
|
369
|
+
- `#statusbar-right` - Content for the right section
|
|
370
|
+
|
|
371
|
+
### Example
|
|
372
|
+
|
|
373
|
+
```vue
|
|
374
|
+
<VueHex
|
|
375
|
+
v-model="data"
|
|
376
|
+
statusbar="bottom"
|
|
377
|
+
:statusbar-layout="{
|
|
378
|
+
left: ['offset', 'slot', 'hex'],
|
|
379
|
+
middle: ['ascii'],
|
|
380
|
+
right: ['selection', 'slot']
|
|
381
|
+
}"
|
|
382
|
+
>
|
|
383
|
+
<template #statusbar-left>
|
|
384
|
+
<span>Mode: RO</span>
|
|
385
|
+
</template>
|
|
386
|
+
|
|
387
|
+
<template #statusbar-right>
|
|
388
|
+
<span>Endian: LE</span>
|
|
389
|
+
</template>
|
|
390
|
+
</VueHex>
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
The `"slot"` entry in `statusbarLayout` determines where your custom content renders relative to built-in status bar items. You can place it at any position within each section array.
|
|
394
|
+
|
|
395
|
+
## License
|
|
396
|
+
|
|
397
|
+
MIT © Vincent Vollers
|