Files
skills/docs/foundation/data/clipboard/src/permissions/permissions.md
2026-05-29 08:20:56 +01:00

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.onchange when addEventListener is 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.