@arbidocs/blocks 0.4.68 → 0.4.70

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.
Files changed (54) hide show
  1. package/README.md +85 -1
  2. package/dist/agents/index.cjs +220 -220
  3. package/dist/agents/index.js +4 -4
  4. package/dist/chat/index.cjs +66 -66
  5. package/dist/chat/index.js +2 -2
  6. package/dist/chunk-4DVEGXZQ.cjs +72 -0
  7. package/dist/chunk-4DVEGXZQ.cjs.map +1 -0
  8. package/dist/{chunk-5ZZCS2EK.cjs → chunk-7M22KND4.cjs} +5 -5
  9. package/dist/{chunk-5ZZCS2EK.cjs.map → chunk-7M22KND4.cjs.map} +1 -1
  10. package/dist/{chunk-ZQB7HNE6.js → chunk-BMWZTNZB.js} +3 -3
  11. package/dist/{chunk-ZQB7HNE6.js.map → chunk-BMWZTNZB.js.map} +1 -1
  12. package/dist/{chunk-FAVN6VUR.js → chunk-HLMFU7L2.js} +5 -5
  13. package/dist/{chunk-FAVN6VUR.js.map → chunk-HLMFU7L2.js.map} +1 -1
  14. package/dist/chunk-ODWCTAH7.js +66 -0
  15. package/dist/chunk-ODWCTAH7.js.map +1 -0
  16. package/dist/{chunk-WKNAFILY.cjs → chunk-XNRGCQPZ.cjs} +3 -3
  17. package/dist/{chunk-WKNAFILY.cjs.map → chunk-XNRGCQPZ.cjs.map} +1 -1
  18. package/dist/document-tools/DocumentToolButtons.d.ts +29 -0
  19. package/dist/document-tools/MarkupNotices.d.ts +12 -0
  20. package/dist/document-tools/MarkupViewNote.d.ts +11 -0
  21. package/dist/document-tools/SignDocumentDialog.d.ts +20 -0
  22. package/dist/document-tools/SignatureCertificate.d.ts +26 -0
  23. package/dist/document-tools/SignatureStatus.d.ts +22 -0
  24. package/dist/document-tools/VersionSnapshotBar.d.ts +27 -0
  25. package/dist/document-tools/index.cjs +633 -0
  26. package/dist/document-tools/index.cjs.map +1 -0
  27. package/dist/document-tools/index.d.ts +7 -0
  28. package/dist/document-tools/index.js +619 -0
  29. package/dist/document-tools/index.js.map +1 -0
  30. package/dist/document-tools/viewer/AnnotatedPdfViewer.d.ts +54 -0
  31. package/dist/document-tools/viewer/SignaturePlacementViewer.d.ts +20 -0
  32. package/dist/document-tools/viewer/index.cjs +273 -0
  33. package/dist/document-tools/viewer/index.cjs.map +1 -0
  34. package/dist/document-tools/viewer/index.d.ts +2 -0
  35. package/dist/document-tools/viewer/index.js +268 -0
  36. package/dist/document-tools/viewer/index.js.map +1 -0
  37. package/dist/facts/index.cjs +1 -1
  38. package/dist/facts/index.js +1 -1
  39. package/dist/files/cells/DocumentNameCell.d.ts +3 -1
  40. package/dist/files/index.cjs +38 -67
  41. package/dist/files/index.cjs.map +1 -1
  42. package/dist/files/index.js +19 -63
  43. package/dist/files/index.js.map +1 -1
  44. package/dist/home/index.cjs +1 -1
  45. package/dist/home/index.js +1 -1
  46. package/dist/index.cjs +651 -651
  47. package/dist/index.js +10 -10
  48. package/dist/settings/index.cjs +2 -2
  49. package/dist/settings/index.js +2 -2
  50. package/dist/shell/index.cjs +1 -1
  51. package/dist/shell/index.js +1 -1
  52. package/dist/studio/index.cjs +1 -1
  53. package/dist/studio/index.js +1 -1
  54. package/package.json +20 -4
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/document-tools/DocumentToolButtons.tsx","../../src/document-tools/MarkupNotices.tsx","../../src/document-tools/MarkupViewNote.tsx","../../src/document-tools/SignDocumentDialog.tsx","../../src/document-tools/SignatureStatus.tsx","../../src/document-tools/SignatureCertificate.tsx","../../src/document-tools/VersionSnapshotBar.tsx"],"names":["jsxs","jsx","Button","useState","LINK"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * The viewer-header buttons of the PDF document tools: Annotate, Show original, Download with\n * markup and Sign. Separate parts so a host can place them among its own header actions. On a\n * narrow (`compact`) header each is icon-only; its accessible name stays.\n */\n\nimport type { ReactElement } from 'react'\nimport { Download, FileText, PencilLine, PenLine } from 'lucide-react'\nimport { Button } from '@arbidocs/react/ui'\n\nconst TOUCH = 'pointer-coarse:min-h-11'\n\ninterface ToggleProps {\n /** On (pressed). */\n active: boolean\n onClick: () => void\n compact?: boolean\n}\n\n/** Annotate mode: highlight, comment, stamp, redact. */\nexport function AnnotateButton({ active, onClick, compact }: ToggleProps): ReactElement {\n return (\n <Button\n type=\"button\"\n variant={active ? 'default' : 'outline'}\n size={compact ? 'icon' : 'sm'}\n aria-pressed={active}\n title=\"Annotate: highlight, comment, stamp, redact\"\n aria-label=\"Annotate\"\n data-testid=\"annotate-toggle\"\n className={TOUCH}\n onClick={onClick}\n >\n <PencilLine className=\"size-4\" />\n {!compact && <span className=\"ml-1\">Annotate</span>}\n </Button>\n )\n}\n\n/** The markup is the default view of a marked-up PDF; this shows the untouched file. */\nexport function ShowOriginalButton({ active, onClick, compact }: ToggleProps): ReactElement {\n return (\n <Button\n type=\"button\"\n variant={active ? 'default' : 'outline'}\n size={compact ? 'icon' : 'sm'}\n aria-pressed={active}\n title={active ? 'Show the markup again' : 'Show the original, without markup'}\n aria-label=\"Show original\"\n data-testid=\"markup-show-original\"\n className={TOUCH}\n onClick={onClick}\n >\n <FileText className=\"size-4\" />\n {!compact && <span className=\"ml-1\">Show original</span>}\n </Button>\n )\n}\n\n/**\n * \"Download with markup\": the PDF with its annotations, which Acrobat and Preview show. With a\n * `disabledReason` (a signed, locked version) it is off and says why.\n */\nexport function DownloadMarkupButton({\n onClick,\n disabledReason,\n}: {\n onClick: () => void\n disabledReason?: string\n}): ReactElement {\n const button = (\n <Button\n type=\"button\"\n variant=\"outline\"\n size=\"icon\"\n title={\n disabledReason ??\n 'Download with markup: the PDF with its annotations (opens in Acrobat or Preview)'\n }\n aria-label=\"Download with markup\"\n aria-description={disabledReason}\n disabled={!!disabledReason}\n data-testid=\"markup-download\"\n className={TOUCH}\n onClick={onClick}\n >\n <Download className=\"size-4\" />\n </Button>\n )\n // A disabled button gets no pointer events, so the reason sits on a wrapper too.\n return disabledReason ? (\n <span title={disabledReason} className=\"inline-flex\" data-testid=\"markup-download-locked\">\n {button}\n </span>\n ) : (\n button\n )\n}\n\n/** One line where a signed version's content can be edited: an edit is a new, unsigned version. */\nexport function SignedEditNote(): ReactElement {\n return (\n <p\n className=\"border-b px-3 py-1.5 text-xs text-muted-foreground\"\n data-testid=\"signed-edit-note\"\n >\n Editing creates a new unsigned version\n </p>\n )\n}\n\n/** Sign: choose where the signature goes, then sign. */\nexport function SignButton({ active, onClick, compact }: ToggleProps): ReactElement {\n return (\n <Button\n type=\"button\"\n variant={active ? 'default' : 'outline'}\n size={compact ? 'icon' : 'sm'}\n aria-pressed={active}\n title=\"Sign document\"\n aria-label=\"Sign\"\n data-testid=\"sign-document-button\"\n className={TOUCH}\n onClick={onClick}\n >\n <PenLine className=\"size-4\" />\n {!compact && <span className=\"ml-1\">Sign</span>}\n </Button>\n )\n}\n","/**\n * The one-line notices above the PDF about its markup: annotations found in this browser from\n * before markup was saved on the server (for a shared document: add them to the shared markup, or\n * discard), and markup that sits on an older version (open it, or copy its open comments here).\n */\n\nimport type { LegacyPrompt, OlderMarkupNote } from '@arbidocs/react/document-tools'\n\nconst BAR = 'flex flex-wrap items-center justify-between gap-2 border-b px-3 py-2 text-xs'\nconst LINK =\n 'font-medium text-primary hover:underline disabled:opacity-50 disabled:no-underline pointer-coarse:min-h-11'\n\nexport interface MarkupNoticesProps {\n legacyPrompt: LegacyPrompt | null\n olderNote: OlderMarkupNote | null\n onOpenVersion: (version: number) => void\n}\n\nexport function MarkupNotices({ legacyPrompt, olderNote, onOpenVersion }: MarkupNoticesProps) {\n return (\n <>\n {legacyPrompt && (\n <div className={BAR} role=\"status\" data-testid=\"markup-migration-prompt\">\n <span>\n {legacyPrompt.count} annotation{legacyPrompt.count === 1 ? '' : 's'} on this document\n {legacyPrompt.count === 1 ? ' is' : ' are'} saved only in this browser. Add{' '}\n {legacyPrompt.count === 1 ? 'it' : 'them'} to the shared markup, where everyone with\n access sees {legacyPrompt.count === 1 ? 'it' : 'them'}?\n </span>\n <span className=\"flex items-center gap-3\">\n <button\n type=\"button\"\n className={LINK}\n disabled={legacyPrompt.busy}\n data-testid=\"markup-migration-add\"\n onClick={legacyPrompt.add}\n >\n {legacyPrompt.busy ? 'Adding…' : 'Add to shared markup'}\n </button>\n <button\n type=\"button\"\n className={LINK}\n disabled={legacyPrompt.busy}\n data-testid=\"markup-migration-discard\"\n onClick={legacyPrompt.discard}\n >\n Discard\n </button>\n </span>\n </div>\n )}\n {olderNote && (\n <div className={BAR} data-testid=\"markup-older-version-note\">\n <span>\n The markup is on version {olderNote.version}. This version started without it.\n {olderNote.signed && (\n <span data-testid=\"markup-older-version-signed\">\n {' '}\n It is signed: comments copied here are kept beside it, and the signed PDF does not\n change.\n </span>\n )}\n </span>\n <span className=\"flex items-center gap-3\">\n <button\n type=\"button\"\n className={LINK}\n data-testid=\"markup-open-older-version\"\n onClick={() => onOpenVersion(olderNote.version)}\n >\n Open version {olderNote.version}\n </button>\n <button\n type=\"button\"\n className={LINK}\n disabled={olderNote.busy}\n data-testid=\"markup-copy-open-threads\"\n title=\"Copy the unresolved comment threads onto this version (redactions never carry over)\"\n onClick={olderNote.copy}\n >\n {olderNote.busy ? 'Copying…' : 'Copy open comments here'}\n </button>\n </span>\n </div>\n )}\n </>\n )\n}\n","/**\n * Which view of a marked-up PDF is on screen, spelled out beside the title, with the switch to the\n * other one. The narrow header's \"Show original\" is an unlabelled page icon, so on its own it read\n * as no control at all, and nothing said whether the page showed the markup or the original.\n */\n\nimport type { ReactElement } from 'react'\nimport { ViewerStatusNote } from '../files/ViewerLayout'\n\nexport interface MarkupViewNoteProps {\n showOriginal: boolean\n onToggle: () => void\n}\n\nexport function MarkupViewNote({ showOriginal, onToggle }: MarkupViewNoteProps): ReactElement {\n return (\n <ViewerStatusNote testId=\"markup-view-note\">\n {showOriginal ? 'Original, without markup' : 'With markup'}\n {' · '}\n <button\n type=\"button\"\n className=\"font-medium text-primary hover:underline pointer-coarse:min-h-11\"\n data-testid=\"markup-view-note-toggle\"\n onClick={onToggle}\n >\n {showOriginal ? 'Show markup' : 'Show original'}\n </button>\n </ViewerStatusNote>\n )\n}\n","/**\n * Sign a document electronically: confirm the name, choose whether the date is shown, read the\n * statement of intent, re-enter the password. Only the signature (and the date, if ticked) is drawn\n * on the page; a role, a firm or a place go on as ordinary annotation text. Anyone can click the\n * signature to check it. The signed copy is saved as a new version and opened, with an offer to\n * email it when the host gives the tools an `emailDocument`. Needs a `<DocumentToolsProvider>` with\n * a `user` (its email) and a `deploymentDomain`, inside a React Query `QueryClientProvider`.\n */\n\nimport { useState, type FormEvent, type ReactElement } from 'react'\nimport {\n intentText,\n useDocumentTools,\n useSignDocument,\n type SignatureAppearance,\n} from '@arbidocs/react/document-tools'\nimport { Button, Checkbox, Input, Label } from '@arbidocs/react/ui'\nimport { ModalScaffold } from '../settings/ModalScaffold'\n\nexport interface SignDocumentDialogProps {\n open: boolean\n onOpenChange: (open: boolean) => void\n documentId: string\n /** The PDF the viewer is showing. */\n pdfBlob: Blob\n /** Where the signature goes; omitted = bottom of the last page. */\n appearance?: SignatureAppearance\n}\n\nexport function SignDocumentDialog({\n open,\n onOpenChange,\n documentId,\n pdfBlob,\n appearance,\n}: SignDocumentDialogProps): ReactElement {\n const { user, notify, openDocument, emailDocument } = useDocumentTools()\n const [name, setName] = useState(() => user?.name ?? '')\n const [includeDate, setIncludeDate] = useState(false)\n const [password, setPassword] = useState('')\n const [error, setError] = useState<string | null>(null)\n const sign = useSignDocument()\n\n const signer = { name }\n\n const handleSubmit = async (e: FormEvent) => {\n e.preventDefault()\n if (!user?.email) return\n setError(null)\n try {\n const result = await sign.mutateAsync({\n documentId,\n pdfBlob,\n email: user.email,\n password,\n signer,\n appearance,\n includeDate,\n })\n const signedId = result.doc_ext_id\n notify(\n `Signed. The signed copy is saved as version ${result.version}.`,\n 'success',\n emailDocument\n ? { action: { label: 'Email it', onClick: () => emailDocument(signedId) } }\n : result.signature.certificate_url\n ? {\n action: {\n label: 'View certificate',\n onClick: () => {\n window.open(result.signature.certificate_url, '_blank', 'noopener,noreferrer')\n },\n },\n }\n : undefined\n )\n setPassword('')\n onOpenChange(false)\n openDocument?.(signedId)\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Signing failed')\n }\n }\n\n return (\n <ModalScaffold\n open={open}\n onOpenChange={(next) => !sign.isPending && onOpenChange(next)}\n title=\"Sign document\"\n description=\"Sign this document electronically. The signed copy is saved as a new version.\"\n showDescription\n testId=\"sign-document-dialog\"\n >\n <form onSubmit={handleSubmit}>\n <ModalScaffold.Body>\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"sign-name\">Name</Label>\n <Input\n id=\"sign-name\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n data-testid=\"sign-document-name-input\"\n required\n />\n </div>\n <div className=\"flex items-center gap-2 pointer-coarse:min-h-11\">\n <Checkbox\n id=\"sign-include-date\"\n checked={includeDate}\n onCheckedChange={(checked) => setIncludeDate(checked === true)}\n data-testid=\"sign-document-include-date\"\n />\n <Label htmlFor=\"sign-include-date\" className=\"font-normal\">\n Include date\n </Label>\n </div>\n <p className=\"text-sm text-muted-foreground\" data-testid=\"sign-document-appearance-note\">\n Only your signature{includeDate ? ' and the date appear' : ' appears'} on the page.\n Anyone can click it to check it.\n </p>\n {name.trim() && (\n <blockquote\n className=\"border-l-2 border-border pl-3 text-sm text-muted-foreground\"\n data-testid=\"sign-document-intent\"\n >\n {intentText(signer)}\n </blockquote>\n )}\n <div className=\"space-y-1.5\">\n <Label htmlFor=\"sign-password\">Password</Label>\n <Input\n id=\"sign-password\"\n type=\"password\"\n autoComplete=\"current-password\"\n value={password}\n onChange={(e) => setPassword(e.target.value)}\n data-testid=\"sign-document-password-input\"\n required\n />\n </div>\n {error && (\n <p className=\"text-sm text-red-text\" role=\"alert\" data-testid=\"sign-document-error\">\n {error}\n </p>\n )}\n </ModalScaffold.Body>\n <ModalScaffold.Footer>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => onOpenChange(false)}\n disabled={sign.isPending}\n >\n Cancel\n </Button>\n <Button\n type=\"submit\"\n disabled={sign.isPending || !name.trim() || !password}\n data-testid=\"sign-document-submit-button\"\n >\n {sign.isPending ? 'Signing...' : 'Sign'}\n </Button>\n </ModalScaffold.Footer>\n </form>\n </ModalScaffold>\n )\n}\n","/**\n * The \"Signed — locked\" note in the viewer header (a signed version changes only by a further\n * signature), which opens the signature details: who signed and when,\n * whether the document is unchanged since, and \"View certificate\", the public page anyone can\n * check the signature on (the same page the signature on the PDF links to). Read from the PDF\n * itself (GET .../signatures). A counter-signed copy lists every signature, oldest first.\n */\n\nimport type { ReactElement, ReactNode } from 'react'\nimport { defaultCertificateUrl, type SignatureStatusResponse } from '@arbidocs/react/document-tools'\nimport { Popover, PopoverContent, PopoverTrigger } from '@arbidocs/react/ui'\n\n/** \"14 Oct 2026, 12:00\" in the reader's locale and time zone. */\nexport function formatSignedAt(iso: string): string {\n const date = new Date(iso)\n if (Number.isNaN(date.getTime())) return iso\n return date.toLocaleString([], { dateStyle: 'medium', timeStyle: 'short' })\n}\n\nexport interface SignatureStatusProps {\n status: SignatureStatusResponse\n /** How the signing time is shown. Default: {@link formatSignedAt}. */\n formatDate?: (iso: string) => string\n /**\n * The certificate page of a signature, only for a record without the `certificate_url` the API\n * returns. Default: `/verify/{reference}` on this origin.\n */\n certificateUrl?: (reference: string) => string\n}\n\nfunction Row({ label, field, children }: { label: string; field: string; children: ReactNode }) {\n return (\n <div className=\"grid grid-cols-[5.5rem_1fr] gap-2\">\n <dt className=\"text-muted-foreground\">{label}</dt>\n <dd className=\"min-w-0 break-words\" data-testid={`signature-detail-${field}`}>\n {children}\n </dd>\n </div>\n )\n}\n\nexport function SignatureStatus({\n status,\n formatDate = formatSignedAt,\n certificateUrl = defaultCertificateUrl,\n}: SignatureStatusProps): ReactElement {\n const signatures = status.signatures ?? []\n // A signed copy can be counter-signed: each signature is listed, oldest first.\n const isCounterSigned = signatures.length > 1\n return (\n <Popover>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n className=\"flex-shrink-0 text-sm text-muted-foreground underline decoration-dotted underline-offset-4 hover:text-foreground pointer-coarse:min-h-11\"\n data-testid=\"document-signature-status\"\n aria-label={`${status.intact ? 'Signed, locked' : 'Modified after signing'}: show signature details`}\n >\n {status.intact ? 'Signed — locked' : 'Modified after signing'}\n </button>\n </PopoverTrigger>\n <PopoverContent\n className=\"max-h-[70vh] w-80 overflow-y-auto p-3 text-sm\"\n align=\"start\"\n data-testid=\"signature-details\"\n >\n <p className=\"mb-2 font-medium\" data-testid=\"signature-details-title\">\n {isCounterSigned\n ? `Electronic signatures (${signatures.length})`\n : 'Electronic signature'}\n </p>\n {signatures.map((signature, index) => (\n <dl\n key={signature.reference}\n className={`mb-3 space-y-1 ${index > 0 ? 'border-t border-border pt-2' : ''}`}\n data-testid={`signature-item-${index}`}\n >\n <Row label=\"Signed by\" field=\"signer\">\n {signature.signer_name || signature.signer_email}\n </Row>\n <Row label=\"On\" field=\"time\">\n {formatDate(signature.signed_at)}\n </Row>\n <dd>\n <a\n href={signature.certificate_url || certificateUrl(signature.reference)}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"inline-flex items-center font-medium text-primary hover:underline pointer-coarse:min-h-11\"\n data-testid={`signature-certificate-link-${index}`}\n >\n View certificate\n </a>\n </dd>\n </dl>\n ))}\n <p\n className={`border-t border-border pt-2 ${status.intact ? '' : 'text-red-text'}`}\n data-testid=\"signature-detail-intact\"\n >\n {status.intact\n ? isCounterSigned\n ? '✓ Unchanged since the last signature'\n : '✓ Unchanged since signing'\n : '✗ Changed after it was signed'}\n </p>\n <p className=\"mt-1 text-xs text-muted-foreground\" data-testid=\"signature-detail-locked\">\n Locked: only further signatures can be added.\n </p>\n </PopoverContent>\n </Popover>\n )\n}\n","/**\n * The certificate of an ARBI signature: the page the link on a signed PDF's signature opens, for\n * anyone, signed in or not. Plain English and short: who signed and when, what ARBI checks, the\n * result, any counter-signatures, and \"Check your copy\", which hashes a PDF in the browser and\n * compares it with the signed document and each signed revision (the file never leaves the\n * device). No email addresses and no\n * document content. Presentational: `verification` comes from `useSignatureVerification` in\n * `@arbidocs/react/document-tools`.\n */\n\nimport { useRef, useState, type DragEvent, type ReactElement, type ReactNode } from 'react'\nimport {\n matchSignedCopy,\n type CopyMatch,\n type SignatureVerification,\n} from '@arbidocs/react/document-tools'\nimport { cn } from '@arbidocs/react/ui'\nimport { formatSignedAt } from './SignatureStatus'\n\nexport interface SignatureCertificateProps {\n /** The signature reference (`sig-…`), shown at the foot of the page. */\n reference?: string\n verification?: SignatureVerification\n isLoading?: boolean\n /** Why the signature could not be checked. */\n error?: string | null\n /** The error is a passing one (too many checks): say it calmly, not as a failure. */\n isErrorTransient?: boolean\n /** How signing times are shown. Default: {@link formatSignedAt}. */\n formatDate?: (iso: string) => string\n /** Offer \"Check your copy\". Default on. */\n allowCopyCheck?: boolean\n}\n\ntype CopyCheck =\n | { state: 'idle' }\n | { state: 'checking'; name: string }\n | { state: 'done'; name: string; match: CopyMatch }\n | { state: 'failed'; name: string }\n\nfunction Frame({ children }: { children: ReactNode }) {\n return (\n <main\n className=\"mx-auto w-full max-w-xl px-4 py-10 text-foreground\"\n data-testid=\"signature-certificate\"\n >\n <h1 className=\"mb-6 text-xl font-semibold\">Signature certificate</h1>\n {children}\n </main>\n )\n}\n\nfunction copyResult(name: string, match: CopyMatch): string {\n if (match.kind === 'current') return `✓ ${name} is the signed document, unchanged.`\n if (match.kind === 'earlier') {\n // A counter-signed PDF: the copy is an earlier signed revision, which is still genuine.\n return `✓ ${name}: this is the version signed by ${match.signature.signer_name || 'an ARBI user'}.`\n }\n return `✗ ${name} is not the signed document: it differs from what was signed.`\n}\n\nexport function SignatureCertificate({\n reference,\n verification,\n isLoading = false,\n error,\n isErrorTransient = false,\n formatDate = formatSignedAt,\n allowCopyCheck = true,\n}: SignatureCertificateProps): ReactElement {\n const [copy, setCopy] = useState<CopyCheck>({ state: 'idle' })\n const [dragging, setDragging] = useState(false)\n const input = useRef<HTMLInputElement>(null)\n\n if (isLoading) {\n return (\n <Frame>\n <p className=\"text-muted-foreground\" data-testid=\"signature-certificate-loading\">\n Checking the signature…\n </p>\n </Frame>\n )\n }\n if (error || !verification) {\n return (\n <Frame>\n <p\n className={isErrorTransient ? 'text-muted-foreground' : 'text-red-text'}\n role={isErrorTransient ? 'status' : 'alert'}\n data-testid=\"signature-certificate-error\"\n >\n {error || 'The signature could not be checked.'}\n </p>\n </Frame>\n )\n }\n\n const [first, ...counter] = verification.signatures\n const check = async (file: File | undefined) => {\n if (!file) return\n setCopy({ state: 'checking', name: file.name })\n try {\n setCopy({ state: 'done', name: file.name, match: await matchSignedCopy(file, verification) })\n } catch {\n setCopy({ state: 'failed', name: file.name })\n }\n }\n const onDrop = (e: DragEvent) => {\n e.preventDefault()\n setDragging(false)\n void check(e.dataTransfer.files[0])\n }\n\n return (\n <Frame>\n <section className=\"space-y-3\">\n {first && (\n <p className=\"text-base\" data-testid=\"signature-certificate-signer\">\n Signed by <strong>{first.signer_name || 'an ARBI user'}</strong> on{' '}\n {formatDate(first.signed_at)}\n </p>\n )}\n {counter.length > 0 && (\n <ul className=\"space-y-1 text-sm\" data-testid=\"signature-certificate-counter\">\n {counter.map((s, i) => (\n <li key={`${s.sha256}-${i}`}>\n Also signed by <strong>{s.signer_name || 'an ARBI user'}</strong> on{' '}\n {formatDate(s.signed_at)}\n </li>\n ))}\n </ul>\n )}\n <p className=\"text-sm text-muted-foreground\">\n ARBI checks that this document hasn’t changed since it was signed. If anything changed,\n this check fails.\n </p>\n <p\n className={cn(\n 'rounded-md border px-3 py-2 font-medium',\n verification.intact\n ? 'border-green-border bg-green-bg text-green-text'\n : 'border-red-text text-red-text'\n )}\n role=\"status\"\n data-testid=\"signature-certificate-result\"\n data-intact={verification.intact}\n >\n {verification.intact\n ? '✓ Unchanged since signing'\n : '✗ Changed since signing: this is not the document that was signed'}\n </p>\n </section>\n\n {allowCopyCheck && (\n <section className=\"mt-8 space-y-2\">\n <h2 className=\"text-sm font-medium\">Check your copy</h2>\n <div\n role=\"button\"\n tabIndex={0}\n className={cn(\n 'flex min-h-24 cursor-pointer flex-col items-center justify-center rounded-md border border-dashed px-4 py-6 text-center text-sm text-muted-foreground pointer-coarse:min-h-32',\n dragging && 'border-primary bg-muted'\n )}\n data-testid=\"signature-certificate-dropzone\"\n onClick={() => input.current?.click()}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n input.current?.click()\n }\n }}\n onDragOver={(e) => {\n e.preventDefault()\n setDragging(true)\n }}\n onDragLeave={() => setDragging(false)}\n onDrop={onDrop}\n >\n Drop the PDF you were sent here, or choose it\n <span className=\"mt-1 text-xs\">It is checked in this browser and never uploaded.</span>\n <input\n ref={input}\n type=\"file\"\n accept=\"application/pdf,.pdf\"\n className=\"sr-only\"\n data-testid=\"signature-certificate-file-input\"\n onChange={(e) => void check(e.target.files?.[0])}\n />\n </div>\n {copy.state !== 'idle' && (\n <p\n className={cn(\n 'text-sm',\n copy.state === 'done' && copy.match.kind !== 'none' && 'text-green-text',\n ((copy.state === 'done' && copy.match.kind === 'none') ||\n copy.state === 'failed') &&\n 'text-red-text'\n )}\n role=\"status\"\n data-testid=\"signature-certificate-copy-result\"\n >\n {copy.state === 'checking'\n ? `Checking ${copy.name}…`\n : copy.state === 'failed'\n ? `${copy.name} could not be read.`\n : copyResult(copy.name, copy.match)}\n </p>\n )}\n </section>\n )}\n\n {reference && (\n <p\n className=\"mt-8 text-xs text-muted-foreground\"\n data-testid=\"signature-certificate-reference\"\n >\n Reference {reference}\n </p>\n )}\n </Frame>\n )\n}\n","/**\n * The bar above an older version opened read-only: which version it is, \"Ask about this version\"\n * (when the host has an assistant) and the way back to the current version. Put it in the viewer's\n * sticky header, not the content area: a PDF view scrolls its first page into view, which would\n * scroll a bar above it out of sight.\n */\n\nimport type { ReactElement } from 'react'\n\nconst LINK = 'font-medium text-primary hover:underline pointer-coarse:min-h-11'\n\nexport interface VersionSnapshotBarLabels {\n /** `Version 2 · read only`; `number` is undefined when the version is not known. */\n title: (number: number | undefined) => string\n ask: string\n returnToCurrent: string\n /** For documents edited live (Word, artifacts), where \"current\" is the live document. */\n returnToLive: string\n}\n\nexport const DEFAULT_VERSION_SNAPSHOT_BAR_LABELS: VersionSnapshotBarLabels = {\n title: (number) => `${number ? `Version ${number}` : 'Saved version'} · read only`,\n ask: 'Ask about this version',\n returnToCurrent: 'Return to current version',\n returnToLive: 'Return to live document',\n}\n\nexport interface VersionSnapshotBarProps {\n /** The version's number, when known. */\n versionNumber?: number\n /** The document is edited live: the way back says \"live document\". */\n live?: boolean\n /** Ask the assistant about this version. Omitted: no ask action. */\n onAsk?: () => void\n onReturn: () => void\n labels?: Partial<VersionSnapshotBarLabels>\n}\n\nexport function VersionSnapshotBar({\n versionNumber,\n live = false,\n onAsk,\n onReturn,\n labels: overrides,\n}: VersionSnapshotBarProps): ReactElement {\n const labels = { ...DEFAULT_VERSION_SNAPSHOT_BAR_LABELS, ...overrides }\n return (\n <div\n className=\"flex items-center justify-between border-b px-3 py-2 text-xs\"\n data-testid=\"version-snapshot-bar\"\n >\n <span>{labels.title(versionNumber)}</span>\n <span className=\"flex items-center gap-3\">\n {onAsk && (\n <button type=\"button\" className={LINK} data-testid=\"version-snapshot-ask\" onClick={onAsk}>\n {labels.ask}\n </button>\n )}\n <button\n type=\"button\"\n className={LINK}\n data-testid=\"version-snapshot-return\"\n onClick={onReturn}\n >\n {live ? labels.returnToLive : labels.returnToCurrent}\n </button>\n </span>\n </div>\n )\n}\n"]}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * The PDF viewer with the document's MARKUP on it: toolbar, per-page overlay and the freeze dialog.
3
+ *
4
+ * The original is never touched. The marks are the version's markup on the server (native PDF
5
+ * annotations in its `{doc}-markup.pdf`, see `createMarkupStore` in `@arbidocs/react/document-tools`),
6
+ * with the document's own privacy:
7
+ * a shared document has one markup that owners and collaborators edit and guests read; a private
8
+ * one is its owner's. Edits autosave a few seconds after the last change and when the viewer
9
+ * closes; colleagues' changes are merged in. "Freeze" renders a new PDF with the marks built in and
10
+ * saves it as a separate document derived from the original (see `uploadFrozenCopy`). Load it
11
+ * lazily: it brings in pdf-lib, which nothing else needs.
12
+ *
13
+ * Needs a `<DocumentToolsProvider>` (API client, user, notify, open, refresh) inside a React Query
14
+ * `QueryClientProvider`. `viewer` is the PDF viewer to draw on (default: the kit `PdfViewer`); a host
15
+ * passes its own binding of it, e.g. one that reports the visible page.
16
+ *
17
+ * `editing` off is the default reading view: the marks show and comments open, read-only, with no
18
+ * toolbar. Unsaved edits still go out when switching from editing to reading.
19
+ */
20
+ import { type ComponentType } from 'react';
21
+ import { type AnnotationStore } from '@arbidocs/react/annotations';
22
+ import { type MarkupSnapshot } from '@arbidocs/react/document-tools';
23
+ import { type PdfViewerProps } from '@arbidocs/react/viewers';
24
+ /** Autosave this long after the last change (the design's "a few seconds"). */
25
+ export declare const MARKUP_AUTOSAVE_MS = 2500;
26
+ /** Look for colleagues' changes this often while idle. */
27
+ export declare const MARKUP_PULL_MS = 20000;
28
+ /** The PDF viewer the marks are drawn on: the kit viewer's props, with a page-overlay slot. */
29
+ export type DocumentPdfViewer = ComponentType<PdfViewerProps>;
30
+ export interface AnnotatedPdfViewerProps extends Omit<PdfViewerProps, 'file' | 'renderPageOverlay'> {
31
+ file: Blob;
32
+ documentId: string;
33
+ /** The version on screen when it is not the current one (its markup is shown, read-only). */
34
+ version?: number;
35
+ fileName: string | null | undefined;
36
+ /** The original's workspace sharing and folder, which the frozen copy takes. */
37
+ shared?: boolean;
38
+ folder?: string | null;
39
+ /** Annotate mode (toolbar, tools). Off: the marks are shown read-only. Default on. */
40
+ editing?: boolean;
41
+ /** After each save: the markup's revision and how many marks it holds. */
42
+ onMarkupChange?: (snapshot: MarkupSnapshot) => void;
43
+ /** Where the layer lives; defaults to the version's markup on the server. */
44
+ store?: AnnotationStore;
45
+ /** The PDF viewer to draw on. Default: the kit `PdfViewer` from `@arbidocs/react/viewers`. */
46
+ viewer?: DocumentPdfViewer;
47
+ /**
48
+ * The version is signed, so locked: marks still go in the markup layer, but there is no
49
+ * "Download with markup" (they are never written into its PDF).
50
+ */
51
+ signed?: boolean;
52
+ }
53
+ export declare function AnnotatedPdfViewer({ file, documentId, version, fileName, shared, folder, editing, onMarkupChange, store: storeOverride, viewer: PdfViewer, signed, ...viewerProps }: AnnotatedPdfViewerProps): import("react").JSX.Element;
54
+ export default AnnotatedPdfViewer;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Choose where a signature goes: the PDF with the annotation overlay's box tool, kept in memory
3
+ * only. The box is not an annotation; it is handed to the Sign dialog, and the backend draws the
4
+ * signature there. Needs no `<DocumentToolsProvider>`.
5
+ */
6
+ import { type ReactElement } from 'react';
7
+ import { type SignatureAppearance } from '@arbidocs/react/document-tools';
8
+ import { type PdfViewerProps } from '@arbidocs/react/viewers';
9
+ import type { DocumentPdfViewer } from './AnnotatedPdfViewer';
10
+ export interface SignaturePlacementViewerProps extends Omit<PdfViewerProps, 'file' | 'renderPageOverlay'> {
11
+ file: Blob;
12
+ documentId: string;
13
+ onCancel: () => void;
14
+ /** The chosen box, or undefined for the default spot (bottom of the last page). */
15
+ onContinue: (appearance: SignatureAppearance | undefined) => void;
16
+ /** The PDF viewer to draw on. Default: the kit `PdfViewer` from `@arbidocs/react/viewers`. */
17
+ viewer?: DocumentPdfViewer;
18
+ }
19
+ export declare function SignaturePlacementViewer({ file, documentId, onCancel, onContinue, viewer: PdfViewer, ...viewerProps }: SignaturePlacementViewerProps): ReactElement;
20
+ export default SignaturePlacementViewer;
@@ -0,0 +1,273 @@
1
+ "use client";
2
+ 'use strict';
3
+
4
+ var react = require('react');
5
+ var annotations = require('@arbidocs/react/annotations');
6
+ var freeze = require('@arbidocs/react/annotations/freeze');
7
+ var documentTools = require('@arbidocs/react/document-tools');
8
+ var viewers = require('@arbidocs/react/viewers');
9
+ var lucideReact = require('lucide-react');
10
+ var jsxRuntime = require('react/jsx-runtime');
11
+ var ui = require('@arbidocs/react/ui');
12
+
13
+ // src/document-tools/viewer/AnnotatedPdfViewer.tsx
14
+ var MARKUP_AUTOSAVE_MS = 2500;
15
+ var MARKUP_PULL_MS = 2e4;
16
+ var FALLBACK_AUTHOR = "You";
17
+ function viewOnly(controller) {
18
+ return { ...controller, readOnly: true, tool: "select", setTool: () => {
19
+ } };
20
+ }
21
+ function AnnotatedPdfViewer({
22
+ file,
23
+ documentId,
24
+ version,
25
+ fileName,
26
+ shared = false,
27
+ folder,
28
+ editing = true,
29
+ onMarkupChange,
30
+ store: storeOverride,
31
+ viewer: PdfViewer = viewers.PdfViewer,
32
+ signed = false,
33
+ ...viewerProps
34
+ }) {
35
+ const { client, user, notify, saveFile, uploadDocument, openDocument, onDocumentsChanged } = documentTools.useDocumentTools();
36
+ const online = documentTools.useIsOnline();
37
+ const onChangeRef = react.useRef(onMarkupChange);
38
+ onChangeRef.current = onMarkupChange;
39
+ const store = react.useMemo(
40
+ () => storeOverride ?? documentTools.createMarkupStore({
41
+ version,
42
+ client,
43
+ onSaved: (snapshot) => onChangeRef.current?.(snapshot)
44
+ }),
45
+ // A new store per document version: its revision and tombstones belong to that markup.
46
+ // eslint-disable-next-line react-hooks/exhaustive-deps
47
+ [storeOverride, client, documentId, version]
48
+ );
49
+ const author = user?.name || FALLBACK_AUTHOR;
50
+ const controller = annotations.useAnnotationLayer({
51
+ documentId,
52
+ store,
53
+ author,
54
+ autosaveMs: MARKUP_AUTOSAVE_MS,
55
+ online,
56
+ pullMs: MARKUP_PULL_MS,
57
+ // An older version is read-only; the hook also asks the store (a guest cannot write).
58
+ readOnly: version !== void 0
59
+ });
60
+ const shown = react.useMemo(
61
+ () => editing && !controller.readOnly ? controller : viewOnly(controller),
62
+ [editing, controller]
63
+ );
64
+ const { flush } = controller;
65
+ react.useEffect(() => {
66
+ if (!editing) void flush();
67
+ }, [editing, flush]);
68
+ const atRisk = controller.dirty && (controller.offline || !!controller.error);
69
+ react.useEffect(() => {
70
+ if (!atRisk) return;
71
+ const warn = (e) => {
72
+ e.preventDefault();
73
+ e.returnValue = "";
74
+ };
75
+ window.addEventListener("beforeunload", warn);
76
+ return () => window.removeEventListener("beforeunload", warn);
77
+ }, [atRisk]);
78
+ const [freezeOpen, setFreezeOpen] = react.useState(false);
79
+ const [busy, setBusy] = react.useState(false);
80
+ const [progress, setProgress] = react.useState(null);
81
+ const [error, setError] = react.useState(null);
82
+ const openFreeze = react.useCallback(() => {
83
+ setError(null);
84
+ setFreezeOpen(true);
85
+ }, []);
86
+ const downloadWithMarkup = react.useCallback(async () => {
87
+ try {
88
+ await controller.flush();
89
+ const { blob, fileName: name } = await documentTools.fetchMarkupPdf(client, documentId, version);
90
+ saveFile(blob, name);
91
+ } catch (e) {
92
+ notify(e instanceof Error ? e.message : "The markup could not be downloaded", "error");
93
+ }
94
+ }, [controller, client, documentId, version, saveFile, notify]);
95
+ const handleFreeze = react.useCallback(
96
+ async (choices) => {
97
+ setBusy(true);
98
+ setError(null);
99
+ try {
100
+ await controller.flush();
101
+ const log = choices.redactionLog ? annotations.redactionLogCsv(controller.layer) : null;
102
+ const bytes = new Uint8Array(await file.arrayBuffer());
103
+ const result = await freeze.freezePdfInBrowser(bytes, controller.layer, {
104
+ ...choices,
105
+ author,
106
+ onProgress: (done, total) => setProgress({ done, total })
107
+ });
108
+ const redacted = result.provenance.redactions.count > 0;
109
+ const newDocId = await documentTools.uploadFrozenCopy(
110
+ uploadDocument,
111
+ result.bytes,
112
+ { documentId, fileName, shared, folder },
113
+ redacted
114
+ );
115
+ if (log) saveFile(new Blob([log], { type: "text/csv" }), documentTools.redactionLogName(fileName));
116
+ if (newDocId) {
117
+ await onDocumentsChanged?.([newDocId], "copy");
118
+ openDocument?.(newDocId);
119
+ }
120
+ notify(
121
+ redacted ? "Redacted copy saved as a new document" : "Annotated copy saved as a new document",
122
+ "success",
123
+ { description: "The original is unchanged and still in your files." }
124
+ );
125
+ for (const warning of result.warnings) notify(warning, "warning");
126
+ setFreezeOpen(false);
127
+ } catch (e) {
128
+ setError(e instanceof Error ? e.message : "The copy could not be created");
129
+ } finally {
130
+ setBusy(false);
131
+ setProgress(null);
132
+ }
133
+ },
134
+ [
135
+ controller,
136
+ author,
137
+ file,
138
+ fileName,
139
+ documentId,
140
+ shared,
141
+ folder,
142
+ uploadDocument,
143
+ saveFile,
144
+ notify,
145
+ onDocumentsChanged,
146
+ openDocument
147
+ ]
148
+ );
149
+ const renderPageOverlay = react.useCallback(
150
+ ({ pageNumber, pageWidthPt }) => /* @__PURE__ */ jsxRuntime.jsx(annotations.AnnotationPageOverlay, { controller: shown, pageNumber, pageWidthPt }),
151
+ [shown]
152
+ );
153
+ const hasMarks = controller.layer.annotations.length > 0;
154
+ return /* @__PURE__ */ jsxRuntime.jsxs(
155
+ "div",
156
+ {
157
+ className: "flex h-full min-h-0 flex-col",
158
+ "data-testid": "annotated-pdf-viewer",
159
+ "data-mode": editing ? "edit" : "view",
160
+ "data-markup-status": controller.status,
161
+ children: [
162
+ editing && /* @__PURE__ */ jsxRuntime.jsx(
163
+ annotations.AnnotationToolbar,
164
+ {
165
+ controller,
166
+ onFreeze: controller.readOnly ? void 0 : openFreeze,
167
+ actions: hasMarks && !controller.dirty && version === void 0 ? /* @__PURE__ */ jsxRuntime.jsxs(
168
+ "button",
169
+ {
170
+ type: "button",
171
+ className: "inline-flex items-center gap-1 text-xs text-primary hover:underline disabled:cursor-not-allowed disabled:text-muted-foreground disabled:no-underline pointer-coarse:min-h-11",
172
+ "data-testid": "annotation-download-markup",
173
+ title: signed ? documentTools.SIGNED_LOCKED_REASON : "Download the PDF with these annotations (opens in Acrobat or Preview)",
174
+ disabled: signed,
175
+ onClick: () => void downloadWithMarkup(),
176
+ children: [
177
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Download, { size: 14 }),
178
+ "Download with markup"
179
+ ]
180
+ }
181
+ ) : null
182
+ }
183
+ ),
184
+ !editing && controller.status === "error" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-b px-3 py-1.5 text-xs text-destructive", "data-testid": "markup-error", children: [
185
+ "The markup could not be loaded: ",
186
+ controller.error
187
+ ] }),
188
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-h-0 flex-1", children: /* @__PURE__ */ jsxRuntime.jsx(PdfViewer, { ...viewerProps, file, renderPageOverlay }) }),
189
+ editing && /* @__PURE__ */ jsxRuntime.jsx(
190
+ annotations.FreezeDialog,
191
+ {
192
+ open: freezeOpen,
193
+ onOpenChange: setFreezeOpen,
194
+ controller,
195
+ onConfirm: handleFreeze,
196
+ busy,
197
+ progress,
198
+ error
199
+ }
200
+ )
201
+ ]
202
+ }
203
+ );
204
+ }
205
+ var SIGNATURE_BOX_COLOR = "#1c7ed6";
206
+ function SignaturePlacementViewer({
207
+ file,
208
+ documentId,
209
+ onCancel,
210
+ onContinue,
211
+ viewer: PdfViewer = viewers.PdfViewer,
212
+ ...viewerProps
213
+ }) {
214
+ const store = react.useMemo(() => annotations.createMemoryStore(), []);
215
+ const controller = annotations.useAnnotationLayer({ documentId, store, author: "signature" });
216
+ const boxes = controller.layer.annotations.filter((a) => a.kind === "box");
217
+ const box = boxes.at(-1);
218
+ const isTooSmall = box !== void 0 && !documentTools.isLegibleSignatureBox(box.rect);
219
+ react.useEffect(() => {
220
+ if (controller.status !== "ready") return;
221
+ controller.setSettings({ colors: { ...controller.settings.colors, box: SIGNATURE_BOX_COLOR } });
222
+ }, [controller.status]);
223
+ react.useEffect(() => {
224
+ if (controller.status !== "ready") return;
225
+ for (const old of boxes.slice(0, -1)) controller.remove(old.id);
226
+ if (box) {
227
+ controller.select(box.id);
228
+ controller.setTool("select");
229
+ } else {
230
+ controller.setTool("box");
231
+ }
232
+ }, [controller.status, boxes.length, box?.id]);
233
+ const redraw = react.useCallback(() => {
234
+ if (box) controller.remove(box.id);
235
+ controller.setTool("box");
236
+ }, [box, controller]);
237
+ const renderPageOverlay = react.useCallback(
238
+ ({ pageNumber, pageWidthPt }) => /* @__PURE__ */ jsxRuntime.jsx(
239
+ annotations.AnnotationPageOverlay,
240
+ {
241
+ controller,
242
+ pageNumber,
243
+ pageWidthPt
244
+ }
245
+ ),
246
+ [controller]
247
+ );
248
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-full min-h-0 flex-col", "data-testid": "signature-placement-viewer", children: [
249
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center gap-2 border-b border-border px-3 py-2 text-sm", children: [
250
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "mr-auto text-muted-foreground", "data-testid": "signature-placement-hint", children: isTooSmall ? "This box is small: the signature will print small. Make it larger to keep it legible." : box ? "Move or resize the box, then continue." : "Drag a box where your signature goes, or continue to sign at the end." }),
251
+ box && /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { type: "button", variant: "ghost", size: "sm", onClick: redraw, children: "Redraw" }),
252
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { type: "button", variant: "outline", size: "sm", onClick: onCancel, children: "Cancel" }),
253
+ /* @__PURE__ */ jsxRuntime.jsx(
254
+ ui.Button,
255
+ {
256
+ type: "button",
257
+ size: "sm",
258
+ onClick: () => onContinue(box ? documentTools.toAppearance(box) : void 0),
259
+ "data-testid": "signature-placement-continue",
260
+ children: "Continue"
261
+ }
262
+ )
263
+ ] }),
264
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-h-0 flex-1", children: /* @__PURE__ */ jsxRuntime.jsx(PdfViewer, { ...viewerProps, file, renderPageOverlay }) })
265
+ ] });
266
+ }
267
+
268
+ exports.AnnotatedPdfViewer = AnnotatedPdfViewer;
269
+ exports.MARKUP_AUTOSAVE_MS = MARKUP_AUTOSAVE_MS;
270
+ exports.MARKUP_PULL_MS = MARKUP_PULL_MS;
271
+ exports.SignaturePlacementViewer = SignaturePlacementViewer;
272
+ //# sourceMappingURL=index.cjs.map
273
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/document-tools/viewer/AnnotatedPdfViewer.tsx","../../../src/document-tools/viewer/SignaturePlacementViewer.tsx"],"names":["KitPdfViewer","useDocumentTools","useIsOnline","useRef","useMemo","createMarkupStore","useAnnotationLayer","useEffect","useState","useCallback","fetchMarkupPdf","redactionLogCsv","freezePdfInBrowser","uploadFrozenCopy","redactionLogName","AnnotationPageOverlay","jsxs","jsx","AnnotationToolbar","SIGNED_LOCKED_REASON","Download","FreezeDialog","createMemoryStore","isLegibleSignatureBox","Button","toAppearance"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * The PDF viewer with the document's MARKUP on it: toolbar, per-page overlay and the freeze dialog.\n *\n * The original is never touched. The marks are the version's markup on the server (native PDF\n * annotations in its `{doc}-markup.pdf`, see `createMarkupStore` in `@arbidocs/react/document-tools`),\n * with the document's own privacy:\n * a shared document has one markup that owners and collaborators edit and guests read; a private\n * one is its owner's. Edits autosave a few seconds after the last change and when the viewer\n * closes; colleagues' changes are merged in. \"Freeze\" renders a new PDF with the marks built in and\n * saves it as a separate document derived from the original (see `uploadFrozenCopy`). Load it\n * lazily: it brings in pdf-lib, which nothing else needs.\n *\n * Needs a `<DocumentToolsProvider>` (API client, user, notify, open, refresh) inside a React Query\n * `QueryClientProvider`. `viewer` is the PDF viewer to draw on (default: the kit `PdfViewer`); a host\n * passes its own binding of it, e.g. one that reports the visible page.\n *\n * `editing` off is the default reading view: the marks show and comments open, read-only, with no\n * toolbar. Unsaved edits still go out when switching from editing to reading.\n */\n\nimport { useCallback, useEffect, useMemo, useRef, useState, type ComponentType } from 'react'\nimport {\n AnnotationPageOverlay,\n AnnotationToolbar,\n FreezeDialog,\n redactionLogCsv,\n useAnnotationLayer,\n type AnnotationController,\n type AnnotationStore,\n type FreezeChoices,\n} from '@arbidocs/react/annotations'\nimport { freezePdfInBrowser } from '@arbidocs/react/annotations/freeze'\nimport {\n createMarkupStore,\n fetchMarkupPdf,\n SIGNED_LOCKED_REASON,\n redactionLogName,\n uploadFrozenCopy,\n useDocumentTools,\n useIsOnline,\n type MarkupSnapshot,\n} from '@arbidocs/react/document-tools'\nimport { PdfViewer as KitPdfViewer, type PdfViewerProps } from '@arbidocs/react/viewers'\nimport { Download } from 'lucide-react'\n\n/** Autosave this long after the last change (the design's \"a few seconds\"). */\nexport const MARKUP_AUTOSAVE_MS = 2500\n/** Look for colleagues' changes this often while idle. */\nexport const MARKUP_PULL_MS = 20_000\n\n/** The PDF viewer the marks are drawn on: the kit viewer's props, with a page-overlay slot. */\nexport type DocumentPdfViewer = ComponentType<PdfViewerProps>\n\nexport interface AnnotatedPdfViewerProps extends Omit<\n PdfViewerProps,\n 'file' | 'renderPageOverlay'\n> {\n file: Blob\n documentId: string\n /** The version on screen when it is not the current one (its markup is shown, read-only). */\n version?: number\n fileName: string | null | undefined\n /** The original's workspace sharing and folder, which the frozen copy takes. */\n shared?: boolean\n folder?: string | null\n /** Annotate mode (toolbar, tools). Off: the marks are shown read-only. Default on. */\n editing?: boolean\n /** After each save: the markup's revision and how many marks it holds. */\n onMarkupChange?: (snapshot: MarkupSnapshot) => void\n /** Where the layer lives; defaults to the version's markup on the server. */\n store?: AnnotationStore\n /** The PDF viewer to draw on. Default: the kit `PdfViewer` from `@arbidocs/react/viewers`. */\n viewer?: DocumentPdfViewer\n /**\n * The version is signed, so locked: marks still go in the markup layer, but there is no\n * \"Download with markup\" (they are never written into its PDF).\n */\n signed?: boolean\n}\n\nconst FALLBACK_AUTHOR = 'You'\n\n/** The same controller, view only: what the overlay gets outside annotate mode. */\nfunction viewOnly(controller: AnnotationController): AnnotationController {\n return { ...controller, readOnly: true, tool: 'select', setTool: () => {} }\n}\n\nexport function AnnotatedPdfViewer({\n file,\n documentId,\n version,\n fileName,\n shared = false,\n folder,\n editing = true,\n onMarkupChange,\n store: storeOverride,\n viewer: PdfViewer = KitPdfViewer,\n signed = false,\n ...viewerProps\n}: AnnotatedPdfViewerProps) {\n const { client, user, notify, saveFile, uploadDocument, openDocument, onDocumentsChanged } =\n useDocumentTools()\n const online = useIsOnline()\n const onChangeRef = useRef(onMarkupChange)\n onChangeRef.current = onMarkupChange\n const store = useMemo(\n () =>\n storeOverride ??\n createMarkupStore({\n version,\n client,\n onSaved: (snapshot) => onChangeRef.current?.(snapshot),\n }),\n // A new store per document version: its revision and tombstones belong to that markup.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [storeOverride, client, documentId, version]\n )\n const author = user?.name || FALLBACK_AUTHOR\n const controller = useAnnotationLayer({\n documentId,\n store,\n author,\n autosaveMs: MARKUP_AUTOSAVE_MS,\n online,\n pullMs: MARKUP_PULL_MS,\n // An older version is read-only; the hook also asks the store (a guest cannot write).\n readOnly: version !== undefined,\n })\n const shown = useMemo(\n () => (editing && !controller.readOnly ? controller : viewOnly(controller)),\n [editing, controller]\n )\n\n // Leaving annotate mode: write what is still waiting on the autosave timer.\n const { flush } = controller\n useEffect(() => {\n if (!editing) void flush()\n }, [editing, flush])\n\n // Edits that cannot be saved right now (offline, or the server refused): warn before leaving.\n const atRisk = controller.dirty && (controller.offline || !!controller.error)\n useEffect(() => {\n if (!atRisk) return\n const warn = (e: BeforeUnloadEvent) => {\n e.preventDefault()\n e.returnValue = ''\n }\n window.addEventListener('beforeunload', warn)\n return () => window.removeEventListener('beforeunload', warn)\n }, [atRisk])\n\n const [freezeOpen, setFreezeOpen] = useState(false)\n const [busy, setBusy] = useState(false)\n const [progress, setProgress] = useState<{ done: number; total: number } | null>(null)\n const [error, setError] = useState<string | null>(null)\n\n const openFreeze = useCallback(() => {\n setError(null)\n setFreezeOpen(true)\n }, [])\n\n const downloadWithMarkup = useCallback(async () => {\n try {\n await controller.flush()\n const { blob, fileName: name } = await fetchMarkupPdf(client, documentId, version)\n saveFile(blob, name)\n } catch (e) {\n notify(e instanceof Error ? e.message : 'The markup could not be downloaded', 'error')\n }\n }, [controller, client, documentId, version, saveFile, notify])\n\n const handleFreeze = useCallback(\n async (choices: FreezeChoices) => {\n setBusy(true)\n setError(null)\n try {\n await controller.flush()\n // The log is taken from the layer as it is frozen; it never holds the redacted text.\n const log = choices.redactionLog ? redactionLogCsv(controller.layer) : null\n const bytes = new Uint8Array(await file.arrayBuffer())\n const result = await freezePdfInBrowser(bytes, controller.layer, {\n ...choices,\n author,\n onProgress: (done, total) => setProgress({ done, total }),\n })\n const redacted = result.provenance.redactions.count > 0\n const newDocId = await uploadFrozenCopy(\n uploadDocument,\n result.bytes,\n { documentId, fileName, shared, folder },\n redacted\n )\n if (log) saveFile(new Blob([log], { type: 'text/csv' }), redactionLogName(fileName))\n if (newDocId) {\n // The copy joins the list beside the original, which stays where it was.\n await onDocumentsChanged?.([newDocId], 'copy')\n openDocument?.(newDocId)\n }\n notify(\n redacted\n ? 'Redacted copy saved as a new document'\n : 'Annotated copy saved as a new document',\n 'success',\n { description: 'The original is unchanged and still in your files.' }\n )\n for (const warning of result.warnings) notify(warning, 'warning')\n setFreezeOpen(false)\n } catch (e) {\n setError(e instanceof Error ? e.message : 'The copy could not be created')\n } finally {\n setBusy(false)\n setProgress(null)\n }\n },\n [\n controller,\n author,\n file,\n fileName,\n documentId,\n shared,\n folder,\n uploadDocument,\n saveFile,\n notify,\n onDocumentsChanged,\n openDocument,\n ]\n )\n\n const renderPageOverlay = useCallback(\n ({ pageNumber, pageWidthPt }: { pageNumber: number; pageWidthPt: number | undefined }) => (\n <AnnotationPageOverlay controller={shown} pageNumber={pageNumber} pageWidthPt={pageWidthPt} />\n ),\n [shown]\n )\n\n const hasMarks = controller.layer.annotations.length > 0\n\n return (\n <div\n className=\"flex h-full min-h-0 flex-col\"\n data-testid=\"annotated-pdf-viewer\"\n data-mode={editing ? 'edit' : 'view'}\n data-markup-status={controller.status}\n >\n {editing && (\n <AnnotationToolbar\n controller={controller}\n onFreeze={controller.readOnly ? undefined : openFreeze}\n actions={\n hasMarks && !controller.dirty && version === undefined ? (\n <button\n type=\"button\"\n className=\"inline-flex items-center gap-1 text-xs text-primary hover:underline disabled:cursor-not-allowed disabled:text-muted-foreground disabled:no-underline pointer-coarse:min-h-11\"\n data-testid=\"annotation-download-markup\"\n title={\n signed\n ? SIGNED_LOCKED_REASON\n : 'Download the PDF with these annotations (opens in Acrobat or Preview)'\n }\n disabled={signed}\n onClick={() => void downloadWithMarkup()}\n >\n <Download size={14} />\n Download with markup\n </button>\n ) : null\n }\n />\n )}\n {!editing && controller.status === 'error' && (\n <div className=\"border-b px-3 py-1.5 text-xs text-destructive\" data-testid=\"markup-error\">\n The markup could not be loaded: {controller.error}\n </div>\n )}\n <div className=\"min-h-0 flex-1\">\n <PdfViewer {...viewerProps} file={file} renderPageOverlay={renderPageOverlay} />\n </div>\n {editing && (\n <FreezeDialog\n open={freezeOpen}\n onOpenChange={setFreezeOpen}\n controller={controller}\n onConfirm={handleFreeze}\n busy={busy}\n progress={progress}\n error={error}\n />\n )}\n </div>\n )\n}\n\nexport default AnnotatedPdfViewer\n","/**\n * Choose where a signature goes: the PDF with the annotation overlay's box tool, kept in memory\n * only. The box is not an annotation; it is handed to the Sign dialog, and the backend draws the\n * signature there. Needs no `<DocumentToolsProvider>`.\n */\n\nimport { useCallback, useEffect, useMemo, type ReactElement } from 'react'\nimport {\n AnnotationPageOverlay,\n createMemoryStore,\n useAnnotationLayer,\n type BoxAnnotation,\n} from '@arbidocs/react/annotations'\nimport {\n isLegibleSignatureBox,\n toAppearance,\n type SignatureAppearance,\n} from '@arbidocs/react/document-tools'\nimport { Button } from '@arbidocs/react/ui'\nimport { PdfViewer as KitPdfViewer, type PdfViewerProps } from '@arbidocs/react/viewers'\nimport type { DocumentPdfViewer } from './AnnotatedPdfViewer'\n\nconst SIGNATURE_BOX_COLOR = '#1c7ed6'\n\nexport interface SignaturePlacementViewerProps extends Omit<\n PdfViewerProps,\n 'file' | 'renderPageOverlay'\n> {\n file: Blob\n documentId: string\n onCancel: () => void\n /** The chosen box, or undefined for the default spot (bottom of the last page). */\n onContinue: (appearance: SignatureAppearance | undefined) => void\n /** The PDF viewer to draw on. Default: the kit `PdfViewer` from `@arbidocs/react/viewers`. */\n viewer?: DocumentPdfViewer\n}\n\nexport function SignaturePlacementViewer({\n file,\n documentId,\n onCancel,\n onContinue,\n viewer: PdfViewer = KitPdfViewer,\n ...viewerProps\n}: SignaturePlacementViewerProps): ReactElement {\n const store = useMemo(() => createMemoryStore(), [])\n const controller = useAnnotationLayer({ documentId, store, author: 'signature' })\n const boxes = controller.layer.annotations.filter((a): a is BoxAnnotation => a.kind === 'box')\n const box = boxes.at(-1)\n const isTooSmall = box !== undefined && !isLegibleSignatureBox(box.rect)\n\n // Draw with the box tool; once there is a box, select it so it can be moved or resized.\n useEffect(() => {\n if (controller.status !== 'ready') return\n controller.setSettings({ colors: { ...controller.settings.colors, box: SIGNATURE_BOX_COLOR } })\n // eslint-disable-next-line react-hooks/exhaustive-deps -- once, when the layer is ready\n }, [controller.status])\n useEffect(() => {\n if (controller.status !== 'ready') return\n // One signature box: drawing another replaces it.\n for (const old of boxes.slice(0, -1)) controller.remove(old.id)\n if (box) {\n controller.select(box.id)\n controller.setTool('select')\n } else {\n controller.setTool('box')\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps -- react to the boxes only\n }, [controller.status, boxes.length, box?.id])\n\n const redraw = useCallback(() => {\n if (box) controller.remove(box.id)\n controller.setTool('box')\n }, [box, controller])\n\n const renderPageOverlay = useCallback(\n ({ pageNumber, pageWidthPt }: { pageNumber: number; pageWidthPt: number | undefined }) => (\n <AnnotationPageOverlay\n controller={controller}\n pageNumber={pageNumber}\n pageWidthPt={pageWidthPt}\n />\n ),\n [controller]\n )\n\n return (\n <div className=\"flex h-full min-h-0 flex-col\" data-testid=\"signature-placement-viewer\">\n <div className=\"flex flex-wrap items-center gap-2 border-b border-border px-3 py-2 text-sm\">\n <span className=\"mr-auto text-muted-foreground\" data-testid=\"signature-placement-hint\">\n {isTooSmall\n ? 'This box is small: the signature will print small. Make it larger to keep it legible.'\n : box\n ? 'Move or resize the box, then continue.'\n : 'Drag a box where your signature goes, or continue to sign at the end.'}\n </span>\n {box && (\n <Button type=\"button\" variant=\"ghost\" size=\"sm\" onClick={redraw}>\n Redraw\n </Button>\n )}\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={onCancel}>\n Cancel\n </Button>\n <Button\n type=\"button\"\n size=\"sm\"\n onClick={() => onContinue(box ? toAppearance(box) : undefined)}\n data-testid=\"signature-placement-continue\"\n >\n Continue\n </Button>\n </div>\n <div className=\"min-h-0 flex-1\">\n <PdfViewer {...viewerProps} file={file} renderPageOverlay={renderPageOverlay} />\n </div>\n </div>\n )\n}\n\nexport default SignaturePlacementViewer\n"]}
@@ -0,0 +1,2 @@
1
+ export { AnnotatedPdfViewer, MARKUP_AUTOSAVE_MS, MARKUP_PULL_MS, type AnnotatedPdfViewerProps, type DocumentPdfViewer, } from './AnnotatedPdfViewer';
2
+ export { SignaturePlacementViewer, type SignaturePlacementViewerProps, } from './SignaturePlacementViewer';