@mediaradar/design-components 0.6.0 → 0.8.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.
- package/README.md +12 -3
- package/dist/index.cjs +1013 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +486 -2
- package/dist/index.d.ts +486 -2
- package/dist/index.js +992 -8
- package/dist/index.js.map +1 -1
- package/package.json +6 -2
- package/scripts/tailwind-coverage.mjs +3 -0
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import * as react from 'react';
|
|
2
|
-
import { ReactNode, RefObject } from 'react';
|
|
2
|
+
import { ReactNode, RefObject, ButtonHTMLAttributes } from 'react';
|
|
3
|
+
import * as class_variance_authority_types from 'class-variance-authority/types';
|
|
4
|
+
import { VariantProps } from 'class-variance-authority';
|
|
3
5
|
|
|
4
6
|
/**
|
|
5
7
|
* @pattern InfoTip
|
|
@@ -1183,4 +1185,486 @@ interface PublisherBreakdownListProps {
|
|
|
1183
1185
|
*/
|
|
1184
1186
|
declare function PublisherBreakdownList({ rows, defaultVisibleCount, padded, viewAllHref, renderLogo }: PublisherBreakdownListProps): react.JSX.Element;
|
|
1185
1187
|
|
|
1186
|
-
|
|
1188
|
+
declare const buttonVariants: (props?: ({
|
|
1189
|
+
variant?: "link" | "primary" | "secondary" | "ghost" | "danger" | null | undefined;
|
|
1190
|
+
size?: "icon" | "sm" | "md" | "lg" | null | undefined;
|
|
1191
|
+
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
1192
|
+
interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
|
|
1193
|
+
/** Render the button styling onto the single child element instead of a `<button>` (e.g. a router `<Link>`). */
|
|
1194
|
+
asChild?: boolean;
|
|
1195
|
+
/** Shows a spinner in place of the leading edge and disables the button. */
|
|
1196
|
+
loading?: boolean;
|
|
1197
|
+
}
|
|
1198
|
+
/**
|
|
1199
|
+
* @pattern Button
|
|
1200
|
+
* @description Primary interactive control for actions. Five visual variants
|
|
1201
|
+
* (primary, secondary, ghost, danger, link) and four sizes (sm, md, lg, icon).
|
|
1202
|
+
* Supports polymorphic rendering via `asChild` (Radix Slot) to apply button
|
|
1203
|
+
* styling to a different element, e.g. a router `<Link>`. Also exports the
|
|
1204
|
+
* raw `buttonVariants` cva function for consumers composing button styling
|
|
1205
|
+
* onto something other than this component.
|
|
1206
|
+
* @tokens bg-brand-primaryAction, text-brand-onprimary, bg-surface, text-text-primary, border-border-interactive, hover:bg-subtle, bg-status-danger, text-status-onstatus, text-text-link, rounded-control, duration-(--mr-motion-duration-interactive), ease-interactive
|
|
1207
|
+
* @dependencies class-variance-authority, @radix-ui/react-slot, lucide-react
|
|
1208
|
+
* @variant primary - The one primary action on a screen. Solid brand fill.
|
|
1209
|
+
* @variant secondary - Any other real action competing for attention (Cancel, Export). Bordered, neutral fill.
|
|
1210
|
+
* @variant ghost - Low-emphasis action inside a dense toolbar or row where a border would add visual noise.
|
|
1211
|
+
* @variant danger - Destructive/irreversible actions (Delete, Remove). Never pair with `primary` in the same control group.
|
|
1212
|
+
* @variant link - Reads as inline text, not a control. Use inside body copy or where a full button would overpower the surrounding content.
|
|
1213
|
+
* @behavior `disabled` removes pointer events entirely (not just a style
|
|
1214
|
+
* change) and dims to 40% opacity. Focus handling is a deliberate exception:
|
|
1215
|
+
* most interactive components use a visible `focus-visible:outline-2` ring,
|
|
1216
|
+
* but Button suppresses it (`focus-visible:outline-hidden focus-visible:ring-0`)
|
|
1217
|
+
* and relies on its per-variant hover/brightness treatment instead. `loading`
|
|
1218
|
+
* implies `disabled` (and sets `aria-busy`), since a control mid-submit
|
|
1219
|
+
* shouldn't accept another click.
|
|
1220
|
+
* @usage
|
|
1221
|
+
* ```tsx
|
|
1222
|
+
* <Button variant="primary" size="md">Save changes</Button>
|
|
1223
|
+
* <Button variant="secondary" size="sm">Cancel</Button>
|
|
1224
|
+
* <Button variant="danger">Delete</Button>
|
|
1225
|
+
* <Button variant="primary" loading>Saving…</Button>
|
|
1226
|
+
* ```
|
|
1227
|
+
*/
|
|
1228
|
+
declare const Button: react.ForwardRefExoticComponent<ButtonProps & react.RefAttributes<HTMLButtonElement>>;
|
|
1229
|
+
|
|
1230
|
+
interface FilterDropdownFooterProps {
|
|
1231
|
+
/** Omit to hide the Clear All action for dropdowns that don't need it. */
|
|
1232
|
+
onClear?: () => void;
|
|
1233
|
+
/** Fires when the primary action is pressed. */
|
|
1234
|
+
onApply: () => void;
|
|
1235
|
+
clearLabel?: string;
|
|
1236
|
+
applyLabel?: string;
|
|
1237
|
+
}
|
|
1238
|
+
/**
|
|
1239
|
+
* @pattern FilterDropdownFooter
|
|
1240
|
+
* @description Fixed Apply/Clear All footer for quick-filter dropdowns —
|
|
1241
|
+
* pinned below the (independently scrollable) option list so it's always
|
|
1242
|
+
* visible. Shared by the Media/Advertiser/Date/Group By/Time Increment quick
|
|
1243
|
+
* filters on Sports Dashboard, Publisher Intel, and Opportunities.
|
|
1244
|
+
* @tokens border-border-default
|
|
1245
|
+
* @usage
|
|
1246
|
+
* ```tsx
|
|
1247
|
+
* <FilterDropdownFooter onApply={handleApply} onClear={handleClear} />
|
|
1248
|
+
* ```
|
|
1249
|
+
*/
|
|
1250
|
+
declare function FilterDropdownFooter({ onClear, onApply, clearLabel, applyLabel, }: FilterDropdownFooterProps): react.JSX.Element;
|
|
1251
|
+
|
|
1252
|
+
interface NameListModalProps {
|
|
1253
|
+
title: string;
|
|
1254
|
+
initialName: string;
|
|
1255
|
+
submitLabel: string;
|
|
1256
|
+
onCancel: () => void;
|
|
1257
|
+
onSubmit: (name: string) => void;
|
|
1258
|
+
}
|
|
1259
|
+
/**
|
|
1260
|
+
* @pattern NameListModal
|
|
1261
|
+
* @description Minimal create/rename dialog — just the list name. Shared by
|
|
1262
|
+
* the Account Lists table and the list detail page so create/rename look
|
|
1263
|
+
* identical.
|
|
1264
|
+
* @tokens rounded-card, border-border-default, bg-surface, shadow-overlay, text-text-primary, text-text-secondary, rounded-control, bg-input, focus:border-brand-primaryAction
|
|
1265
|
+
* @behavior Escape closes the dialog via `onCancel`, same as clicking the
|
|
1266
|
+
* scrim backdrop. Submit is disabled until the name is non-empty (trimmed).
|
|
1267
|
+
* @usage
|
|
1268
|
+
* ```tsx
|
|
1269
|
+
* <NameListModal title="Rename list" initialName={list.name} submitLabel="Save" onCancel={close} onSubmit={rename} />
|
|
1270
|
+
* ```
|
|
1271
|
+
*/
|
|
1272
|
+
declare function NameListModal({ title, initialName, submitLabel, onCancel, onSubmit }: NameListModalProps): react.ReactPortal;
|
|
1273
|
+
|
|
1274
|
+
/** Shared styling for filter-bar chip triggers, so every dropdown chip matches. */
|
|
1275
|
+
declare function chipTriggerClass(): string;
|
|
1276
|
+
interface ChipContentProps {
|
|
1277
|
+
/** Small uppercase label above the value. */
|
|
1278
|
+
caption: string;
|
|
1279
|
+
/** The current selection, shown below the caption. */
|
|
1280
|
+
value: ReactNode;
|
|
1281
|
+
/** Optional leading icon rendered before the caption/value stack. */
|
|
1282
|
+
icon?: ReactNode;
|
|
1283
|
+
}
|
|
1284
|
+
/**
|
|
1285
|
+
* @pattern ChipTrigger
|
|
1286
|
+
* @description Shared foundation for filter-bar chip triggers — pairs
|
|
1287
|
+
* `chipTriggerClass` with `ChipContent` for the caption/value/icon layout, so
|
|
1288
|
+
* every dropdown chip across the app matches.
|
|
1289
|
+
* @tokens rounded-control, bg-input, border-border-strong, text-text-secondary, text-text-tertiary, text-text-primary, hover:bg-subtle, focus-visible:outline-border-focus, hover:text-text-primary
|
|
1290
|
+
* @behavior Provides only the shared `focus-visible:outline-2` keyboard-focus
|
|
1291
|
+
* treatment every dropdown trigger depends on — open/close, Escape, and
|
|
1292
|
+
* outside-click dismissal all live in each consumer, not here. A new dropdown
|
|
1293
|
+
* built on `chipTriggerClass` has to implement its own dismissal handling.
|
|
1294
|
+
* @usage
|
|
1295
|
+
* ```tsx
|
|
1296
|
+
* <button className={chipTriggerClass()}>
|
|
1297
|
+
* <ChipContent caption="Media Type" value="All" />
|
|
1298
|
+
* </button>
|
|
1299
|
+
* ```
|
|
1300
|
+
*/
|
|
1301
|
+
declare function ChipContent({ caption, value, icon }: ChipContentProps): react.JSX.Element;
|
|
1302
|
+
|
|
1303
|
+
interface ChipLike {
|
|
1304
|
+
key: string;
|
|
1305
|
+
label: string;
|
|
1306
|
+
groupLabel: string;
|
|
1307
|
+
}
|
|
1308
|
+
interface FilterChipBarProps<T extends ChipLike> {
|
|
1309
|
+
/** Any `{ key, label, groupLabel }` shape — only those fields are read. */
|
|
1310
|
+
chips: T[];
|
|
1311
|
+
onRemove: (chip: T) => void;
|
|
1312
|
+
onClearAll: () => void;
|
|
1313
|
+
/**
|
|
1314
|
+
* Chip keys that are kept but not applied (e.g. a filter the active
|
|
1315
|
+
* workspace can't resolve). Rendered inactive, still removable.
|
|
1316
|
+
*/
|
|
1317
|
+
parkedKeys?: Set<string>;
|
|
1318
|
+
}
|
|
1319
|
+
/**
|
|
1320
|
+
* @pattern FilterChipBar
|
|
1321
|
+
* @description Applied-filter chips — wrap freely across as many rows as
|
|
1322
|
+
* needed, every chip shown. Each chip reveals its filter category on hover
|
|
1323
|
+
* (tooltip + outline). "Clear all" trails the chips. Generic over the
|
|
1324
|
+
* page's own chip type — only the shared key/label/groupLabel fields are
|
|
1325
|
+
* used.
|
|
1326
|
+
* @tokens rounded-full, bg-subtle, text-text-secondary, text-text-link, text-text-tertiary, bg-text-primary, border-border-default, group-hover:bg-border-default, group-hover:ring-border-interactive, group-hover:text-text-primary, group-hover:text-text-secondary, hover:text-text-primary, shadow-raised, text-surface
|
|
1327
|
+
* @dependencies lucide-react
|
|
1328
|
+
* @behavior A parked chip (key in `parkedKeys`) renders with no fill and a
|
|
1329
|
+
* dashed edge instead of the solid applied style, and its hover tooltip
|
|
1330
|
+
* reads "Not in this workspace" instead of the filter's group label.
|
|
1331
|
+
* @usage
|
|
1332
|
+
* ```tsx
|
|
1333
|
+
* <FilterChipBar chips={activeChips} onRemove={removeChip} onClearAll={clearAll} />
|
|
1334
|
+
* ```
|
|
1335
|
+
*/
|
|
1336
|
+
declare function FilterChipBar<T extends ChipLike>({ chips, onRemove, onClearAll, parkedKeys }: FilterChipBarProps<T>): react.JSX.Element | null;
|
|
1337
|
+
|
|
1338
|
+
type SortDir = "asc" | "desc";
|
|
1339
|
+
/** An active column and direction, or `null` for the unsorted state. */
|
|
1340
|
+
type SortState<K extends string> = {
|
|
1341
|
+
key: K;
|
|
1342
|
+
dir: SortDir;
|
|
1343
|
+
} | null;
|
|
1344
|
+
/**
|
|
1345
|
+
* The state after clicking `key`. `firstDir` is what the column opens on,
|
|
1346
|
+
* since the useful first look differs by column: counts and dates want the
|
|
1347
|
+
* largest or newest first, names want A→Z.
|
|
1348
|
+
*/
|
|
1349
|
+
declare function cycleSort<K extends string>(current: SortState<K>, key: K, firstDir?: SortDir): SortState<K>;
|
|
1350
|
+
/**
|
|
1351
|
+
* `SortState` in the shape SortButton takes. SortButton wants a non-null
|
|
1352
|
+
* object and reads `key: null` as "no column active".
|
|
1353
|
+
*/
|
|
1354
|
+
declare function sortProp<K extends string>(sort: SortState<K>): {
|
|
1355
|
+
key: K | null;
|
|
1356
|
+
dir: SortDir;
|
|
1357
|
+
};
|
|
1358
|
+
|
|
1359
|
+
interface SortButtonProps<K extends string> {
|
|
1360
|
+
label: string;
|
|
1361
|
+
sortKey: K;
|
|
1362
|
+
/** Current sort; a null `key` renders every SortButton inactive. See `sortProp`. */
|
|
1363
|
+
sort: {
|
|
1364
|
+
key: K | null;
|
|
1365
|
+
dir: SortDir;
|
|
1366
|
+
};
|
|
1367
|
+
onSort: (key: K) => void;
|
|
1368
|
+
/** True when there are no rows to order — hides the arrow, drops the click. */
|
|
1369
|
+
disabled?: boolean;
|
|
1370
|
+
}
|
|
1371
|
+
/**
|
|
1372
|
+
* @pattern SortButton
|
|
1373
|
+
* @description Design-system rule: every sortable table column header uses
|
|
1374
|
+
* this exact icon/color treatment. Sortable-but-inactive columns show a
|
|
1375
|
+
* neutral ArrowUpDown in text-tertiary at half opacity, coming up to full on
|
|
1376
|
+
* hover so the column reads as clickable; the active column swaps to a
|
|
1377
|
+
* direction arrow (ArrowUp/ArrowDown) colored with the brand action blue.
|
|
1378
|
+
* @tokens text-text-tertiary, text-brand-primaryAction, hover:text-text-primary
|
|
1379
|
+
* @dependencies lucide-react
|
|
1380
|
+
* @behavior Pair with `cycleSort`/`sortProp` (exported alongside) for the
|
|
1381
|
+
* standard three-state cycle — sort, reverse, then unsorted. `disabled` keeps
|
|
1382
|
+
* the column's inherited header color rather than dimming it — the column
|
|
1383
|
+
* isn't unavailable, there's just no data under it.
|
|
1384
|
+
* @usage
|
|
1385
|
+
* ```tsx
|
|
1386
|
+
* const [sort, setSort] = useState<SortState<'spend'>>(null)
|
|
1387
|
+
* <SortButton label="Spend" sortKey="spend" sort={sortProp(sort)} onSort={(k) => setSort(cycleSort(sort, k))} />
|
|
1388
|
+
* ```
|
|
1389
|
+
*/
|
|
1390
|
+
declare function SortButton<K extends string>({ label, sortKey, sort, onSort, disabled }: SortButtonProps<K>): react.JSX.Element;
|
|
1391
|
+
|
|
1392
|
+
interface PagerProps {
|
|
1393
|
+
/** The current page, 1-indexed. */
|
|
1394
|
+
page: number;
|
|
1395
|
+
totalPages: number;
|
|
1396
|
+
onPage: (p: number) => void;
|
|
1397
|
+
}
|
|
1398
|
+
/**
|
|
1399
|
+
* @pattern Pager
|
|
1400
|
+
* @description Compact prev/next pager with a windowed page-number list —
|
|
1401
|
+
* shows every page up to 7 total, otherwise 1 … current±1 … last with
|
|
1402
|
+
* ellipsis gaps. Shared by My Exports and Account Matcher.
|
|
1403
|
+
* @tokens rounded-control, text-text-secondary, bg-brand-primaryAction, text-brand-onprimary, hover:bg-subtle, hover:text-text-primary, text-text-tertiary
|
|
1404
|
+
* @dependencies lucide-react
|
|
1405
|
+
* @usage
|
|
1406
|
+
* ```tsx
|
|
1407
|
+
* <Pager page={page} totalPages={totalPages} onPage={setPage} />
|
|
1408
|
+
* ```
|
|
1409
|
+
*/
|
|
1410
|
+
declare function Pager({ page, totalPages, onPage }: PagerProps): react.JSX.Element;
|
|
1411
|
+
|
|
1412
|
+
declare const SIZES$1: {
|
|
1413
|
+
/** Matches a 15px lucide icon exactly, so a workspace name in a menu row
|
|
1414
|
+
* left-aligns with labels in icon-led rows above and below it. */
|
|
1415
|
+
readonly xs: "h-[15px] w-[15px] rounded-[4px] text-[8px] tracking-tight";
|
|
1416
|
+
readonly sm: "h-6 w-6 text-[10px]";
|
|
1417
|
+
readonly md: "h-7 w-7 text-[11px]";
|
|
1418
|
+
readonly lg: "h-11 w-11 text-[15px]";
|
|
1419
|
+
};
|
|
1420
|
+
interface WorkspaceAvatarProps {
|
|
1421
|
+
/** Omit for the unscoped "All data workspace". */
|
|
1422
|
+
name?: string;
|
|
1423
|
+
size?: keyof typeof SIZES$1;
|
|
1424
|
+
}
|
|
1425
|
+
/**
|
|
1426
|
+
* @pattern WorkspaceAvatar
|
|
1427
|
+
* @description The square tile that identifies a workspace in a switch
|
|
1428
|
+
* list — first 1–2 word initials of the workspace name. Pass no name for
|
|
1429
|
+
* the unscoped "All data workspace", which renders "AD" through the same
|
|
1430
|
+
* rule so the unscoped default reads as a peer of named workspaces rather
|
|
1431
|
+
* than a special case.
|
|
1432
|
+
* @tokens rounded-control, bg-subtle, text-text-secondary
|
|
1433
|
+
* @usage
|
|
1434
|
+
* ```tsx
|
|
1435
|
+
* <WorkspaceAvatar name="Capital One" size="sm" />
|
|
1436
|
+
* ```
|
|
1437
|
+
*/
|
|
1438
|
+
declare function WorkspaceAvatar({ name, size }: WorkspaceAvatarProps): react.JSX.Element;
|
|
1439
|
+
|
|
1440
|
+
interface TagProps {
|
|
1441
|
+
children: ReactNode;
|
|
1442
|
+
/** Extra classes merged onto the chip. */
|
|
1443
|
+
className?: string;
|
|
1444
|
+
}
|
|
1445
|
+
/**
|
|
1446
|
+
* @pattern Tag
|
|
1447
|
+
* @description Canonical descriptive tag — a neutral beige chip (e.g.
|
|
1448
|
+
* "Digital", a focus area, a category). Use this for every non-semantic
|
|
1449
|
+
* label so tags read the same everywhere. Colored/semantic badges (NEW, ±%
|
|
1450
|
+
* deltas, status, counts) are intentionally NOT this component.
|
|
1451
|
+
* @tokens bg-subtle, text-text-secondary, rounded-full
|
|
1452
|
+
* @usage
|
|
1453
|
+
* ```tsx
|
|
1454
|
+
* <Tag>Digital</Tag>
|
|
1455
|
+
* ```
|
|
1456
|
+
*/
|
|
1457
|
+
declare function Tag({ children, className }: TagProps): react.JSX.Element;
|
|
1458
|
+
|
|
1459
|
+
/**
|
|
1460
|
+
* @pattern TablePagination
|
|
1461
|
+
* @description Full table-footer pagination bar: a rows-per-page select, a
|
|
1462
|
+
* first/prev/pages/next/last pager, and the resolved "1 – 25 of N results"
|
|
1463
|
+
* range. Owns no state — the host page holds `page` and `perPage` so the
|
|
1464
|
+
* paged slice and the bar can't disagree.
|
|
1465
|
+
* @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
|
|
1466
|
+
* @behavior The current page is filled with the brand action color (matching
|
|
1467
|
+
* the Contacts pager). First/prev disable on page 1, next/last on the last
|
|
1468
|
+
* page — disabled controls stay in the layout so the row never reflows.
|
|
1469
|
+
* Changing the per-page count reports it and leaves the host to reset to page
|
|
1470
|
+
* 1. With one page of results the pager still renders, so the bar's height
|
|
1471
|
+
* and the range readout don't come and go as filters narrow.
|
|
1472
|
+
* @usage
|
|
1473
|
+
* ```tsx
|
|
1474
|
+
* <TablePagination
|
|
1475
|
+
* page={page}
|
|
1476
|
+
* perPage={perPage}
|
|
1477
|
+
* totalItems={matching.length}
|
|
1478
|
+
* onPageChange={setPage}
|
|
1479
|
+
* onPerPageChange={(n) => { setPerPage(n); setPage(1) }}
|
|
1480
|
+
* itemLabel="results"
|
|
1481
|
+
* />
|
|
1482
|
+
* ```
|
|
1483
|
+
*/
|
|
1484
|
+
declare function TablePagination({ page, perPage, totalItems, onPageChange, onPerPageChange, perPageOptions, itemLabel, className, }: {
|
|
1485
|
+
page: number;
|
|
1486
|
+
perPage: number;
|
|
1487
|
+
totalItems: number;
|
|
1488
|
+
onPageChange: (page: number) => void;
|
|
1489
|
+
onPerPageChange: (perPage: number) => void;
|
|
1490
|
+
perPageOptions?: number[];
|
|
1491
|
+
itemLabel?: string;
|
|
1492
|
+
className?: string;
|
|
1493
|
+
}): react.JSX.Element;
|
|
1494
|
+
type TablePaginationProps = Parameters<typeof TablePagination>[0];
|
|
1495
|
+
|
|
1496
|
+
/** Resolve a label to its actual [start, end] span, ending at `today`. */
|
|
1497
|
+
declare function resolveRange(label: string, today?: Date): [Date, Date];
|
|
1498
|
+
declare function DateRangePicker({ defaultValue, align, presets, onChange, onRangeChange, showFooter, today, years, }: {
|
|
1499
|
+
defaultValue?: string;
|
|
1500
|
+
align?: 'left' | 'right';
|
|
1501
|
+
/** Rolling presets shown above Custom Range. Defaults to 3/6/12 months. */
|
|
1502
|
+
presets?: string[];
|
|
1503
|
+
onChange?: (label: string) => void;
|
|
1504
|
+
/** Reports the resolved start/end dates — used to drive dependent views (e.g. table columns). */
|
|
1505
|
+
onRangeChange?: (start: Date, end: Date) => void;
|
|
1506
|
+
/** Deferred mode: preset/custom-range picks stage in a draft; only the fixed
|
|
1507
|
+
* Apply footer commits it (no live commit on click). */
|
|
1508
|
+
showFooter?: boolean;
|
|
1509
|
+
/** End of the available data window: rolling presets resolve back from here.
|
|
1510
|
+
* Defaults to the current date. */
|
|
1511
|
+
today?: Date;
|
|
1512
|
+
/** Years offered in the Custom Range selects. Defaults to the last four,
|
|
1513
|
+
* ending with `today`'s year. */
|
|
1514
|
+
years?: number[];
|
|
1515
|
+
}): react.JSX.Element;
|
|
1516
|
+
type DateRangePickerProps = Parameters<typeof DateRangePicker>[0];
|
|
1517
|
+
|
|
1518
|
+
interface MultiSelectGroup {
|
|
1519
|
+
id: string;
|
|
1520
|
+
label: string;
|
|
1521
|
+
children: {
|
|
1522
|
+
id: string;
|
|
1523
|
+
label: string;
|
|
1524
|
+
}[];
|
|
1525
|
+
}
|
|
1526
|
+
/**
|
|
1527
|
+
* @pattern MultiSelectFilter
|
|
1528
|
+
* @description Quick-access multi-select chip — mirrors the DateRangeFilter
|
|
1529
|
+
* button shape (two-line caption + value with a chevron) and opens a
|
|
1530
|
+
* searchable checkbox popover. Used for the page-level Media Type /
|
|
1531
|
+
* Advertiser filters that share state with the filter tray.
|
|
1532
|
+
* @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
|
|
1533
|
+
* @dependencies lucide-react
|
|
1534
|
+
* @behavior Same draft/commit-on-close pattern as AdvertiserQuickFilter — the
|
|
1535
|
+
* draft resyncs from `selected` every time the tray opens, and (without
|
|
1536
|
+
* showFooter) any close path commits it, while showFooter mode requires the
|
|
1537
|
+
* Apply button and discards the draft on every other close. `min` enforces a
|
|
1538
|
+
* selection floor by silently ignoring any toggle that would drop below it —
|
|
1539
|
+
* there's no error state, the click just does nothing. Group parents are
|
|
1540
|
+
* tri-state and toggle all of their children in one action.
|
|
1541
|
+
* @usage
|
|
1542
|
+
* ```tsx
|
|
1543
|
+
* <MultiSelectFilter caption="Media" options={mediaOptions} selected={selected} onChange={setSelected} />
|
|
1544
|
+
* ```
|
|
1545
|
+
*/
|
|
1546
|
+
declare function MultiSelectFilter({ caption, options, groups, selected, onChange, allLabel, searchable, searchPlaceholder, align, fullIsAll, min, icon, showFooter, clearValue, menuWidthClass, plainParent, fullWidth, }: {
|
|
1547
|
+
caption: string;
|
|
1548
|
+
options?: {
|
|
1549
|
+
id: string;
|
|
1550
|
+
label: string;
|
|
1551
|
+
}[];
|
|
1552
|
+
/** When provided, renders a nested parent → children tree (selection tracks
|
|
1553
|
+
* leaf ids; parents are tri-state and toggle all their children). */
|
|
1554
|
+
groups?: MultiSelectGroup[];
|
|
1555
|
+
selected: string[];
|
|
1556
|
+
onChange: (next: string[]) => void;
|
|
1557
|
+
allLabel?: string;
|
|
1558
|
+
searchable?: boolean;
|
|
1559
|
+
/** Overrides the search box's placeholder. The default derives from the
|
|
1560
|
+
* caption, which reads wrong once a caption is singular ("Search topic"). */
|
|
1561
|
+
searchPlaceholder?: string;
|
|
1562
|
+
align?: 'left' | 'right';
|
|
1563
|
+
/** Treat "all options selected" as the unfiltered "All" state in the label. */
|
|
1564
|
+
fullIsAll?: boolean;
|
|
1565
|
+
/** Minimum selections that must remain (a toggle that would drop below is ignored). */
|
|
1566
|
+
min?: number;
|
|
1567
|
+
icon?: React.ReactNode;
|
|
1568
|
+
/** Deferred mode: checkbox edits stage in a draft; only the fixed Apply/Clear
|
|
1569
|
+
* All footer commits or discards them (no live commit on close). */
|
|
1570
|
+
showFooter?: boolean;
|
|
1571
|
+
/** What "Clear all" resets the draft to — the page's default selection. */
|
|
1572
|
+
clearValue?: string[];
|
|
1573
|
+
/** Tailwind width class for the dropdown panel (default `w-60`). Widen it when
|
|
1574
|
+
* option labels are long and would otherwise wrap. */
|
|
1575
|
+
menuWidthClass?: string;
|
|
1576
|
+
/** Render group parents at normal weight instead of semibold. */
|
|
1577
|
+
plainParent?: boolean;
|
|
1578
|
+
/** Stretch the trigger (and, with `menuWidthClass="w-full"`, the panel) to fill
|
|
1579
|
+
* its container — for stacked/full-width form layouts instead of the chip bar. */
|
|
1580
|
+
fullWidth?: boolean;
|
|
1581
|
+
}): react.JSX.Element;
|
|
1582
|
+
type MultiSelectFilterProps = Parameters<typeof MultiSelectFilter>[0];
|
|
1583
|
+
|
|
1584
|
+
/**
|
|
1585
|
+
* Track, knob and travel per size. The knob leaves a 2px gutter at each end, so
|
|
1586
|
+
* its "on" offset is always track − knob − 2 — keep that relationship if a new
|
|
1587
|
+
* size is added, or the knob will sit off-centre at one end.
|
|
1588
|
+
*/
|
|
1589
|
+
declare const SIZES: {
|
|
1590
|
+
readonly sm: {
|
|
1591
|
+
readonly track: "h-5 w-9";
|
|
1592
|
+
readonly knob: "h-4 w-4";
|
|
1593
|
+
readonly on: "translate-x-[18px]";
|
|
1594
|
+
};
|
|
1595
|
+
readonly md: {
|
|
1596
|
+
readonly track: "h-6 w-11";
|
|
1597
|
+
readonly knob: "h-5 w-5";
|
|
1598
|
+
readonly on: "translate-x-[22px]";
|
|
1599
|
+
};
|
|
1600
|
+
};
|
|
1601
|
+
interface ToggleProps {
|
|
1602
|
+
checked: boolean;
|
|
1603
|
+
/** Receives the value being switched TO, not the current one. */
|
|
1604
|
+
onChange: (next: boolean) => void;
|
|
1605
|
+
/** Accessible name; the visible label lives in the row around it. */
|
|
1606
|
+
label: string;
|
|
1607
|
+
size?: keyof typeof SIZES;
|
|
1608
|
+
disabled?: boolean;
|
|
1609
|
+
className?: string;
|
|
1610
|
+
}
|
|
1611
|
+
/**
|
|
1612
|
+
* @pattern Toggle
|
|
1613
|
+
* @description The app's on/off switch. Use it for a setting that takes effect
|
|
1614
|
+
* as a state the user keeps — "only include enriched creatives", "email me a
|
|
1615
|
+
* digest" — where a checkbox would read as an item being ticked off a list.
|
|
1616
|
+
* Rendered as a `<button role="switch">` so the on/off state is announced as a
|
|
1617
|
+
* switch rather than a checkbox, and so the track and knob can carry the brand
|
|
1618
|
+
* fill without fighting a native input's styling hooks.
|
|
1619
|
+
* @tokens bg-brand-primaryAction, bg-border-interactive, bg-surface, shadow-raised, outline-border-focus
|
|
1620
|
+
* @behavior The knob is positioned by `translate-x`, not by flex alignment, so
|
|
1621
|
+
* the slide animates. Off uses `bg-border-interactive` rather than a grey
|
|
1622
|
+
* literal, which keeps the track visible against `bg-surface` in dark mode.
|
|
1623
|
+
* Pair it with a label and any InfoTip in the surrounding row: this component
|
|
1624
|
+
* draws only the switch, so rows stay free to lay the label out however they
|
|
1625
|
+
* need (usually label left, switch pushed right).
|
|
1626
|
+
* @variant md - Settings panels and modals, where the switch is the row's subject.
|
|
1627
|
+
* @variant sm - Dense rows next to 13px body text, where the md track overpowers its own label.
|
|
1628
|
+
* @usage
|
|
1629
|
+
* ```tsx
|
|
1630
|
+
* <Toggle checked={enabled} onChange={setEnabled} label="Email news alerts" />
|
|
1631
|
+
* <Toggle size="sm" checked={enabled} onChange={setEnabled} label="Only include enriched creatives" />
|
|
1632
|
+
* ```
|
|
1633
|
+
*/
|
|
1634
|
+
declare function Toggle({ checked, onChange, label, size, disabled, className }: ToggleProps): react.JSX.Element;
|
|
1635
|
+
|
|
1636
|
+
interface AISparkProps {
|
|
1637
|
+
size?: number;
|
|
1638
|
+
className?: string;
|
|
1639
|
+
}
|
|
1640
|
+
/**
|
|
1641
|
+
* @pattern AISpark
|
|
1642
|
+
* @description Assistant glyph — the lucide Sparkles icon stroked with the
|
|
1643
|
+
* MR orange→violet assistant gradient. Each instance scopes its own gradient
|
|
1644
|
+
* id, and the stops follow light/dark mode.
|
|
1645
|
+
* @dependencies lucide-react
|
|
1646
|
+
* @usage
|
|
1647
|
+
* ```tsx
|
|
1648
|
+
* <AISpark size={14} />
|
|
1649
|
+
* ```
|
|
1650
|
+
*/
|
|
1651
|
+
declare function AISpark({ size, className }: AISparkProps): react.JSX.Element;
|
|
1652
|
+
|
|
1653
|
+
type FreshnessLevel = "fresh" | "recent" | "stale";
|
|
1654
|
+
interface FreshnessProps {
|
|
1655
|
+
level: FreshnessLevel;
|
|
1656
|
+
}
|
|
1657
|
+
/**
|
|
1658
|
+
* @pattern Freshness
|
|
1659
|
+
* @description Freshness dot — prefixed to card meta rows so a row of 4
|
|
1660
|
+
* timestamps stops reading as a wall of identical text. Color carries the
|
|
1661
|
+
* urgency signal at a glance.
|
|
1662
|
+
* @tokens bg-status-success, bg-status-warning, bg-text-tertiary
|
|
1663
|
+
* @usage
|
|
1664
|
+
* ```tsx
|
|
1665
|
+
* <Freshness level="fresh" />
|
|
1666
|
+
* ```
|
|
1667
|
+
*/
|
|
1668
|
+
declare function Freshness({ level }: FreshnessProps): react.JSX.Element;
|
|
1669
|
+
|
|
1670
|
+
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 };
|