@mediaradar/design-components 0.9.0 → 0.10.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/dist/index.d.cts CHANGED
@@ -1312,22 +1312,49 @@ interface NameListModalProps {
1312
1312
  initialName: string;
1313
1313
  submitLabel: string;
1314
1314
  onCancel: () => void;
1315
- onSubmit: (name: string) => void;
1315
+ /**
1316
+ * Called with the trimmed name, and the state of `options` when any were
1317
+ * given. A handler that only takes the name stays valid -- TypeScript lets
1318
+ * a function ignore trailing parameters -- so existing callers are
1319
+ * unaffected.
1320
+ */
1321
+ onSubmit: (name: string, checked: Record<string, boolean>) => void;
1322
+ /**
1323
+ * Relabels the name field, for dialogs that name something other than a
1324
+ * list (e.g. "View name").
1325
+ */
1326
+ fieldLabel?: string;
1327
+ /** Placeholder for the name field, paired with `fieldLabel`. */
1328
+ placeholder?: string;
1329
+ /**
1330
+ * Optional checkboxes below the name field -- e.g. "Set as default" or
1331
+ * "Enable email alerts". Their state is handed to `onSubmit` as the second
1332
+ * argument, keyed by `key`. `initial` sets the starting state.
1333
+ */
1334
+ options?: {
1335
+ key: string;
1336
+ label: string;
1337
+ initial?: boolean;
1338
+ }[];
1316
1339
  }
1317
1340
  /**
1318
1341
  * @pattern NameListModal
1319
- * @description Minimal create/rename dialog — just the list name. Shared by
1320
- * the Account Lists table and the list detail page so create/rename look
1321
- * identical.
1342
+ * @description Create/rename dialog — a name field, and optionally a few
1343
+ * checkboxes under it. Shared by the Account Lists table and the list detail
1344
+ * page so create/rename look identical; `fieldLabel`/`placeholder` relabel it
1345
+ * for dialogs that name something other than a list.
1322
1346
  * @tokens rounded-card, border-border-default, bg-surface, shadow-overlay, text-text-primary, text-text-secondary, rounded-control, bg-input, focus:border-brand-primaryAction
1323
1347
  * @behavior Escape closes the dialog via `onCancel`, same as clicking the
1324
1348
  * scrim backdrop. Submit is disabled until the name is non-empty (trimmed).
1349
+ * When `options` are given they render as CheckBox rows below the field, and
1350
+ * their state comes back as `onSubmit`'s second argument -- a handler that
1351
+ * only takes the name stays valid.
1325
1352
  * @usage
1326
1353
  * ```tsx
1327
1354
  * <NameListModal title="Rename list" initialName={list.name} submitLabel="Save" onCancel={close} onSubmit={rename} />
1328
1355
  * ```
1329
1356
  */
1330
- declare function NameListModal({ title, initialName, submitLabel, onCancel, onSubmit }: NameListModalProps): react.ReactPortal;
1357
+ declare function NameListModal({ title, initialName, submitLabel, onCancel, onSubmit, fieldLabel, placeholder, options, }: NameListModalProps): react.ReactPortal;
1331
1358
 
1332
1359
  /**
1333
1360
  * Which stroke a chip trigger carries.
@@ -1352,6 +1379,10 @@ interface ChipContentProps {
1352
1379
  * @description Shared foundation for filter-bar chip triggers — pairs
1353
1380
  * `chipTriggerClass` with `ChipContent` for the caption/value/icon layout, so
1354
1381
  * every dropdown chip across the app matches.
1382
+ * @props
1383
+ * caption: string -- small uppercase label above the value
1384
+ * value: ReactNode -- the current selection, shown below the caption
1385
+ * icon?: ReactNode -- optional leading icon rendered before the caption/value stack
1355
1386
  * @tokens rounded-control, bg-input, border-border-default, border-border-strong, text-text-secondary, text-text-tertiary, text-text-primary, hover:bg-subtle, focus-visible:outline-border-focus, hover:text-text-primary
1356
1387
  * @behavior `chipTriggerClass` takes a `ChipVariant`: `box` (default, the
1357
1388
  * boxed two-line chip on the default border) or `inline` (same fill, darker
@@ -1564,11 +1595,19 @@ declare function TablePagination({ page, perPage, totalItems, onPageChange, onPe
1564
1595
  }): react.JSX.Element;
1565
1596
  type TablePaginationProps = Parameters<typeof TablePagination>[0];
1566
1597
 
1598
+ /** What the Custom Range From/To selects pick. */
1599
+ type DateGranularity = 'month' | 'quarter' | 'year';
1567
1600
  /** Resolve a label to its actual [start, end] span, ending at `today`. */
1568
1601
  declare function resolveRange(label: string, today?: Date): [Date, Date];
1569
- declare function DateRangePicker({ defaultValue, align, presets, onChange, onRangeChange, showFooter, today, years, }: {
1602
+ declare function DateRangePicker({ defaultValue, granularity, align, presets, onChange, onRangeChange, showFooter, today, years, }: {
1570
1603
  defaultValue?: string;
1571
1604
  align?: 'left' | 'right';
1605
+ /**
1606
+ * What the Custom Range From/To selects pick. `month` shows month + year
1607
+ * selects, `quarter` shows quarter + year, `year` shows year alone -- and
1608
+ * the applied label follows suit. Pair it with matching `presets`.
1609
+ */
1610
+ granularity?: DateGranularity;
1572
1611
  /** Rolling presets shown above Custom Range. Defaults to 3/6/12 months. */
1573
1612
  presets?: string[];
1574
1613
  onChange?: (label: string) => void;
@@ -1602,7 +1641,14 @@ interface MultiSelectGroup {
1602
1641
  * Advertiser filters that share state with the filter tray.
1603
1642
  * @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, text-brand-onprimary
1604
1643
  * @dependencies lucide-react
1605
- * @behavior Same draft/commit-on-close pattern as AdvertiserQuickFilter — the
1644
+ * @behavior `variant` picks the trigger's chip stroke: `box` (default, the
1645
+ * boxed two-line chip on the default border) or `inline` (same fill,
1646
+ * darker stroke, for chips sitting directly on the canvas). Left out of
1647
+ * the catalog's variant list deliberately: check-prop-drift can't resolve
1648
+ * the imported ChipVariant alias through this component's inline prop
1649
+ * type, so such a tag would be unvalidated -- and this exact component
1650
+ * has had stale ones stripped before.
1651
+ * Same draft/commit-on-close pattern as AdvertiserQuickFilter — the
1606
1652
  * draft resyncs from `selected` every time the tray opens, and (without
1607
1653
  * showFooter) any close path commits it, while showFooter mode requires the
1608
1654
  * Apply button and discards the draft on every other close. `min` enforces a
@@ -1614,8 +1660,17 @@ interface MultiSelectGroup {
1614
1660
  * <MultiSelectFilter caption="Media" options={mediaOptions} selected={selected} onChange={setSelected} />
1615
1661
  * ```
1616
1662
  */
1617
- declare function MultiSelectFilter({ caption, options, groups, selected, onChange, allLabel, searchable, searchPlaceholder, align, fullIsAll, min, icon, showFooter, clearValue, menuWidthClass, plainParent, fullWidth, }: {
1663
+ declare function MultiSelectFilter({ caption, options, groups, counts, variant, selected, onChange, allLabel, searchable, searchPlaceholder, align, fullIsAll, min, icon, showFooter, clearValue, menuWidthClass, plainParent, fullWidth, }: {
1618
1664
  caption: string;
1665
+ /**
1666
+ * Live option-id -> result count. Supplying it makes the menu faceted:
1667
+ * every label gets a "(n)" suffix and options with nothing behind them
1668
+ * drop out. A selected option is always kept, or there would be no way to
1669
+ * undo it.
1670
+ */
1671
+ counts?: Record<string, number>;
1672
+ /** Chip stroke for the trigger. See ChipVariant. */
1673
+ variant?: ChipVariant;
1619
1674
  options?: {
1620
1675
  id: string;
1621
1676
  label: string;
@@ -1742,4 +1797,4 @@ interface FreshnessProps {
1742
1797
  */
1743
1798
  declare function Freshness({ level }: FreshnessProps): react.JSX.Element;
1744
1799
 
1745
- export { AISpark, type AISparkProps, AdvertiserNoResults, type AdvertiserNoResultsProps, AdvertiserQuickFilter, type AdvertiserQuickFilterProps, AdvertiserSearchPrompt, type AdvertiserSearchPromptProps, BarChartPlaceholder, type BarChartPlaceholderProps, Button, type ButtonProps, Card, type CardProps, CheckBox, CheckBoxBox, type CheckBoxBoxProps, type CheckBoxProps, ChipContent, type ChipContentProps, type ChipVariant, 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 };
1800
+ export { AISpark, type AISparkProps, AdvertiserNoResults, type AdvertiserNoResultsProps, AdvertiserQuickFilter, type AdvertiserQuickFilterProps, AdvertiserSearchPrompt, type AdvertiserSearchPromptProps, BarChartPlaceholder, type BarChartPlaceholderProps, Button, type ButtonProps, Card, type CardProps, CheckBox, CheckBoxBox, type CheckBoxBoxProps, type CheckBoxProps, ChipContent, type ChipContentProps, type ChipVariant, DEFAULT_SEARCH_MATCH, DataScopeFilter, type DataScopeFilterProps, type DateGranularity, 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
@@ -1312,22 +1312,49 @@ interface NameListModalProps {
1312
1312
  initialName: string;
1313
1313
  submitLabel: string;
1314
1314
  onCancel: () => void;
1315
- onSubmit: (name: string) => void;
1315
+ /**
1316
+ * Called with the trimmed name, and the state of `options` when any were
1317
+ * given. A handler that only takes the name stays valid -- TypeScript lets
1318
+ * a function ignore trailing parameters -- so existing callers are
1319
+ * unaffected.
1320
+ */
1321
+ onSubmit: (name: string, checked: Record<string, boolean>) => void;
1322
+ /**
1323
+ * Relabels the name field, for dialogs that name something other than a
1324
+ * list (e.g. "View name").
1325
+ */
1326
+ fieldLabel?: string;
1327
+ /** Placeholder for the name field, paired with `fieldLabel`. */
1328
+ placeholder?: string;
1329
+ /**
1330
+ * Optional checkboxes below the name field -- e.g. "Set as default" or
1331
+ * "Enable email alerts". Their state is handed to `onSubmit` as the second
1332
+ * argument, keyed by `key`. `initial` sets the starting state.
1333
+ */
1334
+ options?: {
1335
+ key: string;
1336
+ label: string;
1337
+ initial?: boolean;
1338
+ }[];
1316
1339
  }
1317
1340
  /**
1318
1341
  * @pattern NameListModal
1319
- * @description Minimal create/rename dialog — just the list name. Shared by
1320
- * the Account Lists table and the list detail page so create/rename look
1321
- * identical.
1342
+ * @description Create/rename dialog — a name field, and optionally a few
1343
+ * checkboxes under it. Shared by the Account Lists table and the list detail
1344
+ * page so create/rename look identical; `fieldLabel`/`placeholder` relabel it
1345
+ * for dialogs that name something other than a list.
1322
1346
  * @tokens rounded-card, border-border-default, bg-surface, shadow-overlay, text-text-primary, text-text-secondary, rounded-control, bg-input, focus:border-brand-primaryAction
1323
1347
  * @behavior Escape closes the dialog via `onCancel`, same as clicking the
1324
1348
  * scrim backdrop. Submit is disabled until the name is non-empty (trimmed).
1349
+ * When `options` are given they render as CheckBox rows below the field, and
1350
+ * their state comes back as `onSubmit`'s second argument -- a handler that
1351
+ * only takes the name stays valid.
1325
1352
  * @usage
1326
1353
  * ```tsx
1327
1354
  * <NameListModal title="Rename list" initialName={list.name} submitLabel="Save" onCancel={close} onSubmit={rename} />
1328
1355
  * ```
1329
1356
  */
1330
- declare function NameListModal({ title, initialName, submitLabel, onCancel, onSubmit }: NameListModalProps): react.ReactPortal;
1357
+ declare function NameListModal({ title, initialName, submitLabel, onCancel, onSubmit, fieldLabel, placeholder, options, }: NameListModalProps): react.ReactPortal;
1331
1358
 
1332
1359
  /**
1333
1360
  * Which stroke a chip trigger carries.
@@ -1352,6 +1379,10 @@ interface ChipContentProps {
1352
1379
  * @description Shared foundation for filter-bar chip triggers — pairs
1353
1380
  * `chipTriggerClass` with `ChipContent` for the caption/value/icon layout, so
1354
1381
  * every dropdown chip across the app matches.
1382
+ * @props
1383
+ * caption: string -- small uppercase label above the value
1384
+ * value: ReactNode -- the current selection, shown below the caption
1385
+ * icon?: ReactNode -- optional leading icon rendered before the caption/value stack
1355
1386
  * @tokens rounded-control, bg-input, border-border-default, border-border-strong, text-text-secondary, text-text-tertiary, text-text-primary, hover:bg-subtle, focus-visible:outline-border-focus, hover:text-text-primary
1356
1387
  * @behavior `chipTriggerClass` takes a `ChipVariant`: `box` (default, the
1357
1388
  * boxed two-line chip on the default border) or `inline` (same fill, darker
@@ -1564,11 +1595,19 @@ declare function TablePagination({ page, perPage, totalItems, onPageChange, onPe
1564
1595
  }): react.JSX.Element;
1565
1596
  type TablePaginationProps = Parameters<typeof TablePagination>[0];
1566
1597
 
1598
+ /** What the Custom Range From/To selects pick. */
1599
+ type DateGranularity = 'month' | 'quarter' | 'year';
1567
1600
  /** Resolve a label to its actual [start, end] span, ending at `today`. */
1568
1601
  declare function resolveRange(label: string, today?: Date): [Date, Date];
1569
- declare function DateRangePicker({ defaultValue, align, presets, onChange, onRangeChange, showFooter, today, years, }: {
1602
+ declare function DateRangePicker({ defaultValue, granularity, align, presets, onChange, onRangeChange, showFooter, today, years, }: {
1570
1603
  defaultValue?: string;
1571
1604
  align?: 'left' | 'right';
1605
+ /**
1606
+ * What the Custom Range From/To selects pick. `month` shows month + year
1607
+ * selects, `quarter` shows quarter + year, `year` shows year alone -- and
1608
+ * the applied label follows suit. Pair it with matching `presets`.
1609
+ */
1610
+ granularity?: DateGranularity;
1572
1611
  /** Rolling presets shown above Custom Range. Defaults to 3/6/12 months. */
1573
1612
  presets?: string[];
1574
1613
  onChange?: (label: string) => void;
@@ -1602,7 +1641,14 @@ interface MultiSelectGroup {
1602
1641
  * Advertiser filters that share state with the filter tray.
1603
1642
  * @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, text-brand-onprimary
1604
1643
  * @dependencies lucide-react
1605
- * @behavior Same draft/commit-on-close pattern as AdvertiserQuickFilter — the
1644
+ * @behavior `variant` picks the trigger's chip stroke: `box` (default, the
1645
+ * boxed two-line chip on the default border) or `inline` (same fill,
1646
+ * darker stroke, for chips sitting directly on the canvas). Left out of
1647
+ * the catalog's variant list deliberately: check-prop-drift can't resolve
1648
+ * the imported ChipVariant alias through this component's inline prop
1649
+ * type, so such a tag would be unvalidated -- and this exact component
1650
+ * has had stale ones stripped before.
1651
+ * Same draft/commit-on-close pattern as AdvertiserQuickFilter — the
1606
1652
  * draft resyncs from `selected` every time the tray opens, and (without
1607
1653
  * showFooter) any close path commits it, while showFooter mode requires the
1608
1654
  * Apply button and discards the draft on every other close. `min` enforces a
@@ -1614,8 +1660,17 @@ interface MultiSelectGroup {
1614
1660
  * <MultiSelectFilter caption="Media" options={mediaOptions} selected={selected} onChange={setSelected} />
1615
1661
  * ```
1616
1662
  */
1617
- declare function MultiSelectFilter({ caption, options, groups, selected, onChange, allLabel, searchable, searchPlaceholder, align, fullIsAll, min, icon, showFooter, clearValue, menuWidthClass, plainParent, fullWidth, }: {
1663
+ declare function MultiSelectFilter({ caption, options, groups, counts, variant, selected, onChange, allLabel, searchable, searchPlaceholder, align, fullIsAll, min, icon, showFooter, clearValue, menuWidthClass, plainParent, fullWidth, }: {
1618
1664
  caption: string;
1665
+ /**
1666
+ * Live option-id -> result count. Supplying it makes the menu faceted:
1667
+ * every label gets a "(n)" suffix and options with nothing behind them
1668
+ * drop out. A selected option is always kept, or there would be no way to
1669
+ * undo it.
1670
+ */
1671
+ counts?: Record<string, number>;
1672
+ /** Chip stroke for the trigger. See ChipVariant. */
1673
+ variant?: ChipVariant;
1619
1674
  options?: {
1620
1675
  id: string;
1621
1676
  label: string;
@@ -1742,4 +1797,4 @@ interface FreshnessProps {
1742
1797
  */
1743
1798
  declare function Freshness({ level }: FreshnessProps): react.JSX.Element;
1744
1799
 
1745
- export { AISpark, type AISparkProps, AdvertiserNoResults, type AdvertiserNoResultsProps, AdvertiserQuickFilter, type AdvertiserQuickFilterProps, AdvertiserSearchPrompt, type AdvertiserSearchPromptProps, BarChartPlaceholder, type BarChartPlaceholderProps, Button, type ButtonProps, Card, type CardProps, CheckBox, CheckBoxBox, type CheckBoxBoxProps, type CheckBoxProps, ChipContent, type ChipContentProps, type ChipVariant, 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 };
1800
+ export { AISpark, type AISparkProps, AdvertiserNoResults, type AdvertiserNoResultsProps, AdvertiserQuickFilter, type AdvertiserQuickFilterProps, AdvertiserSearchPrompt, type AdvertiserSearchPromptProps, BarChartPlaceholder, type BarChartPlaceholderProps, Button, type ButtonProps, Card, type CardProps, CheckBox, CheckBoxBox, type CheckBoxBoxProps, type CheckBoxProps, ChipContent, type ChipContentProps, type ChipVariant, DEFAULT_SEARCH_MATCH, DataScopeFilter, type DataScopeFilterProps, type DateGranularity, 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.js CHANGED
@@ -2662,8 +2662,21 @@ function FilterDropdownFooter({
2662
2662
  import { useEffect as useEffect10, useState as useState11 } from "react";
2663
2663
  import { createPortal as createPortal5 } from "react-dom";
2664
2664
  import { jsx as jsx26, jsxs as jsxs24 } from "react/jsx-runtime";
2665
- function NameListModal({ title, initialName, submitLabel, onCancel, onSubmit }) {
2665
+ function NameListModal({
2666
+ title,
2667
+ initialName,
2668
+ submitLabel,
2669
+ onCancel,
2670
+ onSubmit,
2671
+ fieldLabel = "List name",
2672
+ placeholder = "e.g. Q4 prospecting targets",
2673
+ options
2674
+ }) {
2666
2675
  const [name, setName] = useState11(initialName);
2676
+ const [checked, setChecked] = useState11(
2677
+ () => Object.fromEntries((options ?? []).map((o) => [o.key, !!o.initial]))
2678
+ );
2679
+ const toggle = (key) => setChecked((c) => ({ ...c, [key]: !c[key] }));
2667
2680
  useEffect10(() => {
2668
2681
  const onKey = (e) => e.key === "Escape" && onCancel();
2669
2682
  window.addEventListener("keydown", onKey);
@@ -2688,7 +2701,7 @@ function NameListModal({ title, initialName, submitLabel, onCancel, onSubmit })
2688
2701
  children: [
2689
2702
  /* @__PURE__ */ jsx26("h2", { className: "text-[16px] font-semibold text-text-primary", children: title }),
2690
2703
  /* @__PURE__ */ jsxs24("div", { className: "mt-4 flex flex-col gap-1.5", children: [
2691
- /* @__PURE__ */ jsx26("label", { htmlFor: "account-list-name", className: "text-[12px] font-medium text-text-secondary", children: "List name" }),
2704
+ /* @__PURE__ */ jsx26("label", { htmlFor: "account-list-name", className: "text-[12px] font-medium text-text-secondary", children: fieldLabel }),
2692
2705
  /* @__PURE__ */ jsx26(
2693
2706
  "input",
2694
2707
  {
@@ -2696,14 +2709,18 @@ function NameListModal({ title, initialName, submitLabel, onCancel, onSubmit })
2696
2709
  autoFocus: true,
2697
2710
  value: name,
2698
2711
  onChange: (e) => setName(e.target.value),
2699
- placeholder: "e.g. Q4 prospecting targets",
2712
+ placeholder,
2700
2713
  className: "h-10 rounded-control border border-border-default bg-input px-3 text-sm outline-hidden focus:border-brand-primaryAction"
2701
2714
  }
2702
2715
  )
2703
2716
  ] }),
2717
+ options && options.length > 0 && /* @__PURE__ */ jsx26("div", { className: "mt-4 flex flex-col gap-2.5", children: options.map((o) => /* @__PURE__ */ jsxs24("label", { className: "flex cursor-pointer items-center gap-2.5 text-[13px] text-text-primary", children: [
2718
+ /* @__PURE__ */ jsx26(CheckBox, { checked: !!checked[o.key], onChange: () => toggle(o.key), ariaLabel: o.label }),
2719
+ o.label
2720
+ ] }, o.key)) }),
2704
2721
  /* @__PURE__ */ jsxs24("div", { className: "mt-5 flex items-center justify-end gap-2", children: [
2705
2722
  /* @__PURE__ */ jsx26(Button, { variant: "secondary", onClick: onCancel, children: "Cancel" }),
2706
- /* @__PURE__ */ jsx26(Button, { disabled: !name.trim(), onClick: () => onSubmit(name.trim()), children: submitLabel })
2723
+ /* @__PURE__ */ jsx26(Button, { disabled: !name.trim(), onClick: () => onSubmit(name.trim(), checked), children: submitLabel })
2707
2724
  ] })
2708
2725
  ]
2709
2726
  }
@@ -3075,6 +3092,7 @@ import { useEffect as useEffect11, useMemo as useMemo4, useRef as useRef11, useS
3075
3092
  import { ChevronDown as ChevronDown10 } from "lucide-react";
3076
3093
  import { jsx as jsx34, jsxs as jsxs30 } from "react/jsx-runtime";
3077
3094
  var MONTH_ABBR = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
3095
+ var QUARTER_ABBR = ["Q1", "Q2", "Q3", "Q4"];
3078
3096
  var PRESETS = ["Rolling 3 months", "Rolling 6 months", "Rolling 12 months"];
3079
3097
  var startOfToday = () => {
3080
3098
  const d = /* @__PURE__ */ new Date();
@@ -3123,6 +3141,7 @@ function MiniSelect({ value, onChange, options }) {
3123
3141
  }
3124
3142
  function DateRangePicker({
3125
3143
  defaultValue = "Rolling 6 months",
3144
+ granularity = "month",
3126
3145
  align = "left",
3127
3146
  presets = PRESETS,
3128
3147
  onChange,
@@ -3141,6 +3160,8 @@ function DateRangePicker({
3141
3160
  const [fromYr, setFromYr] = useState12(end.getFullYear() - 1);
3142
3161
  const [toMo, setToMo] = useState12(end.getMonth());
3143
3162
  const [toYr, setToYr] = useState12(end.getFullYear());
3163
+ const [fromQ, setFromQ] = useState12(Math.floor(end.getMonth() / 3));
3164
+ const [toQ, setToQ] = useState12(Math.floor(end.getMonth() / 3));
3144
3165
  useEffect11(() => {
3145
3166
  const [s, e] = resolveRange(value, end);
3146
3167
  onRangeChange?.(s, e);
@@ -3167,11 +3188,11 @@ function DateRangePicker({
3167
3188
  onChange?.(label);
3168
3189
  setOpen(false);
3169
3190
  };
3170
- const span = toYr * 12 + toMo - (fromYr * 12 + fromMo) + 1;
3191
+ const span = granularity === "year" ? toYr - fromYr + 1 : granularity === "quarter" ? toYr * 4 + toQ - (fromYr * 4 + fromQ) + 1 : toYr * 12 + toMo - (fromYr * 12 + fromMo) + 1;
3171
3192
  const valid = span >= 1;
3172
3193
  const applyCustom = () => {
3173
3194
  if (!valid) return;
3174
- const label = `${MONTH_ABBR[fromMo]} ${fromYr} \u2013 ${MONTH_ABBR[toMo]} ${toYr}`;
3195
+ const label = granularity === "year" ? `${fromYr} \u2013 ${toYr}` : granularity === "quarter" ? `${QUARTER_ABBR[fromQ]} ${fromYr} \u2013 ${QUARTER_ABBR[toQ]} ${toYr}` : `${MONTH_ABBR[fromMo]} ${fromYr} \u2013 ${MONTH_ABBR[toMo]} ${toYr}`;
3175
3196
  if (showFooter) setDraft(label);
3176
3197
  else commit(label);
3177
3198
  };
@@ -3210,14 +3231,16 @@ function DateRangePicker({
3210
3231
  /* @__PURE__ */ jsxs30("label", { className: "flex items-center justify-between gap-2 text-[12px] text-text-secondary", children: [
3211
3232
  "From",
3212
3233
  /* @__PURE__ */ jsxs30("span", { className: "flex gap-1", children: [
3213
- /* @__PURE__ */ jsx34(MiniSelect, { value: fromMo, onChange: setFromMo, options: MONTH_ABBR.map((mm, i) => ({ label: mm, value: i })) }),
3234
+ granularity === "month" && /* @__PURE__ */ jsx34(MiniSelect, { value: fromMo, onChange: setFromMo, options: MONTH_ABBR.map((mm, i) => ({ label: mm, value: i })) }),
3235
+ granularity === "quarter" && /* @__PURE__ */ jsx34(MiniSelect, { value: fromQ, onChange: setFromQ, options: QUARTER_ABBR.map((qq, i) => ({ label: qq, value: i })) }),
3214
3236
  /* @__PURE__ */ jsx34(MiniSelect, { value: fromYr, onChange: setFromYr, options: yearOptions.map((y) => ({ label: String(y), value: y })) })
3215
3237
  ] })
3216
3238
  ] }),
3217
3239
  /* @__PURE__ */ jsxs30("label", { className: "flex items-center justify-between gap-2 text-[12px] text-text-secondary", children: [
3218
3240
  "To",
3219
3241
  /* @__PURE__ */ jsxs30("span", { className: "flex gap-1", children: [
3220
- /* @__PURE__ */ jsx34(MiniSelect, { value: toMo, onChange: setToMo, options: MONTH_ABBR.map((mm, i) => ({ label: mm, value: i })) }),
3242
+ granularity === "month" && /* @__PURE__ */ jsx34(MiniSelect, { value: toMo, onChange: setToMo, options: MONTH_ABBR.map((mm, i) => ({ label: mm, value: i })) }),
3243
+ granularity === "quarter" && /* @__PURE__ */ jsx34(MiniSelect, { value: toQ, onChange: setToQ, options: QUARTER_ABBR.map((qq, i) => ({ label: qq, value: i })) }),
3221
3244
  /* @__PURE__ */ jsx34(MiniSelect, { value: toYr, onChange: setToYr, options: yearOptions.map((y) => ({ label: String(y), value: y })) })
3222
3245
  ] })
3223
3246
  ] }),
@@ -3246,6 +3269,8 @@ function MultiSelectFilter({
3246
3269
  caption,
3247
3270
  options = [],
3248
3271
  groups,
3272
+ counts,
3273
+ variant = "box",
3249
3274
  selected,
3250
3275
  onChange,
3251
3276
  allLabel = "All",
@@ -3303,14 +3328,18 @@ function MultiSelectFilter({
3303
3328
  return next;
3304
3329
  });
3305
3330
  const toggleGroup = (g) => setDraft((cur) => {
3306
- const ids = groupLeaves(g).map((c) => c.id);
3331
+ const ids = groupLeaves(g).map((c) => c.id).filter((id) => !counts || (counts[id] ?? 0) > 0 || cur.includes(id));
3332
+ if (!ids.length) return cur;
3307
3333
  const allSel = ids.every((id) => cur.includes(id));
3308
3334
  const next = allSel ? cur.filter((id) => !ids.includes(id)) : [.../* @__PURE__ */ new Set([...cur, ...ids])];
3309
3335
  if (next.length < min) return cur;
3310
3336
  return next;
3311
3337
  });
3338
+ const isAvailable = (id) => !counts || (counts[id] ?? 0) > 0 || draft.includes(id);
3339
+ const countFor = (id) => counts?.[id] ?? 0;
3312
3340
  const groupState = (g) => {
3313
- const ids = groupLeaves(g).map((c) => c.id);
3341
+ const ids = groupLeaves(g).map((c) => c.id).filter(isAvailable);
3342
+ if (!ids.length) return "none";
3314
3343
  const sel = ids.filter((id) => draft.includes(id)).length;
3315
3344
  return sel === 0 ? "none" : sel === ids.length ? "all" : "some";
3316
3345
  };
@@ -3318,10 +3347,12 @@ function MultiSelectFilter({
3318
3347
  const isAll = shown.length === 0 || fullIsAll && shown.length === leafOptions.length;
3319
3348
  const value = isAll ? allLabel : shown.length === 1 ? leafOptions.find((o) => o.id === shown[0])?.label ?? `${shown.length} selected` : `${shown.length} selected`;
3320
3349
  const ql = q.trim().toLowerCase();
3321
- const items = options.filter((o) => !ql || o.label.toLowerCase().includes(ql));
3350
+ const items = options.filter((o) => isAvailable(o.id) && (!ql || o.label.toLowerCase().includes(ql)));
3322
3351
  const visibleGroups = groups ? groups.map((g) => {
3323
- if (!ql || g.label.toLowerCase().includes(ql)) return g;
3324
- const kids = g.children.filter((c) => c.label.toLowerCase().includes(ql));
3352
+ const live = g.children.filter((c) => isAvailable(c.id));
3353
+ if (!live.length && !isAvailable(g.id)) return null;
3354
+ if (!ql || g.label.toLowerCase().includes(ql)) return { ...g, children: live };
3355
+ const kids = live.filter((c) => c.label.toLowerCase().includes(ql));
3325
3356
  return kids.length ? { ...g, children: kids } : null;
3326
3357
  }).filter((g) => g !== null) : [];
3327
3358
  return /* @__PURE__ */ jsxs31("div", { className: cn("relative", fullWidth && "w-full"), ref, children: [
@@ -3331,7 +3362,7 @@ function MultiSelectFilter({
3331
3362
  type: "button",
3332
3363
  onClick: () => open ? close() : openTray(),
3333
3364
  "aria-expanded": open,
3334
- className: cn(chipTriggerClass(), fullWidth && "w-full justify-between"),
3365
+ className: cn(chipTriggerClass(variant), fullWidth && "w-full justify-between"),
3335
3366
  children: [
3336
3367
  /* @__PURE__ */ jsx35(ChipContent, { caption, value, icon }),
3337
3368
  /* @__PURE__ */ jsx35(
@@ -3382,7 +3413,8 @@ function MultiSelectFilter({
3382
3413
  className: "flex w-full items-center gap-2.5 rounded-control px-2 py-2 text-left transition-colors hover:bg-subtle",
3383
3414
  children: [
3384
3415
  /* @__PURE__ */ jsx35(TriCheck, { state }),
3385
- /* @__PURE__ */ jsx35("span", { className: cn("flex-1 text-[14px] text-text-primary", !plainParent && "font-semibold"), children: g.label })
3416
+ /* @__PURE__ */ jsx35("span", { className: cn("flex-1 text-[14px] text-text-primary", !plainParent && "font-semibold"), children: g.label }),
3417
+ counts && /* @__PURE__ */ jsx35(OptionCount, { n: countFor(g.id) })
3386
3418
  ]
3387
3419
  }
3388
3420
  ),
@@ -3396,7 +3428,8 @@ function MultiSelectFilter({
3396
3428
  className: "flex w-full items-center gap-2.5 rounded-control py-2 pl-9 pr-2 text-left transition-colors hover:bg-subtle",
3397
3429
  children: [
3398
3430
  /* @__PURE__ */ jsx35(TriCheck, { state: checked ? "all" : "none" }),
3399
- /* @__PURE__ */ jsx35("span", { className: "flex-1 text-[14px] text-text-primary", children: c.label })
3431
+ /* @__PURE__ */ jsx35("span", { className: "flex-1 text-[14px] text-text-primary", children: c.label }),
3432
+ counts && /* @__PURE__ */ jsx35(OptionCount, { n: countFor(c.id) })
3400
3433
  ]
3401
3434
  },
3402
3435
  c.id
@@ -3422,7 +3455,8 @@ function MultiSelectFilter({
3422
3455
  children: checked && /* @__PURE__ */ jsx35(Check7, { size: 13, strokeWidth: 3 })
3423
3456
  }
3424
3457
  ),
3425
- /* @__PURE__ */ jsx35("span", { className: "flex-1 text-[14px] text-text-primary", children: o.label })
3458
+ /* @__PURE__ */ jsx35("span", { className: "flex-1 text-[14px] text-text-primary", children: o.label }),
3459
+ counts && /* @__PURE__ */ jsx35(OptionCount, { n: countFor(o.id) })
3426
3460
  ]
3427
3461
  },
3428
3462
  o.id
@@ -3463,6 +3497,13 @@ function TriCheck({ state }) {
3463
3497
  }
3464
3498
  );
3465
3499
  }
3500
+ function OptionCount({ n }) {
3501
+ return /* @__PURE__ */ jsxs31("span", { className: "shrink-0 text-[12px] tabular-nums text-text-tertiary", children: [
3502
+ "(",
3503
+ n.toLocaleString(),
3504
+ ")"
3505
+ ] });
3506
+ }
3466
3507
 
3467
3508
  // src/Toggle.tsx
3468
3509
  import { jsx as jsx36 } from "react/jsx-runtime";