diff --git a/README.md b/README.md index 053270ee..2e52e39a 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,7 @@ Select several objects with Shift-click or a lasso. Position and size changes ap ### 4. Print or export -The **ZPL** panel at the bottom shows the generated ZPL, **Copy** puts it on the clipboard. On desktop the panel names the configured printer. A click shows its state and offers to read its configuration. The canvas is ZPLab's rendering of the label. A second rendering comes from the preview renderer under **File → Settings… → App → Preview**: the connected printer (desktop) or, with consent, the third-party service [Labelary](https://labelary.com/). **Preview** shows it for comparison. +The **ZPL** panel at the bottom shows the generated ZPL, **Copy** puts it on the clipboard. **Output** opens the output dialog. On desktop the panel names the configured printer. A click shows its state and offers to read its configuration. The canvas is ZPLab's rendering of the label. A second rendering comes from the preview renderer under **File → Settings… → App → Preview**: the connected printer (desktop) or, with consent, the third-party service [Labelary](https://labelary.com/). **Preview** shows it for comparison. - **File → Export ZPL:** saves a `.zpl` file, or `.prn` where the save dialog offers file types - **File → Output:** opens the output dialog with two destinations. diff --git a/src/components/Output/ZPLOutput.preview.test.tsx b/src/components/Output/ZPLOutput.preview.test.tsx index f1e2e335..26b1a831 100644 --- a/src/components/Output/ZPLOutput.preview.test.tsx +++ b/src/components/Output/ZPLOutput.preview.test.tsx @@ -1,6 +1,6 @@ // @vitest-environment jsdom import { describe, it, expect, beforeEach, afterEach } from "vitest"; -import { render, cleanup } from "@testing-library/react"; +import { render, cleanup, fireEvent } from "@testing-library/react"; import { ZPLOutput } from "./ZPLOutput"; import { useLabelStore } from "../../store/labelStore"; import { fallbackTranslations as en } from "../../locales"; @@ -35,3 +35,22 @@ describe("ZPLOutput preview button", () => { expect(canvas.queryByRole("button", { name: en.output.previewHeading })).toBeNull(); }); }); + +describe("ZPLOutput output button", () => { + it("opens the output dialog for the label from the bar", () => { + useLabelStore.setState({ outputSource: null }); + const r = render( undefined} />); + fireEvent.click(r.getByRole("button", { name: en.zebraPrint.outputHeading })); + expect(useLabelStore.getState().outputSource).toBe("label"); + }); + + it("stays disabled while a source-edit session is open and ignores a click", () => { + useLabelStore.setState({ outputSource: null }); + useLabelStore.getState().enterSourceEdit("^XA^FO10,10^A0N,30,30^FDdraft^FS^XZ"); + const r = render( undefined} />); + const button = r.getByRole("button", { name: en.zebraPrint.outputHeading }) as HTMLButtonElement; + expect(button.disabled).toBe(true); + fireEvent.click(button); + expect(useLabelStore.getState().outputSource).toBeNull(); + }); +}); diff --git a/src/components/Output/ZPLOutput.tsx b/src/components/Output/ZPLOutput.tsx index 57441d71..93b53640 100644 --- a/src/components/Output/ZPLOutput.tsx +++ b/src/components/Output/ZPLOutput.tsx @@ -1,5 +1,5 @@ import { useRef } from 'react'; -import { CheckIcon, ClipboardDocumentIcon, ChevronDownIcon, ChevronUpIcon, EyeIcon } from '@heroicons/react/16/solid'; +import { CheckIcon, ClipboardDocumentIcon, ChevronDownIcon, ChevronUpIcon, EyeIcon, PrinterIcon } from '@heroicons/react/16/solid'; import { useLabelStore, selectEffectivePreviewProvider, selectPreviewLocksEditor } from '../../store/labelStore'; import { useZplOutputView } from '../../hooks/useZplOutputView'; import { useCopyToClipboard } from '../../hooks/useCopyToClipboard'; @@ -37,6 +37,7 @@ export function ZPLOutput({ collapsed, onCollapse, onExpand, onResizeMouseDown } useZplOutputView(collapsed ?? false); // The body keeps its metadata (the apply reparses it); the button copies the export form. const { copy, copied } = useCopyToClipboard(() => finishZplExport(shownText)); + const openOutput = useLabelStore((s) => s.openOutput); const previewAvailable = effectiveProvider !== 'none'; @@ -104,6 +105,17 @@ export function ZPLOutput({ collapsed, onCollapse, onExpand, onResizeMouseDown } : <>{t.output.copy}} + {/* Otherwise the dialog is reachable only through the File menu. */} + + +