{"$schema":"https://ui.shadcn.com/schema/registry-item.json","name":"c-signature-pad-5","type":"registry:block","title":"Export PNG, JPEG, SVG or JSON","description":"Export the signature in 4 formats with a preview, payload size and download link.","dependencies":[],"registryDependencies":["button","button-group","@reui/frame","@reui/signature-pad"],"files":[{"path":"c-signature-pad-5.tsx","type":"registry:block","content":"\"use client\"\n\nimport { useState } from \"react\"\nimport { Frame, FramePanel } from \"@/components/reui/frame\"\nimport {\n  getSignaturePadBounds,\n  SignaturePad,\n  SignaturePadArea,\n  SignaturePadClear,\n  SignaturePadGuide,\n  SignaturePadPlaceholder,\n  SignaturePadSave,\n  type SignaturePadFormat,\n} from \"@/components/reui/signature-pad\"\n\nimport { buttonVariants } from \"@/components/ui/button\"\nimport {\n  ButtonGroup,\n  ButtonGroupText,\n} from \"@/components/ui/button-group\"\n\nconst FORMATS: { format: SignaturePadFormat; label: string; ext: string }[] = [\n  { format: \"png\", label: \"PNG\", ext: \"png\" },\n  { format: \"jpeg\", label: \"JPEG\", ext: \"jpg\" },\n  { format: \"svg\", label: \"SVG\", ext: \"svg\" },\n  { format: \"json\", label: \"JSON\", ext: \"json\" },\n]\n\ntype Result = (typeof FORMATS)[number] & {\n  value: string\n  width: number\n  height: number\n}\n\nconst PADDING = 16\n\nexport function Pattern() {\n  const [result, setResult] = useState<Result | null>(null)\n  const isImage = result !== null && result.format !== \"json\"\n\n  return (\n    <div className=\"mx-auto flex w-full max-w-lg flex-col gap-4\">\n      <SignaturePad onValueChange={() => setResult(null)}>\n        <SignaturePadArea className=\"h-44\">\n          <SignaturePadGuide />\n          <SignaturePadPlaceholder />\n        </SignaturePadArea>\n        <div className=\"flex flex-wrap items-center gap-2\">\n          <ButtonGroup aria-label=\"Export format\">\n            <ButtonGroupText>Export</ButtonGroupText>\n            {FORMATS.map((item) => (\n              <SignaturePadSave\n                key={item.format}\n                format={item.format}\n                /* Paper-white, so the export reads the same in a dark UI. */\n                options={{ background: \"#ffffff\", padding: PADDING }}\n                size=\"sm\"\n                onSave={(value, strokes) => {\n                  const bounds = getSignaturePadBounds(strokes)\n                  setResult({\n                    ...item,\n                    value,\n                    width: Math.ceil((bounds?.width ?? 0) + PADDING * 2),\n                    height: Math.ceil((bounds?.height ?? 0) + PADDING * 2),\n                  })\n                }}\n              >\n                {item.label}\n              </SignaturePadSave>\n            ))}\n          </ButtonGroup>\n          <SignaturePadClear variant=\"ghost\" size=\"sm\" className=\"ms-auto\">\n            Clear\n          </SignaturePadClear>\n        </div>\n      </SignaturePad>\n      <p role=\"status\" className=\"sr-only\">\n        {result &&\n          `${result.label} ready, ${(new Blob([result.value]).size / 1024).toFixed(1)} KB`}\n      </p>\n      {result && (\n        <Frame spacing=\"sm\">\n          <FramePanel>\n            <div className=\"flex flex-col gap-3\">\n              <div className=\"flex items-center gap-2 text-sm\">\n                <span className=\"font-medium\">{result.label}</span>\n                <span\n                  aria-hidden=\"true\"\n                  className=\"bg-muted-foreground/40 size-1 shrink-0 rounded-full\"\n                />\n                <span className=\"text-muted-foreground\">\n                  {(new Blob([result.value]).size / 1024).toFixed(1)} KB\n                </span>\n                <a\n                  href={\n                    isImage\n                      ? result.value\n                      : `data:application/json;charset=utf-8,${encodeURIComponent(result.value)}`\n                  }\n                  download={`signature.${result.ext}`}\n                  className={buttonVariants({\n                    variant: \"outline\",\n                    size: \"xs\",\n                    className: \"ms-auto\",\n                  })}\n                >\n                  Download\n                </a>\n              </div>\n              {isImage ? (\n                <img\n                  src={result.value}\n                  alt={`Signature exported as ${result.label}`}\n                  width={result.width}\n                  height={result.height}\n                  className=\"max-h-32 w-auto self-start\"\n                />\n              ) : (\n                <p className=\"text-muted-foreground line-clamp-3 font-mono text-xs break-all\">\n                  {result.value}\n                </p>\n              )}\n            </div>\n          </FramePanel>\n        </Frame>\n      )}\n    </div>\n  )\n}","target":"components/examples/c-signature-pad-5.tsx"}],"meta":{"order":5,"label":"Export Formats"}}