Allow heading tags (h1-h6) in ContentSanitizer so news editor headings render

This commit is contained in:
2026-06-04 07:52:57 +02:00
parent 0b33a1b074
commit 15870ddb1f
191 changed files with 15453 additions and 1786 deletions

View File

@@ -0,0 +1,53 @@
import React from 'react'
export default function BeforeAfterSlider({ beforeUrl, afterUrl, beforeAlt = 'Original image', afterAlt = 'Enhanced image' }) {
const [position, setPosition] = React.useState(50)
if (!beforeUrl || !afterUrl) {
return null
}
return (
<div className="rounded-[28px] border border-white/10 bg-[#08111d] p-5 shadow-[0_18px_48px_rgba(2,6,23,0.2)]">
<div className="flex items-center justify-between gap-3">
<div>
<p className="text-[11px] font-semibold uppercase tracking-[0.22em] text-slate-400">Before / after</p>
<h3 className="mt-2 text-xl font-semibold tracking-[-0.03em] text-white">Compare the original with the enhanced result</h3>
</div>
<span className="rounded-full border border-white/10 bg-white/[0.05] px-3 py-1 text-xs font-semibold uppercase tracking-[0.16em] text-slate-200">{position}%</span>
</div>
<div className="relative mt-5 overflow-hidden rounded-[24px] border border-white/10 bg-black/40">
<img src={beforeUrl} alt={beforeAlt} className="block w-full object-cover" />
<div className="pointer-events-none absolute inset-y-0 left-0 overflow-hidden border-r border-white/80" style={{ width: `${position}%` }}>
<img src={afterUrl} alt={afterAlt} className="block h-full w-full object-cover" />
</div>
<div className="pointer-events-none absolute inset-y-0 left-0" style={{ left: `calc(${position}% - 1px)` }}>
<div className="flex h-full items-center">
<div className="flex h-10 w-10 -translate-x-1/2 items-center justify-center rounded-full border border-white/80 bg-black/60 text-white shadow-[0_0_30px_rgba(15,23,42,0.5)]">
<i className="fa-solid fa-left-right text-xs" />
</div>
</div>
</div>
<div className="pointer-events-none absolute left-3 top-3 rounded-full border border-white/10 bg-[#08111dd8] px-3 py-1 text-[11px] font-semibold uppercase tracking-[0.16em] text-slate-100">Original</div>
<div className="pointer-events-none absolute right-3 top-3 rounded-full border border-emerald-300/20 bg-emerald-400/12 px-3 py-1 text-[11px] font-semibold uppercase tracking-[0.16em] text-emerald-100">Enhanced</div>
</div>
<label className="mt-5 block">
<span className="sr-only">Adjust before and after comparison slider</span>
<input
type="range"
min="0"
max="100"
step="1"
value={position}
onChange={(event) => setPosition(Number(event.target.value || 50))}
className="h-2 w-full cursor-pointer appearance-none rounded-full bg-white/10 accent-sky-300"
aria-label="Adjust before and after comparison slider"
/>
</label>
</div>
)
}

View File

@@ -0,0 +1,34 @@
import React from 'react'
const TONES = {
pending: 'border-white/10 bg-white/[0.05] text-slate-200',
queued: 'border-sky-300/20 bg-sky-400/12 text-sky-100',
processing: 'border-violet-300/20 bg-violet-400/12 text-violet-100',
completed: 'border-emerald-300/20 bg-emerald-400/12 text-emerald-100',
failed: 'border-rose-300/20 bg-rose-400/12 text-rose-100',
cancelled: 'border-amber-300/20 bg-amber-400/12 text-amber-100',
expired: 'border-white/10 bg-white/[0.05] text-slate-300',
unknown: 'border-white/10 bg-white/[0.04] text-slate-300',
}
const LABELS = {
pending: 'Pending',
queued: 'Queued',
processing: 'Processing',
completed: 'Completed',
failed: 'Failed',
cancelled: 'Cancelled',
expired: 'Expired',
}
export default function EnhanceStatusBadge({ status, className = '' }) {
const key = String(status || '').toLowerCase()
const tone = TONES[key] || TONES.unknown
const label = LABELS[key] || 'Unknown'
return (
<span className={`inline-flex items-center rounded-full border px-3 py-1 text-[11px] font-semibold uppercase tracking-[0.16em] ${tone} ${className}`.trim()}>
{label}
</span>
)
}

View File

@@ -0,0 +1,14 @@
import React from 'react'
export default function EnhanceStubWarning({ config, moderation = false, className = '' }) {
if (!config?.showStubWarning) {
return null
}
return (
<div className={`rounded-2xl border border-amber-300/20 bg-amber-400/10 px-4 py-3 text-sm text-amber-50 ${className}`.trim()}>
<div>Skinbase Enhance is currently running in preview mode. The generated result is a workflow placeholder until the real upscaling worker is enabled.</div>
{moderation ? <div className="mt-2 text-xs uppercase tracking-[0.14em] text-amber-100/80">Engine: {config.engine}. This is not a real AI upscale result.</div> : null}
</div>
)
}