A PDF viewer with signature fields: a rail of page thumbnails, a toolbar, the page and a panel of signers.
The server owns page and zoom. The page is drawn by pdf.js in the browser when a src is given (the
DevactionUI.PdfViewer hook loads pdfjs-dist with import() and takes the worker from worker_src), and
the :sheet slot is the server-rendered page that shows until then, and stays when there is no src, so the
viewer works, and is testable, without pdf.js. The toolbar (toolbar/1) and the panel (signatures/1) are
plain function components that work without any JavaScript.
The signature fields come as a list of maps %{page, x, y, w, h, signer, state}, the box in percent of the
page and the state one of :signed (green), :mine ("you sign here": amber, dashed, with a small label)
and :pending (neutral). A field may carry a label (the word on it, such as "Signed"); the hook never draws
fields, they are part of the markup, so they sit over the page at any zoom.
The hook sends page and zoom to the server with pushEventTo, to the events named by page_event and
zoom_event, as %{"page" => 3} and %{"zoom" => 125}, which are the payloads of the buttons too. Keys:
+, - and 0 zoom, PageUp, PageDown, Home and End turn pages, and the thumbnails are a listbox that the
arrows move through. zoom_in/1, zoom_out/1, clamp_page/2 and my_page/1 are the server's side of that.
Summary
Functions
A page number held to 1..total.
The page of the first field the viewer's person has to sign, or nil.
The panel of signers: avatar, name, role and a status for each, a note, and the jump to my signature.
The toolbar of the viewer: the file name, the zoom, the page n of total and the jump to my signature.
A PDF viewer with a thumbnail rail, a toolbar, the page with its signature fields, and a panel.
The zoom one step in from zoom, which stops at the biggest step.
The zoom one step out from zoom, which stops at the smallest step.
Functions
A page number held to 1..total.
The page of the first field the viewer's person has to sign, or nil.
@spec signatures(map()) :: Phoenix.LiveView.Rendered.t()
The panel of signers: avatar, name, role and a status for each, a note, and the jump to my signature.
Attributes
title(:string) (required) - the heading of the panel, such asSignatures.signers(:list) (required) -%{name, role, status, status_label}per signer;statusis:signedor:pending,toneis:red,:indigo,:greenor:grayandmine: truemarks the viewer's person.jump_event(:any) - the jump to my signature: a string or a%JS{}. Defaults tonil.jump_label(:string) - the text of the primary button, which shows when it is given. Defaults tonil.target(:any) - Defaults tonil.class(:any) - Defaults tonil.- Global attributes are accepted.
Slots
note- a note under the signers, such as where the field is.
@spec toolbar(map()) :: Phoenix.LiveView.Rendered.t()
The toolbar of the viewer: the file name, the zoom, the page n of total and the jump to my signature.
Attributes
name(:string) (required)page(:integer) (required)pages(:integer) (required)zoom(:integer) (required)zoom_event(:string) (required) - sent withzoom, the next step in or out.jump_event(:any) - the jump to my signature: a string or a%JS{}. Defaults tonil.target(:any) - Defaults tonil.page_label(:string) (required)zoom_label(:string) (required)zoom_out_label(:string) (required)zoom_in_label(:string) (required)jump_label(:string) - names the jump button; the button shows when it is given. Defaults tonil.class(:any) - Defaults tonil.- Global attributes are accepted.
Slots
jump_icon- the icon of the jump button, such as a signature.zoom_out_icon- replaces the minus sign.zoom_in_icon- replaces the plus sign.actions- more buttons at the end, such as a download.
@spec viewer(map()) :: Phoenix.LiveView.Rendered.t()
A PDF viewer with a thumbnail rail, a toolbar, the page with its signature fields, and a panel.
Attributes
id(:string) (required)name(:string) (required) - the file name, shown in the toolbar.page(:integer) - the current page, owned by the server. Defaults to1.pages(:integer) (required) - how many pages the file has.zoom(:integer) - the zoom in percent, owned by the server. Defaults to100.fields(:list) - signature fields,%{page, x, y, w, h, signer, state}with the box in percent of the page. Defaults to[].src(:string) - the URL of the PDF; pdf.js draws it. Without it the:sheetslot is the page. Defaults tonil.worker_src(:string) - the URL of the pdf.js worker (pdf.worker.min.mjs), set by the host. Defaults tonil.page_width(:integer) - the width of a page in px at 100%. Defaults to420.page_height(:integer) - the height of a page in px at 100%. Defaults to560.page_event(:string) (required) - sent withpageby the thumbnails and the keys.zoom_event(:string) (required) - sent withzoomby the buttons and the keys.jump_event(:any) - the jump to my signature: a string or a%JS{}. Defaults tonil.field_event(:any) - sent by a field when pressed, withpageandsigner. Defaults tonil.target(:any) - aphx-target(a@myself) when used inside a LiveComponent. Defaults tonil.pages_label(:string) (required) - names the rail of thumbnails.page_label(:string) (required) - the word for a page, such asPage.zoom_label(:string) (required) - names the zoom value, such asZoom.zoom_out_label(:string) (required)zoom_in_label(:string) (required)jump_label(:string) - names the jump button of the toolbar. Defaults tonil.mine_label(:string) - the small label on the field of the viewer's person. Defaults tonil.class(:any) - the height of the viewer, 680px by default. Defaults to"h-[680px]".- Global attributes are accepted.
Slots
sheet- the server-rendered page, given the page number; it shows until pdf.js draws the file.jump_icon- the icon of the jump button, such as a signature.zoom_out_icon- replaces the minus sign.zoom_in_icon- replaces the plus sign.actions- more buttons at the end of the toolbar, such as a download.panel- the right panel, usuallysignatures/1.
The zoom one step in from zoom, which stops at the biggest step.
The zoom one step out from zoom, which stops at the smallest step.