Data display

Watermark

A repeating mark drawn over its children, on a canvas raster tiled across the region. The overlay is created and repaired by `@crosskit-ui/core` rather than rendered by the framework, so deleting it in the inspector, hiding it from a stylesheet or stripping its attributes all bring it straight back. That resists accidental and casual removal — it is explicitly not a security boundary, since the mark lives in the page it is protecting. New in v2, React first.

data-scope="watermark"

Usage

<Watermark content={["CrossKit", "confidential"]}>
  <article>…</article>
</Watermark>
<Watermark :content="['CrossKit', 'confidential']">
  <article>…</article>
</Watermark>
<Watermark content={["CrossKit", "confidential"]}>
  <article>…</article>
</Watermark>
<ck-watermark [content]="['CrossKit', 'confidential']">
  <article>…</article>
</ck-watermark>

Props

PropTypeDefaultNotes
contentstring | string[]React firstText mark; one entry per line.
imagestringReact firstURL or data URI. Wins over `content`, which stays the fallback if it fails to load. Drawn into the cell, so it does not keep its aspect ratio.
widthnumberReact firstOne mark's cell in px. Measured when omitted for text; 120 for an image.
heightnumberReact firstLines x line-height when omitted for text; 64 for an image.
rotatenumber-22React firstDegrees, clockwise.
zIndexnumber9React firstStacking order inside the region. A child with a higher `z-index` paints above the mark.
gap[number, number][100, 100]React first`[x, y]` px between marks.
offset[number, number]half the gapReact first`[x, y]` px shift of the whole pattern. Physical, so it does not mirror in RTL.
font{ color, fontSize, fontWeight, fontFamily, fontStyle }React first`fontWeight: "light"` is mapped to 300 rather than passed through — one invalid token makes canvas drop the entire font and draw 10px sans-serif without a word.

Prop names are identical in all four frameworks. Only two-way binding differs, and each framework uses its own idiom over the same underlying prop. The marked rows are the exception, and a temporary one, in both directions: React first exists in React while the other three adapters catch up, and Not in React is the prop it replaced, still live everywhere else.

Parts

data-partDescription
rootThe wrapper. Positioned, so the overlay resolves against it.
overlayThe mark itself, `aria-hidden` and `pointer-events: none`. Written imperatively — style it through the props, not with CSS, because anything a stylesheet changes here is restored.