@fairmint/ui 0.2.31 → 0.2.32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -44998,6 +44998,526 @@ function EquityGrantCard({
44998
44998
  }
44999
44999
  );
45000
45000
  }
45001
+ const DEFAULT_RIBBON_CONFIG = {
45002
+ baseline: 0.82,
45003
+ xEndStagger: 9e-3,
45004
+ xEndDraw: [0.84, 0.849, 0.858, 0.867, 0.876],
45005
+ xEndCurve: 0.914,
45006
+ xStart: [0.05, 0.19, 0.34, 0.5, 0.66],
45007
+ kArr: [1.7, 2.4, 3.1, 3.9, 4.9],
45008
+ V: [0.082, 0.102, 0.132, 0.172, 0.21],
45009
+ vMin: [0.038, 0.04, 0.042, 0.044, 0.046],
45010
+ xStem: [0.05, 0.04, 0.035, 0.03, 0.025],
45011
+ labelX: [0.08, 0.24, 0.4, 0.56, 0.8],
45012
+ labelAboveGap: [0.034, 0.03, 0.028, 0.024],
45013
+ labelLeftGap: 0.055,
45014
+ labelLiquidityGap: 0.016,
45015
+ labelNudge: [
45016
+ [0, 0],
45017
+ [0, 0],
45018
+ [0, 0],
45019
+ [0, 0],
45020
+ [0, -0.012]
45021
+ ],
45022
+ samples: 72
45023
+ };
45024
+ const MARK_RIBBON_RIGHT_EDGE = 0.936;
45025
+ const MARK_FIT_HORIZONTAL_COMPRESS = 0.78;
45026
+ const MARK_RIBBON_CONFIG = {
45027
+ ...DEFAULT_RIBBON_CONFIG,
45028
+ baseline: 0.97,
45029
+ xEndDraw: [
45030
+ MARK_RIBBON_RIGHT_EDGE,
45031
+ MARK_RIBBON_RIGHT_EDGE,
45032
+ MARK_RIBBON_RIGHT_EDGE,
45033
+ MARK_RIBBON_RIGHT_EDGE,
45034
+ MARK_RIBBON_RIGHT_EDGE
45035
+ ],
45036
+ xEndCurve: 0.94,
45037
+ xStart: [0.08, 0.2, 0.32, 0.44, 0.56],
45038
+ xStem: [0.028, 0.022, 0.018, 0.015, 0.012]
45039
+ };
45040
+ function labelGapAbove(i, config2) {
45041
+ const lastBand = config2.xStart.length - 1;
45042
+ if (i === lastBand) return config2.labelLiquidityGap;
45043
+ return config2.labelAboveGap[i] ?? config2.labelLiquidityGap;
45044
+ }
45045
+ function mergeBounds(a, b) {
45046
+ return {
45047
+ minX: Math.min(a.minX, b.minX),
45048
+ minY: Math.min(a.minY, b.minY),
45049
+ maxX: Math.max(a.maxX, b.maxX),
45050
+ maxY: Math.max(a.maxY, b.maxY)
45051
+ };
45052
+ }
45053
+ function transformPathD(d, scaleX, scaleY, tx, ty) {
45054
+ return d.replace(/(-?[\d.]+),(-?[\d.]+)/g, (_, x, y) => {
45055
+ const px2 = Number(x) * scaleX + tx;
45056
+ const py = Number(y) * scaleY + ty;
45057
+ return `${px2.toFixed(1)},${py.toFixed(1)}`;
45058
+ });
45059
+ }
45060
+ function computeMarkFitTransform(bounds, width, height, paddingRatio) {
45061
+ const pad = paddingRatio * Math.min(width, height);
45062
+ const bw = bounds.maxX - bounds.minX;
45063
+ const bh = bounds.maxY - bounds.minY;
45064
+ if (bw <= 0 || bh <= 0) {
45065
+ return { scaleX: 1, scaleY: 1, tx: 0, ty: 0 };
45066
+ }
45067
+ const scaleY = (height - pad * 2) / bh;
45068
+ let scaleX = scaleY * MARK_FIT_HORIZONTAL_COMPRESS;
45069
+ if (bw * scaleX > width - pad * 2) {
45070
+ scaleX = (width - pad * 2) / bw;
45071
+ }
45072
+ const tx = (width - bw * scaleX) / 2 - bounds.minX * scaleX;
45073
+ const ty = (height - bh * scaleY) / 2 - bounds.minY * scaleY;
45074
+ return { scaleX, scaleY, tx, ty };
45075
+ }
45076
+ function valAt(i, xf, config2) {
45077
+ const { xStart, xEndCurve, kArr, V, vMin, xStem } = config2;
45078
+ const xLo = xStart[i] - xStem[i];
45079
+ if (xf < xLo || xf > xEndCurve) return 0;
45080
+ if (xf < xStart[i]) return vMin[i];
45081
+ const u = (xf - xStart[i]) / (xEndCurve - xStart[i]);
45082
+ const grow = (Math.exp(kArr[i] * u) - 1) / (Math.exp(kArr[i]) - 1);
45083
+ return vMin[i] + (V[i] - vMin[i]) * grow;
45084
+ }
45085
+ function cumBelow(i, xf, config2) {
45086
+ let sum = 0;
45087
+ for (let j = 0; j < i; j++) sum += valAt(j, xf, config2);
45088
+ return sum;
45089
+ }
45090
+ function buildBandPath(i, width, height, config2) {
45091
+ const { xStart, xEndCurve, xStem, baseline } = config2;
45092
+ const samples = Math.max(1, Math.floor(config2.samples));
45093
+ const xLo = xStart[i] - xStem[i];
45094
+ const top = [];
45095
+ const bot = [];
45096
+ for (let s = 0; s <= samples; s++) {
45097
+ const xf = xLo + (xEndCurve - xLo) * (s / samples);
45098
+ const below = cumBelow(i, xf, config2);
45099
+ const v = valAt(i, xf, config2);
45100
+ const x = xf * width;
45101
+ top.push([x, (baseline - below - v) * height]);
45102
+ bot.push([x, (baseline - below) * height]);
45103
+ }
45104
+ let minX = Number.POSITIVE_INFINITY;
45105
+ let minY = Number.POSITIVE_INFINITY;
45106
+ let maxX = Number.NEGATIVE_INFINITY;
45107
+ let maxY = Number.NEGATIVE_INFINITY;
45108
+ for (const [x, y] of [...top, ...bot]) {
45109
+ minX = Math.min(minX, x);
45110
+ minY = Math.min(minY, y);
45111
+ maxX = Math.max(maxX, x);
45112
+ maxY = Math.max(maxY, y);
45113
+ }
45114
+ let d = `M${top[0][0].toFixed(1)},${top[0][1].toFixed(1)}`;
45115
+ for (let s = 1; s <= samples; s++) {
45116
+ d += ` L${top[s][0].toFixed(1)},${top[s][1].toFixed(1)}`;
45117
+ }
45118
+ d += ` L${bot[samples][0].toFixed(1)},${bot[samples][1].toFixed(1)}`;
45119
+ for (let s = samples - 1; s >= 0; s--) {
45120
+ d += ` L${bot[s][0].toFixed(1)},${bot[s][1].toFixed(1)}`;
45121
+ }
45122
+ return { d: `${d} Z`, bounds: { minX, minY, maxX, maxY } };
45123
+ }
45124
+ function buildLabel(i, text, _width, _height, config2, offsetXNorm) {
45125
+ const { baseline, xStart, xStem, labelNudge } = config2;
45126
+ const xf = xStart[i] - xStem[i] + offsetXNorm;
45127
+ const below = cumBelow(i, xf, config2);
45128
+ const v = valAt(i, xf, config2);
45129
+ const yTop = baseline - below - v;
45130
+ const [nudgeX, nudgeY] = labelNudge[i];
45131
+ return {
45132
+ index: i,
45133
+ text,
45134
+ leftPct: (xf + nudgeX) * 100,
45135
+ topPct: (yTop - labelGapAbove(i, config2) + nudgeY) * 100,
45136
+ placement: "start"
45137
+ };
45138
+ }
45139
+ function clampBandCount(count2, max2 = 5) {
45140
+ if (!Number.isFinite(count2)) return max2;
45141
+ return Math.min(max2, Math.max(1, Math.round(count2)));
45142
+ }
45143
+ function buildRibbonGeometry(width, height, labels, config2 = DEFAULT_RIBBON_CONFIG, bandCount = config2.xStart.length, layout = "hero") {
45144
+ const totalBands = config2.xStart.length;
45145
+ const visibleBands = clampBandCount(bandCount, totalBands);
45146
+ if (width <= 0 || height <= 0) {
45147
+ return null;
45148
+ }
45149
+ const paths = [];
45150
+ const clipWidthPx = [];
45151
+ let bounds = null;
45152
+ for (let i = 0; i < visibleBands; i++) {
45153
+ const band = buildBandPath(i, width, height, config2);
45154
+ paths.push(band.d);
45155
+ clipWidthPx.push(config2.xEndDraw[i] * width);
45156
+ bounds = bounds ? mergeBounds(bounds, band.bounds) : band.bounds;
45157
+ }
45158
+ let fitPaths = paths;
45159
+ let fitClips = clipWidthPx;
45160
+ let offsetXNorm = 0;
45161
+ if (bounds) {
45162
+ if (layout === "mark") {
45163
+ const { scaleX, scaleY, tx, ty } = computeMarkFitTransform(bounds, width, height, 0.05);
45164
+ fitPaths = paths.map((p) => transformPathD(p, scaleX, scaleY, tx, ty));
45165
+ const alignedClipRight = MARK_RIBBON_RIGHT_EDGE * width * scaleX + tx;
45166
+ fitClips = clipWidthPx.map(() => alignedClipRight);
45167
+ offsetXNorm = tx / width;
45168
+ } else if (layout === "hero") {
45169
+ const bw = bounds.maxX - bounds.minX;
45170
+ const tx = (width - bw) / 2 - bounds.minX;
45171
+ fitPaths = paths.map((p) => transformPathD(p, 1, 1, tx, 0));
45172
+ fitClips = clipWidthPx.map((w) => w + tx);
45173
+ offsetXNorm = tx / width;
45174
+ }
45175
+ }
45176
+ const paddedLabels = Array.from({ length: visibleBands }, (_, i) => labels[i] ?? "");
45177
+ const builtLabels = paddedLabels.map(
45178
+ (text, i) => buildLabel(i, text, width, height, config2, offsetXNorm)
45179
+ );
45180
+ return {
45181
+ paths: fitPaths,
45182
+ clipWidthPx: fitClips,
45183
+ labels: builtLabels,
45184
+ width,
45185
+ height,
45186
+ bandCount: visibleBands
45187
+ };
45188
+ }
45189
+ function easePower1InOut(t) {
45190
+ const p = Math.max(0, Math.min(1, t));
45191
+ return p < 0.5 ? 2 * p * p : 1 - (-2 * p + 2) ** 2 / 2;
45192
+ }
45193
+ function easePower2Out(t) {
45194
+ const p = Math.max(0, Math.min(1, t));
45195
+ return 1 - (1 - p) ** 2;
45196
+ }
45197
+ function ribbonLabelRevealTime(labelIndex, duration2, config2 = DEFAULT_RIBBON_CONFIG) {
45198
+ return Math.min(duration2, config2.labelX[labelIndex] * duration2 + 0.25);
45199
+ }
45200
+ const ribbonChartLabelDefault = "#FFFFFF";
45201
+ const ribbonChartSurface = {
45202
+ white: "#FFFFFF",
45203
+ black: "#0D1023"
45204
+ };
45205
+ const ribbonBandGradientStops = [
45206
+ { idSuffix: "0", start: "#33198C", end: "#5B2BF0" },
45207
+ { idSuffix: "1", start: "#4A22C8", end: "#7A3DF5" },
45208
+ { idSuffix: "2", start: "#6A32E8", end: "#9A6BFF" },
45209
+ { idSuffix: "3", start: "#8A52F5", end: "#BD84FF" },
45210
+ { idSuffix: "4", start: "#A86BFF", end: "#E6ABFF" }
45211
+ ];
45212
+ const RIBBON_BACKGROUND_CLASS = {
45213
+ white: "fairmint-equity-ribbon--bg-white",
45214
+ black: "fairmint-equity-ribbon--bg-black",
45215
+ transparent: "fairmint-equity-ribbon--bg-transparent"
45216
+ };
45217
+ const DEFAULT_RIBBON_LABELS = [
45218
+ "Cap Table",
45219
+ "Fundraising",
45220
+ "Grants",
45221
+ "Secondaries",
45222
+ "Liquidity"
45223
+ ];
45224
+ const RIBBON_BAND_GRADIENTS = ribbonBandGradientStops;
45225
+ const RIBBON_SURFACE_CSS_VARS = {
45226
+ "--fairmint-ribbon-surface-white": ribbonChartSurface.white,
45227
+ "--fairmint-ribbon-surface-black": ribbonChartSurface.black
45228
+ };
45229
+ const REVEAL_DURATION_MS = 2300;
45230
+ const REVEAL_DELAY_MS = 420;
45231
+ function labelAnchorTransform(_placement, yOffsetPx) {
45232
+ return `translate(0, calc(-100% + ${yOffsetPx}px))`;
45233
+ }
45234
+ function labelClassName(_placement) {
45235
+ return "fairmint-equity-ribbon__label fairmint-equity-ribbon__label--start";
45236
+ }
45237
+ function resolveGradients(gradients, bandCount) {
45238
+ const source = gradients ?? RIBBON_BAND_GRADIENTS;
45239
+ return Array.from({ length: bandCount }, (_, i) => {
45240
+ const fallback = RIBBON_BAND_GRADIENTS[i] ?? RIBBON_BAND_GRADIENTS[RIBBON_BAND_GRADIENTS.length - 1];
45241
+ const g = source[i] ?? fallback;
45242
+ return {
45243
+ idSuffix: String(i),
45244
+ start: g.start,
45245
+ end: g.end
45246
+ };
45247
+ });
45248
+ }
45249
+ function EquityRibbonChart({
45250
+ labels = DEFAULT_RIBBON_LABELS,
45251
+ bandCount: bandCountProp = 5,
45252
+ gradients,
45253
+ animated = true,
45254
+ hideLabels = false,
45255
+ background = "transparent",
45256
+ layout = "hero",
45257
+ labelColor = ribbonChartLabelDefault,
45258
+ className,
45259
+ height,
45260
+ style
45261
+ }) {
45262
+ const bandCount = clampBandCount(bandCountProp);
45263
+ const labelsKey = labels.join("");
45264
+ const labelsRef = useRef(labels);
45265
+ labelsRef.current = labels;
45266
+ const bandGradients = resolveGradients(gradients, bandCount);
45267
+ const uid = useId$2().replace(/:/g, "");
45268
+ const rootRef = useRef(null);
45269
+ const playedRef = useRef(false);
45270
+ const rafRef = useRef(null);
45271
+ const revealGenerationRef = useRef(0);
45272
+ const revealScheduleRef = useRef(0);
45273
+ const cancelRevealAnimation = useCallback(() => {
45274
+ revealGenerationRef.current += 1;
45275
+ if (rafRef.current !== null) {
45276
+ cancelAnimationFrame(rafRef.current);
45277
+ rafRef.current = null;
45278
+ }
45279
+ }, []);
45280
+ const [geometry, setGeometry] = useState(null);
45281
+ const [revealWidth, setRevealWidth] = useState(0);
45282
+ const [labelStyles, setLabelStyles] = useState(
45283
+ () => labels.slice(0, bandCount).map(() => ({ opacity: 0, transform: "translateY(6px)" }))
45284
+ );
45285
+ const rebuild = useCallback(() => {
45286
+ cancelRevealAnimation();
45287
+ const el = rootRef.current;
45288
+ if (!el) return;
45289
+ const width = el.clientWidth;
45290
+ const heightPx = el.clientHeight;
45291
+ const config2 = layout === "mark" ? MARK_RIBBON_CONFIG : void 0;
45292
+ const built = buildRibbonGeometry(
45293
+ width,
45294
+ heightPx,
45295
+ labelsRef.current,
45296
+ config2,
45297
+ bandCount,
45298
+ layout
45299
+ );
45300
+ setGeometry(built);
45301
+ if (built && (playedRef.current || !animated)) {
45302
+ setRevealWidth(built.width);
45303
+ setLabelStyles(
45304
+ built.labels.map((lbl) => ({
45305
+ opacity: 1,
45306
+ transform: labelAnchorTransform(lbl.placement, 0)
45307
+ }))
45308
+ );
45309
+ }
45310
+ }, [animated, bandCount, cancelRevealAnimation, labelsKey, layout]);
45311
+ useLayoutEffect(() => {
45312
+ playedRef.current = false;
45313
+ revealScheduleRef.current = 0;
45314
+ cancelRevealAnimation();
45315
+ if (animated) {
45316
+ setRevealWidth(0);
45317
+ setLabelStyles(
45318
+ labelsRef.current.slice(0, bandCount).map(() => ({
45319
+ opacity: 0,
45320
+ transform: "translateY(6px)"
45321
+ }))
45322
+ );
45323
+ }
45324
+ rebuild();
45325
+ }, [animated, bandCount, cancelRevealAnimation, rebuild]);
45326
+ useEffect(() => () => cancelRevealAnimation(), [cancelRevealAnimation]);
45327
+ useEffect(() => {
45328
+ const el = rootRef.current;
45329
+ if (!el) return;
45330
+ if (typeof ResizeObserver === "undefined") {
45331
+ rebuild();
45332
+ return;
45333
+ }
45334
+ const ro = new ResizeObserver(() => {
45335
+ rebuild();
45336
+ });
45337
+ ro.observe(el);
45338
+ return () => ro.disconnect();
45339
+ }, [rebuild]);
45340
+ const runReveal = useCallback(() => {
45341
+ if (!geometry || playedRef.current) return;
45342
+ if (!animated) {
45343
+ playedRef.current = true;
45344
+ setRevealWidth(geometry.width);
45345
+ setLabelStyles(
45346
+ geometry.labels.map((lbl) => ({
45347
+ opacity: 1,
45348
+ transform: labelAnchorTransform(lbl.placement, 0)
45349
+ }))
45350
+ );
45351
+ return;
45352
+ }
45353
+ const reduceMotion = typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
45354
+ if (reduceMotion) {
45355
+ playedRef.current = true;
45356
+ setRevealWidth(geometry.width);
45357
+ setLabelStyles(
45358
+ geometry.labels.map((lbl) => ({
45359
+ opacity: 1,
45360
+ transform: labelAnchorTransform(lbl.placement, 0)
45361
+ }))
45362
+ );
45363
+ return;
45364
+ }
45365
+ playedRef.current = true;
45366
+ setRevealWidth(0);
45367
+ setLabelStyles(
45368
+ geometry.labels.map((lbl) => ({
45369
+ opacity: 0,
45370
+ transform: labelAnchorTransform(lbl.placement, 6)
45371
+ }))
45372
+ );
45373
+ const generation = revealGenerationRef.current;
45374
+ const start = performance.now();
45375
+ const tick = (now) => {
45376
+ if (generation !== revealGenerationRef.current) return;
45377
+ const elapsed = now - start;
45378
+ const t = Math.min(1, elapsed / REVEAL_DURATION_MS);
45379
+ const eased = easePower1InOut(t);
45380
+ setRevealWidth(geometry.width * eased);
45381
+ setLabelStyles(
45382
+ geometry.labels.map((lbl, i) => {
45383
+ const labelStart = ribbonLabelRevealTime(i, REVEAL_DURATION_MS / 1e3) * 1e3;
45384
+ const labelDur = 550;
45385
+ const lt2 = Math.min(1, Math.max(0, (elapsed - labelStart) / labelDur));
45386
+ const lo = easePower2Out(lt2);
45387
+ const y = 6 * (1 - lo);
45388
+ return { opacity: lo, transform: labelAnchorTransform(lbl.placement, y) };
45389
+ })
45390
+ );
45391
+ if (t < 1) {
45392
+ rafRef.current = requestAnimationFrame(tick);
45393
+ } else {
45394
+ setRevealWidth(geometry.width);
45395
+ setLabelStyles(
45396
+ geometry.labels.map((lbl) => ({
45397
+ opacity: 1,
45398
+ transform: labelAnchorTransform(lbl.placement, 0)
45399
+ }))
45400
+ );
45401
+ }
45402
+ };
45403
+ rafRef.current = requestAnimationFrame(tick);
45404
+ }, [animated, geometry]);
45405
+ useEffect(() => {
45406
+ if (!geometry || playedRef.current) return;
45407
+ const scheduleId = ++revealScheduleRef.current;
45408
+ const delay = scheduleId === 1 ? REVEAL_DELAY_MS : 0;
45409
+ const timer = window.setTimeout(() => {
45410
+ if (scheduleId !== revealScheduleRef.current) return;
45411
+ runReveal();
45412
+ }, delay);
45413
+ return () => window.clearTimeout(timer);
45414
+ }, [geometry, runReveal]);
45415
+ const suppressLabels = hideLabels || layout === "mark";
45416
+ const activeGeometry = geometry && geometry.bandCount === bandCount ? geometry : null;
45417
+ const rootClass = [
45418
+ "fairmint-equity-ribbon",
45419
+ RIBBON_BACKGROUND_CLASS[background],
45420
+ layout === "mark" ? "fairmint-equity-ribbon--layout-mark" : "",
45421
+ suppressLabels ? "fairmint-equity-ribbon--hidden-labels" : "",
45422
+ className ?? ""
45423
+ ].filter(Boolean).join(" ");
45424
+ const rootStyle = {
45425
+ ...RIBBON_SURFACE_CSS_VARS,
45426
+ ...style,
45427
+ ...height ? { height } : {}
45428
+ };
45429
+ return /* @__PURE__ */ jsxs("div", { ref: rootRef, className: rootClass, style: rootStyle, children: [
45430
+ /* @__PURE__ */ jsxs(
45431
+ "svg",
45432
+ {
45433
+ className: "fairmint-equity-ribbon__svg",
45434
+ preserveAspectRatio: "none",
45435
+ "aria-hidden": "true",
45436
+ viewBox: activeGeometry ? `0 0 ${activeGeometry.width} ${activeGeometry.height}` : "0 0 1 1",
45437
+ children: [
45438
+ /* @__PURE__ */ jsxs("defs", { children: [
45439
+ bandGradients.map((g) => /* @__PURE__ */ jsxs(
45440
+ "linearGradient",
45441
+ {
45442
+ id: `${uid}-bg${g.idSuffix}`,
45443
+ x1: "0",
45444
+ y1: "1",
45445
+ x2: "1",
45446
+ y2: "0",
45447
+ children: [
45448
+ /* @__PURE__ */ jsx("stop", { offset: "0", stopColor: g.start }),
45449
+ /* @__PURE__ */ jsx("stop", { offset: "1", stopColor: g.end })
45450
+ ]
45451
+ },
45452
+ g.idSuffix
45453
+ )),
45454
+ /* @__PURE__ */ jsx("clipPath", { id: `${uid}-revealclip`, children: /* @__PURE__ */ jsx("rect", { x: 0, y: -1, width: revealWidth, height: (activeGeometry?.height ?? 1) + 2 }) }),
45455
+ activeGeometry ? activeGeometry.paths.map((_, i) => /* @__PURE__ */ jsx("clipPath", { id: `${uid}-bandclip${i}`, children: /* @__PURE__ */ jsx(
45456
+ "rect",
45457
+ {
45458
+ x: 0,
45459
+ y: -1,
45460
+ width: activeGeometry.clipWidthPx[i],
45461
+ height: activeGeometry.height + 2
45462
+ }
45463
+ ) }, `bandclip-${bandGradients[i].idSuffix}`)) : null
45464
+ ] }),
45465
+ /* @__PURE__ */ jsx("g", { clipPath: `url(#${uid}-revealclip)`, children: activeGeometry?.paths.map((d, i) => /* @__PURE__ */ jsx(
45466
+ "path",
45467
+ {
45468
+ className: "fairmint-equity-ribbon__band",
45469
+ fill: `url(#${uid}-bg${bandGradients[i].idSuffix})`,
45470
+ clipPath: `url(#${uid}-bandclip${i})`,
45471
+ d
45472
+ },
45473
+ bandGradients[i].idSuffix
45474
+ )) })
45475
+ ]
45476
+ }
45477
+ ),
45478
+ !suppressLabels && activeGeometry?.labels.map((lbl, i) => /* @__PURE__ */ jsx(
45479
+ "div",
45480
+ {
45481
+ className: labelClassName(lbl.placement),
45482
+ style: {
45483
+ left: `${lbl.leftPct}%`,
45484
+ top: `${lbl.topPct}%`,
45485
+ color: labelColor,
45486
+ opacity: labelStyles[i]?.opacity ?? 0,
45487
+ transform: labelStyles[i]?.transform
45488
+ },
45489
+ children: lbl.text
45490
+ },
45491
+ `${lbl.text}-${lbl.index}`
45492
+ ))
45493
+ ] });
45494
+ }
45495
+ function FairmintRibbonMark({
45496
+ size: size2 = 64,
45497
+ bandCount = 5,
45498
+ gradients,
45499
+ background = "black",
45500
+ labelColor,
45501
+ className,
45502
+ style
45503
+ }) {
45504
+ const dimension = `${size2}px`;
45505
+ return /* @__PURE__ */ jsx(
45506
+ EquityRibbonChart,
45507
+ {
45508
+ bandCount,
45509
+ gradients,
45510
+ background,
45511
+ labelColor,
45512
+ layout: "mark",
45513
+ animated: false,
45514
+ hideLabels: true,
45515
+ className: ["fairmint-ribbon-mark", className].filter(Boolean).join(" "),
45516
+ height: dimension,
45517
+ style: { width: dimension, height: dimension, ...style }
45518
+ }
45519
+ );
45520
+ }
45001
45521
  function InvestmentCard({
45002
45522
  companyName,
45003
45523
  logoUrl,
@@ -45768,6 +46288,8 @@ export {
45768
46288
  ConfirmDialog,
45769
46289
  Container,
45770
46290
  Currency,
46291
+ DEFAULT_RIBBON_CONFIG,
46292
+ DEFAULT_RIBBON_LABELS,
45771
46293
  DataRow,
45772
46294
  DataTable,
45773
46295
  DateDisplay,
@@ -45780,12 +46302,14 @@ export {
45780
46302
  EmailField,
45781
46303
  EmptyState,
45782
46304
  EquityGrantCard,
46305
+ EquityRibbonChart,
45783
46306
  ErrorFallback,
45784
46307
  ErrorPage,
45785
46308
  EthereumAddressField,
45786
46309
  Eyebrow,
45787
46310
  FairmintLogo,
45788
46311
  FairmintProvider,
46312
+ FairmintRibbonMark,
45789
46313
  Flex,
45790
46314
  Form,
45791
46315
  FormField,
@@ -45796,6 +46320,8 @@ export {
45796
46320
  ListRow,
45797
46321
  Loader,
45798
46322
  LoadingSpinner,
46323
+ MARK_RIBBON_CONFIG,
46324
+ MARK_RIBBON_RIGHT_EDGE,
45799
46325
  MOBILE_BREAKPOINT,
45800
46326
  Menu,
45801
46327
  Modal,
@@ -45815,6 +46341,8 @@ export {
45815
46341
  PhotoCropModal,
45816
46342
  PinInput,
45817
46343
  Progress,
46344
+ RIBBON_BACKGROUND_CLASS,
46345
+ RIBBON_BAND_GRADIENTS,
45818
46346
  RadioCard,
45819
46347
  RedactedValue,
45820
46348
  ScrollArea,
@@ -45848,6 +46376,7 @@ export {
45848
46376
  ZERO_ETHEREUM_ADDRESS,
45849
46377
  ZipField,
45850
46378
  brandColors,
46379
+ clampBandCount,
45851
46380
  colors,
45852
46381
  createFairmintMantineProviderProps,
45853
46382
  createZipSchema,