DKBezeler
diklein/dk-bezelerFreeComponent
Display components for DKBezeler's baked device frames: a framed still as a plain image, and the light and dark video versions swapped with CSS. Bake the assets with npx @diklein/dkbezeler.
Install it
npx shadcn@latest add https://diklein.com/r/dk-bezeler.jsonSource
1import type { ReactNode } from 'react'23/* Display components for DKBezeler's baked outputs. Both are deliberately plain:4 * the bake did the hard part, so a framed still is just an image and a framed clip5 * is just a pair of videos. No dependencies, no client JS. */67export interface DKBezelImageProps {8 /** The baked -framed.png. */9 src: string10 alt?: string11 /** Intrinsic pixels of the baked PNG (dkbezeler prints them). Declaring them12 * reserves layout before the file arrives. */13 width: number14 height: number15 /** Display width cap. The bake is transparent outside the device, so it sits on16 * any background. */17 maxWidth?: number18 className?: string19 /** Render the image yourself (e.g. with next/image). */20 renderImage?: (src: string, ctx: { alt: string; className: string }) => ReactNode21}2223export function DKBezelImage({ src, alt, width, height, maxWidth = 460, className, renderImage }: DKBezelImageProps) {24 return (25 <figure className={`dkbz-figure${className ? ` ${className}` : ''}`} style={{ maxWidth }}>26 {renderImage ? (27 renderImage(src, { alt: alt ?? '', className: 'dkbz-img' })28 ) : (29 <img src={src} alt={alt ?? ''} width={width} height={height} className="dkbz-img" loading="lazy" />30 )}31 </figure>32 )33}3435export interface DKBezelVideoProps {36 /** Base path of the baked pair: `${base}-light.mp4`, `${base}-dark.mp4` and the37 * matching .jpg posters, exactly as dkbezeler wrote them. */38 base: string39 /** Accessible label for the clip. */40 alt?: string41 /** Intrinsic pixels of the baked videos (dkbezeler prints them). Declares the42 * aspect ratio so the box holds its size before video metadata arrives (a bare43 * <video> is 300x150 until then, which costs CLS). */44 width: number45 height: number46 maxWidth?: number47 className?: string48}4950/**51 * H.264 has no alpha, so the bake writes a light version and a dark version with52 * corners matched to each theme's page background. Both render; CSS shows exactly one53 * (`.dark` class convention, falling back to prefers-color-scheme). The hidden one54 * is display:none, so it never fetches past metadata or plays.55 */56export function DKBezelVideo({ base, alt, width, height, maxWidth = 460, className }: DKBezelVideoProps) {57 return (58 <figure className={`dkbz-figure${className ? ` ${className}` : ''}`} style={{ maxWidth }}>59 {(['light', 'dark'] as const).map((theme) => (60 <video61 key={theme}62// … truncated
Files it writes
More from diklein
All 3 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| DKMediaViewerdk-media-viewer | diklein | Components | Free | 1 dep · 5 files | |
| DKProductCarddk-product-card | diklein | Components | Free | 1 dep · 2 files |
