vuehex 0.5.7 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +157 -12
- package/dist/index.js +1333 -485
- package/dist/styles.css +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# VueHex
|
|
2
2
|
|
|
3
|
-
VueHex is a fast, virtualized hex viewer component for Vue 3. It can be used both for cleanly
|
|
3
|
+
VueHex is a fast, virtualized hex viewer/editor component for Vue 3. It can be used both for cleanly viewing and editing binary data and for efficiently handling very large datasets.
|
|
4
4
|
|
|
5
5
|
* No dependencies
|
|
6
6
|
* Small package (~64KB minimized / ~15KB zipped)
|
|
@@ -68,6 +68,7 @@ const windowData = ref(backingFile.slice(0, 16 * 48));
|
|
|
68
68
|
| `statusbar` | `null` | Status bar placement: `'top'`, `'bottom'`, or `null` to hide. Shows byte info on hover and selection details. |
|
|
69
69
|
| `statusbarLayout` | — | Configuration object controlling which items appear in the status bar and their placement (`left`, `middle`, `right` sections). |
|
|
70
70
|
| `cursor` | `false` | Enable keyboard/click cursor navigation. Navigate with arrow keys when focused or click bytes to move cursor. |
|
|
71
|
+
| `editable` | `false` | Enable editor mode. Typing/paste/cut emit `edit` intents. Cursor is automatically enabled while editing. |
|
|
71
72
|
|
|
72
73
|
## Models
|
|
73
74
|
|
|
@@ -86,12 +87,101 @@ VueHex emits several events to enable interactive features:
|
|
|
86
87
|
| Event | Payload | Description |
|
|
87
88
|
|-------|---------|-------------|
|
|
88
89
|
| `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. |
|
|
90
|
+
| `edit` | `VueHexEditIntent` | Emitted when `editable` is enabled and the user types, deletes, pastes, or cuts. In windowed mode, the parent should apply the intent to the backing store and refresh `v-model`. |
|
|
89
91
|
| `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
92
|
| `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
93
|
| `row-hover-on` / `row-hover-off` | `{ offset: number }` | Emitted when hovering over/leaving a row. |
|
|
92
94
|
| `hex-hover-on` / `hex-hover-off` | `{ index: number, byte: number }` | Emitted when hovering over/leaving a hex cell. |
|
|
93
95
|
| `ascii-hover-on` / `ascii-hover-off` | `{ index: number, byte: number }` | Emitted when hovering over/leaving an ASCII cell. |
|
|
94
96
|
|
|
97
|
+
## Editable mode
|
|
98
|
+
|
|
99
|
+
Set `editable` to turn VueHex into a hex editor. VueHex emits a single `edit` event describing user intent.
|
|
100
|
+
|
|
101
|
+
Editing highlights:
|
|
102
|
+
|
|
103
|
+
- Click hex vs ASCII to choose the active column (or press `Tab` to toggle).
|
|
104
|
+
- Press `Insert` to toggle insert/overwrite mode.
|
|
105
|
+
- Hex typing commits after two nibbles.
|
|
106
|
+
- Selection integrates with editing: typing/paste replaces the selection; `Delete`/`Backspace` delete the selection.
|
|
107
|
+
- Clipboard shortcuts:
|
|
108
|
+
- `Ctrl/Cmd+C` copy selection
|
|
109
|
+
- `Ctrl/Cmd+V` paste (hex column treats clipboard as hex bytes; whitespace is ignored)
|
|
110
|
+
- `Ctrl/Cmd+X` cut (copy + delete selection)
|
|
111
|
+
- Undo/redo shortcuts:
|
|
112
|
+
- `Ctrl/Cmd+Z` undo
|
|
113
|
+
- `Ctrl/Cmd+Y` redo (also `Ctrl/Cmd+Shift+Z`)
|
|
114
|
+
|
|
115
|
+
### Buffer mode (self-managed)
|
|
116
|
+
|
|
117
|
+
In `data-mode="buffer"`, VueHex will apply edits to `v-model` automatically. Listening to `@edit` is optional.
|
|
118
|
+
|
|
119
|
+
Undo/redo is built-in in this mode and is implemented as a compact history of edit diffs (not full buffer snapshots).
|
|
120
|
+
|
|
121
|
+
```vue
|
|
122
|
+
<template>
|
|
123
|
+
<VueHex v-model="bytes" data-mode="buffer" editable style="height: 320px" />
|
|
124
|
+
</template>
|
|
125
|
+
|
|
126
|
+
<script setup lang="ts">
|
|
127
|
+
import { ref } from "vue";
|
|
128
|
+
import VueHex from "vuehex";
|
|
129
|
+
|
|
130
|
+
const bytes = ref(new Uint8Array(await file.arrayBuffer()));
|
|
131
|
+
</script>
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Window mode (parent-managed)
|
|
135
|
+
|
|
136
|
+
In `data-mode="window"`, VueHex does not own the full dataset. The parent is responsible for applying `edit` intents to the backing store and then refreshing `windowData`.
|
|
137
|
+
|
|
138
|
+
For undo/redo in windowed mode, VueHex emits `{ kind: "undo" }` / `{ kind: "redo" }` intents on the `edit` event and the parent should implement history.
|
|
139
|
+
|
|
140
|
+
```vue
|
|
141
|
+
<template>
|
|
142
|
+
<VueHex
|
|
143
|
+
v-model="windowData"
|
|
144
|
+
data-mode="window"
|
|
145
|
+
:window-offset="windowOffset"
|
|
146
|
+
:total-size="store.length"
|
|
147
|
+
:get-selection-data="getSelectionData"
|
|
148
|
+
editable
|
|
149
|
+
style="height: 320px"
|
|
150
|
+
@updateVirtualData="handleUpdateVirtualData"
|
|
151
|
+
@edit="handleEdit"
|
|
152
|
+
/>
|
|
153
|
+
</template>
|
|
154
|
+
|
|
155
|
+
<script setup lang="ts">
|
|
156
|
+
import { ref } from "vue";
|
|
157
|
+
import VueHex, { type VueHexEditIntent, type VueHexWindowRequest } from "vuehex";
|
|
158
|
+
|
|
159
|
+
const store = ref(new Uint8Array(await file.arrayBuffer()));
|
|
160
|
+
const windowOffset = ref(0);
|
|
161
|
+
const windowData = ref(new Uint8Array());
|
|
162
|
+
let windowLength = 0x4000;
|
|
163
|
+
|
|
164
|
+
function handleUpdateVirtualData(request: VueHexWindowRequest) {
|
|
165
|
+
windowOffset.value = request.offset;
|
|
166
|
+
windowLength = request.length ?? windowLength;
|
|
167
|
+
windowData.value = store.value.slice(windowOffset.value, windowOffset.value + windowLength);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function getSelectionData(start: number, end: number) {
|
|
171
|
+
const from = Math.min(start, end);
|
|
172
|
+
const to = Math.max(start, end);
|
|
173
|
+
return store.value.slice(from, to + 1);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function handleEdit(intent: VueHexEditIntent) {
|
|
177
|
+
// Apply the intent to your backing store, then refresh windowData.
|
|
178
|
+
// (See Storybook "Editable (windowed)" / docs guide for a complete apply function.)
|
|
179
|
+
store.value = applyEditIntent(store.value, intent);
|
|
180
|
+
windowData.value = store.value.slice(windowOffset.value, windowOffset.value + windowLength);
|
|
181
|
+
}
|
|
182
|
+
</script>
|
|
183
|
+
```
|
|
184
|
+
|
|
95
185
|
## Styling options
|
|
96
186
|
|
|
97
187
|
1. Import `vuehex/styles` for the default look.
|
|
@@ -117,7 +207,7 @@ VueHex solves this with optimized **virtual scrolling**:
|
|
|
117
207
|
|
|
118
208
|
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
209
|
|
|
120
|
-
For a hex viewer with 16 bytes per row and 24px row height:
|
|
210
|
+
For a hex viewer/editor with 16 bytes per row and 24px row height:
|
|
121
211
|
- **Firefox limit:** ~746,000 rows = ~11.4 MB of data
|
|
122
212
|
- **Chrome limit:** ~1.4 million rows = ~21.4 MB of data
|
|
123
213
|
|
|
@@ -358,17 +448,72 @@ Customize individual chunk items with access to chunk data and active state:
|
|
|
358
448
|
|
|
359
449
|
Both slots are optional. If not provided, VueHex uses the default chunk navigator appearance.
|
|
360
450
|
|
|
361
|
-
## Status
|
|
451
|
+
## Status bar
|
|
452
|
+
|
|
453
|
+
Enable the status bar by setting `statusbar="top"` or `statusbar="bottom"`. You can control which items appear (and where) using `statusbarLayout`.
|
|
454
|
+
|
|
455
|
+
### Layout
|
|
456
|
+
|
|
457
|
+
`statusbarLayout` splits the status bar into three sections:
|
|
458
|
+
|
|
459
|
+
- `left` (left-aligned)
|
|
460
|
+
- `middle` (centered)
|
|
461
|
+
- `right` (right-aligned)
|
|
362
462
|
|
|
363
|
-
|
|
463
|
+
Each section is an array of **status bar components** (strings or `{ name, config }` objects). Unknown component names are ignored.
|
|
364
464
|
|
|
365
|
-
|
|
465
|
+
When `statusbarLayout` is omitted, VueHex defaults to:
|
|
366
466
|
|
|
367
|
-
-
|
|
368
|
-
-
|
|
369
|
-
- `#statusbar-right` - Content for the right section
|
|
467
|
+
- `left: ["offset", "hex", "ascii"]`
|
|
468
|
+
- `right: ["selection"]`
|
|
370
469
|
|
|
371
|
-
###
|
|
470
|
+
### Built-in components
|
|
471
|
+
|
|
472
|
+
- `offset`: hovered byte offset (respects `uppercase` + `isPrintable`/`renderAscii` where relevant)
|
|
473
|
+
- `hex`: hovered byte value as a 2-digit hex string
|
|
474
|
+
- `ascii`: hovered byte rendered as ASCII (or `nonPrintableChar`)
|
|
475
|
+
- `selection`: selection summary (`"<count> bytes (start–end)"`)
|
|
476
|
+
- `editable`: editor state label (`VIEW` / `EDIT`)
|
|
477
|
+
- `mode`: editor mode (`INS` / `OVR`) or placeholder when not available
|
|
478
|
+
- `column`: active editor column (`HEX` / `ASCII`) or placeholder when not available
|
|
479
|
+
- `total`: total size in bytes (derived from `totalSize` when provided; otherwise `v-model.length`). Does not include the EOF "ghost" cell.
|
|
480
|
+
- `slot`: renders one of the status bar slots (see below)
|
|
481
|
+
|
|
482
|
+
Notes:
|
|
483
|
+
|
|
484
|
+
- The hover-driven items (`offset`, `hex`, `ascii`) reflect the cell under the mouse, not the keyboard cursor.
|
|
485
|
+
- Editor items (`editable`, `mode`, `column`) render whenever they are included in the layout (they do not auto-hide when `editable` is false).
|
|
486
|
+
|
|
487
|
+
### Per-component configuration (`config`)
|
|
488
|
+
|
|
489
|
+
All built-ins support:
|
|
490
|
+
|
|
491
|
+
- `label` (string): overrides the label text
|
|
492
|
+
- `valueMinWidth` (string): CSS length (e.g. `"10ch"`) for stable widths
|
|
493
|
+
- `valueWidth` (string): CSS length (e.g. `"120px"`)
|
|
494
|
+
|
|
495
|
+
Component-specific keys:
|
|
496
|
+
|
|
497
|
+
- `offset`: `format` (`"hex"` or `"decimal"`), `pad` (number), `prefix` (boolean)
|
|
498
|
+
- `hex`: `prefix` (boolean)
|
|
499
|
+
- `ascii`: `quote` (boolean)
|
|
500
|
+
- `selection`: `showWhenEmpty` (boolean)
|
|
501
|
+
- `editable`: `short` (boolean)
|
|
502
|
+
- `mode`: `short` (boolean), `placeholder` (string)
|
|
503
|
+
- `column`: `short` (boolean), `placeholder` (string)
|
|
504
|
+
- `total`: `format` (`"human"` or `"hex"`), `decimals` (number, for `"human"`), `unit` (boolean), `pad` (number, for `"hex"`), `prefix` (boolean, for `"hex"`)
|
|
505
|
+
|
|
506
|
+
### Slot components
|
|
507
|
+
|
|
508
|
+
Use the built-in `"slot"` component name to render your own custom content inside the status bar.
|
|
509
|
+
|
|
510
|
+
Available slots:
|
|
511
|
+
|
|
512
|
+
- `#statusbar-left`
|
|
513
|
+
- `#statusbar-middle`
|
|
514
|
+
- `#statusbar-right`
|
|
515
|
+
|
|
516
|
+
Example:
|
|
372
517
|
|
|
373
518
|
```vue
|
|
374
519
|
<VueHex
|
|
@@ -377,20 +522,20 @@ When using the status bar (`statusbar="top"` or `statusbar="bottom"`), you can p
|
|
|
377
522
|
:statusbar-layout="{
|
|
378
523
|
left: ['offset', 'slot', 'hex'],
|
|
379
524
|
middle: ['ascii'],
|
|
380
|
-
right: ['selection', 'slot']
|
|
525
|
+
right: ['selection', 'slot'],
|
|
381
526
|
}"
|
|
382
527
|
>
|
|
383
528
|
<template #statusbar-left>
|
|
384
529
|
<span>Mode: RO</span>
|
|
385
530
|
</template>
|
|
386
|
-
|
|
531
|
+
|
|
387
532
|
<template #statusbar-right>
|
|
388
533
|
<span>Endian: LE</span>
|
|
389
534
|
</template>
|
|
390
535
|
</VueHex>
|
|
391
536
|
```
|
|
392
537
|
|
|
393
|
-
The `"slot"` entry
|
|
538
|
+
The `"slot"` entry controls where your slot content renders relative to built-in items.
|
|
394
539
|
|
|
395
540
|
## License
|
|
396
541
|
|