@refraction-ui/react 0.14.0 → 0.15.0

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.
@@ -0,0 +1,57 @@
1
+ /** Recording or live stream status for the browser chrome mock. */
2
+ type BrowserChromeStatus = 'live' | 'rec';
3
+ interface BrowserChromeMockProps {
4
+ /** URL to display in the address bar. */
5
+ url: string;
6
+ /** Optional status badge shown in the chrome bar. */
7
+ status?: BrowserChromeStatus;
8
+ }
9
+ interface BrowserChromeMockAPI {
10
+ /** ARIA attributes to spread on the group element. */
11
+ ariaProps: {
12
+ role: 'group';
13
+ 'aria-label': string;
14
+ };
15
+ /** Data attributes for styling hooks. */
16
+ dataAttributes: Record<string, string>;
17
+ }
18
+ /** Split a URL into bold domain and normal path segments. */
19
+ declare function splitUrl(url: string): {
20
+ domain: string;
21
+ path: string;
22
+ };
23
+ /**
24
+ * Build the framework-agnostic props for a BrowserChromeMock.
25
+ *
26
+ * Returns a `role="group"` aria label plus optional `data-status` so adapters
27
+ * can hook CSS without duplicating logic.
28
+ */
29
+ declare function createBrowserChromeMock(props?: Pick<BrowserChromeMockProps, 'status'>): BrowserChromeMockAPI;
30
+
31
+ /** Outer frame wrapping the chrome bar and content. */
32
+ declare const browserChromeMockVariants: (props?: ({} & {
33
+ className?: string;
34
+ }) | undefined) => string;
35
+ /** The chrome toolbar row containing dots, URL bar, and optional badge. */
36
+ declare const chromeBarClass = "flex items-center gap-2 bg-muted/40 border-b border-border px-3 py-2";
37
+ /** A single traffic-light dot. */
38
+ declare const trafficDotClass = "size-2.5 rounded-full border border-border";
39
+ /** Centered URL bar. */
40
+ declare const urlBarClass = "flex-1 text-center font-mono text-[11px] text-muted-foreground";
41
+ /** Bold domain segment inside the URL bar. */
42
+ declare const urlDomainClass = "font-semibold text-foreground";
43
+ /**
44
+ * Status badge shown in the chrome bar.
45
+ *
46
+ * live → emerald tint (approved exception to semantic tokens)
47
+ * rec → destructive tint with a pulsing dot
48
+ */
49
+ declare const statusBadgeVariants: (props?: ({
50
+ status?: "live" | "rec" | undefined;
51
+ } & {
52
+ className?: string;
53
+ }) | undefined) => string;
54
+ /** Inner content area that receives slotted/children content. */
55
+ declare const contentAreaClass = "p-0";
56
+
57
+ export { type BrowserChromeMockAPI, type BrowserChromeMockProps, type BrowserChromeStatus, browserChromeMockVariants, chromeBarClass, contentAreaClass, createBrowserChromeMock, splitUrl, statusBadgeVariants, trafficDotClass, urlBarClass, urlDomainClass };
@@ -0,0 +1,60 @@
1
+ /** Visual size of a mastery bar. */
2
+ type MasteryBarSize = 'sm' | 'md' | 'lg';
3
+ interface MasteryBarProps {
4
+ /** Progress value (0–100). Values outside this range are clamped. */
5
+ value: number;
6
+ /** Label shown on the right side of the header row. */
7
+ label?: string;
8
+ /** Label shown on the left side of the header row. */
9
+ leadingLabel?: string;
10
+ /** Visual size of the track. */
11
+ size?: MasteryBarSize;
12
+ /** Renders the fill at reduced opacity to indicate a muted/secondary state. */
13
+ muted?: boolean;
14
+ }
15
+ interface MasteryBarAPI {
16
+ /** ARIA attributes to spread on the progressbar element. */
17
+ ariaProps: Record<string, string | number | boolean>;
18
+ /** Data attributes for styling hooks. */
19
+ dataAttributes: Record<string, string>;
20
+ }
21
+ /**
22
+ * Clamp a raw numeric value to the [0, 100] range.
23
+ *
24
+ * Values below 0 become 0; values above 100 become 100; NaN is treated as 0.
25
+ */
26
+ declare function clampPercent(value: number): number;
27
+ /**
28
+ * Build the framework-agnostic progressbar props for a mastery bar.
29
+ *
30
+ * Returns `role="progressbar"` ARIA attributes plus data attributes; adapters
31
+ * spread these onto their track element.
32
+ */
33
+ declare function createMasteryBar({ value }: Pick<MasteryBarProps, 'value'>): MasteryBarAPI;
34
+
35
+ /**
36
+ * Track (outer container): rounded, muted background.
37
+ * `size` variant controls the track height.
38
+ */
39
+ declare const masteryBarVariants: (props?: ({
40
+ size?: "sm" | "md" | "lg" | undefined;
41
+ } & {
42
+ className?: string;
43
+ }) | undefined) => string;
44
+ /**
45
+ * Fill (inner bar): rounded, primary background.
46
+ * `muted` variant renders at reduced opacity for secondary/inactive states.
47
+ */
48
+ declare const masteryBarFillVariants: (props?: ({
49
+ muted?: "true" | "false" | undefined;
50
+ } & {
51
+ className?: string;
52
+ }) | undefined) => string;
53
+ /** Class applied to each text label (leading or trailing). */
54
+ declare const masteryBarLabelClass = "text-xs text-muted-foreground";
55
+ /** Class for the leading (left-side) label. */
56
+ declare const masteryBarLeadingLabelClass = "text-xs text-muted-foreground";
57
+ /** Header row above the track: leading label on the left, label on the right. */
58
+ declare const masteryBarHeaderClass = "flex justify-between items-baseline mb-1";
59
+
60
+ export { type MasteryBarAPI, type MasteryBarProps, type MasteryBarSize, clampPercent, createMasteryBar, masteryBarFillVariants, masteryBarHeaderClass, masteryBarLabelClass, masteryBarLeadingLabelClass, masteryBarVariants };
@@ -0,0 +1,71 @@
1
+ /** A single step item in the numbered steps grid. */
2
+ type NumberedStepItem = {
3
+ /** Step title displayed prominently below the ordinal badge. */
4
+ title: string;
5
+ /** Step body copy displayed below the title. */
6
+ body: string;
7
+ };
8
+ interface NumberedStepsProps {
9
+ /** The step items to display. */
10
+ items: NumberedStepItem[];
11
+ /**
12
+ * Number of grid columns. When omitted, defaults to clamping the item count
13
+ * to the 2–5 range via {@link stepColumns}.
14
+ */
15
+ columns?: number;
16
+ }
17
+ interface NumberedStepsAPI {
18
+ /** ARIA attributes to spread on the container element (`role="list"`). */
19
+ ariaProps: {
20
+ role: 'list';
21
+ };
22
+ /** Data attributes for styling hooks. */
23
+ dataAttributes: Record<string, string>;
24
+ }
25
+ /**
26
+ * Zero-pad a 1-indexed ordinal to at least two digits.
27
+ *
28
+ * @example
29
+ * padOrdinal(1) // '01'
30
+ * padOrdinal(10) // '10'
31
+ */
32
+ declare function padOrdinal(n: number): string;
33
+ /**
34
+ * Derive the number of grid columns from the item count.
35
+ * Clamps the count to the 2–5 range.
36
+ *
37
+ * @example
38
+ * stepColumns(3) // 3
39
+ * stepColumns(1) // 2
40
+ * stepColumns(6) // 5
41
+ */
42
+ declare function stepColumns(count: number): number;
43
+ /**
44
+ * Build the framework-agnostic container props for a numbered-steps grid.
45
+ *
46
+ * Returns `role="list"` plus data attributes; adapters spread these onto their
47
+ * container and render each step as a `role="listitem"`.
48
+ */
49
+ declare function createNumberedSteps(): NumberedStepsAPI;
50
+
51
+ /**
52
+ * Container grid for the numbered steps. The `columns` variant maps to a
53
+ * fixed Tailwind grid-cols class; adapters that need a dynamic column count
54
+ * use `gridTemplateColumns` inline style via {@link stepColumns} instead and
55
+ * omit this variant.
56
+ */
57
+ declare const numberedStepsVariants: (props?: ({
58
+ columns?: "2" | "3" | "4" | "5" | undefined;
59
+ } & {
60
+ className?: string;
61
+ }) | undefined) => string;
62
+ /** Individual step card. */
63
+ declare const numberedStepsItemClass = "rounded-xl border border-border bg-card p-5";
64
+ /** Zero-padded ordinal badge above each step title. */
65
+ declare const numberedStepsOrdinalClass = "font-mono text-sm text-primary";
66
+ /** Step title. */
67
+ declare const numberedStepsTitleClass = "mt-2 text-sm font-bold text-foreground";
68
+ /** Step body copy. */
69
+ declare const numberedStepsBodyClass = "mt-1 text-xs text-muted-foreground leading-relaxed";
70
+
71
+ export { type NumberedStepItem, type NumberedStepsAPI, type NumberedStepsProps, createNumberedSteps, numberedStepsBodyClass, numberedStepsItemClass, numberedStepsOrdinalClass, numberedStepsTitleClass, numberedStepsVariants, padOrdinal, stepColumns };
@@ -0,0 +1,61 @@
1
+ import { AccessibilityProps } from '../shared/index.js';
2
+
3
+ /** CTA button/link visual variant. */
4
+ type PricingCtaVariant = 'default' | 'outline';
5
+ interface PricingCardOptions {
6
+ /** Whether this card is highlighted as the featured / recommended plan. */
7
+ featured?: boolean;
8
+ }
9
+ interface PricingCardAPI {
10
+ /** ARIA props to spread on the card container. */
11
+ ariaProps: Partial<AccessibilityProps>;
12
+ /** Data attributes for styling hooks and CSS selectors. */
13
+ dataAttributes: Record<string, string>;
14
+ }
15
+ /**
16
+ * Build the framework-agnostic props for a pricing plan card.
17
+ *
18
+ * Returns `role="group"` (semantically groups the plan's content without
19
+ * imposing listitem semantics on a standalone card) and a `data-featured`
20
+ * attribute that adapters can use for conditional ring/highlight styling.
21
+ */
22
+ declare function createPricingCard(options?: PricingCardOptions): PricingCardAPI;
23
+
24
+ /**
25
+ * Root pricing card container. The `featured` variant adds a primary-coloured
26
+ * ring to draw the eye to the recommended plan.
27
+ */
28
+ declare const pricingCardVariants: (props?: ({
29
+ featured?: "true" | "false" | undefined;
30
+ } & {
31
+ className?: string;
32
+ }) | undefined) => string;
33
+ /** "Best value" / "Most popular" badge above the plan name. */
34
+ declare const pricingCardBadgeClass = "mb-3 inline-flex items-center rounded-full bg-primary/10 px-2.5 py-0.5 text-xs font-medium text-primary";
35
+ /** Plan name (e.g. "Pro", "Starter"). */
36
+ declare const pricingCardNameClass = "text-lg font-bold text-foreground";
37
+ /** Main price figure (e.g. "$29", "Free"). */
38
+ declare const pricingCardPriceClass = "text-3xl font-bold text-foreground";
39
+ /** Billing period or qualifier (e.g. "/ month", "forever"). */
40
+ declare const pricingCardPeriodClass = "text-sm text-muted-foreground";
41
+ /** Short marketing description beneath the price. */
42
+ declare const pricingCardDescriptionClass = "text-sm text-muted-foreground";
43
+ /** Unordered list of included features. */
44
+ declare const pricingCardFeatureListClass = "flex flex-col gap-2";
45
+ /** A single feature row — tick icon + text. */
46
+ declare const pricingCardFeatureRowClass = "flex items-start gap-2 text-sm text-foreground";
47
+ /** Inline check SVG rendered before each feature string. */
48
+ declare const pricingCardFeatureTickClass = "mt-0.5 size-4 shrink-0 text-primary";
49
+ /**
50
+ * CTA button/link that appears at the bottom of the card.
51
+ *
52
+ * `default` — filled primary style (call to action on featured plans).
53
+ * `outline` — bordered secondary style (for non-featured plans).
54
+ */
55
+ declare const pricingCtaVariants: (props?: ({
56
+ variant?: "default" | "outline" | undefined;
57
+ } & {
58
+ className?: string;
59
+ }) | undefined) => string;
60
+
61
+ export { type PricingCardAPI, type PricingCardOptions, type PricingCtaVariant, createPricingCard, pricingCardBadgeClass, pricingCardDescriptionClass, pricingCardFeatureListClass, pricingCardFeatureRowClass, pricingCardFeatureTickClass, pricingCardNameClass, pricingCardPeriodClass, pricingCardPriceClass, pricingCardVariants, pricingCtaVariants };
@@ -0,0 +1,22 @@
1
+ import * as React from 'react';
2
+
3
+ interface AudienceFeatureCardProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'title'> {
4
+ /** Kicker text displayed above the title (e.g. "For teams"). */
5
+ kicker?: React.ReactNode;
6
+ /** Main title — required. */
7
+ title: React.ReactNode;
8
+ /** Body copy. */
9
+ body: React.ReactNode;
10
+ /** Footer slot — pushed to bottom of the card. */
11
+ footer?: React.ReactNode;
12
+ }
13
+ /**
14
+ * AudienceFeatureCard — a marketing feature/audience card.
15
+ *
16
+ * Full-height flex-col layout so footers align across a row of cards.
17
+ * Accepts kicker, title, body, and an optional footer slot.
18
+ * Spreads `role="group"` from the headless core for accessibility.
19
+ */
20
+ declare const AudienceFeatureCard: React.ForwardRefExoticComponent<AudienceFeatureCardProps & React.RefAttributes<HTMLDivElement>>;
21
+
22
+ export { AudienceFeatureCard, type AudienceFeatureCardProps };
@@ -0,0 +1,30 @@
1
+ import * as React from 'react';
2
+
3
+ interface BrandNetworkCellProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'color' | 'content'> {
4
+ /** Single character or short string used as the brand monogram. */
5
+ glyph: string;
6
+ /** CSS colour value for the glyph box background (brand tint). Applied via inline style. */
7
+ glyphBg?: string;
8
+ /** CSS colour value for the glyph text (brand tint). Applied via inline style. */
9
+ glyphColor?: string;
10
+ /** Primary identifier shown below the glyph (product domain or name). */
11
+ domain: string;
12
+ /** Supporting description text. */
13
+ body: string;
14
+ /** When provided, renders a link at the bottom of the card. */
15
+ href?: string;
16
+ /** Label for the link. Defaults to "Visit →". */
17
+ linkLabel?: string;
18
+ /** Marks this cell as the current/active product in the network. */
19
+ current?: boolean;
20
+ }
21
+ /**
22
+ * BrandNetworkCell — a card for surfacing related products in a brand network.
23
+ *
24
+ * Renders a glyph monogram (brand tint via inline style), the product domain,
25
+ * a "You are here" badge when `current`, body copy, and an optional visit link.
26
+ * The `current` variant adds `ring-1 ring-primary` to the card border.
27
+ */
28
+ declare const BrandNetworkCell: React.ForwardRefExoticComponent<BrandNetworkCellProps & React.RefAttributes<HTMLDivElement>>;
29
+
30
+ export { BrandNetworkCell, type BrandNetworkCellProps };
@@ -0,0 +1,21 @@
1
+ import * as React from 'react';
2
+ import { BrowserChromeStatus } from '../browser-chrome-mock/index.js';
3
+ export { BrowserChromeStatus } from '../browser-chrome-mock/index.js';
4
+
5
+ interface BrowserChromeMockProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'color' | 'content'> {
6
+ /** URL to display in the address bar. Bold domain + normal path. */
7
+ url: string;
8
+ /** Optional status badge shown in the chrome bar. */
9
+ status?: BrowserChromeStatus;
10
+ }
11
+ /**
12
+ * BrowserChromeMock — a decorative browser window frame.
13
+ *
14
+ * Renders a mock browser chrome with traffic-light dots, a monospace URL bar
15
+ * (bold domain + normal path), an optional live/rec status badge, and a
16
+ * content area for arbitrary children. Logic and styles come from the headless
17
+ * `@refraction-ui/browser-chrome-mock` core.
18
+ */
19
+ declare const BrowserChromeMock: React.ForwardRefExoticComponent<BrowserChromeMockProps & React.RefAttributes<HTMLDivElement>>;
20
+
21
+ export { BrowserChromeMock, type BrowserChromeMockProps };
@@ -0,0 +1,33 @@
1
+ import * as React from 'react';
2
+
3
+ interface MarqueeStripProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'color' | 'content'> {
4
+ /** Eyebrow label shown before the items. */
5
+ label?: string;
6
+ /** List of text items to display. */
7
+ items: string[];
8
+ /**
9
+ * When `true` the items scroll continuously using a CSS `marquee` keyframe.
10
+ * The keyframe must be defined in the consuming app's global CSS:
11
+ *
12
+ * ```css
13
+ * @keyframes marquee {
14
+ * from { transform: translateX(0); }
15
+ * to { transform: translateX(-50%); }
16
+ * }
17
+ * ```
18
+ *
19
+ * @default false
20
+ */
21
+ scroll?: boolean;
22
+ }
23
+ /**
24
+ * MarqueeStrip — a full-width label + tag strip, optionally scrolling.
25
+ *
26
+ * Static mode (`scroll={false}`, default): items flex-wrap in a row after the
27
+ * label. Scroll mode: items loop continuously via a CSS marquee animation;
28
+ * items are duplicated once internally for a seamless loop. Logic and
29
+ * data attributes come from the headless `@refraction-ui/marquee-strip` core.
30
+ */
31
+ declare const MarqueeStrip: React.ForwardRefExoticComponent<MarqueeStripProps & React.RefAttributes<HTMLDivElement>>;
32
+
33
+ export { MarqueeStrip, type MarqueeStripProps };
@@ -0,0 +1,26 @@
1
+ import * as React from 'react';
2
+ import { MasteryBarSize } from '../mastery-bar/index.js';
3
+ export { MasteryBarSize } from '../mastery-bar/index.js';
4
+
5
+ interface MasteryBarProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'color' | 'content' | 'results'> {
6
+ /** Progress value (0–100). Values outside this range are clamped. */
7
+ value: number;
8
+ /** Label shown on the right side of the header row. */
9
+ label?: string;
10
+ /** Label shown on the left side of the header row. */
11
+ leadingLabel?: string;
12
+ /** Visual size of the track. */
13
+ size?: MasteryBarSize;
14
+ /** Renders the fill at reduced opacity to indicate a muted/secondary state. */
15
+ muted?: boolean;
16
+ }
17
+ /**
18
+ * MasteryBar — a labelled linear progress bar for skill/concept mastery.
19
+ *
20
+ * Renders `role="progressbar"` with aria-valuenow/min/max. Optionally renders
21
+ * a header row with a leading label (left) and a trailing label (right). Logic
22
+ * and styles come from the headless `@refraction-ui/mastery-bar` core.
23
+ */
24
+ declare const MasteryBar: React.ForwardRefExoticComponent<MasteryBarProps & React.RefAttributes<HTMLDivElement>>;
25
+
26
+ export { MasteryBar, type MasteryBarProps };
@@ -0,0 +1,24 @@
1
+ import * as React from 'react';
2
+ import { NumberedStepItem } from '../numbered-steps/index.js';
3
+ export { NumberedStepItem } from '../numbered-steps/index.js';
4
+
5
+ interface NumberedStepsProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'color' | 'content'> {
6
+ /** The step items to display (3–5 recommended). */
7
+ items: NumberedStepItem[];
8
+ /**
9
+ * Override the number of grid columns. Defaults to clamping item count to
10
+ * 2–5 via `stepColumns`.
11
+ */
12
+ columns?: number;
13
+ }
14
+ /**
15
+ * NumberedSteps — a static how-it-works step grid.
16
+ *
17
+ * Renders a CSS grid of step cards, each with a zero-padded ordinal badge
18
+ * (01, 02…), a title, and body copy. Not a stateful stepper — use the `Steps`
19
+ * component for that. Exposes `role="list"` semantics with each card as
20
+ * `role="listitem"`.
21
+ */
22
+ declare const NumberedSteps: React.ForwardRefExoticComponent<NumberedStepsProps & React.RefAttributes<HTMLDivElement>>;
23
+
24
+ export { NumberedSteps, type NumberedStepsProps };
@@ -0,0 +1,40 @@
1
+ import * as React from 'react';
2
+ import { PricingCtaVariant } from '../pricing-card/index.js';
3
+ export { PricingCtaVariant } from '../pricing-card/index.js';
4
+
5
+ interface PricingCardProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'content'> {
6
+ /** Optional badge label shown above the plan name (e.g. "Most popular"). */
7
+ badge?: string;
8
+ /** Plan name (e.g. "Pro", "Starter"). */
9
+ name: string;
10
+ /** Price string (e.g. "$29", "Free"). */
11
+ price: string;
12
+ /** Billing period or qualifier (e.g. "/ month"). */
13
+ period?: string;
14
+ /** Short marketing description. */
15
+ description?: string;
16
+ /** List of included features to render as a checklist. */
17
+ features: string[];
18
+ /** CTA button/link label. */
19
+ cta: string;
20
+ /** Visual variant for the CTA. */
21
+ ctaVariant?: PricingCtaVariant;
22
+ /** When provided, the CTA renders as an `<a>` tag. */
23
+ ctaHref?: string;
24
+ /** Click handler for the CTA button (ignored when `ctaHref` is provided). */
25
+ onCtaClick?: React.MouseEventHandler<HTMLButtonElement>;
26
+ /** Highlights the card with a primary ring. */
27
+ featured?: boolean;
28
+ }
29
+ /**
30
+ * PricingCard — a self-contained pricing plan card.
31
+ *
32
+ * Renders an optional badge, the plan name, price + optional period, optional
33
+ * description, a feature checklist, and a full-width CTA (anchor when
34
+ * `ctaHref` is set, button otherwise). The `featured` prop adds a primary-
35
+ * colour ring to highlight the recommended plan. Logic and styles come from
36
+ * the headless `@refraction-ui/pricing-card` core.
37
+ */
38
+ declare const PricingCard: React.ForwardRefExoticComponent<PricingCardProps & React.RefAttributes<HTMLDivElement>>;
39
+
40
+ export { PricingCard, type PricingCardProps };
@@ -0,0 +1,27 @@
1
+ import * as React from 'react';
2
+ import { SectionHeadAlign } from '../section-head/index.js';
3
+ export { SectionHeadAlign } from '../section-head/index.js';
4
+
5
+ interface SectionHeadProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'title'> {
6
+ /** Optional eyebrow / kicker rendered above the title. */
7
+ kicker?: React.ReactNode;
8
+ /** Primary heading content (required). */
9
+ title: React.ReactNode;
10
+ /** Optional lede paragraph rendered below the title. */
11
+ lede?: React.ReactNode;
12
+ /** Horizontal alignment of the cluster. */
13
+ align?: SectionHeadAlign;
14
+ /** Override the heading element rendered for the title. Defaults to `h2`. */
15
+ as?: 'h1' | 'h2' | 'h3';
16
+ }
17
+ /**
18
+ * SectionHead — marketing section heading cluster.
19
+ *
20
+ * Renders an optional small-caps kicker above an `<h2>` title (configurable
21
+ * via `as`) with an optional lede paragraph below. Alignment is controlled via
22
+ * the `align` prop; layout classes come from the headless
23
+ * `@refraction-ui/section-head` core.
24
+ */
25
+ declare const SectionHead: React.ForwardRefExoticComponent<SectionHeadProps & React.RefAttributes<HTMLDivElement>>;
26
+
27
+ export { SectionHead, type SectionHeadProps };
@@ -0,0 +1,29 @@
1
+ import * as React from 'react';
2
+ export { StatItem, statColumns } from '../stat-grid/index.js';
3
+
4
+ interface StatGridItem {
5
+ /** The primary value displayed prominently. Allows rich content in React. */
6
+ value: React.ReactNode;
7
+ /** The descriptive label shown below the value. */
8
+ label: React.ReactNode;
9
+ }
10
+ interface StatGridProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'content'> {
11
+ /** The stat items to display in the grid. */
12
+ items: StatGridItem[];
13
+ /**
14
+ * Number of columns. Defaults to `statColumns(items.length)`:
15
+ * 1 item → 1, 2 items → 2, 3+ items → 3.
16
+ */
17
+ columns?: number;
18
+ }
19
+ /**
20
+ * StatGrid — a marketing-style grid of stat callouts.
21
+ *
22
+ * Each item shows a large bold value and a small muted label. The grid
23
+ * automatically computes the column count from the number of items, or you can
24
+ * override it with `columns`. Uses `role="list"` / `role="listitem"` for
25
+ * accessible enumeration.
26
+ */
27
+ declare const StatGrid: React.ForwardRefExoticComponent<StatGridProps & React.RefAttributes<HTMLDivElement>>;
28
+
29
+ export { StatGrid, type StatGridItem, type StatGridProps };
@@ -0,0 +1,36 @@
1
+ /** Horizontal alignment of the section head cluster. */
2
+ type SectionHeadAlign = 'center' | 'left';
3
+ interface SectionHeadProps {
4
+ /** Alignment of the kicker, title, and lede. */
5
+ align?: SectionHeadAlign;
6
+ }
7
+ interface SectionHeadAPI {
8
+ /** Data attributes for styling hooks. */
9
+ dataAttributes: Record<string, string>;
10
+ }
11
+ /**
12
+ * Build the framework-agnostic data attributes for a SectionHead.
13
+ *
14
+ * Returns data-align so adapters can apply styles via CSS or Tailwind
15
+ * variants. All visual logic (classes, cva) lives in `section-head.styles.ts`.
16
+ */
17
+ declare function createSectionHead(props?: SectionHeadProps): SectionHeadAPI;
18
+
19
+ /**
20
+ * Container variant that controls the alignment of the whole cluster.
21
+ * Center: auto-margins + text-center + constrained max-width for comfortable
22
+ * line length. Left: no margin constraint, flush left.
23
+ */
24
+ declare const sectionHeadVariants: (props?: ({
25
+ align?: "center" | "left" | undefined;
26
+ } & {
27
+ className?: string;
28
+ }) | undefined) => string;
29
+ /** Small-caps eyebrow label above the title. */
30
+ declare const sectionHeadKickerClass = "text-[11px] uppercase tracking-widest text-primary font-semibold";
31
+ /** Primary h2 heading. */
32
+ declare const sectionHeadTitleClass = "text-3xl sm:text-4xl font-bold tracking-tight text-foreground";
33
+ /** Optional lede paragraph below the title. */
34
+ declare const sectionHeadLedeClass = "mt-3 text-muted-foreground leading-relaxed";
35
+
36
+ export { type SectionHeadAPI, type SectionHeadAlign, type SectionHeadProps, createSectionHead, sectionHeadKickerClass, sectionHeadLedeClass, sectionHeadTitleClass, sectionHeadVariants };
@@ -0,0 +1,45 @@
1
+ /** A single stat callout displayed in the grid. */
2
+ type StatItem = {
3
+ /** The primary value displayed prominently (e.g. "10k+", "$4.2M"). */
4
+ value: string;
5
+ /** The descriptive label shown below the value. */
6
+ label: string;
7
+ };
8
+ interface StatGridAPI {
9
+ /** ARIA attributes to spread on the grid container element (`role="list"`). */
10
+ ariaProps: {
11
+ role: 'list';
12
+ };
13
+ /** Data attributes for styling hooks. */
14
+ dataAttributes: Record<string, string>;
15
+ }
16
+ /**
17
+ * Compute the number of grid columns for a stat grid.
18
+ *
19
+ * - 1 item → 1 column
20
+ * - 2 items → 2 columns
21
+ * - 3 or more items → capped at `max` (default 3)
22
+ */
23
+ declare function statColumns(count: number, max?: number): number;
24
+ /**
25
+ * Build the framework-agnostic container props for a stat grid.
26
+ *
27
+ * Returns `role="list"` and data attributes; adapters spread these onto their
28
+ * container element and render the items themselves.
29
+ */
30
+ declare function createStatGrid(): StatGridAPI;
31
+
32
+ /** Grid container that lays out stat items. */
33
+ declare const statGridVariants: (props?: ({
34
+ columns?: "1" | "2" | "3" | undefined;
35
+ } & {
36
+ className?: string;
37
+ }) | undefined) => string;
38
+ /** Individual stat item container (role="listitem"). */
39
+ declare const statItemClass = "flex flex-col";
40
+ /** The large bold value of the stat. */
41
+ declare const statValueClass = "text-xl sm:text-2xl font-bold text-primary";
42
+ /** The descriptive label below the value. */
43
+ declare const statLabelClass = "mt-1 text-sm text-muted-foreground leading-snug";
44
+
45
+ export { type StatGridAPI, type StatItem, createStatGrid, statColumns, statGridVariants, statItemClass, statLabelClass, statValueClass };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@refraction-ui/react",
3
- "version": "0.14.0",
3
+ "version": "0.15.0",
4
4
  "description": "All Refraction UI React components in one package — headless, accessible, zero-dependency",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -54,13 +54,16 @@
54
54
  "@refraction-ui/react-analytics": "workspace:*",
55
55
  "@refraction-ui/react-animated-text": "workspace:*",
56
56
  "@refraction-ui/react-app-shell": "workspace:*",
57
+ "@refraction-ui/react-audience-feature-card": "workspace:*",
57
58
  "@refraction-ui/react-audio-room": "workspace:*",
58
59
  "@refraction-ui/react-auth": "workspace:*",
59
60
  "@refraction-ui/react-avatar": "workspace:*",
60
61
  "@refraction-ui/react-avatar-group": "workspace:*",
61
62
  "@refraction-ui/react-badge": "workspace:*",
62
63
  "@refraction-ui/react-bottom-nav": "workspace:*",
64
+ "@refraction-ui/react-brand-network-cell": "workspace:*",
63
65
  "@refraction-ui/react-breadcrumbs": "workspace:*",
66
+ "@refraction-ui/react-browser-chrome-mock": "workspace:*",
64
67
  "@refraction-ui/react-button": "workspace:*",
65
68
  "@refraction-ui/react-calendar": "workspace:*",
66
69
  "@refraction-ui/react-call-controls": "workspace:*",
@@ -112,9 +115,12 @@
112
115
  "@refraction-ui/react-live-transcript": "workspace:*",
113
116
  "@refraction-ui/react-logger": "workspace:*",
114
117
  "@refraction-ui/react-markdown-renderer": "workspace:*",
118
+ "@refraction-ui/react-marquee-strip": "workspace:*",
119
+ "@refraction-ui/react-mastery-bar": "workspace:*",
115
120
  "@refraction-ui/react-mini-map": "workspace:*",
116
121
  "@refraction-ui/react-mobile-nav": "workspace:*",
117
122
  "@refraction-ui/react-navbar": "workspace:*",
123
+ "@refraction-ui/react-numbered-steps": "workspace:*",
118
124
  "@refraction-ui/react-otp-input": "workspace:*",
119
125
  "@refraction-ui/react-pagination": "workspace:*",
120
126
  "@refraction-ui/react-password-input": "workspace:*",
@@ -122,6 +128,7 @@
122
128
  "@refraction-ui/react-popover": "workspace:*",
123
129
  "@refraction-ui/react-pre-call-lobby": "workspace:*",
124
130
  "@refraction-ui/react-presence-indicator": "workspace:*",
131
+ "@refraction-ui/react-pricing-card": "workspace:*",
125
132
  "@refraction-ui/react-progress-display": "workspace:*",
126
133
  "@refraction-ui/react-radial-gauge": "workspace:*",
127
134
  "@refraction-ui/react-radio": "workspace:*",
@@ -130,6 +137,7 @@
130
137
  "@refraction-ui/react-resizable-layout": "workspace:*",
131
138
  "@refraction-ui/react-rich-editor": "workspace:*",
132
139
  "@refraction-ui/react-search-bar": "workspace:*",
140
+ "@refraction-ui/react-section-head": "workspace:*",
133
141
  "@refraction-ui/react-segmented-control": "workspace:*",
134
142
  "@refraction-ui/react-select": "workspace:*",
135
143
  "@refraction-ui/react-separator": "workspace:*",
@@ -140,6 +148,7 @@
140
148
  "@refraction-ui/react-slide-viewer": "workspace:*",
141
149
  "@refraction-ui/react-slider": "workspace:*",
142
150
  "@refraction-ui/react-social-auth-button": "workspace:*",
151
+ "@refraction-ui/react-stat-grid": "workspace:*",
143
152
  "@refraction-ui/react-status-indicator": "workspace:*",
144
153
  "@refraction-ui/react-steps": "workspace:*",
145
154
  "@refraction-ui/react-sticky-note": "workspace:*",