{{.Heading}} {{.DocTitle}} {{.BackLabel}} {{if .Error}}{{template "callout" (dict "Body" .Error "Tone" "negative" "Alert" true)}}{{end}} {{/* Who reaches it today. An empty list says so in words rather than rendering an empty table, because a table with no rows reads as a thing that failed to load. Each row's revoke is its own , not a link: revoking is a mutation and a GET that changes state is one a prefetcher can fire. That is also why the address rides a hidden field rather than the URL. */}} {{if .Grants}} {{range .Grants}} {{.Address}} {{.Role}} {{$.RevokeButton}} {{end}} {{else}} {{.EmptyBody}} {{end}} {{/* Adding somebody. The role is a pair of option cards rather than a select so both are visible without opening anything. Reader is checked by default: the safer of the two is the one a person gets by not choosing. Scriptless, per spec §6.2: a plain POST, and a 303 back here afterwards so a reload never re-posts. */}} {{template "field" (dict "ID" "share-address" "Name" "address" "Type" "email" "Label" .AddressLabel "Autocomplete" "email" "Required" true)}} {{template "choice-field" (dict "Legend" .RoleLabel "Name" "role" "Options" .RoleChoices)}} {{.ShareButton}} {{/* The third rung: a read-only link anyone can follow, signed in or not. One whichever way the switch currently points, with the direction in a hidden field — so a page left open in a tab cannot turn publishing back on from a button that still says "off". The link appears only in the render that follows the publish that minted it — the database holds a SHA-256 and cannot produce a URL (suite ruling 16). It is a read-only field rather than a link: it is meant to be copied into a message, not followed from here. The Copy button is fixtures/share-link.mjs's, hidden until that script runs; without it the field selects on focus for a manual copy. */}} {{.PublicHeading}} {{.PublicBody}} {{if .Published}} {{if .PublicURL}} {{template "callout" (dict "Body" .OnceWarning "Tone" "warning")}} {{.CopyButton}} {{else}} {{.PublishedBody}} {{end}} {{.CopyHint}} {{.ReplaceButton}} {{.UnpublishBtn}} {{else}} {{.PublishButton}} {{end}}