Files
member-console/internal/embeds/static/copy-button.js
T
cgalo5758 6dbce6140f Type the ConfigSpec seam and move the connect target to core
Register bool and duration ConfigSpec keys from the Default's type, move
fedwiki's four sync knobs and discourse's two into their integrations'
ConfigSpecs, and replace core's read of fedwiki-custom-domain-target
with a core domains-connect-target key resolved once and threaded
through server and worker config.

Generate init's optional-integration scaffold sections from each
registered ConfigSpec instead of the hand-maintained list, and reword
the Temporal boot warning generically.

Archives the integration-config-parity change; status bookkeeping and
the verify-skill doc follow with the test-stack commit.
2026-08-01 04:13:48 -05:00

46 lines
2.0 KiB
JavaScript

// Copy-to-clipboard for `.js-copy` buttons, loaded by the Domains page only
// (domains-registry D9).
//
// Delegated on document so it survives the claim status view's 5s HTMX
// self-swap, and CSP-safe: strict CSP drops inline handlers, so every button
// carries its payload in data-copy and nothing else.
//
// An integration's dashboard card that needs the same behavior ships its own
// copy inside its card script (the member-dashboard contract requires card
// scripts to come from the integration's own static mount), so this handler
// may be functionally duplicated by integration bundles. Core's copy and an
// integration's never load on the same page — this one belongs to core
// surfaces — so there is no double-fire and neither may be deleted in favor
// of the other.
(function () {
document.addEventListener("click", function (evt) {
var button = evt.target.closest(".js-copy");
if (!button || !button.dataset.copy) return;
// Clipboard API requires a secure context (HTTPS or localhost — both true
// for every supported deployment).
if (!navigator.clipboard) return;
var showFeedback = function (html) {
if (button.dataset.copyRestore) return; // feedback already showing
button.dataset.copyRestore = button.innerHTML;
button.innerHTML = html;
setTimeout(function () {
// The 5s poll may have replaced the node; only restore if it's live.
if (button.isConnected && button.dataset.copyRestore) {
button.innerHTML = button.dataset.copyRestore;
delete button.dataset.copyRestore;
}
}, 1500);
};
navigator.clipboard
.writeText(button.dataset.copy)
.then(function () {
showFeedback('<span class="small text-success">Copied ✓</span>');
})
.catch(function () {
// Permission denied or document unfocused — tell the member instead
// of failing silently (and swallow the rejection).
showFeedback('<span class="small text-danger">Copy failed</span>');
});
});
})();