@mediaradar/design-components 0.7.0 → 0.8.1

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.
package/dist/index.d.cts CHANGED
@@ -165,6 +165,7 @@ declare function AdvertiserSearchPrompt({ label }: AdvertiserSearchPromptProps):
165
165
  * ```
166
166
  */
167
167
  interface CheckBoxProps {
168
+ /** Whether the box is checked. Controlled: the parent owns this value. */
168
169
  checked: boolean;
169
170
  /**
170
171
  * Some-but-not-all state for a "select all" checkbox -- shows a dash
@@ -172,9 +173,14 @@ interface CheckBoxProps {
172
173
  * plain boolean.
173
174
  */
174
175
  indeterminate?: boolean;
176
+ /**
177
+ * Called on click with no argument -- flip `checked` yourself. The click
178
+ * doesn't bubble, so a row that toggles on its own click won't fire twice.
179
+ */
175
180
  onChange: () => void;
176
181
  /** Accessible label -- required since the control carries no visible text of its own. */
177
182
  ariaLabel: string;
183
+ /** Blocks clicks, dims the box to 50% opacity, and cancels its hover preview. */
178
184
  disabled?: boolean;
179
185
  /** Forwarded as `data-testid`, for Playwright/test selectors. */
180
186
  testId?: string;
@@ -493,6 +499,8 @@ interface CardProps extends Omit<React.HTMLAttributes<HTMLElement>, "title"> {
493
499
  subtitle?: string;
494
500
  /** Trailing header content, e.g. a "View all" link. Ignored without `title`. */
495
501
  action?: ReactNode;
502
+ /** Card body. Rendered edge to edge without `title`; inside the standard padding with it. */
503
+ children?: ReactNode;
496
504
  }
497
505
  declare const Card: react.ForwardRefExoticComponent<CardProps & react.RefAttributes<HTMLElement>>;
498
506
 
@@ -1194,6 +1202,8 @@ interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement>, VariantPr
1194
1202
  asChild?: boolean;
1195
1203
  /** Shows a spinner in place of the leading edge and disables the button. */
1196
1204
  loading?: boolean;
1205
+ /** Button label and/or icon. With `asChild`, the single element that receives the button styling. */
1206
+ children?: ReactNode;
1197
1207
  }
1198
1208
  /**
1199
1209
  * @pattern Button
@@ -1409,7 +1419,7 @@ interface PagerProps {
1409
1419
  */
1410
1420
  declare function Pager({ page, totalPages, onPage }: PagerProps): react.JSX.Element;
1411
1421
 
1412
- declare const SIZES: {
1422
+ declare const SIZES$1: {
1413
1423
  /** Matches a 15px lucide icon exactly, so a workspace name in a menu row
1414
1424
  * left-aligns with labels in icon-led rows above and below it. */
1415
1425
  readonly xs: "h-[15px] w-[15px] rounded-[4px] text-[8px] tracking-tight";
@@ -1420,7 +1430,7 @@ declare const SIZES: {
1420
1430
  interface WorkspaceAvatarProps {
1421
1431
  /** Omit for the unscoped "All data workspace". */
1422
1432
  name?: string;
1423
- size?: keyof typeof SIZES;
1433
+ size?: keyof typeof SIZES$1;
1424
1434
  }
1425
1435
  /**
1426
1436
  * @pattern WorkspaceAvatar
@@ -1437,4 +1447,239 @@ interface WorkspaceAvatarProps {
1437
1447
  */
1438
1448
  declare function WorkspaceAvatar({ name, size }: WorkspaceAvatarProps): react.JSX.Element;
1439
1449
 
1440
- export { AdvertiserNoResults, type AdvertiserNoResultsProps, AdvertiserQuickFilter, type AdvertiserQuickFilterProps, AdvertiserSearchPrompt, type AdvertiserSearchPromptProps, BarChartPlaceholder, type BarChartPlaceholderProps, Button, type ButtonProps, Card, type CardProps, CheckBox, type CheckBoxProps, ChipContent, type ChipContentProps, DEFAULT_SEARCH_MATCH, DataScopeFilter, type DataScopeFilterProps, DateRangeFilter, type DateRangeFilterProps, FilterChipBar, type FilterChipBarProps, FilterDropdownFooter, type FilterDropdownFooterProps, InfoTip, type InfoTipProps, LineChartPlaceholder, type LineChartPlaceholderProps, NO_RESULTS_BODY, NO_RESULTS_TITLE, NameListModal, type NameListModalProps, type NoResultsAction, NoResultsEmptyState, type NoResultsEmptyStateProps, PRIMARY_ACTION_CLASS, Pager, type PagerProps, type PickerColumn, type PickerFilter, type PickerRow, PieChartPlaceholder, type PieChartPlaceholderProps, type PubBreak, PublisherBreakdownList, type PublisherBreakdownListProps, QUIET_ACTION_CLASS, SearchBar, type SearchBarProps, type SearchBarVariant, type SearchMatchMode, type SearchMatchValue, SectionRail, type SectionRailProps, SelectAllVisible, type SelectAllVisibleProps, SelectFilter, type SelectFilterProps, SelectedSection, type SelectedSectionProps, SelectionPicker, type SelectionPickerAccountList, type SelectionPickerProps, SortButton, type SortButtonProps, type SortDir, type SortState, StackedColumnPlaceholder, type StackedColumnPlaceholderProps, type SummaryGroup, type SummaryGroupItemValue, Tooltip, type TooltipProps, WorkspaceAvatar, type WorkspaceAvatarProps, WorkspaceSelectedCard, type WorkspaceSelectedCardProps, buttonVariants, chipTriggerClass, cycleSort, noResultsBody, sortProp };
1450
+ interface TagProps {
1451
+ /** The tag's text, e.g. "Digital". Keep it short: the chip doesn't wrap or truncate. */
1452
+ children: ReactNode;
1453
+ /** Extra classes merged onto the chip. */
1454
+ className?: string;
1455
+ }
1456
+ /**
1457
+ * @pattern Tag
1458
+ * @description Canonical descriptive tag — a neutral beige chip (e.g.
1459
+ * "Digital", a focus area, a category). Use this for every non-semantic
1460
+ * label so tags read the same everywhere. Colored/semantic badges (NEW, ±%
1461
+ * deltas, status, counts) are intentionally NOT this component.
1462
+ * @tokens bg-subtle, text-text-secondary, rounded-full
1463
+ * @usage
1464
+ * ```tsx
1465
+ * <Tag>Digital</Tag>
1466
+ * ```
1467
+ */
1468
+ declare function Tag({ children, className }: TagProps): react.JSX.Element;
1469
+
1470
+ /**
1471
+ * @pattern TablePagination
1472
+ * @description Full table-footer pagination bar: a rows-per-page select, a
1473
+ * first/prev/pages/next/last pager, and the resolved "1 – 25 of N results"
1474
+ * range. Owns no state — the host page holds `page` and `perPage` so the
1475
+ * paged slice and the bar can't disagree.
1476
+ * @tokens rounded-control, border-border-default, bg-input, text-text-primary, text-text-secondary, text-text-tertiary, bg-brand-primaryAction, text-brand-onprimary, hover:bg-subtle, hover:text-text-primary, focus:outline-border-focus
1477
+ * @behavior The current page is filled with the brand action color (matching
1478
+ * the Contacts pager). First/prev disable on page 1, next/last on the last
1479
+ * page — disabled controls stay in the layout so the row never reflows.
1480
+ * Changing the per-page count reports it and leaves the host to reset to page
1481
+ * 1. With one page of results the pager still renders, so the bar's height
1482
+ * and the range readout don't come and go as filters narrow.
1483
+ * @usage
1484
+ * ```tsx
1485
+ * <TablePagination
1486
+ * page={page}
1487
+ * perPage={perPage}
1488
+ * totalItems={matching.length}
1489
+ * onPageChange={setPage}
1490
+ * onPerPageChange={(n) => { setPerPage(n); setPage(1) }}
1491
+ * itemLabel="results"
1492
+ * />
1493
+ * ```
1494
+ */
1495
+ declare function TablePagination({ page, perPage, totalItems, onPageChange, onPerPageChange, perPageOptions, itemLabel, className, }: {
1496
+ page: number;
1497
+ perPage: number;
1498
+ totalItems: number;
1499
+ onPageChange: (page: number) => void;
1500
+ onPerPageChange: (perPage: number) => void;
1501
+ perPageOptions?: number[];
1502
+ itemLabel?: string;
1503
+ className?: string;
1504
+ }): react.JSX.Element;
1505
+ type TablePaginationProps = Parameters<typeof TablePagination>[0];
1506
+
1507
+ /** Resolve a label to its actual [start, end] span, ending at `today`. */
1508
+ declare function resolveRange(label: string, today?: Date): [Date, Date];
1509
+ declare function DateRangePicker({ defaultValue, align, presets, onChange, onRangeChange, showFooter, today, years, }: {
1510
+ defaultValue?: string;
1511
+ align?: 'left' | 'right';
1512
+ /** Rolling presets shown above Custom Range. Defaults to 3/6/12 months. */
1513
+ presets?: string[];
1514
+ onChange?: (label: string) => void;
1515
+ /** Reports the resolved start/end dates — used to drive dependent views (e.g. table columns). */
1516
+ onRangeChange?: (start: Date, end: Date) => void;
1517
+ /** Deferred mode: preset/custom-range picks stage in a draft; only the fixed
1518
+ * Apply footer commits it (no live commit on click). */
1519
+ showFooter?: boolean;
1520
+ /** End of the available data window: rolling presets resolve back from here.
1521
+ * Defaults to the current date. */
1522
+ today?: Date;
1523
+ /** Years offered in the Custom Range selects. Defaults to the last four,
1524
+ * ending with `today`'s year. */
1525
+ years?: number[];
1526
+ }): react.JSX.Element;
1527
+ type DateRangePickerProps = Parameters<typeof DateRangePicker>[0];
1528
+
1529
+ interface MultiSelectGroup {
1530
+ id: string;
1531
+ label: string;
1532
+ children: {
1533
+ id: string;
1534
+ label: string;
1535
+ }[];
1536
+ }
1537
+ /**
1538
+ * @pattern MultiSelectFilter
1539
+ * @description Quick-access multi-select chip — mirrors the DateRangeFilter
1540
+ * button shape (two-line caption + value with a chevron) and opens a
1541
+ * searchable checkbox popover. Used for the page-level Media Type /
1542
+ * Advertiser filters that share state with the filter tray.
1543
+ * @tokens rounded-control, rounded-card, border-border-default, bg-surface, shadow-overlay, text-text-primary, text-text-secondary, text-text-tertiary, text-text-link, border-border-interactive, bg-brand-primaryAction, bg-input, hover:bg-subtle, hover:text-text-primary, placeholder:text-text-tertiary
1544
+ * @dependencies lucide-react
1545
+ * @behavior Same draft/commit-on-close pattern as AdvertiserQuickFilter — the
1546
+ * draft resyncs from `selected` every time the tray opens, and (without
1547
+ * showFooter) any close path commits it, while showFooter mode requires the
1548
+ * Apply button and discards the draft on every other close. `min` enforces a
1549
+ * selection floor by silently ignoring any toggle that would drop below it —
1550
+ * there's no error state, the click just does nothing. Group parents are
1551
+ * tri-state and toggle all of their children in one action.
1552
+ * @usage
1553
+ * ```tsx
1554
+ * <MultiSelectFilter caption="Media" options={mediaOptions} selected={selected} onChange={setSelected} />
1555
+ * ```
1556
+ */
1557
+ declare function MultiSelectFilter({ caption, options, groups, selected, onChange, allLabel, searchable, searchPlaceholder, align, fullIsAll, min, icon, showFooter, clearValue, menuWidthClass, plainParent, fullWidth, }: {
1558
+ caption: string;
1559
+ options?: {
1560
+ id: string;
1561
+ label: string;
1562
+ }[];
1563
+ /** When provided, renders a nested parent → children tree (selection tracks
1564
+ * leaf ids; parents are tri-state and toggle all their children). */
1565
+ groups?: MultiSelectGroup[];
1566
+ selected: string[];
1567
+ onChange: (next: string[]) => void;
1568
+ allLabel?: string;
1569
+ searchable?: boolean;
1570
+ /** Overrides the search box's placeholder. The default derives from the
1571
+ * caption, which reads wrong once a caption is singular ("Search topic"). */
1572
+ searchPlaceholder?: string;
1573
+ align?: 'left' | 'right';
1574
+ /** Treat "all options selected" as the unfiltered "All" state in the label. */
1575
+ fullIsAll?: boolean;
1576
+ /** Minimum selections that must remain (a toggle that would drop below is ignored). */
1577
+ min?: number;
1578
+ icon?: React.ReactNode;
1579
+ /** Deferred mode: checkbox edits stage in a draft; only the fixed Apply/Clear
1580
+ * All footer commits or discards them (no live commit on close). */
1581
+ showFooter?: boolean;
1582
+ /** What "Clear all" resets the draft to — the page's default selection. */
1583
+ clearValue?: string[];
1584
+ /** Tailwind width class for the dropdown panel (default `w-60`). Widen it when
1585
+ * option labels are long and would otherwise wrap. */
1586
+ menuWidthClass?: string;
1587
+ /** Render group parents at normal weight instead of semibold. */
1588
+ plainParent?: boolean;
1589
+ /** Stretch the trigger (and, with `menuWidthClass="w-full"`, the panel) to fill
1590
+ * its container — for stacked/full-width form layouts instead of the chip bar. */
1591
+ fullWidth?: boolean;
1592
+ }): react.JSX.Element;
1593
+ type MultiSelectFilterProps = Parameters<typeof MultiSelectFilter>[0];
1594
+
1595
+ /**
1596
+ * Track, knob and travel per size. The knob leaves a 2px gutter at each end, so
1597
+ * its "on" offset is always track − knob − 2 — keep that relationship if a new
1598
+ * size is added, or the knob will sit off-centre at one end.
1599
+ */
1600
+ declare const SIZES: {
1601
+ readonly sm: {
1602
+ readonly track: "h-5 w-9";
1603
+ readonly knob: "h-4 w-4";
1604
+ readonly on: "translate-x-[18px]";
1605
+ };
1606
+ readonly md: {
1607
+ readonly track: "h-6 w-11";
1608
+ readonly knob: "h-5 w-5";
1609
+ readonly on: "translate-x-[22px]";
1610
+ };
1611
+ };
1612
+ interface ToggleProps {
1613
+ /** Whether the switch is on. Controlled: the parent owns this value. */
1614
+ checked: boolean;
1615
+ /** Receives the value being switched TO, not the current one. */
1616
+ onChange: (next: boolean) => void;
1617
+ /** Accessible name; the visible label lives in the row around it. */
1618
+ label: string;
1619
+ /** `md` for settings rows where the switch is the subject; `sm` for dense rows next to 13px text. */
1620
+ size?: keyof typeof SIZES;
1621
+ /** Blocks clicks and dims the switch to 50% opacity. */
1622
+ disabled?: boolean;
1623
+ /** Extra classes merged onto the track (the outer `<button>`). */
1624
+ className?: string;
1625
+ }
1626
+ /**
1627
+ * @pattern Toggle
1628
+ * @description The app's on/off switch. Use it for a setting that takes effect
1629
+ * as a state the user keeps — "only include enriched creatives", "email me a
1630
+ * digest" — where a checkbox would read as an item being ticked off a list.
1631
+ * Rendered as a `<button role="switch">` so the on/off state is announced as a
1632
+ * switch rather than a checkbox, and so the track and knob can carry the brand
1633
+ * fill without fighting a native input's styling hooks.
1634
+ * @tokens bg-brand-primaryAction, bg-border-interactive, bg-surface, shadow-raised, outline-border-focus
1635
+ * @behavior The knob is positioned by `translate-x`, not by flex alignment, so
1636
+ * the slide animates. Off uses `bg-border-interactive` rather than a grey
1637
+ * literal, which keeps the track visible against `bg-surface` in dark mode.
1638
+ * Pair it with a label and any InfoTip in the surrounding row: this component
1639
+ * draws only the switch, so rows stay free to lay the label out however they
1640
+ * need (usually label left, switch pushed right).
1641
+ * @variant md - Settings panels and modals, where the switch is the row's subject.
1642
+ * @variant sm - Dense rows next to 13px body text, where the md track overpowers its own label.
1643
+ * @usage
1644
+ * ```tsx
1645
+ * <Toggle checked={enabled} onChange={setEnabled} label="Email news alerts" />
1646
+ * <Toggle size="sm" checked={enabled} onChange={setEnabled} label="Only include enriched creatives" />
1647
+ * ```
1648
+ */
1649
+ declare function Toggle({ checked, onChange, label, size, disabled, className }: ToggleProps): react.JSX.Element;
1650
+
1651
+ interface AISparkProps {
1652
+ size?: number;
1653
+ className?: string;
1654
+ }
1655
+ /**
1656
+ * @pattern AISpark
1657
+ * @description Assistant glyph — the lucide Sparkles icon stroked with the
1658
+ * MR orange→violet assistant gradient. Each instance scopes its own gradient
1659
+ * id, and the stops follow light/dark mode.
1660
+ * @dependencies lucide-react
1661
+ * @usage
1662
+ * ```tsx
1663
+ * <AISpark size={14} />
1664
+ * ```
1665
+ */
1666
+ declare function AISpark({ size, className }: AISparkProps): react.JSX.Element;
1667
+
1668
+ type FreshnessLevel = "fresh" | "recent" | "stale";
1669
+ interface FreshnessProps {
1670
+ level: FreshnessLevel;
1671
+ }
1672
+ /**
1673
+ * @pattern Freshness
1674
+ * @description Freshness dot — prefixed to card meta rows so a row of 4
1675
+ * timestamps stops reading as a wall of identical text. Color carries the
1676
+ * urgency signal at a glance.
1677
+ * @tokens bg-status-success, bg-status-warning, bg-text-tertiary
1678
+ * @usage
1679
+ * ```tsx
1680
+ * <Freshness level="fresh" />
1681
+ * ```
1682
+ */
1683
+ declare function Freshness({ level }: FreshnessProps): react.JSX.Element;
1684
+
1685
+ export { AISpark, type AISparkProps, AdvertiserNoResults, type AdvertiserNoResultsProps, AdvertiserQuickFilter, type AdvertiserQuickFilterProps, AdvertiserSearchPrompt, type AdvertiserSearchPromptProps, BarChartPlaceholder, type BarChartPlaceholderProps, Button, type ButtonProps, Card, type CardProps, CheckBox, type CheckBoxProps, ChipContent, type ChipContentProps, DEFAULT_SEARCH_MATCH, DataScopeFilter, type DataScopeFilterProps, DateRangeFilter, type DateRangeFilterProps, DateRangePicker, type DateRangePickerProps, FilterChipBar, type FilterChipBarProps, FilterDropdownFooter, type FilterDropdownFooterProps, Freshness, type FreshnessLevel, type FreshnessProps, InfoTip, type InfoTipProps, LineChartPlaceholder, type LineChartPlaceholderProps, MultiSelectFilter, type MultiSelectFilterProps, type MultiSelectGroup, NO_RESULTS_BODY, NO_RESULTS_TITLE, NameListModal, type NameListModalProps, type NoResultsAction, NoResultsEmptyState, type NoResultsEmptyStateProps, PRIMARY_ACTION_CLASS, Pager, type PagerProps, type PickerColumn, type PickerFilter, type PickerRow, PieChartPlaceholder, type PieChartPlaceholderProps, type PubBreak, PublisherBreakdownList, type PublisherBreakdownListProps, QUIET_ACTION_CLASS, SearchBar, type SearchBarProps, type SearchBarVariant, type SearchMatchMode, type SearchMatchValue, SectionRail, type SectionRailProps, SelectAllVisible, type SelectAllVisibleProps, SelectFilter, type SelectFilterProps, SelectedSection, type SelectedSectionProps, SelectionPicker, type SelectionPickerAccountList, type SelectionPickerProps, SortButton, type SortButtonProps, type SortDir, type SortState, StackedColumnPlaceholder, type StackedColumnPlaceholderProps, type SummaryGroup, type SummaryGroupItemValue, TablePagination, type TablePaginationProps, Tag, type TagProps, Toggle, type ToggleProps, Tooltip, type TooltipProps, WorkspaceAvatar, type WorkspaceAvatarProps, WorkspaceSelectedCard, type WorkspaceSelectedCardProps, buttonVariants, chipTriggerClass, cycleSort, noResultsBody, resolveRange, sortProp };
package/dist/index.d.ts CHANGED
@@ -165,6 +165,7 @@ declare function AdvertiserSearchPrompt({ label }: AdvertiserSearchPromptProps):
165
165
  * ```
166
166
  */
167
167
  interface CheckBoxProps {
168
+ /** Whether the box is checked. Controlled: the parent owns this value. */
168
169
  checked: boolean;
169
170
  /**
170
171
  * Some-but-not-all state for a "select all" checkbox -- shows a dash
@@ -172,9 +173,14 @@ interface CheckBoxProps {
172
173
  * plain boolean.
173
174
  */
174
175
  indeterminate?: boolean;
176
+ /**
177
+ * Called on click with no argument -- flip `checked` yourself. The click
178
+ * doesn't bubble, so a row that toggles on its own click won't fire twice.
179
+ */
175
180
  onChange: () => void;
176
181
  /** Accessible label -- required since the control carries no visible text of its own. */
177
182
  ariaLabel: string;
183
+ /** Blocks clicks, dims the box to 50% opacity, and cancels its hover preview. */
178
184
  disabled?: boolean;
179
185
  /** Forwarded as `data-testid`, for Playwright/test selectors. */
180
186
  testId?: string;
@@ -493,6 +499,8 @@ interface CardProps extends Omit<React.HTMLAttributes<HTMLElement>, "title"> {
493
499
  subtitle?: string;
494
500
  /** Trailing header content, e.g. a "View all" link. Ignored without `title`. */
495
501
  action?: ReactNode;
502
+ /** Card body. Rendered edge to edge without `title`; inside the standard padding with it. */
503
+ children?: ReactNode;
496
504
  }
497
505
  declare const Card: react.ForwardRefExoticComponent<CardProps & react.RefAttributes<HTMLElement>>;
498
506
 
@@ -1194,6 +1202,8 @@ interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement>, VariantPr
1194
1202
  asChild?: boolean;
1195
1203
  /** Shows a spinner in place of the leading edge and disables the button. */
1196
1204
  loading?: boolean;
1205
+ /** Button label and/or icon. With `asChild`, the single element that receives the button styling. */
1206
+ children?: ReactNode;
1197
1207
  }
1198
1208
  /**
1199
1209
  * @pattern Button
@@ -1409,7 +1419,7 @@ interface PagerProps {
1409
1419
  */
1410
1420
  declare function Pager({ page, totalPages, onPage }: PagerProps): react.JSX.Element;
1411
1421
 
1412
- declare const SIZES: {
1422
+ declare const SIZES$1: {
1413
1423
  /** Matches a 15px lucide icon exactly, so a workspace name in a menu row
1414
1424
  * left-aligns with labels in icon-led rows above and below it. */
1415
1425
  readonly xs: "h-[15px] w-[15px] rounded-[4px] text-[8px] tracking-tight";
@@ -1420,7 +1430,7 @@ declare const SIZES: {
1420
1430
  interface WorkspaceAvatarProps {
1421
1431
  /** Omit for the unscoped "All data workspace". */
1422
1432
  name?: string;
1423
- size?: keyof typeof SIZES;
1433
+ size?: keyof typeof SIZES$1;
1424
1434
  }
1425
1435
  /**
1426
1436
  * @pattern WorkspaceAvatar
@@ -1437,4 +1447,239 @@ interface WorkspaceAvatarProps {
1437
1447
  */
1438
1448
  declare function WorkspaceAvatar({ name, size }: WorkspaceAvatarProps): react.JSX.Element;
1439
1449
 
1440
- export { AdvertiserNoResults, type AdvertiserNoResultsProps, AdvertiserQuickFilter, type AdvertiserQuickFilterProps, AdvertiserSearchPrompt, type AdvertiserSearchPromptProps, BarChartPlaceholder, type BarChartPlaceholderProps, Button, type ButtonProps, Card, type CardProps, CheckBox, type CheckBoxProps, ChipContent, type ChipContentProps, DEFAULT_SEARCH_MATCH, DataScopeFilter, type DataScopeFilterProps, DateRangeFilter, type DateRangeFilterProps, FilterChipBar, type FilterChipBarProps, FilterDropdownFooter, type FilterDropdownFooterProps, InfoTip, type InfoTipProps, LineChartPlaceholder, type LineChartPlaceholderProps, NO_RESULTS_BODY, NO_RESULTS_TITLE, NameListModal, type NameListModalProps, type NoResultsAction, NoResultsEmptyState, type NoResultsEmptyStateProps, PRIMARY_ACTION_CLASS, Pager, type PagerProps, type PickerColumn, type PickerFilter, type PickerRow, PieChartPlaceholder, type PieChartPlaceholderProps, type PubBreak, PublisherBreakdownList, type PublisherBreakdownListProps, QUIET_ACTION_CLASS, SearchBar, type SearchBarProps, type SearchBarVariant, type SearchMatchMode, type SearchMatchValue, SectionRail, type SectionRailProps, SelectAllVisible, type SelectAllVisibleProps, SelectFilter, type SelectFilterProps, SelectedSection, type SelectedSectionProps, SelectionPicker, type SelectionPickerAccountList, type SelectionPickerProps, SortButton, type SortButtonProps, type SortDir, type SortState, StackedColumnPlaceholder, type StackedColumnPlaceholderProps, type SummaryGroup, type SummaryGroupItemValue, Tooltip, type TooltipProps, WorkspaceAvatar, type WorkspaceAvatarProps, WorkspaceSelectedCard, type WorkspaceSelectedCardProps, buttonVariants, chipTriggerClass, cycleSort, noResultsBody, sortProp };
1450
+ interface TagProps {
1451
+ /** The tag's text, e.g. "Digital". Keep it short: the chip doesn't wrap or truncate. */
1452
+ children: ReactNode;
1453
+ /** Extra classes merged onto the chip. */
1454
+ className?: string;
1455
+ }
1456
+ /**
1457
+ * @pattern Tag
1458
+ * @description Canonical descriptive tag — a neutral beige chip (e.g.
1459
+ * "Digital", a focus area, a category). Use this for every non-semantic
1460
+ * label so tags read the same everywhere. Colored/semantic badges (NEW, ±%
1461
+ * deltas, status, counts) are intentionally NOT this component.
1462
+ * @tokens bg-subtle, text-text-secondary, rounded-full
1463
+ * @usage
1464
+ * ```tsx
1465
+ * <Tag>Digital</Tag>
1466
+ * ```
1467
+ */
1468
+ declare function Tag({ children, className }: TagProps): react.JSX.Element;
1469
+
1470
+ /**
1471
+ * @pattern TablePagination
1472
+ * @description Full table-footer pagination bar: a rows-per-page select, a
1473
+ * first/prev/pages/next/last pager, and the resolved "1 – 25 of N results"
1474
+ * range. Owns no state — the host page holds `page` and `perPage` so the
1475
+ * paged slice and the bar can't disagree.
1476
+ * @tokens rounded-control, border-border-default, bg-input, text-text-primary, text-text-secondary, text-text-tertiary, bg-brand-primaryAction, text-brand-onprimary, hover:bg-subtle, hover:text-text-primary, focus:outline-border-focus
1477
+ * @behavior The current page is filled with the brand action color (matching
1478
+ * the Contacts pager). First/prev disable on page 1, next/last on the last
1479
+ * page — disabled controls stay in the layout so the row never reflows.
1480
+ * Changing the per-page count reports it and leaves the host to reset to page
1481
+ * 1. With one page of results the pager still renders, so the bar's height
1482
+ * and the range readout don't come and go as filters narrow.
1483
+ * @usage
1484
+ * ```tsx
1485
+ * <TablePagination
1486
+ * page={page}
1487
+ * perPage={perPage}
1488
+ * totalItems={matching.length}
1489
+ * onPageChange={setPage}
1490
+ * onPerPageChange={(n) => { setPerPage(n); setPage(1) }}
1491
+ * itemLabel="results"
1492
+ * />
1493
+ * ```
1494
+ */
1495
+ declare function TablePagination({ page, perPage, totalItems, onPageChange, onPerPageChange, perPageOptions, itemLabel, className, }: {
1496
+ page: number;
1497
+ perPage: number;
1498
+ totalItems: number;
1499
+ onPageChange: (page: number) => void;
1500
+ onPerPageChange: (perPage: number) => void;
1501
+ perPageOptions?: number[];
1502
+ itemLabel?: string;
1503
+ className?: string;
1504
+ }): react.JSX.Element;
1505
+ type TablePaginationProps = Parameters<typeof TablePagination>[0];
1506
+
1507
+ /** Resolve a label to its actual [start, end] span, ending at `today`. */
1508
+ declare function resolveRange(label: string, today?: Date): [Date, Date];
1509
+ declare function DateRangePicker({ defaultValue, align, presets, onChange, onRangeChange, showFooter, today, years, }: {
1510
+ defaultValue?: string;
1511
+ align?: 'left' | 'right';
1512
+ /** Rolling presets shown above Custom Range. Defaults to 3/6/12 months. */
1513
+ presets?: string[];
1514
+ onChange?: (label: string) => void;
1515
+ /** Reports the resolved start/end dates — used to drive dependent views (e.g. table columns). */
1516
+ onRangeChange?: (start: Date, end: Date) => void;
1517
+ /** Deferred mode: preset/custom-range picks stage in a draft; only the fixed
1518
+ * Apply footer commits it (no live commit on click). */
1519
+ showFooter?: boolean;
1520
+ /** End of the available data window: rolling presets resolve back from here.
1521
+ * Defaults to the current date. */
1522
+ today?: Date;
1523
+ /** Years offered in the Custom Range selects. Defaults to the last four,
1524
+ * ending with `today`'s year. */
1525
+ years?: number[];
1526
+ }): react.JSX.Element;
1527
+ type DateRangePickerProps = Parameters<typeof DateRangePicker>[0];
1528
+
1529
+ interface MultiSelectGroup {
1530
+ id: string;
1531
+ label: string;
1532
+ children: {
1533
+ id: string;
1534
+ label: string;
1535
+ }[];
1536
+ }
1537
+ /**
1538
+ * @pattern MultiSelectFilter
1539
+ * @description Quick-access multi-select chip — mirrors the DateRangeFilter
1540
+ * button shape (two-line caption + value with a chevron) and opens a
1541
+ * searchable checkbox popover. Used for the page-level Media Type /
1542
+ * Advertiser filters that share state with the filter tray.
1543
+ * @tokens rounded-control, rounded-card, border-border-default, bg-surface, shadow-overlay, text-text-primary, text-text-secondary, text-text-tertiary, text-text-link, border-border-interactive, bg-brand-primaryAction, bg-input, hover:bg-subtle, hover:text-text-primary, placeholder:text-text-tertiary
1544
+ * @dependencies lucide-react
1545
+ * @behavior Same draft/commit-on-close pattern as AdvertiserQuickFilter — the
1546
+ * draft resyncs from `selected` every time the tray opens, and (without
1547
+ * showFooter) any close path commits it, while showFooter mode requires the
1548
+ * Apply button and discards the draft on every other close. `min` enforces a
1549
+ * selection floor by silently ignoring any toggle that would drop below it —
1550
+ * there's no error state, the click just does nothing. Group parents are
1551
+ * tri-state and toggle all of their children in one action.
1552
+ * @usage
1553
+ * ```tsx
1554
+ * <MultiSelectFilter caption="Media" options={mediaOptions} selected={selected} onChange={setSelected} />
1555
+ * ```
1556
+ */
1557
+ declare function MultiSelectFilter({ caption, options, groups, selected, onChange, allLabel, searchable, searchPlaceholder, align, fullIsAll, min, icon, showFooter, clearValue, menuWidthClass, plainParent, fullWidth, }: {
1558
+ caption: string;
1559
+ options?: {
1560
+ id: string;
1561
+ label: string;
1562
+ }[];
1563
+ /** When provided, renders a nested parent → children tree (selection tracks
1564
+ * leaf ids; parents are tri-state and toggle all their children). */
1565
+ groups?: MultiSelectGroup[];
1566
+ selected: string[];
1567
+ onChange: (next: string[]) => void;
1568
+ allLabel?: string;
1569
+ searchable?: boolean;
1570
+ /** Overrides the search box's placeholder. The default derives from the
1571
+ * caption, which reads wrong once a caption is singular ("Search topic"). */
1572
+ searchPlaceholder?: string;
1573
+ align?: 'left' | 'right';
1574
+ /** Treat "all options selected" as the unfiltered "All" state in the label. */
1575
+ fullIsAll?: boolean;
1576
+ /** Minimum selections that must remain (a toggle that would drop below is ignored). */
1577
+ min?: number;
1578
+ icon?: React.ReactNode;
1579
+ /** Deferred mode: checkbox edits stage in a draft; only the fixed Apply/Clear
1580
+ * All footer commits or discards them (no live commit on close). */
1581
+ showFooter?: boolean;
1582
+ /** What "Clear all" resets the draft to — the page's default selection. */
1583
+ clearValue?: string[];
1584
+ /** Tailwind width class for the dropdown panel (default `w-60`). Widen it when
1585
+ * option labels are long and would otherwise wrap. */
1586
+ menuWidthClass?: string;
1587
+ /** Render group parents at normal weight instead of semibold. */
1588
+ plainParent?: boolean;
1589
+ /** Stretch the trigger (and, with `menuWidthClass="w-full"`, the panel) to fill
1590
+ * its container — for stacked/full-width form layouts instead of the chip bar. */
1591
+ fullWidth?: boolean;
1592
+ }): react.JSX.Element;
1593
+ type MultiSelectFilterProps = Parameters<typeof MultiSelectFilter>[0];
1594
+
1595
+ /**
1596
+ * Track, knob and travel per size. The knob leaves a 2px gutter at each end, so
1597
+ * its "on" offset is always track − knob − 2 — keep that relationship if a new
1598
+ * size is added, or the knob will sit off-centre at one end.
1599
+ */
1600
+ declare const SIZES: {
1601
+ readonly sm: {
1602
+ readonly track: "h-5 w-9";
1603
+ readonly knob: "h-4 w-4";
1604
+ readonly on: "translate-x-[18px]";
1605
+ };
1606
+ readonly md: {
1607
+ readonly track: "h-6 w-11";
1608
+ readonly knob: "h-5 w-5";
1609
+ readonly on: "translate-x-[22px]";
1610
+ };
1611
+ };
1612
+ interface ToggleProps {
1613
+ /** Whether the switch is on. Controlled: the parent owns this value. */
1614
+ checked: boolean;
1615
+ /** Receives the value being switched TO, not the current one. */
1616
+ onChange: (next: boolean) => void;
1617
+ /** Accessible name; the visible label lives in the row around it. */
1618
+ label: string;
1619
+ /** `md` for settings rows where the switch is the subject; `sm` for dense rows next to 13px text. */
1620
+ size?: keyof typeof SIZES;
1621
+ /** Blocks clicks and dims the switch to 50% opacity. */
1622
+ disabled?: boolean;
1623
+ /** Extra classes merged onto the track (the outer `<button>`). */
1624
+ className?: string;
1625
+ }
1626
+ /**
1627
+ * @pattern Toggle
1628
+ * @description The app's on/off switch. Use it for a setting that takes effect
1629
+ * as a state the user keeps — "only include enriched creatives", "email me a
1630
+ * digest" — where a checkbox would read as an item being ticked off a list.
1631
+ * Rendered as a `<button role="switch">` so the on/off state is announced as a
1632
+ * switch rather than a checkbox, and so the track and knob can carry the brand
1633
+ * fill without fighting a native input's styling hooks.
1634
+ * @tokens bg-brand-primaryAction, bg-border-interactive, bg-surface, shadow-raised, outline-border-focus
1635
+ * @behavior The knob is positioned by `translate-x`, not by flex alignment, so
1636
+ * the slide animates. Off uses `bg-border-interactive` rather than a grey
1637
+ * literal, which keeps the track visible against `bg-surface` in dark mode.
1638
+ * Pair it with a label and any InfoTip in the surrounding row: this component
1639
+ * draws only the switch, so rows stay free to lay the label out however they
1640
+ * need (usually label left, switch pushed right).
1641
+ * @variant md - Settings panels and modals, where the switch is the row's subject.
1642
+ * @variant sm - Dense rows next to 13px body text, where the md track overpowers its own label.
1643
+ * @usage
1644
+ * ```tsx
1645
+ * <Toggle checked={enabled} onChange={setEnabled} label="Email news alerts" />
1646
+ * <Toggle size="sm" checked={enabled} onChange={setEnabled} label="Only include enriched creatives" />
1647
+ * ```
1648
+ */
1649
+ declare function Toggle({ checked, onChange, label, size, disabled, className }: ToggleProps): react.JSX.Element;
1650
+
1651
+ interface AISparkProps {
1652
+ size?: number;
1653
+ className?: string;
1654
+ }
1655
+ /**
1656
+ * @pattern AISpark
1657
+ * @description Assistant glyph — the lucide Sparkles icon stroked with the
1658
+ * MR orange→violet assistant gradient. Each instance scopes its own gradient
1659
+ * id, and the stops follow light/dark mode.
1660
+ * @dependencies lucide-react
1661
+ * @usage
1662
+ * ```tsx
1663
+ * <AISpark size={14} />
1664
+ * ```
1665
+ */
1666
+ declare function AISpark({ size, className }: AISparkProps): react.JSX.Element;
1667
+
1668
+ type FreshnessLevel = "fresh" | "recent" | "stale";
1669
+ interface FreshnessProps {
1670
+ level: FreshnessLevel;
1671
+ }
1672
+ /**
1673
+ * @pattern Freshness
1674
+ * @description Freshness dot — prefixed to card meta rows so a row of 4
1675
+ * timestamps stops reading as a wall of identical text. Color carries the
1676
+ * urgency signal at a glance.
1677
+ * @tokens bg-status-success, bg-status-warning, bg-text-tertiary
1678
+ * @usage
1679
+ * ```tsx
1680
+ * <Freshness level="fresh" />
1681
+ * ```
1682
+ */
1683
+ declare function Freshness({ level }: FreshnessProps): react.JSX.Element;
1684
+
1685
+ export { AISpark, type AISparkProps, AdvertiserNoResults, type AdvertiserNoResultsProps, AdvertiserQuickFilter, type AdvertiserQuickFilterProps, AdvertiserSearchPrompt, type AdvertiserSearchPromptProps, BarChartPlaceholder, type BarChartPlaceholderProps, Button, type ButtonProps, Card, type CardProps, CheckBox, type CheckBoxProps, ChipContent, type ChipContentProps, DEFAULT_SEARCH_MATCH, DataScopeFilter, type DataScopeFilterProps, DateRangeFilter, type DateRangeFilterProps, DateRangePicker, type DateRangePickerProps, FilterChipBar, type FilterChipBarProps, FilterDropdownFooter, type FilterDropdownFooterProps, Freshness, type FreshnessLevel, type FreshnessProps, InfoTip, type InfoTipProps, LineChartPlaceholder, type LineChartPlaceholderProps, MultiSelectFilter, type MultiSelectFilterProps, type MultiSelectGroup, NO_RESULTS_BODY, NO_RESULTS_TITLE, NameListModal, type NameListModalProps, type NoResultsAction, NoResultsEmptyState, type NoResultsEmptyStateProps, PRIMARY_ACTION_CLASS, Pager, type PagerProps, type PickerColumn, type PickerFilter, type PickerRow, PieChartPlaceholder, type PieChartPlaceholderProps, type PubBreak, PublisherBreakdownList, type PublisherBreakdownListProps, QUIET_ACTION_CLASS, SearchBar, type SearchBarProps, type SearchBarVariant, type SearchMatchMode, type SearchMatchValue, SectionRail, type SectionRailProps, SelectAllVisible, type SelectAllVisibleProps, SelectFilter, type SelectFilterProps, SelectedSection, type SelectedSectionProps, SelectionPicker, type SelectionPickerAccountList, type SelectionPickerProps, SortButton, type SortButtonProps, type SortDir, type SortState, StackedColumnPlaceholder, type StackedColumnPlaceholderProps, type SummaryGroup, type SummaryGroupItemValue, TablePagination, type TablePaginationProps, Tag, type TagProps, Toggle, type ToggleProps, Tooltip, type TooltipProps, WorkspaceAvatar, type WorkspaceAvatarProps, WorkspaceSelectedCard, type WorkspaceSelectedCardProps, buttonVariants, chipTriggerClass, cycleSort, noResultsBody, resolveRange, sortProp };