Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ Both `.zpl` and `.json` round-trip cleanly. `.zpl` preserves all printable conte

## Coverage

98 of the 202 ZPL II commands tracked in the [roadmap](docs/zpl-roadmap.md) are supported today. Categorical breakdown:
102 of the 202 ZPL II commands tracked in the [roadmap](docs/zpl-roadmap.md) are supported today. Categorical breakdown:

| Area | Supported |
|---|---|
Expand All @@ -128,9 +128,9 @@ Both `.zpl` and `.json` round-trip cleanly. `.zpl` preserves all printable conte
| Clock & time | 2 / 3 |
| Identity & access | 3 / 3 |
| Graphics | 6 / 12 |
| Media & feed | 5 / 10 |
| Media & feed | 8 / 10 |
| Text & fonts | 6 / 14 |
| Print quality | 4 / 14 |
| Print quality | 5 / 14 |
| Configuration & persistence | 3 / 5 |
| Hardware / Host comm / RFID / Network | 0 / 67 |

Expand Down
8 changes: 4 additions & 4 deletions docs/zpl-roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,12 +158,12 @@ The Printer Settings Modal (Media & Feed / Print Quality / Clock & Time / Encodi
| `[x]` | `^ML` | maximum label length | |
| `[x]` | `^MF` | media feed | |
| `[x]` | `^XB` | suppress backfeed | |
| `[ ]` | `^MA` | maintenance alert | `Coming soon` |
| `[x]` | `^MA` | maintenance alert | |
| `[ ]` | `^MC` | map clear | `Coming soon` |
| `[ ]` | `^MI` | maintenance info message | `Coming soon` |
| `[x]` | `^MI` | maintenance info message | |
| `[ ]` | `^MP` | mode protection | `Coming soon` |
| `[x]` | `^MU` | units of measure | |
| `[ ]` | `^MW` | head cold warning | `Coming soon` |
| `[x]` | `^MW` | head cold warning | |

## Print quality

Expand All @@ -173,7 +173,7 @@ The Printer Settings Modal (Media & Feed / Print Quality / Clock & Time / Encodi
| `[x]` | `^JT` | head test interval | |
| `[x]` | `~TA` | tear off adjust | |
| `[ ]` | `^PA` | advanced text properties | `Coming soon` |
| `[ ]` | `^JH` | early warning settings | `Coming soon` |
| `[x]` | `^JH` | early warning settings | |
| `[ ]` | `^PF` | slew dot rows | `Coming soon` |
| `[ ]` | `^PH` / `~PH` | slew to home | `Coming soon` |
| `[ ]` | `^PN` | present now | `Coming soon` |
Expand Down
4 changes: 4 additions & 0 deletions src/components/PrinterSettings/ClockAndTimeTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,10 @@ export function ClockAndTimeTab() {
min={CLOCK_TOLERANCE_RANGE.min}
max={CLOCK_TOLERANCE_RANGE.max}
value={profile.clockTolerance}
// Required while clockMode='TOL': empty blur snaps the
// draft back to the last committed value with no patch
// sent, so the input stays in sync with the store.
required
onChange={(v) => patchPrinterProfile({ clockTolerance: v })}
/>
)}
Expand Down
11 changes: 4 additions & 7 deletions src/components/PrinterSettings/EncodingAndLanguageTab.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useId } from "react";
import { useT } from "../../lib/useT";
import { useLabelStore } from "../../store/labelStore";
import { inputCls } from "../ui/formStyles";
import { PRINTER_LOCALE_VALUES, ZPL_MODE_VALUES, isPrinterLocale, isZplMode, type PrinterLocale, type ZplMode } from "../../types/PrinterProfile";
import {
SafeStringInput,
ZplCommandLabel,
ZplEnumSelect,
ZplField,
Expand Down Expand Up @@ -67,15 +67,12 @@ export function EncodingAndLanguageTab() {
conventions vary. */}
<ZplField>
<ZplCommandLabel text={loc.encodingTable} command="^SE" htmlFor={encodingId} />
<input
<SafeStringInput
id={encodingId}
type="text"
className={`${inputCls} invalid:border-warning`}
className="invalid:border-warning"
pattern={SE_PATH_PATTERN}
value={profile.encodingTable ?? ""}
onChange={(e) =>
patchPrinterProfile({ encodingTable: e.target.value || undefined })
}
onChange={(v) => patchPrinterProfile({ encodingTable: v || undefined })}
/>
<span className="font-mono text-[10px] text-muted/70 normal-case tracking-normal">
{loc.encodingTableHint}
Expand Down
29 changes: 10 additions & 19 deletions src/components/PrinterSettings/IdentityTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
isConfigUpdateAction,
} from "../../types/PrinterProfile";
import {
SafeStringInput,
ZplCommandLabel,
ZplEnumSelect,
ZplField,
Expand Down Expand Up @@ -40,13 +41,11 @@ export function IdentityTab() {
const loc = t.printerSettings.identity;
const nameId = useId();
const passwordId = useId();
// Local mirror for the 4-digit input: progressive typing ("4", "47")
// is shown immediately but only commits to the store once the regex
// matches. Without this, partial values would always be filtered out
// and the user could never finish entering a password. Re-sync on
// store changes (import, reset) uses the adjust-state-during-render
// pattern so the React compiler doesn't flag a useEffect → setState
// cascade.
// Progressive-commit draft: store only accepts a complete 4-digit
// value, but the user has to type intermediate states. SafeStringInput
// is fully controlled and would clobber the partial draft, so the
// ^KP input stays hand-rolled. Adjust-state-during-render reseeds on
// external changes (import, reset).
const storedPassword = profile.setPassword ?? "";
const [passwordDraft, setPasswordDraft] = useState(storedPassword);
const [lastStoredPassword, setLastStoredPassword] = useState(storedPassword);
Expand All @@ -64,30 +63,22 @@ export function IdentityTab() {
MediaFeedTab). */}
<ZplField>
<ZplCommandLabel text={loc.printerName} command="^KN" htmlFor={nameId} />
<input
<SafeStringInput
id={nameId}
type="text"
maxLength={PRINTER_NAME_MAX_LEN}
className={inputCls}
value={profile.printerName ?? ""}
onChange={(e) =>
patchPrinterProfile({ printerName: e.target.value || undefined })
}
onChange={(v) => patchPrinterProfile({ printerName: v || undefined })}
/>
<span className={`${labelCls} normal-case tracking-normal text-muted/70`}>
{loc.printerNameHint}
</span>

<ZplSubField label={loc.printerDescription}>
{(id) => (
<input
<SafeStringInput
id={id}
type="text"
className={inputCls}
value={profile.printerDescription ?? ""}
onChange={(e) =>
patchPrinterProfile({ printerDescription: e.target.value || undefined })
}
onChange={(v) => patchPrinterProfile({ printerDescription: v || undefined })}
/>
)}
</ZplSubField>
Expand Down
Loading