component Clipboard { outputs { copy(payload: { value: string; sourceEvent?: Event }) success(payload: { value: string; sourceEvent?: Event }) error(payload: { error: Error | string; value: string; sourceEvent?: Event }) } props { value: string = "" label: string = "Copy" copiedLabel: string = "Copied" errorLabel: string = "Copy failed" title: string = "Clipboard" description: string = "" code: boolean = true size: string = "default" color: string = "primary" disabled: boolean = false class: string = "" } state status = "idle" functions { client function resetStatus() { status = "idle" } client function copySucceeded() { status = "success" output.success({ value: value }) setTimeout(resetStatus, 1600) } client function copyFailed(error) { status = "error" output.error({ error: error, value: value }) setTimeout(resetStatus, 1600) } client function copyValue(sourceEvent) { if (disabled || status === "copying") { return } status = "copying" output.copy({ value: value, sourceEvent: sourceEvent }) if (!window.navigator.clipboard || !window.navigator.clipboard.writeText) { copyFailed(new Error("Clipboard API is unavailable")) return } return window.navigator.clipboard.writeText(value).then(copySucceeded).catch(copyFailed) } } view {
{#if title}{title}{/if} {#if description}

{description}

{/if}
{#if code} {value} {:else} {value} {/if}
} style { .wrn-clipboard { display: grid; gap: 0.5rem; color: var(--wrn-color-text); } .wrn-clipboard__title { font-size: 0.875rem; } .wrn-clipboard__description { margin: 0; color: var(--wrn-color-muted); font-size: 0.8rem; } .wrn-clipboard__control { display: flex; min-width: 0; align-items: stretch; overflow: hidden; border: 1px solid var(--wrn-color-border); border-radius: var(--wrn-radius); background: var(--wrn-color-surface); box-shadow: var(--wrn-shadow-1); } .wrn-clipboard__value { min-width: 0; flex: 1; overflow: auto; padding: 0.7rem 0.85rem; color: var(--wrn-color-text); background: var(--wrn-color-surface-2); font: inherit; font-family: var(--wrn-font-mono, ui-monospace, monospace); white-space: nowrap; } .wrn-clipboard__button { display: inline-flex; align-items: center; gap: 0.4rem; padding: 0.6rem 0.85rem; border: 0; border-left: 1px solid var(--wrn-color-border); color: var(--wrn-color-primary); background: transparent; font: inherit; font-size: 0.8rem; font-weight: 700; cursor: pointer; } .wrn-clipboard__button:hover { background: var(--wrn-color-primary-soft); } .wrn-clipboard__button:focus-visible { outline: 2px solid var(--wrn-color-focus); outline-offset: -3px; } .wrn-clipboard__button:disabled { cursor: not-allowed; opacity: 0.55; } .wrn-clipboard[data-status="success"] .wrn-clipboard__button { color: var(--wrn-color-success); } .wrn-clipboard[data-status="error"] .wrn-clipboard__button { color: var(--wrn-color-danger); } .wrn-clipboard__icon { width: 1rem; height: 1rem; flex: none; } } }