The Brella Co. :: Interactive Map
Parent / Core
Divisions
Subsidiaries
Offerings
Services
Drag bubbles to pin • Shift+drag to unpin • Scroll to zoom
import React, { useMemo, useState } from "react"; import { Card } from "@/components/ui/card"; import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"; import { Switch } from "@/components/ui/switch"; import { Slider } from "@/components/ui/slider"; import { Download, Plus, Trash2, RefreshCcw } from "lucide-react"; /** * Equity & Phantom Exit Calculator * * Designed for Brella (parent) + brand subsidiaries like Popsicle Air & Levi's Garage. * - Adjust sale prices per company * - Adjust brand equity splits (Parent vs external investors) * - Adjust brand-level phantom (e.g., D‑Buck on Popsicle, Levi on Levi's Garage) * - Adjust parent-level phantom (e.g., Viv, Piero, Jake across all exits) * - Choose phantom payout model: CARVE-OUT (from equity pool) or ON-TOP (extra cost) * - Final payouts: brand equity holders, brand phantom recipients, parent phantom recipients, and parent equity holders (Zac, David) * * Notes: * - All percentages are in % (0–100). Internally converted to decimals for math. * - Totals validate visually; out-of-range sums show warnings. * - This is a single-file React component ready to embed in your site. */ // --------------------------- Types --------------------------- type PersonKey = string; type EquityHolder = { id: PersonKey; name: string; percent: number; // % at this layer }; type PhantomHolder = { id: PersonKey; name: string; percent: number; // % phantom against sale price (brand) or against parent net (parent) }; type Brand = { id: string; name: string; salePrice: number; // dollars equityHolders: EquityHolder[]; // at brand level (e.g., Parent vs Investor(s)) must sum to 100 phantomHolders: PhantomHolder[]; // brand-level phantom (e.g., D‑Buck, Levi) }; // --------------------------- Helpers --------------------------- const toMoney = (n: number) => n.toLocaleString(undefined, { style: "currency", currency: "USD", maximumFractionDigits: 0 }); const clampPct = (p: number) => Math.max(0, Math.min(100, p)); // --------------------------- Component --------------------------- export default function EquityPhantomExitCalculator() { // Phantom model toggle: carve-out vs on-top const [brandPhantomCarveOut, setBrandPhantomCarveOut] = useState(true); const [parentPhantomCarveOut, setParentPhantomCarveOut] = useState(true); // Parent equity (Brella) internal owners const [parentEquity, setParentEquity] = useState([ { id: "zac", name: "Zac", percent: 90 }, { id: "david", name: "David", percent: 10 }, ]); // Parent-level phantom (applies to all brand proceeds flowing to parent net) const [parentPhantom, setParentPhantom] = useState([ { id: "viv", name: "Viv", percent: 2 }, { id: "piero", name: "Piero", percent: 2 }, { id: "jake", name: "Jake", percent: 0.5 }, ]); // Brands (start with Popsicle & Levi's with defaults you discussed) const [brands, setBrands] = useState([ { id: "popsicle", name: "Popsicle Air", salePrice: 100_000_000, equityHolders: [ { id: "parent", name: "Parent (Brella)", percent: 100 }, // Add external investor rows here if needed ], phantomHolders: [ { id: "dbuck", name: "D‑Buck (Brand Phantom)", percent: 3 }, ], }, { id: "levis", name: "Levi's Garage", salePrice: 100_000_000, equityHolders: [ { id: "parent", name: "Parent (Brella)", percent: 100 }, ], phantomHolders: [ { id: "levi", name: "Levi (Brand Phantom)", percent: 3 }, ], }, ]); // --------------------------- Calculations --------------------------- const brandResults = useMemo(() => { return brands.map((brand) => { const sale = brand.salePrice; const brandPhantomPct = brand.phantomHolders.reduce((a, h) => a + (h.percent || 0), 0) / 100; const phantomPayout = sale * brandPhantomPct; // if on-top, paid in addition; if carve-out, subtracted from equity pool const equityPool = brandPhantomCarveOut ? sale - phantomPayout : sale; // Equity payouts at brand level const equityPayouts = brand.equityHolders.map((eh) => ({ id: eh.id, name: eh.name, amount: equityPool * (clampPct(eh.percent) / 100), })); // Phantom payouts at brand level const phantomPayouts = brand.phantomHolders.map((ph) => ({ id: ph.id, name: ph.name, amount: sale * (clampPct(ph.percent) / 100), })); return { brandId: brand.id, brandName: brand.name, sale, equityPool, phantomPayout, equityPayouts, phantomPayouts, equitySum: equityPayouts.reduce((a, r) => a + r.amount, 0), phantomSum: phantomPayouts.reduce((a, r) => a + r.amount, 0), equityPercentTotal: brand.equityHolders.reduce((a, r) => a + clampPct(r.percent), 0), phantomPercentTotal: brand.phantomHolders.reduce((a, r) => a + clampPct(r.percent), 0), }; }); }, [brands, brandPhantomCarveOut]); // Total cash flowing to Parent (Brella) from all brands before parent phantom const totalToParentBeforeParentPhantom = useMemo(() => { return brandResults.reduce((sum, br) => { const row = br.equityPayouts.find((e) => e.id === "parent"); return sum + (row ? row.amount : 0); }, 0); }, [brandResults]); // Parent phantom payouts const parentPhantomPct = useMemo( () => parentPhantom.reduce((a, h) => a + clampPct(h.percent), 0) / 100, [parentPhantom] ); const parentPhantomPayout = parentPhantomCarveOut ? totalToParentBeforeParentPhantom * parentPhantomPct : 0; // if ON-TOP, we don't reduce the pool here (we could show separately if desired) const parentEquityPoolAfterParentPhantom = parentPhantomCarveOut ? totalToParentBeforeParentPhantom - parentPhantomPayout : totalToParentBeforeParentPhantom; // Parent equity split (Zac / David) const parentEquityPayouts = useMemo(() => { return parentEquity.map((eh) => ({ id: eh.id, name: eh.name, amount: parentEquityPoolAfterParentPhantom * (clampPct(eh.percent) / 100), })); }, [parentEquity, parentEquityPoolAfterParentPhantom]); const parentPhantomPayouts = useMemo(() => { const base = parentPhantomCarveOut ? totalToParentBeforeParentPhantom : totalToParentBeforeParentPhantom; // same base for display; carve-out toggles reduction path return parentPhantom.map((ph) => ({ id: ph.id, name: ph.name, amount: base * (clampPct(ph.percent) / 100), })); }, [parentPhantom, parentPhantomCarveOut, totalToParentBeforeParentPhantom]); // --------------------------- UI Helpers --------------------------- const updateBrand = (id: string, updater: (b: Brand) => Brand) => { setBrands((prev) => prev.map((b) => (b.id === id ? updater(b) : b))); }; const addBrand = () => { const idx = brands.length + 1; setBrands((prev) => [ ...prev, { id: `brand_${idx}`, name: `New Company ${idx}`, salePrice: 50_000_000, equityHolders: [{ id: "parent", name: "Parent (Brella)", percent: 100 }], phantomHolders: [], }, ]); }; const removeBrand = (id: string) => setBrands((prev) => prev.filter((b) => b.id !== id)); const downloadCSV = () => { const rows: string[] = []; rows.push( [ "Layer", "Entity", "Name", "Amount", ].join(",") ); brandResults.forEach((br) => { br.equityPayouts.forEach((p) => { rows.push(["Brand Equity", br.brandName, p.name, Math.round(p.amount).toString()].join(",")); }); br.phantomPayouts.forEach((p) => { rows.push(["Brand Phantom", br.brandName, p.name, Math.round(p.amount).toString()].join(",")); }); }); parentEquityPayouts.forEach((p) => { rows.push(["Parent Equity", "Brella", p.name, Math.round(p.amount).toString()].join(",")); }); parentPhantomPayouts.forEach((p) => { rows.push(["Parent Phantom", "Brella", p.name, Math.round(p.amount).toString()].join(",")); }); const blob = new Blob([rows.join("\n")], { type: "text/csv;charset=utf-8;" }); const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = `brella_exit_calculator_${Date.now()}.csv`; a.click(); URL.revokeObjectURL(url); }; const resetDefaults = () => { setBrandPhantomCarveOut(true); setParentPhantomCarveOut(true); setParentEquity([ { id: "zac", name: "Zac", percent: 90 }, { id: "david", name: "David", percent: 10 }, ]); setParentPhantom([ { id: "viv", name: "Viv", percent: 2 }, { id: "piero", name: "Piero", percent: 2 }, { id: "jake", name: "Jake", percent: 0.5 }, ]); setBrands([ { id: "popsicle", name: "Popsicle Air", salePrice: 100_000_000, equityHolders: [{ id: "parent", name: "Parent (Brella)", percent: 100 }], phantomHolders: [{ id: "dbuck", name: "D‑Buck (Brand Phantom)", percent: 3 }], }, { id: "levis", name: "Levi's Garage", salePrice: 100_000_000, equityHolders: [{ id: "parent", name: "Parent (Brella)", percent: 100 }], phantomHolders: [{ id: "levi", name: "Levi (Brand Phantom)", percent: 3 }], }, ]); }; // --------------------------- Render --------------------------- return (

Equity & Phantom Exit Calculator