Reference
Everything <zpl-editor> offers a host page. How to use the load/save API in context: Embed the editor.
Attributes and properties#
Attributes are strings; every attribute also has a property (camelCase). Getters return the live state, including changes the user made in the editor's own controls.
| Attribute | Property | Type | Default | |
|---|---|---|---|---|
value | value | string | blank 4 x 6 label | The ZPL template. Setting a different value replaces the document, clears the undo history and makes it the saved state; setting the current value (or the one the last change reported) does nothing. Never fires change. For documents from your database prefer load(). |
sample-data | sampleData | object | array (attribute: JSON) | none | Sample record(s): preview with sample data, the Variables tab, Export merged, Test with API. |
dpmm | dpmm | 6 | 8 | 12 | 24 | 8 | Printhead density. |
width, height | width, height | inches, 0.1-15 | 4, 6 | Label size. Set from outside, they do not rewrite ^PW/^LL (the size menu in the editor does). |
upright | upright | boolean | true | Ignore ^PO I so the label reads the right way up. upright="false" turns it off. |
zoom | zoom | fit | actual | number | fit | Number = CSS pixels per printer dot (1 = 100%; "150%" works too). |
api-base | apiBase | URL | the install the SDK was loaded from | The labelviewer install used by Test with API and the API tab, and whose license applies. Loaded from /sdk/... it is that install's origin; bundled from npm it is empty (those features are hidden) until you set it. '' returns to the default. |
fonts-base-url | fontsBaseUrl | URL | fonts/ next to the script | Where the font files are (SDK › Fonts). Read on connect. |
readonly | readonly | boolean | false | View and inspect only: no toolbox, no undo, no editing. Sample data and zoom still work. |
features | features | tokens | all on | Turn parts of the UI off, see Features. |
warn-unsaved | warnUnsaved | boolean | false | While the template is unsaved, the browser asks before the page is closed or reloaded (beforeunload). Removed when the element leaves the page. |
autosave-key | autosaveKey | string | none | localStorage key for a draft (template, sample data, view) that survives reloads. Without it nothing is stored. Read on connect. See Drafts. |
| — | saveHandler | function | none | Property only. ({ value, sampleData, settings, fileName }) => Promise<void | { value }>, called on Save. See Save it. |
| — | samples | array | the built-in starter samples | Property only. The New from sample… gallery: [{ id, title, retailer?, description, widthIn, heightIn, dpmm, zpl, data? }] (retailer is a hint shown as "Similar fields to: …", data goes to the Sample data tab). [] hides the action; undefined restores the built-in list, so ed.samples = [...ed.samples, mine] adds one. The built-in samples are not verified (Starter samples). |
| — | dirty (read-only) | boolean | The template differs from the saved state (set by load(), value, markSaved() or a successful saveHandler). | |
| — | ready (read-only) | Promise | Resolves after the fonts are loaded and the first render is done. |
Slot title: content shown at the start of the toolbar, e.g. <h1 slot="title">Templates</h1>.
Features#
features is a space-separated list of no-<feature> tokens. They hide UI only; the methods keep working.
| Token | Hides |
|---|---|
no-file | The file actions: New, New from sample, Open, Save, Copy, Export, Test with API |
no-samples | New from sample |
no-history | Undo and redo buttons |
no-settings | Density, size and upright controls |
no-help | The keyboard shortcuts button |
no-toolbox | The left pane (add element, field list) |
no-properties | The right pane (properties of the selection) |
no-code, no-data, no-variables, no-api, no-warnings | The bottom tabs: ZPL code, Sample data, Variables, API, Warnings. Without any tab the bottom panel goes away. |
<!-- A layout-only designer: no file menu, no code, no API -->
<zpl-editor features="no-file no-code no-api"></zpl-editor>
Methods#
| Method | |
|---|---|
load({ zpl, sampleData?, dpmm?, width?, height?, fileName? }) | Replace the document in one step: template, sample data (object, array or JSON text; omitted = none), density, size in inches and the file name reported by save. Clears the undo history, makes zpl the saved state (dirty = false) and fires no change. Throws a TypeError for a non-string zpl, an unknown density or a size outside 0.1-15 in. |
markSaved(value?) | Make value (default: the current template) the saved state, after your code stored it. Needed only without a saveHandler. |
getValue(), setValue(zpl) | Same as the value property. |
render() | Render now; returns { labels, warnings }. |
exportMerged(data?) | The template merged in the browser with data (default: the sample data). Throws a MergeError with details. |
undo(), redo() | |
focus() | Focuses the canvas, so keyboard shortcuts work. |
Events#
All are CustomEvents that bubble and cross the shadow root.
| Event | detail | When |
|---|---|---|
change | { value } | Every edit by the user (canvas, properties, code, undo/redo, New, New from sample, Open). Code typing is debounced (150 ms); a drag fires once, on release. Not for load(), value or a stored value returned by saveHandler. |
save | { value, sampleData, settings: { dpmm, widthIn, heightIn }, fileName } | Ctrl/Cmd+S or the Save button, always, before the saveHandler runs. sampleData is a copy (undefined when there is none). |
dirty-change | { dirty } | dirty flipped. |
select | { field, ordinals } | The selection changed. field = { ordinal, kind, command, start, end, box } of the first selected field (box in label dots, null when it draws nothing), or null. |
render | { labels, warnings } | After each render (not during a drag). labels is the number of labels. |
sample-load | { id } | The user picked a sample in New from sample… and it replaced the document (after change). |
error | { source, message, status?, details? } | source: fonts, render, api (Test with API failed; status), save (the saveHandler threw), license (the install's license does not cover the Editor: a notice replaces the designer, and exportMerged() throws). |
Native events of the inner controls that are composed (input, keydown, focus...) also reach listeners on the
element; native change and select events do not leave the shadow root.
Keyboard shortcuts#
They act only while the focus is inside the element (click the canvas, or call focus()). Press ? in the editor for
this list.
| Keys | Action |
|---|---|
| Click / Shift+Click | Select / add to selection (click again to pick the element below) |
| Drag | Move; on an empty label area: select by rectangle |
| Arrow keys | Nudge 1 dot (Shift: 10 dots) |
| Del / Backspace | Delete the selection |
| Ctrl/Cmd+D | Duplicate |
| Ctrl/Cmd+C / X / V | Copy / cut / paste fields |
| Ctrl/Cmd+A | Select every field of the label |
] / [ | Bring to front / send to back |
| Ctrl/Cmd+Z, Ctrl/Cmd+Shift+Z | Undo, redo |
+ / - / 0 / 1 | Zoom in / out / fit / 100% |
| Ctrl/Cmd+Wheel | Zoom at the pointer |
| Space+Drag, Wheel | Pan |
| Ctrl/Cmd+S | Save the template |
| Esc | Clear the selection |
? | Show the shortcuts |
Theming#
Set these custom properties on the element (or any ancestor); they inherit into the shadow root:
| Property | Default | |
|---|---|---|
--lv-accent | #1f6feb | Primary buttons, selection, focus, grid |
--lv-accent-hover | #1858c4 | Primary button hover |
--lv-bg | #f3f4f6 | Editor background |
--lv-panel | #ffffff | Panes |
--lv-border | #d9dce1 | Borders |
--lv-text | #1f2933 | Text |
--lv-muted | #616e7c | Secondary text |
--lv-ok, --lv-warn, --lv-error | #1a7f37, #9a6700, #cf222e | Status colours |
--lv-font, --lv-font-mono | system UI, system monospace | Fonts of the UI (not the label) |
--lv-toolbar-bg, --lv-toolbar-text, --lv-toolbar-muted | #24292f, #fff, #c9d1d9 | Toolbar |
--lv-radius | 4px | Control corner radius |
zpl-editor { height: 720px; --lv-accent: #7b3fe4; --lv-toolbar-bg: #2d2640; }
Parts for anything else (zpl-editor::part(toolbar) { ... }):
| Part | |
|---|---|
shell | Everything |
toolbar | The top bar |
toolbox | The left pane |
canvas | Rulers and label |
status | The status bar |
panel | The bottom tabs |
properties | The right pane |
Layout and lifecycle#
- The element is
height: 640pxby default and needs about 1000 px of width; below that it scrolls horizontally. Its layout tightens below 1440 px of element width (a container query, not the window). In adisplay: flexparent, give it amin-height. - Several editors on one page are independent: each has its own document, history, selection and shortcuts.
- Removing the element from the page tears it down (listeners, observers, timers). Moving it within the page keeps its state. Adding a removed element back starts a fresh editor with the same value, sample data and saved state.
value = ...andload()start a new document, so they are not undoable; user edits are.- Test with API sends
POST ${apiBase}/v1/mergewith the template and the sample data, withcredentials: 'omit'and no credentials of any kind. If a gateway in front of the install requires credentials, do not put them in browser code: setapi-baseto a route on your backend that forwards to labelviewer, or hide the feature withfeatures="no-api".
Troubleshooting#
| Symptom | Cause |
|---|---|
| The editor is 0 px high | Give it a height; a parent with display: flex may shrink it (min-height). |
| Test with API is missing | Bundled from npm: set api-base. Also check features (no-api, no-file). |
| "This label component is not licensed for this installation" | The install's license does not cover the Editor: see the install's Status page. |
| A red X across the label | The install runs on a trial license. The X is drawn on screen only: the template, saves and exports are not changed. |
| Save does nothing visible | Without a saveHandler the editor only fires save and stays unsaved until markSaved(). |
A draft replaced the template I set with value | Drafts win over value; use load() for documents from your database, or a per-template autosave-key. |
| Keyboard shortcuts do nothing | They act only while the focus is inside the editor: click the canvas first, or call focus(). |
React: onChange never fires | Use onchange (lower case) with React 19, or addEventListener('change', ...). |
React: saveHandler / sampleData ignored | React 18, or the module was loaded after React rendered the element. Use a ref. |
Problems loading the SDK, fonts, CORS, integrity or CSP: SDK › Troubleshooting.