Skip to content
Brok UI

Loading…

No results

Charts

Open source

Token-themed data visualisations — the core multi-series chart plus dependency-free SVG variants for sankey, word-cloud, venn and violin plots.

Version
v1.2.1
Stability
stable
License
MIT
Related
Chart
Chart Tooltip
Partition Bar
6 of 7

Venn Diagram — A dependency-free, token-themed SVG Venn diagram for 2 or 3 sets, with translucent overlap lobes and a hover tooltip showing each set's label and value.

Preview

A dependency-free SVG Venn diagram. Pass `:sets` — 2 or 3 `[label, value]` pairs — and optional `:intersections` (`sets` indexes + `value`) to size each circle by its value and label every overlap.

previews.components.chart-venn.default.blade.php Blade
<div class="space-y-4">
    <x-ui.chart-venn :height="320" label="{{ __('Channel overlap') }}" />

    <p class="text-sm text-muted-foreground">
        {{ __('A dependency-free SVG Venn diagram. Pass `:sets` — 2 or 3 `[label, value]` pairs — and optional `:intersections` (`sets` indexes + `value`) to size each circle by its value and label every overlap.') }}
    </p>
</div>

Installation

terminal
php artisan ui:add chart-venn

Note

This component ships an Alpine behavior module at resources/js/ui/chart-venn.js. Import it once from your bundle so it registers on alpine:init:

resources/js/ui/index.js JS
import './chart-venn.js';

Registry contract

php artisan ui:add chart-venn writes only the files below. The CLI validates each file hash before writing and asks before it replaces a local change, unless you pass --force.

  • blade resources/views/components/ui/chart-venn.blade.php
  • js resources/js/ui/chart-venn.js
Registry dependencies
chart-tooltip
Packages
composer: jml/brok:^0.2
npm: alpinejs

Use with AI

A brief for your coding agent: install command, usage, props, guidance and the rules. Copy it, or open a prompt about this component in an assistant.

chart-venn.md
# Brok UI: Venn Diagram (`chart-venn`)

A dependency-free, token-themed SVG Venn diagram for 2 or 3 sets, with translucent overlap lobes and a hover tooltip showing each set's label and value.

Brok UI is a Laravel Blade component registry. Installed components are plain Blade files the app owns.

## Install

```bash
php artisan ui:add chart-venn
```

## Usage

```blade
<div class="space-y-4">
    <x-ui.chart-venn :height="320" label="{{ __('Channel overlap') }}" />

    <p class="text-sm text-muted-foreground">
        {{ __('A dependency-free SVG Venn diagram. Pass `:sets` — 2 or 3 `[label, value]` pairs — and optional `:intersections` (`sets` indexes + `value`) to size each circle by its value and label every overlap.') }}
    </p>
</div>
```

## Props

- `sets` (mixed|null, default `null`) — 2 or 3 sets: each an object with label and a numeric value. Defaults to demo channel-reach data.
- `intersections` (mixed|null, default `null`) — Optional overlap counts: each an object with sets (0-based indexes into sets, e.g. [0, 1, 2] for the triple overlap) and a numeric value.
- `height` (int, default `320`) — SVG height in pixels; the viewBox fits the circles.
- `label` (string, default `Venn diagram`) — Accessible name for the figure.
- `proportional` (bool, default `true`) — Sizes every circle by its value (area-proportional) instead of drawing equal radii.

## Use when

- Use when trend, distribution, flow, intensity, or relationship questions are easier to answer visually than in raw numbers.
- Showing how two or three sets overlap, such as customers reached across marketing channels.
- Wanting overlap area to read honestly: a given intersection's lens area matches its value.

## Avoid when

- Do not use a chart when users mainly need exact lookup or when a single metric would be clearer as text or a stat.
- There are more than three sets to compare; a Venn diagram cannot stay readable past three circles.
- The sets do not meaningfully overlap; use chart's bar type to compare them side by side instead.

## Anti-patterns

- Decorative charts without a meaningful question

## Rules

- Use the `<brok:chart-venn>` tag (or `<x-ui.chart-venn>`) in Blade; do not rewrite the component.
- Prefer the documented props and variants over utility-class overrides; when a utility must win, use the `!` important modifier.
- Use semantic design tokens (`bg-primary`, `text-muted-foreground`), never raw colour utilities.
- Keep the `data-slot` attributes; they are the styling and test hooks.

## Links

- Docs: https://brokui.dev/docs/components/chart-venn
- Registry JSON (files, props, contract): https://brokui.dev/r/open/chart-venn.json

Working in Claude Code, Cursor or Codex? Give the agent the whole registry through the MCP server or the Brok UI skill.

Examples

channels.blade.php Blade
{{-- The default three-set diagram framed by chart-card with a neutral count badge. --}}
<x-ui.chart-card heading="Channel overlap" subheading="Users reachable per channel" trend="3 channels" trend-variant="neutral">
    <x-ui.chart-venn :height="320" label="{{ __('Users reachable per channel') }}" />
</x-ui.chart-card>
two-sets.blade.php Blade
<div class="grid gap-6 sm:grid-cols-2">
    <x-ui.chart-venn
        :sets="[['label' => __('Trial users'), 'value' => 1240], ['label' => __('Paying'), 'value' => 380]]"
        :intersections="[['sets' => [0, 1], 'value' => 296, 'label' => __('Converted')]]"
        :height="260"
        label="{{ __('Most paying customers came from a trial') }}"
    />
    <x-ui.chart-venn
        :sets="[['label' => __('Newsletter'), 'value' => 900], ['label' => __('Webinar'), 'value' => 700]]"
        :intersections="[['sets' => [0, 1], 'value' => 60]]"
        :height="260"
        label="{{ __('Newsletter and webinar audiences barely overlap') }}"
    />
</div>

API

manifest knowledge + registry-derived coverage

Props

Props accepted by this component: name, type, default value and description.
Prop Type Default Description
sets mixed | null null 2 or 3 sets: each an object with label and a numeric value. Defaults to demo channel-reach data.
intersections mixed | null null Optional overlap counts: each an object with sets (0-based indexes into sets, e.g. [0, 1, 2] for the triple overlap) and a numeric value.
height int 320 SVG height in pixels; the viewBox fits the circles.
label string Venn diagram Accessible name for the figure.
proportional bool true Sizes every circle by its value (area-proportional) instead of drawing equal radii.

Slots

  • default — Unused; the diagram renders from the sets and intersections props only.

Data slots

Stable hooks for CSS overrides and browser tests.

chart-tooltip-row chart-venn chart-venn-label chart-venn-overlap chart-venn-set chart-venn-sets chart-venn-value

Behavior

  • Renders without arguments using built-in demo data, so it previews immediately.
  • When an intersection value is given, the two circles are positioned so the overlap lens area matches it, computed by a binary search on the centre distance; without one, circles overlap by a fixed share of their radii.
  • Hovering a set or an overlap region shows a chart-tooltip with that item's label and value.
  • Installs a JavaScript behavior module when the registry item includes resources/js/ui files.
  • Declares registry capability flags: a11y, interactive, responsive, rtl, darkMode, localized.

Guidance

Chart and visual analytics

Reveal a visual trend, distribution, flow, or relationship.

Use when

  • Use when trend, distribution, flow, intensity, or relationship questions are easier to answer visually than in raw numbers.
  • Showing how two or three sets overlap, such as customers reached across marketing channels.
  • Wanting overlap area to read honestly: a given intersection's lens area matches its value.

Avoid when

  • Do not use a chart when users mainly need exact lookup or when a single metric would be clearer as text or a stat.
  • There are more than three sets to compare; a Venn diagram cannot stay readable past three circles.
  • The sets do not meaningfully overlap; use chart's bar type to compare them side by side instead.

Use instead

  • Table for exact lookup
  • Stat for a single value

Anti-patterns

  • Decorative charts without a meaningful question
Anatomy
root chart-venn-sets chart-venn-set chart-venn-overlap chart-venn-label chart-venn-value
Theming hooks
chart-tooltip-row chart-venn chart-venn-label chart-venn-overlap chart-venn-set chart-venn-sets chart-venn-value

Accessibility

WCAG 2.2 AA Keyboard focus-visible RTL-ready Localized labels Dark mode
Keyboard
managed
Focus
none
  • The figure carries role="img" with an aria-label from label, so a screen reader hears a named summary instead of parsing raw SVG.
  • Each region's label and value render as visible text, not only as hover-only tooltip content.
  • Semantic HTML and a stable data-slot attribute for styling and scripting hooks.
  • Focus-visible rings use the ring token, so keyboard focus is always visible.
  • Disabled and invalid states are conveyed to assistive tech, not by color alone.
  • Targets WCAG 2.2 AA; verify contrast in light, dark, admin and customer surfaces in the preview.
  • Labels go through __() and layout uses logical properties (ms-*, text-start), so it mirrors under dir="rtl" — flip the preview to RTL to confirm.
  • Dark mode uses the same semantic tokens under the dark class; high contrast follows forced-color system tokens.

Livewire

Needs wire:key

Add a stable wire:key when Livewire can reorder this interactive component.

livewire-component.blade.php Blade
<div wire:key="chart-venn-{{ $record->id }}">
    <div class="space-y-4">
        <x-ui.chart-venn :height="320" label="{{ __('Channel overlap') }}" />
    
        <p class="text-sm text-muted-foreground">
            {{ __('A dependency-free SVG Venn diagram. Pass `:sets` — 2 or 3 `[label, value]` pairs — and optional `:intersections` (`sets` indexes + `value`) to size each circle by its value and label every overlap.') }}
        </p>
    </div>
</div>

Source

The exact, editable files ui:add writes into your app. Previews render this same code; there are no preview-only components.

resources/views/components/ui/chart-venn.blade.php Blade
@props([
    // Sets: each ['label' => string, 'value' => number]. Pass 2 OR 3 sets.
    'sets' => null,
    // Optional overlap counts: each ['sets' => [0, 1], 'value' => number] using
    // 0-based indexes into `sets`; [0, 1, 2] labels the triple overlap.
    'intersections' => null,
    'height' => 320,
    'label' => 'Venn diagram',
    // Size every circle by its value (area-proportional) instead of equal radii.
    'proportional' => true,
])

@php
    // ── Demo data so it renders without args ──────────────────────────────────
    $sets ??= [
        ['label' => __('Email'), 'value' => 820],
        ['label' => __('Push'), 'value' => 540],
        ['label' => __('SMS'), 'value' => 410],
    ];
    $intersections ??= [
        ['sets' => [0, 1], 'value' => 210],
        ['sets' => [1, 2], 'value' => 120],
        ['sets' => [0, 2], 'value' => 160],
        ['sets' => [0, 1, 2], 'value' => 64],
    ];

    // Clamp to a 2- or 3-set Venn; ignore anything past the third set.
    $sets = array_slice(array_values($sets), 0, 3);
    $count = max(2, count($sets));
    $proportional = filter_var($proportional, FILTER_VALIDATE_BOOLEAN);

    $H = max(160, (int) $height);
    $palette = ['text-chart-1', 'text-chart-2', 'text-chart-3'];
    // Label fills as fixed utilities (never spliced) so the JIT emits them.
    $labelFills = ['fill-chart-1', 'fill-chart-2', 'fill-chart-3'];

    // ── Geometry (the viewBox is fitted to the circles below) ──────────────
    // Radii follow √value so AREA is proportional to the set size; the largest
    // circle is pinned to a fixed radius and the rest scale down from it. When
    // a pairwise intersection is given, the two circles are placed so the LENS
    // between them has that area (a binary search on the centre distance), so
    // the picture states the overlap honestly; without one they overlap by a
    // fixed share of their radii.
    $values = array_map(fn ($s) => max(0.0, (float) ($s['value'] ?? 0)), $sets);
    $maxV = max($values) ?: 1;
    $R = $count === 2 ? 92 : 84;
    $radii = array_map(fn ($v) => $proportional ? max(28, $R * sqrt($v / $maxV)) : $R, $values);
    $areaPerUnit = M_PI * $R * $R / $maxV;   // px² per unit of value
    $overlap = 0.72;

    // Pairwise intersection values keyed "a-b" (a < b).
    $pairValue = [];
    foreach ((array) $intersections as $ix) {
        $ids = array_values(array_unique(array_map('intval', (array) ($ix['sets'] ?? []))));
        if (count($ids) === 2) {
            sort($ids);
            $pairValue[$ids[0].'-'.$ids[1]] = max(0.0, (float) ($ix['value'] ?? 0));
        }
    }

    // Lens area of two circles at centre distance d.
    $lens = function (float $r1, float $r2, float $d): float {
        if ($d >= $r1 + $r2) {
            return 0.0;
        }
        if ($d <= abs($r1 - $r2)) {
            return M_PI * min($r1, $r2) ** 2;
        }
        $a = $r1 ** 2 * acos(max(-1, min(1, ($d ** 2 + $r1 ** 2 - $r2 ** 2) / (2 * $d * $r1))));
        $b = $r2 ** 2 * acos(max(-1, min(1, ($d ** 2 + $r2 ** 2 - $r1 ** 2) / (2 * $d * $r2))));
        $c = 0.5 * sqrt(max(0, (-$d + $r1 + $r2) * ($d + $r1 - $r2) * ($d - $r1 + $r2) * ($d + $r1 + $r2)));

        return $a + $b - $c;
    };

    // Centre distance for a pair: solved from the lens area when known.
    $distance = function (int $a, int $b) use ($radii, $pairValue, $areaPerUnit, $lens, $overlap, $proportional): float {
        $r1 = $radii[$a];
        $r2 = $radii[$b];
        $key = min($a, $b).'-'.max($a, $b);
        if (! $proportional || ! isset($pairValue[$key])) {
            return ($r1 + $r2) * $overlap;
        }
        $target = min($pairValue[$key] * $areaPerUnit, M_PI * min($r1, $r2) ** 2);
        // Keep at least a sliver of lens so the pair still reads as related.
        $lo = abs($r1 - $r2) + 0.5;
        $hi = $r1 + $r2 - 6;
        for ($i = 0; $i < 40; $i++) {
            $mid = ($lo + $hi) / 2;
            if ($lens($r1, $r2, $mid) > $target) {
                $lo = $mid;
            } else {
                $hi = $mid;
            }
        }

        return ($lo + $hi) / 2;
    };

    $centers = [];
    if ($count === 2) {
        $d = $distance(0, 1);
        $cx = 200;
        $cy = 160;
        $centers = [[$cx - $d / 2, $cy], [$cx + $d / 2, $cy]];
    } else {
        // Two on top, one below; each pair's distance comes from its overlap.
        $d01 = $distance(0, 1);
        $d02 = $distance(0, 2);
        $d12 = $distance(1, 2);
        // The three distances must form a triangle; stretch the longest apart
        // if they do not (a third set that overlaps both far more than they
        // overlap each other).
        $d01 = max($d01, abs($d02 - $d12) + 1);
        $x0 = 0;
        $x1 = $d01;
        $x2 = ($d02 ** 2 - $d12 ** 2 + $d01 ** 2) / (2 * $d01);
        $y2 = sqrt(max(0, $d02 ** 2 - $x2 ** 2));
        $centers = [[$x0, 0], [$x1, 0], [$x2, $y2]];
        // Centre the triangle's bounding box in the frame.
        $minX = min(array_map(fn ($c, $r) => $c[0] - $r, $centers, $radii));
        $maxX = max(array_map(fn ($c, $r) => $c[0] + $r, $centers, $radii));
        $minY = min(array_map(fn ($c, $r) => $c[1] - $r, $centers, $radii));
        $maxY = max(array_map(fn ($c, $r) => $c[1] + $r, $centers, $radii));
        $dx = 200 - ($minX + $maxX) / 2;
        $dy = 160 - ($minY + $maxY) / 2;
        $centers = array_map(fn ($c) => [$c[0] + $dx, $c[1] + $dy], $centers);
    }

    // The viewBox hugs the circles plus a gutter for the outside labels, so a
    // long set name is never clipped by a fixed frame.
    $bx0 = min(array_map(fn ($c, $r) => $c[0] - $r, $centers, $radii)) - 104;
    $bx1 = max(array_map(fn ($c, $r) => $c[0] + $r, $centers, $radii)) + 104;
    $by0 = min(array_map(fn ($c, $r) => $c[1] - $r, $centers, $radii)) - 40;
    $by1 = max(array_map(fn ($c, $r) => $c[1] + $r, $centers, $radii)) + 40;

    // Set labels sit just outside each circle, pushed away from the diagram's
    // centroid so they never land on another set.
    $gx = array_sum(array_column($centers, 0)) / $count;
    $gy = array_sum(array_column($centers, 1)) / $count;
    $labels = [];
    foreach ($centers as $i => $c) {
        $vx = $c[0] - $gx;
        $vy = $c[1] - $gy;
        $len = sqrt($vx ** 2 + $vy ** 2) ?: 1;
        $ux = $vx / $len;
        $uy = $vy / $len;
        $labels[] = [
            'x' => $c[0] + $ux * ($radii[$i] + 10),
            'y' => $c[1] + $uy * ($radii[$i] + 10),
            'anchor' => abs($ux) < 0.35 ? 'middle' : ($ux < 0 ? 'end' : 'start'),
            'baseline' => abs($uy) < 0.35 ? 'middle' : ($uy < 0 ? 'auto' : 'hanging'),
        ];
    }

    // Intersection readouts: a pair label sits on the lens (between the two
    // centres, nudged away from the third), the triple in the centroid.
    $format = fn ($v) => number_format((float) $v);
    $overlaps = [];
    foreach ((array) $intersections as $ix) {
        $ids = array_values(array_unique(array_map('intval', (array) ($ix['sets'] ?? []))));
        $ids = array_values(array_filter($ids, fn ($id) => isset($centers[$id])));
        if (count($ids) < 2) {
            continue;
        }
        if (count($ids) >= 3) {
            $x = $gx;
            $y = $gy;
        } else {
            [$a, $b] = $ids;
            // The lens centre: along the line of centres, midway between the
            // two far edges of the overlap (not the midpoint of the centres,
            // which sits off-lens when the circles differ in size).
            $dd = hypot($centers[$b][0] - $centers[$a][0], $centers[$b][1] - $centers[$a][1]) ?: 1;
            $ux = ($centers[$b][0] - $centers[$a][0]) / $dd;
            $uy = ($centers[$b][1] - $centers[$a][1]) / $dd;
            $from = $dd - $radii[$b];   // lens starts here along the line (from a)
            $to = $radii[$a];           // and ends here
            $mid = ($from + $to) / 2;
            $x = $centers[$a][0] + $ux * $mid;
            $y = $centers[$a][1] + $uy * $mid;
            if ($count === 3) {
                $third = array_values(array_diff([0, 1, 2], $ids))[0];
                $vx = $x - $centers[$third][0];
                $vy = $y - $centers[$third][1];
                $len = sqrt($vx ** 2 + $vy ** 2) ?: 1;
                $x += ($vx / $len) * 22;
                $y += ($vy / $len) * 22;
            }
        }
        $overlaps[] = [
            'x' => $x,
            'y' => $y,
            'value' => $format($ix['value'] ?? 0),
            'label' => $ix['label'] ?? implode(' ∩ ', array_map(fn ($id) => $sets[$id]['label'] ?? '', $ids)),
        ];
    }
@endphp

<div
    x-data="uiChartVenn()"
    data-slot="chart-venn"
    role="img"
    aria-label="{{ $label }}"
    {{ $attributes->merge(['class' => 'relative w-full']) }}
>
    {{-- Pointer tooltip; reads the data-* attributes each set circle carries. --}}
    <x-ui.chart-tooltip
        x-show="open"
        x-cloak
        class="absolute -translate-x-1/2 -translate-y-full -mt-2 whitespace-nowrap"
        ::style="`inset-inline-start:${x}px; top:${y}px`"
    >
        <div data-slot="chart-tooltip-row" class="flex items-center justify-between gap-4">
            <span class="text-muted-foreground" x-text="label"></span>
            <span class="font-medium tabular-nums" x-text="value"></span>
        </div>
    </x-ui.chart-tooltip>

    <svg
        viewBox="{{ round($bx0, 2) }} {{ round($by0, 2) }} {{ round($bx1 - $bx0, 2) }} {{ round($by1 - $by0, 2) }}"
        width="100%"
        height="{{ $H }}"
        preserveAspectRatio="xMidYMid meet"
        class="h-auto w-full"
        fill="none"
        aria-hidden="true"
    >
        {{-- Set circles: a solid 2px outline in the set's hue over a light fill
             of the same hue, so each set keeps its colour and the lenses read
             as darker where fills stack. --}}
        <g data-slot="chart-venn-sets">
            @foreach ($sets as $i => $set)
                <circle
                    data-slot="chart-venn-set"
                    class="{{ $palette[$i % count($palette)] }} transition-[fill-opacity] duration-200 hover:[fill-opacity:0.4]"
                    cx="{{ round($centers[$i][0], 2) }}"
                    cy="{{ round($centers[$i][1], 2) }}"
                    r="{{ round($radii[$i], 2) }}"
                    fill="currentColor"
                    fill-opacity="0.22"
                    stroke="currentColor"
                    stroke-width="2"
                    data-label="{{ $set['label'] }}"
                    data-value="{{ $format($set['value'] ?? 0) }}"
                />
            @endforeach
        </g>

        {{-- Overlap counts on the lenses. --}}
        @foreach ($overlaps as $o)
            <text
                data-slot="chart-venn-overlap"
                class="pointer-events-none fill-foreground text-2xs font-semibold tabular-nums stroke-background [paint-order:stroke] [stroke-linejoin:round]"
                stroke-width="3"
                x="{{ round($o['x'], 2) }}"
                y="{{ round($o['y'], 2) }}"
                text-anchor="middle"
                dominant-baseline="middle"
                data-label="{{ $o['label'] }}"
                data-value="{{ $o['value'] }}"
            >{{ $o['value'] }}</text>
        @endforeach

        {{-- Set labels + totals, outside each circle. --}}
        @foreach ($sets as $i => $set)
            @php($l = $labels[$i])
            <text
                data-slot="chart-venn-label"
                class="pointer-events-none {{ $labelFills[$i % count($labelFills)] }} text-xs font-semibold"
                x="{{ round($l['x'], 2) }}"
                y="{{ round($l['baseline'] === 'middle' ? $l['y'] - 7 : $l['y'], 2) }}"
                text-anchor="{{ $l['anchor'] }}"
                dominant-baseline="{{ $l['baseline'] === 'middle' ? 'auto' : $l['baseline'] }}"
            >{{ $set['label'] }}</text>
            <text
                data-slot="chart-venn-value"
                class="pointer-events-none fill-muted-foreground text-2xs tabular-nums"
                x="{{ round($l['x'], 2) }}"
                y="{{ round(($l['baseline'] === 'middle' ? $l['y'] - 7 : $l['y']) + 14, 2) }}"
                text-anchor="{{ $l['anchor'] }}"
                dominant-baseline="{{ $l['baseline'] === 'middle' ? 'auto' : $l['baseline'] }}"
            >{{ $format($set['value'] ?? 0) }}</text>
        @endforeach
    </svg>
</div>
resources/js/ui/chart-venn.js JS
/**
 * Venn chart hover tooltips.
 *
 * The Venn itself is dependency-free static SVG; this adds a lightweight pointer
 * tooltip that reads the data-* attributes the Blade stamps onto each set circle
 * (data-label / data-value). A single delegated mousemove listener on the host
 * drives it, and both listeners are removed on teardown so unmounting mid-hover
 * can't leak.
 *
 * Self-registers on `alpine:init` so import order does not matter — import this
 * file once from your bundle (e.g. resources/js/ui/index.js).
 *
 * Note: this file is plain JS served by the registry — no Blade syntax allowed.
 */
document.addEventListener('alpine:init', () => {
    window.Alpine.data('uiChartVenn', () => ({
        open: false,
        label: '',
        value: '',
        x: 0,
        y: 0,
        onMove: null,
        onLeave: null,

        init() {
            this.onMove = (event) => {
                const target = event.target.closest('[data-slot="chart-venn-set"]');

                if (!target) {
                    this.open = false;

                    return;
                }

                const rect = this.$root.getBoundingClientRect();
                this.x = event.clientX - rect.left;
                this.y = event.clientY - rect.top;
                this.label = target.dataset.label ?? '';
                this.value = target.dataset.value ?? '';
                this.open = true;
            };

            this.onLeave = () => {
                this.open = false;
            };

            this.$root.addEventListener('mousemove', this.onMove);
            this.$root.addEventListener('mouseleave', this.onLeave);
        },

        destroy() {
            this.$root.removeEventListener('mousemove', this.onMove);
            this.$root.removeEventListener('mouseleave', this.onLeave);
        },
    }));
});

Ownership & lifecycle

Owner, release state, review evidence and adoption for this item.
Owner
Platform UI (@JoshJML)
Current version
1.2.1
Status
Stable
License
open
Accessibility reviewed
No review date recorded
Last breaking change
No date recorded
Deprecation
Not deprecated
Contract
v6
Foundation
≥ 1.0.0