3.2 KiB
permissions/permissions.ts
(no submodules)
Purpose
Probe and subscribe to clipboard permission state via the browser's
Permissions API. checkPermissions returns a snapshot of the
clipboard-read and clipboard-write permission states with graceful
degradation to "prompt" when the API is missing or a query rejects.
onPermissionChange subscribes a callback to PermissionStatus.change
events on both descriptors so UI surfaces can reflect real-time grants
and revocations without polling.
Features
checkPermissions(nav)—{ read, write }snapshot; never throws.onPermissionChange(nav, cb)— subscribe with one callback, unsubscribe with a single returned function.- Tolerant of partial API support: falls back to
PermissionStatus.onchangewhenaddEventListeneris unavailable. - Tolerant of permission-query rejection: skips that slot without re-throwing.
Usage: Basic
import { checkPermissions } from "@suaveplan/clipboard";
const { read, write } = await checkPermissions(navigator);
if (read === "denied" || write === "denied") {
showFallbackUi();
}
Usage: Advanced
import { onPermissionChange } from "@suaveplan/clipboard";
const unsubscribe = await onPermissionChange(
navigator,
(snapshot, descriptor) => {
console.info(
"[clipboard] permission change",
descriptor,
snapshot,
);
if (snapshot.read === "granted" && snapshot.write === "granted") {
enableCopyButtons();
}
},
);
// later — on unmount / dispose
unsubscribe();
API Reference
checkPermissions(nav: ClipboardNavigator): Promise<PermissionResult>
Resolves with { read, write }. Each slot is one of "granted",
"denied", "prompt". Returns { read: "prompt", write: "prompt" }
when nav.permissions is undefined, and "prompt" for any individual
descriptor whose query() rejects or returns an unknown state.
onPermissionChange(nav, cb): Promise<() => void>
Subscribes cb to permission changes on both clipboard-read and
clipboard-write. Returns an unsubscribe function. The callback receives
the latest PermissionResult snapshot plus the descriptor name whose
state changed. The change handler internally re-runs checkPermissions
so both read and write are always up to date on every callback.
Implementation Notes
The Permissions API exposes two listener mechanisms — addEventListener
and onchange. Some platforms (older WebKit / mobile) support only one,
so the module attaches via addEventListener when available and falls
back to assigning onchange otherwise. The unsubscribe function clears
the corresponding mechanism for each subscription. The
checkPermissions helper normalises unknown state strings to "prompt"
so callers never have to defend against future spec values. Query
rejection is treated as "prompt" rather than "denied" because a
rejection typically signals "API not supported" rather than "user
explicitly refused" — pessimistic mapping would block correct callers in
older browsers. Tests cover both addEventListener and onchange paths,
plus the unsubscribe contract.