mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-13 15:13:07 +00:00
Collection contentEvent (hidden, sem hooks, sem PII) + beacon público POST /api/content-events fail-soft, download contado no servidor na rota de mídia, agregação em uma query group-by e a coluna "Circulação" na lista interna + painel na ficha (port classe-a-classe do artefato estendido, crítica final do designer certificada).
60 lines
1.8 KiB
TypeScript
60 lines
1.8 KiB
TypeScript
'use client'
|
|
|
|
import { CheckIcon, CopyIcon } from 'lucide-react'
|
|
|
|
import { Button } from '@/components/ui/button'
|
|
import { copyFeedbackLabels, copyFeedbackLiveMessages, useCopyFeedback } from '@/lib/copyFeedback'
|
|
import { cn } from '@/lib/utils'
|
|
|
|
type CopyLinkButtonProps = {
|
|
/** Absolute URL or a same-origin path — resolved against the current origin on click. */
|
|
url: string
|
|
variant?: 'default' | 'outline' | 'ghost'
|
|
className?: string
|
|
/**
|
|
* Called only when the text actually landed in the clipboard (C213 counts the
|
|
* share-by-link of a piece). The control itself never counts: it is shared
|
|
* with the cut surfaces.
|
|
*/
|
|
onCopied?: () => void
|
|
}
|
|
|
|
/**
|
|
* The one copy-to-clipboard control of the cut surfaces (public page, result
|
|
* card, library): same feedback label/auto-reset and screen-reader live region.
|
|
* A relative path is resolved against the current origin on click, so a server
|
|
* component can pass `publicPath` directly.
|
|
*/
|
|
export const CopyLinkButton = ({
|
|
url,
|
|
variant = 'outline',
|
|
className,
|
|
onCopied,
|
|
}: CopyLinkButtonProps) => {
|
|
const { feedback, copy } = useCopyFeedback()
|
|
|
|
return (
|
|
<>
|
|
<Button
|
|
type="button"
|
|
variant={variant}
|
|
className={cn('min-h-10', className)}
|
|
onClick={() => {
|
|
void copy(new URL(url, window.location.origin).toString()).then((copied) => {
|
|
if (copied) onCopied?.()
|
|
})
|
|
}}
|
|
>
|
|
{feedback === 'copied' ? (
|
|
<CheckIcon data-icon="inline-start" aria-hidden="true" />
|
|
) : (
|
|
<CopyIcon data-icon="inline-start" aria-hidden="true" />
|
|
)}
|
|
{copyFeedbackLabels[feedback]}
|
|
</Button>
|
|
<span aria-live="polite" className="sr-only">
|
|
{copyFeedbackLiveMessages[feedback]}
|
|
</span>
|
|
</>
|
|
)
|
|
}
|