@wallarm-org/design-system 1.28.2-rc-fix-table-window-scroll-root.2 → 1.30.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.
Files changed (105) hide show
  1. package/dist/components/Avatar/Avatar.d.ts +32 -0
  2. package/dist/components/Avatar/Avatar.figma.d.ts +1 -0
  3. package/dist/components/Avatar/Avatar.figma.js +27 -0
  4. package/dist/components/Avatar/Avatar.js +42 -0
  5. package/dist/components/Avatar/AvatarFallback.d.ts +11 -0
  6. package/dist/components/Avatar/AvatarFallback.js +25 -0
  7. package/dist/components/Avatar/AvatarImage.d.ts +9 -0
  8. package/dist/components/Avatar/AvatarImage.js +18 -0
  9. package/dist/components/Avatar/AvatarOverlay.d.ts +11 -0
  10. package/dist/components/Avatar/AvatarOverlay.js +22 -0
  11. package/dist/components/Avatar/classes.d.ts +6 -0
  12. package/dist/components/Avatar/classes.js +17 -0
  13. package/dist/components/Avatar/index.d.ts +4 -0
  14. package/dist/components/Avatar/index.js +4 -0
  15. package/dist/components/FileUpload/FileUploadTrigger.d.ts +5 -0
  16. package/dist/components/FileUpload/FileUploadTrigger.js +18 -5
  17. package/dist/components/FileUpload/index.d.ts +1 -0
  18. package/dist/components/FileUpload/index.js +1 -0
  19. package/dist/components/FileUpload/useFilePreviewUrl.d.ts +6 -0
  20. package/dist/components/FileUpload/useFilePreviewUrl.js +14 -0
  21. package/dist/components/FilterDropdown/FilterDropdown.d.ts +58 -0
  22. package/dist/components/FilterDropdown/FilterDropdown.js +168 -0
  23. package/dist/components/FilterDropdown/FilterDropdownAllOption.d.ts +14 -0
  24. package/dist/components/FilterDropdown/FilterDropdownAllOption.js +25 -0
  25. package/dist/components/FilterDropdown/FilterDropdownClear.d.ts +12 -0
  26. package/dist/components/FilterDropdown/FilterDropdownClear.js +33 -0
  27. package/dist/components/FilterDropdown/FilterDropdownContent.d.ts +13 -0
  28. package/dist/components/FilterDropdown/FilterDropdownContent.js +57 -0
  29. package/dist/components/FilterDropdown/FilterDropdownContext.d.ts +60 -0
  30. package/dist/components/FilterDropdown/FilterDropdownContext.js +21 -0
  31. package/dist/components/FilterDropdown/FilterDropdownEmpty.d.ts +9 -0
  32. package/dist/components/FilterDropdown/FilterDropdownEmpty.js +21 -0
  33. package/dist/components/FilterDropdown/FilterDropdownFooter.d.ts +9 -0
  34. package/dist/components/FilterDropdown/FilterDropdownFooter.js +19 -0
  35. package/dist/components/FilterDropdown/FilterDropdownFooterClear.d.ts +9 -0
  36. package/dist/components/FilterDropdown/FilterDropdownFooterClear.js +40 -0
  37. package/dist/components/FilterDropdown/FilterDropdownGroup.d.ts +5 -0
  38. package/dist/components/FilterDropdown/FilterDropdownGroup.js +8 -0
  39. package/dist/components/FilterDropdown/FilterDropdownGroupLabel.d.ts +4 -0
  40. package/dist/components/FilterDropdown/FilterDropdownGroupLabel.js +8 -0
  41. package/dist/components/FilterDropdown/FilterDropdownOption.d.ts +15 -0
  42. package/dist/components/FilterDropdown/FilterDropdownOption.js +32 -0
  43. package/dist/components/FilterDropdown/FilterDropdownSearch.d.ts +12 -0
  44. package/dist/components/FilterDropdown/FilterDropdownSearch.js +38 -0
  45. package/dist/components/FilterDropdown/FilterDropdownSelected.d.ts +16 -0
  46. package/dist/components/FilterDropdown/FilterDropdownSelected.js +38 -0
  47. package/dist/components/FilterDropdown/FilterDropdownTrigger.d.ts +16 -0
  48. package/dist/components/FilterDropdown/FilterDropdownTrigger.js +139 -0
  49. package/dist/components/FilterDropdown/classes.d.ts +16 -0
  50. package/dist/components/FilterDropdown/classes.js +43 -0
  51. package/dist/components/FilterDropdown/index.d.ts +15 -0
  52. package/dist/components/FilterDropdown/index.js +15 -0
  53. package/dist/components/FilterDropdown/lib/index.d.ts +1 -0
  54. package/dist/components/FilterDropdown/lib/index.js +1 -0
  55. package/dist/components/FilterDropdown/lib/values.d.ts +59 -0
  56. package/dist/components/FilterDropdown/lib/values.js +58 -0
  57. package/dist/components/NavRail/NavRailItem.d.ts +1 -1
  58. package/dist/components/NavRail/NavRailItem.js +9 -12
  59. package/dist/components/Select/Select.d.ts +1 -1
  60. package/dist/components/Select/SelectContent.d.ts +2 -1
  61. package/dist/components/Select/SelectContent.js +3 -2
  62. package/dist/components/Select/SelectEmptyState.d.ts +1 -0
  63. package/dist/components/Select/SelectEmptyState.js +2 -1
  64. package/dist/components/Select/SelectFooter.d.ts +7 -2
  65. package/dist/components/Select/SelectFooter.js +6 -3
  66. package/dist/components/Select/SelectGroup.d.ts +8 -2
  67. package/dist/components/Select/SelectGroup.js +3 -2
  68. package/dist/components/Select/SelectGroupLabel.d.ts +5 -2
  69. package/dist/components/Select/SelectGroupLabel.js +2 -2
  70. package/dist/components/Select/SelectOption.js +1 -1
  71. package/dist/components/Select/SelectOptionHint.d.ts +11 -0
  72. package/dist/components/Select/SelectOptionHint.js +15 -0
  73. package/dist/components/Select/SelectPositioner.d.ts +13 -3
  74. package/dist/components/Select/SelectPositioner.js +2 -1
  75. package/dist/components/Select/SelectSearchInput.d.ts +5 -2
  76. package/dist/components/Select/SelectSearchInput.js +11 -1
  77. package/dist/components/Select/classes.d.ts +3 -0
  78. package/dist/components/Select/classes.js +13 -0
  79. package/dist/components/Select/index.d.ts +4 -2
  80. package/dist/components/Select/index.js +2 -0
  81. package/dist/components/Table/TableBody/TableBodyVirtualizedCore.js +1 -1
  82. package/dist/components/Table/TableBody/TableBodyVirtualizedWindow.js +8 -26
  83. package/dist/components/Table/TableInner/TableInnerWindow.js +2 -7
  84. package/dist/components/Table/hooks/index.d.ts +0 -1
  85. package/dist/components/Table/hooks/index.js +0 -1
  86. package/dist/components/Table/hooks/infiniteScroll/useInfiniteScroll.d.ts +2 -4
  87. package/dist/components/Table/hooks/infiniteScroll/useInfiniteScroll.js +1 -4
  88. package/dist/components/Table/hooks/infiniteScroll/usePrependScrollAnchor.d.ts +1 -4
  89. package/dist/components/Table/hooks/infiniteScroll/usePrependScrollAnchor.js +11 -13
  90. package/dist/components/Table/hooks/infiniteScroll/useScrollEdge.d.ts +1 -4
  91. package/dist/components/Table/hooks/infiniteScroll/useScrollEdge.js +18 -6
  92. package/dist/components/Table/lib/index.d.ts +0 -1
  93. package/dist/components/Table/lib/index.js +0 -1
  94. package/dist/components/Table/types.d.ts +1 -4
  95. package/dist/index.d.ts +4 -2
  96. package/dist/index.js +4 -2
  97. package/dist/metadata/components.json +16122 -9667
  98. package/dist/theme/semantic.css +2 -0
  99. package/dist/utils/getInitials.d.ts +5 -0
  100. package/dist/utils/getInitials.js +13 -0
  101. package/package.json +1 -1
  102. package/dist/components/Table/hooks/useWindowScrollRoot.d.ts +0 -14
  103. package/dist/components/Table/hooks/useWindowScrollRoot.js +0 -35
  104. package/dist/components/Table/lib/scrollRoot.d.ts +0 -24
  105. package/dist/components/Table/lib/scrollRoot.js +0 -22
@@ -0,0 +1,33 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { X } from "../../icons/index.js";
3
+ import { cn } from "../../utils/cn.js";
4
+ import { useTestId } from "../../utils/testId.js";
5
+ import { filterDropdownClearClassName } from "./classes.js";
6
+ import { useFilterDropdownContext } from "./FilterDropdownContext.js";
7
+ const FilterDropdownClear = ({ ref, className, children, disabled, onClick, 'aria-label': ariaLabel, 'data-testid': testIdProp, ...props })=>{
8
+ const { multiple, value, label, clear, triggerRef, disabled: rootDisabled } = useFilterDropdownContext();
9
+ const testId = useTestId('clear', testIdProp);
10
+ if (!multiple || 0 === value.length) return null;
11
+ const handleClick = (event)=>{
12
+ onClick?.(event);
13
+ if (event.defaultPrevented) return;
14
+ triggerRef.current?.focus();
15
+ clear();
16
+ };
17
+ return /*#__PURE__*/ jsx("button", {
18
+ type: "button",
19
+ ...props,
20
+ ref: ref,
21
+ "data-slot": "filter-dropdown-clear",
22
+ "data-testid": testId,
23
+ "aria-label": ariaLabel ?? `Clear ${label}`,
24
+ disabled: rootDisabled || disabled,
25
+ onClick: handleClick,
26
+ className: cn(filterDropdownClearClassName, className),
27
+ children: children ?? /*#__PURE__*/ jsx(X, {
28
+ size: "md"
29
+ })
30
+ });
31
+ };
32
+ FilterDropdownClear.displayName = 'FilterDropdownClear';
33
+ export { FilterDropdownClear };
@@ -0,0 +1,13 @@
1
+ import { type FC, type ReactNode, type Ref } from 'react';
2
+ import type { Select as ArkUiSelect } from '@ark-ui/react/select';
3
+ import { type TestableProps } from '../../utils/testId';
4
+ export interface FilterDropdownContentProps extends Omit<ArkUiSelect.ContentProps, 'asChild' | 'children'>, TestableProps {
5
+ ref?: Ref<HTMLDivElement>;
6
+ children?: ReactNode;
7
+ }
8
+ /**
9
+ * The menu panel. `FilterDropdownSearch` children are pinned above the scrolling list and
10
+ * `FilterDropdownFooter` children below it; everything else scrolls. Hugs its options up to
11
+ * 360px and at most 340px tall, and keeps its width while a query narrows the list.
12
+ */
13
+ export declare const FilterDropdownContent: FC<FilterDropdownContentProps>;
@@ -0,0 +1,57 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { Children, isValidElement } from "react";
3
+ import { cn } from "../../utils/cn.js";
4
+ import { mergeRefs } from "../../utils/mergeRefs.js";
5
+ import { TestIdProvider, useTestId } from "../../utils/testId.js";
6
+ import { SelectContent } from "../Select/SelectContent.js";
7
+ import { SelectHeader } from "../Select/SelectHeader.js";
8
+ import { SelectPositioner } from "../Select/SelectPositioner.js";
9
+ import { filterDropdownContentClassName } from "./classes.js";
10
+ import { useFilterDropdownContext } from "./FilterDropdownContext.js";
11
+ import { FilterDropdownFooter } from "./FilterDropdownFooter.js";
12
+ import { FilterDropdownSearch } from "./FilterDropdownSearch.js";
13
+ const FilterDropdownContent = ({ ref, className, style, children, 'data-testid': testIdProp, ...props })=>{
14
+ const { isSearchable, isSearchActive, lockedWidth, contentRef } = useFilterDropdownContext();
15
+ const testId = useTestId('content', testIdProp);
16
+ const listTestId = useTestId('list');
17
+ const baseTestId = useTestId();
18
+ const header = [];
19
+ const footer = [];
20
+ const body = [];
21
+ Children.forEach(children, (child)=>{
22
+ if (/*#__PURE__*/ isValidElement(child) && child.type === FilterDropdownSearch) header.push(child);
23
+ else if (/*#__PURE__*/ isValidElement(child) && child.type === FilterDropdownFooter) footer.push(child);
24
+ else body.push(child);
25
+ });
26
+ const width = isSearchActive && lockedWidth ? lockedWidth : void 0;
27
+ return /*#__PURE__*/ jsxs(SelectPositioner, {
28
+ className: cn(filterDropdownContentClassName, className),
29
+ contentProps: {
30
+ ...props,
31
+ ref: mergeRefs(ref, contentRef),
32
+ style: void 0 === width ? style : {
33
+ ...style,
34
+ width
35
+ },
36
+ 'data-slot': 'filter-dropdown-content',
37
+ 'data-testid': testId
38
+ },
39
+ children: [
40
+ isSearchable && header.length > 0 && /*#__PURE__*/ jsx(SelectHeader, {
41
+ children: header
42
+ }),
43
+ /*#__PURE__*/ jsx(SelectContent, {
44
+ "data-testid": listTestId,
45
+ tabIndex: -1,
46
+ "data-no-autofocus": "",
47
+ children: /*#__PURE__*/ jsx(TestIdProvider, {
48
+ value: baseTestId,
49
+ children: body
50
+ })
51
+ }),
52
+ footer
53
+ ]
54
+ });
55
+ };
56
+ FilterDropdownContent.displayName = 'FilterDropdownContent';
57
+ export { FilterDropdownContent };
@@ -0,0 +1,60 @@
1
+ import { type RefObject } from 'react';
2
+ import type { CollectionItem, ListCollection } from '@ark-ui/react/collection';
3
+ import type { FilterDropdownSpecialItem } from './lib';
4
+ export interface FilterDropdownContextValue {
5
+ /** Attribute name: trigger text in multi, aria labels, «Clear {label}». */
6
+ label: string;
7
+ /** Single mode: trigger text while unset and the default «All» option text. */
8
+ allLabel: string;
9
+ multiple: boolean;
10
+ disabled: boolean;
11
+ /** The consumer value (base values only, `[]` = unset). */
12
+ value: string[];
13
+ /** The consumer's collection, unfiltered. */
14
+ collection: ListCollection<CollectionItem>;
15
+ /** The consumer's collection narrowed by the search query. */
16
+ filteredCollection: ListCollection<CollectionItem>;
17
+ /** `filteredCollection.group()` — groups with no matches are absent. */
18
+ groups: [string, CollectionItem[]][];
19
+ query: string;
20
+ setQuery: (query: string) => void;
21
+ /** The search field is shown: the collection has at least `searchThreshold` items. */
22
+ isSearchable: boolean;
23
+ /** A non-empty query is narrowing the list. */
24
+ isSearchActive: boolean;
25
+ /** Single mode and no query: «All» is part of the list. */
26
+ showAll: boolean;
27
+ allItem: FilterDropdownSpecialItem;
28
+ /**
29
+ * Multi mode, `selectedOnTop`, searchable, no query and something was picked when the menu
30
+ * opened.
31
+ */
32
+ showSelected: boolean;
33
+ /** Alias rows of the "Selected" snapshot, in pick order. */
34
+ aliasItems: FilterDropdownSpecialItem[];
35
+ clear: () => void;
36
+ triggerRef: RefObject<HTMLButtonElement | null>;
37
+ contentRef: RefObject<HTMLDivElement | null>;
38
+ /** Width the menu is pinned to while a query is active, so it does not jump as rows drop. */
39
+ lockedWidth: number | undefined;
40
+ }
41
+ export declare const FilterDropdownContext: import("react").Context<FilterDropdownContextValue | null>;
42
+ export declare const useFilterDropdownContext: () => FilterDropdownContextValue;
43
+ /** Set by `FilterDropdownSelected` around each of its rows: the alias that row stands for. */
44
+ export declare const FilterDropdownAliasContext: import("react").Context<FilterDropdownSpecialItem<any> | null>;
45
+ export interface UseFilterDropdownResult<T extends CollectionItem = CollectionItem> {
46
+ /** The collection narrowed by the current query (the whole collection when it is empty). */
47
+ filteredCollection: ListCollection<T>;
48
+ /** `filteredCollection.group()`; render these so the list follows the search. */
49
+ groups: [string, T[]][];
50
+ query: string;
51
+ isSearchActive: boolean;
52
+ multiple: boolean;
53
+ value: string[];
54
+ clear: () => void;
55
+ }
56
+ /**
57
+ * Reads the state of the surrounding `FilterDropdown` — chiefly the filtered items and groups
58
+ * to render inside `FilterDropdownContent`.
59
+ */
60
+ export declare const useFilterDropdown: <T extends CollectionItem = CollectionItem>() => UseFilterDropdownResult<T>;
@@ -0,0 +1,21 @@
1
+ import { createContext, useContext } from "react";
2
+ const FilterDropdownContext = /*#__PURE__*/ createContext(null);
3
+ const useFilterDropdownContext = ()=>{
4
+ const context = useContext(FilterDropdownContext);
5
+ if (!context) throw new Error('FilterDropdown parts must be rendered inside <FilterDropdown>');
6
+ return context;
7
+ };
8
+ const FilterDropdownAliasContext = /*#__PURE__*/ createContext(null);
9
+ const useFilterDropdown = ()=>{
10
+ const { filteredCollection, groups, query, isSearchActive, multiple, value, clear } = useFilterDropdownContext();
11
+ return {
12
+ filteredCollection: filteredCollection,
13
+ groups: groups,
14
+ query,
15
+ isSearchActive,
16
+ multiple,
17
+ value,
18
+ clear
19
+ };
20
+ };
21
+ export { FilterDropdownAliasContext, FilterDropdownContext, useFilterDropdown, useFilterDropdownContext };
@@ -0,0 +1,9 @@
1
+ import type { FC, HTMLAttributes, ReactNode, Ref } from 'react';
2
+ import { type TestableProps } from '../../utils/testId';
3
+ export interface FilterDropdownEmptyProps extends Omit<HTMLAttributes<HTMLDivElement>, 'children'>, TestableProps {
4
+ ref?: Ref<HTMLDivElement>;
5
+ /** @default 'Nothing matches' */
6
+ children?: ReactNode;
7
+ }
8
+ /** Shown in place of the options when the query matches none of them. */
9
+ export declare const FilterDropdownEmpty: FC<FilterDropdownEmptyProps>;
@@ -0,0 +1,21 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { useTestId } from "../../utils/testId.js";
3
+ import { SelectEmptyState } from "../Select/SelectEmptyState.js";
4
+ import { useFilterDropdownContext } from "./FilterDropdownContext.js";
5
+ const FilterDropdownEmpty = ({ ref, children, 'data-testid': testIdProp, ...props })=>{
6
+ const { filteredCollection } = useFilterDropdownContext();
7
+ const testId = useTestId('empty', testIdProp);
8
+ if (filteredCollection.size > 0) return null;
9
+ return /*#__PURE__*/ jsx("div", {
10
+ ...props,
11
+ ref: ref,
12
+ "data-slot": "filter-dropdown-empty",
13
+ "data-testid": testId,
14
+ children: /*#__PURE__*/ jsx(SelectEmptyState, {
15
+ className: "w-full max-w-240",
16
+ description: children ?? 'Nothing matches'
17
+ })
18
+ });
19
+ };
20
+ FilterDropdownEmpty.displayName = 'FilterDropdownEmpty';
21
+ export { FilterDropdownEmpty };
@@ -0,0 +1,9 @@
1
+ import type { FC } from 'react';
2
+ import { type TestableProps } from '../../utils/testId';
3
+ import { type SelectFooterProps } from '../Select/SelectFooter';
4
+ export type FilterDropdownFooterProps = Omit<SelectFooterProps, 'variant' | 'data-testid'> & TestableProps;
5
+ /**
6
+ * Footer pinned under the list. Multi mode only, and only while something is picked; its default
7
+ * content is `FilterDropdownFooterClear`.
8
+ */
9
+ export declare const FilterDropdownFooter: FC<FilterDropdownFooterProps>;
@@ -0,0 +1,19 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { useTestId } from "../../utils/testId.js";
3
+ import { SelectFooter } from "../Select/SelectFooter.js";
4
+ import { useFilterDropdownContext } from "./FilterDropdownContext.js";
5
+ import { FilterDropdownFooterClear } from "./FilterDropdownFooterClear.js";
6
+ const FilterDropdownFooter = ({ children, 'data-testid': testIdProp, ...props })=>{
7
+ const { multiple, value } = useFilterDropdownContext();
8
+ const testId = useTestId('footer', testIdProp);
9
+ if (!multiple || 0 === value.length) return null;
10
+ return /*#__PURE__*/ jsx(SelectFooter, {
11
+ ...props,
12
+ variant: "actions",
13
+ "data-slot": "filter-dropdown-footer",
14
+ "data-testid": testId,
15
+ children: children ?? /*#__PURE__*/ jsx(FilterDropdownFooterClear, {})
16
+ });
17
+ };
18
+ FilterDropdownFooter.displayName = 'FilterDropdownFooter';
19
+ export { FilterDropdownFooter };
@@ -0,0 +1,9 @@
1
+ import type { FC } from 'react';
2
+ import { type TestableProps } from '../../utils/testId';
3
+ import { type ButtonProps } from '../Button';
4
+ export type FilterDropdownFooterClearProps = Omit<ButtonProps<'button'>, 'variant' | 'color' | 'size' | 'as' | 'asChild'> & TestableProps;
5
+ /**
6
+ * The «Clear» button of the multi-mode footer. Keeps the menu open and moves focus back into it
7
+ * (the search, or the list) before the footer disappears.
8
+ */
9
+ export declare const FilterDropdownFooterClear: FC<FilterDropdownFooterClearProps>;
@@ -0,0 +1,40 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { useTestId } from "../../utils/testId.js";
3
+ import { Button } from "../Button/index.js";
4
+ import { useFilterDropdownContext } from "./FilterDropdownContext.js";
5
+ const BUTTON_OWNED_KEYS = new Set([
6
+ 'Enter',
7
+ ' '
8
+ ]);
9
+ const FilterDropdownFooterClear = ({ children, onClick, onKeyDown, 'data-testid': testIdProp, ...props })=>{
10
+ const { clear } = useFilterDropdownContext();
11
+ const testId = useTestId('footer-clear', testIdProp);
12
+ const handleKeyDown = (event)=>{
13
+ onKeyDown?.(event);
14
+ if (BUTTON_OWNED_KEYS.has(event.key)) event.stopPropagation();
15
+ };
16
+ const handleClick = (event)=>{
17
+ onClick?.(event);
18
+ if (event.defaultPrevented) return;
19
+ const content = event.currentTarget.closest('[data-scope="select"][data-part="content"]');
20
+ const search = content?.querySelector('[data-slot="filter-dropdown-search"] input');
21
+ (search ?? content)?.focus({
22
+ preventScroll: true
23
+ });
24
+ clear();
25
+ };
26
+ return /*#__PURE__*/ jsx(Button, {
27
+ ...props,
28
+ "data-slot": "filter-dropdown-footer-clear",
29
+ "data-testid": testId,
30
+ "data-no-autofocus": "",
31
+ variant: "ghost",
32
+ color: "neutral",
33
+ size: "small",
34
+ onClick: handleClick,
35
+ onKeyDown: handleKeyDown,
36
+ children: children ?? 'Clear'
37
+ });
38
+ };
39
+ FilterDropdownFooterClear.displayName = 'FilterDropdownFooterClear';
40
+ export { FilterDropdownFooterClear };
@@ -0,0 +1,5 @@
1
+ import type { ComponentProps, FC } from 'react';
2
+ import { SelectGroup } from '../Select/SelectGroup';
3
+ export type FilterDropdownGroupProps = ComponentProps<typeof SelectGroup>;
4
+ /** A labelled run of options. Render one per entry of `useFilterDropdown().groups`. */
5
+ export declare const FilterDropdownGroup: FC<FilterDropdownGroupProps>;
@@ -0,0 +1,8 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { SelectGroup } from "../Select/SelectGroup.js";
3
+ const FilterDropdownGroup = (props)=>/*#__PURE__*/ jsx(SelectGroup, {
4
+ ...props,
5
+ "data-slot": "filter-dropdown-group"
6
+ });
7
+ FilterDropdownGroup.displayName = 'FilterDropdownGroup';
8
+ export { FilterDropdownGroup };
@@ -0,0 +1,4 @@
1
+ import type { ComponentProps, FC } from 'react';
2
+ import { SelectGroupLabel } from '../Select/SelectGroupLabel';
3
+ export type FilterDropdownGroupLabelProps = ComponentProps<typeof SelectGroupLabel>;
4
+ export declare const FilterDropdownGroupLabel: FC<FilterDropdownGroupLabelProps>;
@@ -0,0 +1,8 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { SelectGroupLabel } from "../Select/SelectGroupLabel.js";
3
+ const FilterDropdownGroupLabel = (props)=>/*#__PURE__*/ jsx(SelectGroupLabel, {
4
+ ...props,
5
+ "data-slot": "filter-dropdown-group-label"
6
+ });
7
+ FilterDropdownGroupLabel.displayName = 'FilterDropdownGroupLabel';
8
+ export { FilterDropdownGroupLabel };
@@ -0,0 +1,15 @@
1
+ import { type ComponentProps, type ReactNode, type Ref } from 'react';
2
+ import type { CollectionItem } from '@ark-ui/react/collection';
3
+ import { SelectOption } from '../Select/SelectOption';
4
+ export interface FilterDropdownOptionProps<T extends CollectionItem = CollectionItem> extends Omit<ComponentProps<typeof SelectOption>, 'item' | 'children'> {
5
+ ref?: Ref<HTMLDivElement>;
6
+ item: T;
7
+ /** Secondary text at the right end of the row, such as a count. */
8
+ hint?: ReactNode;
9
+ /** Row text. Defaults to the item's label from the collection. */
10
+ children?: ReactNode;
11
+ }
12
+ export declare function FilterDropdownOption<T extends CollectionItem>({ item, hint, children, 'data-testid': testIdProp, ...props }: FilterDropdownOptionProps<T>): import("react").JSX.Element;
13
+ export declare namespace FilterDropdownOption {
14
+ var displayName: string;
15
+ }
@@ -0,0 +1,32 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { useContext } from "react";
3
+ import { useTestId } from "../../utils/testId.js";
4
+ import { SelectOption } from "../Select/SelectOption.js";
5
+ import { SelectOptionHint } from "../Select/SelectOptionHint.js";
6
+ import { SelectOptionIndicator } from "../Select/SelectOptionIndicator.js";
7
+ import { SelectOptionText } from "../Select/SelectOptionText.js";
8
+ import { FilterDropdownAliasContext, useFilterDropdownContext } from "./FilterDropdownContext.js";
9
+ const FilterDropdownOption = ({ item, hint, children, 'data-testid': testIdProp, ...props })=>{
10
+ const { collection } = useFilterDropdownContext();
11
+ const alias = useContext(FilterDropdownAliasContext);
12
+ const value = collection.getItemValue(item);
13
+ const isCopy = alias?.source !== void 0 && collection.getItemValue(alias.source) === value;
14
+ const copyTestId = useTestId('selected-option');
15
+ return /*#__PURE__*/ jsxs(SelectOption, {
16
+ ...props,
17
+ item: isCopy && alias ? alias : item,
18
+ "data-slot": "filter-dropdown-option",
19
+ "data-testid": testIdProp ?? (isCopy ? copyTestId : void 0),
20
+ children: [
21
+ /*#__PURE__*/ jsx(SelectOptionText, {
22
+ children: children ?? collection.stringifyItem(item)
23
+ }),
24
+ null != hint && /*#__PURE__*/ jsx(SelectOptionHint, {
25
+ children: hint
26
+ }),
27
+ /*#__PURE__*/ jsx(SelectOptionIndicator, {})
28
+ ]
29
+ });
30
+ };
31
+ FilterDropdownOption.displayName = 'FilterDropdownOption';
32
+ export { FilterDropdownOption };
@@ -0,0 +1,12 @@
1
+ import type { FC } from 'react';
2
+ import { type TestableProps } from '../../utils/testId';
3
+ import { type SelectSearchInputProps } from '../Select/SelectSearchInput';
4
+ export interface FilterDropdownSearchProps extends Omit<SelectSearchInputProps, 'value' | 'onChange' | 'data-testid'>, TestableProps {
5
+ /** Called after the query changes; the root owns the query itself. */
6
+ onChange?: (query: string) => void;
7
+ }
8
+ /**
9
+ * The search field pinned above the list. Renders only once the collection reaches
10
+ * `searchThreshold` items, and takes focus when the menu opens. Attributes land on the `<input>`.
11
+ */
12
+ export declare const FilterDropdownSearch: FC<FilterDropdownSearchProps>;
@@ -0,0 +1,38 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { useSelectContext } from "@ark-ui/react/select";
3
+ import { useTestId } from "../../utils/testId.js";
4
+ import { SelectSearchInput } from "../Select/SelectSearchInput.js";
5
+ import { useFilterDropdownContext } from "./FilterDropdownContext.js";
6
+ const FilterDropdownSearch = ({ onChange, 'aria-label': ariaLabel, 'data-testid': testIdProp, ...props })=>{
7
+ const { label, query, setQuery, isSearchable } = useFilterDropdownContext();
8
+ const testId = useTestId('search', testIdProp);
9
+ const select = useSelectContext();
10
+ if (!isSearchable) return null;
11
+ const handleChange = (next)=>{
12
+ setQuery(next);
13
+ onChange?.(next);
14
+ };
15
+ const highlighted = select.highlightedItem;
16
+ const activeDescendant = highlighted ? select.getItemProps({
17
+ item: highlighted
18
+ }).id : void 0;
19
+ return /*#__PURE__*/ jsx("div", {
20
+ "data-slot": "filter-dropdown-search",
21
+ className: "-mb-3",
22
+ children: /*#__PURE__*/ jsx(SelectSearchInput, {
23
+ "data-autofocus": "",
24
+ role: "combobox",
25
+ "aria-autocomplete": "list",
26
+ "aria-expanded": select.open,
27
+ "aria-controls": select.getContentProps().id,
28
+ "aria-activedescendant": activeDescendant,
29
+ ...props,
30
+ "aria-label": ariaLabel ?? `Search ${label}`,
31
+ value: query,
32
+ onChange: handleChange,
33
+ "data-testid": testId
34
+ })
35
+ });
36
+ };
37
+ FilterDropdownSearch.displayName = 'FilterDropdownSearch';
38
+ export { FilterDropdownSearch };
@@ -0,0 +1,16 @@
1
+ import type { ComponentProps, ReactNode } from 'react';
2
+ import type { CollectionItem } from '@ark-ui/react/collection';
3
+ import { SelectGroup } from '../Select/SelectGroup';
4
+ export interface FilterDropdownSelectedProps<T extends CollectionItem = CollectionItem> extends Omit<ComponentProps<typeof SelectGroup>, 'children'> {
5
+ /** @default 'Selected' */
6
+ label?: ReactNode;
7
+ /**
8
+ * Renders one row; return the same `FilterDropdownOption` as in the list (hint included) and it
9
+ * becomes this row's copy. Defaults to a plain option with the item's label.
10
+ */
11
+ children?: (item: T) => ReactNode;
12
+ }
13
+ export declare function FilterDropdownSelected<T extends CollectionItem>({ label, children, 'data-testid': testIdProp, ...props }: FilterDropdownSelectedProps<T>): import("react").JSX.Element | null;
14
+ export declare namespace FilterDropdownSelected {
15
+ var displayName: string;
16
+ }
@@ -0,0 +1,38 @@
1
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
+ import { useTestId } from "../../utils/testId.js";
3
+ import { SelectGroup } from "../Select/SelectGroup.js";
4
+ import { SelectGroupLabel } from "../Select/SelectGroupLabel.js";
5
+ import { SelectSeparator } from "../Select/SelectSeparator.js";
6
+ import { FilterDropdownAliasContext, useFilterDropdownContext } from "./FilterDropdownContext.js";
7
+ import { FilterDropdownOption } from "./FilterDropdownOption.js";
8
+ const FilterDropdownSelected = ({ label = 'Selected', children, 'data-testid': testIdProp, ...props })=>{
9
+ const { showSelected, aliasItems } = useFilterDropdownContext();
10
+ const testId = useTestId('selected', testIdProp);
11
+ if (!showSelected) return null;
12
+ return /*#__PURE__*/ jsxs(Fragment, {
13
+ children: [
14
+ /*#__PURE__*/ jsxs(SelectGroup, {
15
+ ...props,
16
+ "data-slot": "filter-dropdown-selected",
17
+ "data-testid": testId,
18
+ children: [
19
+ /*#__PURE__*/ jsx(SelectGroupLabel, {
20
+ children: label
21
+ }),
22
+ aliasItems.map((alias)=>{
23
+ const source = alias.source;
24
+ return /*#__PURE__*/ jsx(FilterDropdownAliasContext.Provider, {
25
+ value: alias,
26
+ children: children ? children(source) : /*#__PURE__*/ jsx(FilterDropdownOption, {
27
+ item: source
28
+ })
29
+ }, alias.value);
30
+ })
31
+ ]
32
+ }),
33
+ /*#__PURE__*/ jsx(SelectSeparator, {})
34
+ ]
35
+ });
36
+ };
37
+ FilterDropdownSelected.displayName = 'FilterDropdownSelected';
38
+ export { FilterDropdownSelected };
@@ -0,0 +1,16 @@
1
+ import { type ButtonHTMLAttributes, type FC, type ReactNode, type Ref } from 'react';
2
+ import { type TestableProps } from '../../utils/testId';
3
+ export interface FilterDropdownTriggerProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'children'>, TestableProps {
4
+ ref?: Ref<HTMLButtonElement>;
5
+ /**
6
+ * Only a `<FilterDropdownClear />`, to replace the ✕ rendered in multi mode. The label is
7
+ * derived from the value and is not overridable.
8
+ */
9
+ children?: ReactNode;
10
+ }
11
+ /**
12
+ * The 36px trigger. Dashed while unset, solid once set; reads «All …» / the value in single mode
13
+ * and «Name», «Name • value» or «Name • N» in multi mode. In multi mode Backspace/Delete on the
14
+ * focused trigger clears the filter.
15
+ */
16
+ export declare const FilterDropdownTrigger: FC<FilterDropdownTriggerProps>;