@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,139 @@
1
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
+ import { Children, isValidElement } from "react";
3
+ import { Select } from "@ark-ui/react/select";
4
+ import { cn } from "../../utils/cn.js";
5
+ import { mergeRefs } from "../../utils/mergeRefs.js";
6
+ import { TestIdProvider, useTestId } from "../../utils/testId.js";
7
+ import { NumericBadge } from "../NumericBadge/index.js";
8
+ import { OverflowTooltip, OverflowTooltipContent, OverflowTooltipTrigger } from "../OverflowTooltip/index.js";
9
+ import { SelectArrow } from "../Select/SelectArrow.js";
10
+ import { filterDropdownControlVariants, filterDropdownLabelVariants, filterDropdownTriggerVariants } from "./classes.js";
11
+ import { FilterDropdownClear } from "./FilterDropdownClear.js";
12
+ import { useFilterDropdownContext } from "./FilterDropdownContext.js";
13
+ const CLEAR_KEYS = new Set([
14
+ 'Backspace',
15
+ 'Delete'
16
+ ]);
17
+ const TruncatedText = ({ text, emphasis, className })=>/*#__PURE__*/ jsx(TestIdProvider, {
18
+ value: void 0,
19
+ children: /*#__PURE__*/ jsxs(OverflowTooltip, {
20
+ children: [
21
+ /*#__PURE__*/ jsx(OverflowTooltipTrigger, {
22
+ children: /*#__PURE__*/ jsx("span", {
23
+ className: cn(filterDropdownLabelVariants({
24
+ emphasis
25
+ }), className),
26
+ children: text
27
+ })
28
+ }),
29
+ /*#__PURE__*/ jsx(OverflowTooltipContent, {
30
+ children: text
31
+ })
32
+ ]
33
+ })
34
+ });
35
+ const Separator = ()=>/*#__PURE__*/ jsx("span", {
36
+ "aria-hidden": true,
37
+ className: "shrink-0 text-xs text-text-tertiary",
38
+ children: "•"
39
+ });
40
+ const FilterDropdownTrigger = ({ ref, className, children, onKeyDown, 'aria-label': ariaLabel, 'data-testid': testIdProp, ...props })=>{
41
+ const { label, allLabel, multiple, value, collection, clear, triggerRef } = useFilterDropdownContext();
42
+ const controlTestId = useTestId('control');
43
+ const testId = useTestId('trigger', testIdProp);
44
+ const isSet = value.length > 0;
45
+ const clearable = multiple && isSet;
46
+ const labels = value.map((v)=>collection.stringify(v) ?? v);
47
+ const customClear = Children.toArray(children).find((child)=>/*#__PURE__*/ isValidElement(child) && child.type === FilterDropdownClear);
48
+ const handleKeyDown = (event)=>{
49
+ onKeyDown?.(event);
50
+ if (event.defaultPrevented || !clearable || !CLEAR_KEYS.has(event.key)) return;
51
+ event.preventDefault();
52
+ clear();
53
+ };
54
+ let content;
55
+ let composedLabel = label;
56
+ if (multiple) if (isSet) if (1 === value.length) {
57
+ content = /*#__PURE__*/ jsxs(Fragment, {
58
+ children: [
59
+ /*#__PURE__*/ jsx(TruncatedText, {
60
+ text: label,
61
+ emphasis: "name"
62
+ }),
63
+ /*#__PURE__*/ jsx(Separator, {}),
64
+ /*#__PURE__*/ jsx(TruncatedText, {
65
+ text: labels[0] ?? '',
66
+ emphasis: "value",
67
+ className: "min-w-24"
68
+ })
69
+ ]
70
+ });
71
+ composedLabel = `${label}, ${labels[0]}`;
72
+ } else {
73
+ content = /*#__PURE__*/ jsxs(Fragment, {
74
+ children: [
75
+ /*#__PURE__*/ jsx(TruncatedText, {
76
+ text: label,
77
+ emphasis: "name"
78
+ }),
79
+ /*#__PURE__*/ jsx(Separator, {}),
80
+ /*#__PURE__*/ jsx("span", {
81
+ "aria-hidden": true,
82
+ className: "inline-flex shrink-0",
83
+ children: /*#__PURE__*/ jsx(NumericBadge, {
84
+ type: "primary",
85
+ children: value.length
86
+ })
87
+ })
88
+ ]
89
+ });
90
+ composedLabel = `${label}, ${value.length} selected: ${labels.join(', ')}`;
91
+ }
92
+ else content = /*#__PURE__*/ jsx(TruncatedText, {
93
+ text: label,
94
+ emphasis: "name"
95
+ });
96
+ else {
97
+ content = isSet ? /*#__PURE__*/ jsx(TruncatedText, {
98
+ text: labels[0] ?? '',
99
+ emphasis: "value"
100
+ }) : /*#__PURE__*/ jsx(TruncatedText, {
101
+ text: allLabel,
102
+ emphasis: "name"
103
+ });
104
+ if (isSet) composedLabel = `${label}, ${labels[0]}`;
105
+ }
106
+ return /*#__PURE__*/ jsxs(Select.Control, {
107
+ "data-slot": "filter-dropdown-control",
108
+ "data-testid": controlTestId,
109
+ className: filterDropdownControlVariants({
110
+ applied: isSet,
111
+ clearable
112
+ }),
113
+ children: [
114
+ /*#__PURE__*/ jsxs(Select.Trigger, {
115
+ ...props,
116
+ ref: mergeRefs(ref, triggerRef),
117
+ "data-slot": "filter-dropdown-trigger",
118
+ "data-testid": testId,
119
+ "aria-label": ariaLabel ?? composedLabel,
120
+ onKeyDown: handleKeyDown,
121
+ className: cn(filterDropdownTriggerVariants({
122
+ clearable
123
+ }), className),
124
+ children: [
125
+ /*#__PURE__*/ jsx("span", {
126
+ className: "flex min-w-0 items-center gap-4 overflow-hidden",
127
+ children: content
128
+ }),
129
+ !clearable && /*#__PURE__*/ jsx(SelectArrow, {
130
+ className: "text-icon-primary"
131
+ })
132
+ ]
133
+ }),
134
+ customClear ?? /*#__PURE__*/ jsx(FilterDropdownClear, {})
135
+ ]
136
+ });
137
+ };
138
+ FilterDropdownTrigger.displayName = 'FilterDropdownTrigger';
139
+ export { FilterDropdownTrigger };
@@ -0,0 +1,16 @@
1
+ /**
2
+ * The pill that holds the trigger and, when a multi filter is set, the ✕. It owns the border,
3
+ * surface and state overlays so the two buttons read as one control (Figma `filter-dropdown`).
4
+ */
5
+ export declare const filterDropdownControlVariants: (props?: ({
6
+ applied?: boolean | null | undefined;
7
+ clearable?: boolean | null | undefined;
8
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
9
+ export declare const filterDropdownTriggerVariants: (props?: ({
10
+ clearable?: boolean | null | undefined;
11
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
12
+ export declare const filterDropdownLabelVariants: (props?: ({
13
+ emphasis?: "name" | "value" | null | undefined;
14
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
15
+ export declare const filterDropdownClearClassName: string;
16
+ export declare const filterDropdownContentClassName: string;
@@ -0,0 +1,43 @@
1
+ import { cva } from "class-variance-authority";
2
+ import { cn } from "../../utils/cn.js";
3
+ const filterDropdownControlVariants = cva(cn('inline-flex h-36 min-w-0 max-w-180 items-stretch', 'rounded-12 border-1 border-border-primary bg-component-outline-button-bg', 'font-sans text-sm text-text-primary', 'overlay hover:not-data-disabled:overlay-states-primary-hover', 'active:not-data-disabled:overlay-states-primary-pressed data-[state=open]:overlay-states-primary-pressed', 'transition-[border,box-shadow,opacity]', 'has-[[data-slot=filter-dropdown-trigger]:focus-visible]:ring-3 has-[[data-slot=filter-dropdown-trigger]:focus-visible]:ring-focus-primary', 'data-disabled:opacity-50 data-disabled:cursor-not-allowed'), {
4
+ variants: {
5
+ applied: {
6
+ true: 'border-solid shadow-2xs has-[[data-slot=filter-dropdown-trigger]:focus-visible]:shadow-none',
7
+ false: 'border-dashed'
8
+ },
9
+ clearable: {
10
+ true: 'pr-6',
11
+ false: ''
12
+ }
13
+ },
14
+ defaultVariants: {
15
+ applied: false,
16
+ clearable: false
17
+ }
18
+ });
19
+ const filterDropdownTriggerVariants = cva(cn('flex min-w-0 flex-1 items-center gap-8 py-8 pl-16', 'cursor-pointer outline-none disabled:cursor-not-allowed', '[&_svg]:pointer-events-none [&_svg]:shrink-0'), {
20
+ variants: {
21
+ clearable: {
22
+ true: 'pr-4',
23
+ false: 'pr-10'
24
+ }
25
+ },
26
+ defaultVariants: {
27
+ clearable: false
28
+ }
29
+ });
30
+ const filterDropdownLabelVariants = cva('min-w-0 truncate', {
31
+ variants: {
32
+ emphasis: {
33
+ value: 'font-medium',
34
+ name: 'font-normal'
35
+ }
36
+ },
37
+ defaultVariants: {
38
+ emphasis: 'name'
39
+ }
40
+ });
41
+ const filterDropdownClearClassName = cn('inline-flex size-24 shrink-0 items-center justify-center self-center rounded-6', 'cursor-pointer text-icon-secondary transition-colors hover:not-disabled:text-icon-primary', 'outline-none focus-visible:ring-3 focus-visible:ring-focus-primary', 'disabled:cursor-not-allowed [&_svg]:icon-md [&_svg]:pointer-events-none');
42
+ const filterDropdownContentClassName = cn('min-w-128 max-w-360', 'max-h-[min(340px,var(--available-height))]');
43
+ export { filterDropdownClearClassName, filterDropdownContentClassName, filterDropdownControlVariants, filterDropdownLabelVariants, filterDropdownTriggerVariants };
@@ -0,0 +1,15 @@
1
+ export { filterDropdownControlVariants, filterDropdownTriggerVariants } from './classes';
2
+ export { FilterDropdown, type FilterDropdownOpenChangeDetails, type FilterDropdownProps, type FilterDropdownValueChangeDetails, } from './FilterDropdown';
3
+ export { FilterDropdownAllOption, type FilterDropdownAllOptionProps, } from './FilterDropdownAllOption';
4
+ export { FilterDropdownClear, type FilterDropdownClearProps } from './FilterDropdownClear';
5
+ export { FilterDropdownContent, type FilterDropdownContentProps } from './FilterDropdownContent';
6
+ export { type UseFilterDropdownResult, useFilterDropdown } from './FilterDropdownContext';
7
+ export { FilterDropdownEmpty, type FilterDropdownEmptyProps } from './FilterDropdownEmpty';
8
+ export { FilterDropdownFooter, type FilterDropdownFooterProps } from './FilterDropdownFooter';
9
+ export { FilterDropdownFooterClear, type FilterDropdownFooterClearProps, } from './FilterDropdownFooterClear';
10
+ export { FilterDropdownGroup, type FilterDropdownGroupProps } from './FilterDropdownGroup';
11
+ export { FilterDropdownGroupLabel, type FilterDropdownGroupLabelProps, } from './FilterDropdownGroupLabel';
12
+ export { FilterDropdownOption, type FilterDropdownOptionProps } from './FilterDropdownOption';
13
+ export { FilterDropdownSearch, type FilterDropdownSearchProps } from './FilterDropdownSearch';
14
+ export { FilterDropdownSelected, type FilterDropdownSelectedProps } from './FilterDropdownSelected';
15
+ export { FilterDropdownTrigger, type FilterDropdownTriggerProps } from './FilterDropdownTrigger';
@@ -0,0 +1,15 @@
1
+ export { filterDropdownControlVariants, filterDropdownTriggerVariants } from "./classes.js";
2
+ export { FilterDropdown } from "./FilterDropdown.js";
3
+ export { FilterDropdownAllOption } from "./FilterDropdownAllOption.js";
4
+ export { FilterDropdownClear } from "./FilterDropdownClear.js";
5
+ export { FilterDropdownContent } from "./FilterDropdownContent.js";
6
+ export { useFilterDropdown } from "./FilterDropdownContext.js";
7
+ export { FilterDropdownEmpty } from "./FilterDropdownEmpty.js";
8
+ export { FilterDropdownFooter } from "./FilterDropdownFooter.js";
9
+ export { FilterDropdownFooterClear } from "./FilterDropdownFooterClear.js";
10
+ export { FilterDropdownGroup } from "./FilterDropdownGroup.js";
11
+ export { FilterDropdownGroupLabel } from "./FilterDropdownGroupLabel.js";
12
+ export { FilterDropdownOption } from "./FilterDropdownOption.js";
13
+ export { FilterDropdownSearch } from "./FilterDropdownSearch.js";
14
+ export { FilterDropdownSelected } from "./FilterDropdownSelected.js";
15
+ export { FilterDropdownTrigger } from "./FilterDropdownTrigger.js";
@@ -0,0 +1 @@
1
+ export { ALL_VALUE, createAliasItem, createAllItem, type FilterDropdownSpecialItem, isAliasValue, isSpecialItem, SELECTED_PREFIX, toAliasValue, toBaseValue, toConsumerValue, toInternalValue, } from './values';
@@ -0,0 +1 @@
1
+ export { ALL_VALUE, SELECTED_PREFIX, createAliasItem, createAllItem, isAliasValue, isSpecialItem, toAliasValue, toBaseValue, toConsumerValue, toInternalValue } from "./values.js";
@@ -0,0 +1,59 @@
1
+ import type { CollectionItem, ListCollection } from '@ark-ui/react/collection';
2
+ /**
3
+ * Value of the single-mode «All …» option inside Ark. The consumer never sees it: it maps to `[]`.
4
+ */
5
+ export declare const ALL_VALUE = "__all__";
6
+ /**
7
+ * Prefix of the alias values that back the rows of the multi-mode "Selected" section. Ark keys
8
+ * items by value, so a row rendered twice needs a second value; the root strips the prefix before
9
+ * anything reaches the consumer.
10
+ */
11
+ export declare const SELECTED_PREFIX = "__selected__:";
12
+ declare const SPECIAL: unique symbol;
13
+ /** An item that exists only inside the Ark collection: the «All» sentinel or a "Selected" alias. */
14
+ export interface FilterDropdownSpecialItem<T extends CollectionItem = CollectionItem> {
15
+ readonly [SPECIAL]: true;
16
+ readonly value: string;
17
+ readonly label: string;
18
+ /** The base item an alias duplicates; absent on the «All» sentinel. */
19
+ readonly source?: T;
20
+ }
21
+ export declare const isSpecialItem: (item: unknown) => item is FilterDropdownSpecialItem;
22
+ export declare const toAliasValue: (value: string) => string;
23
+ export declare const isAliasValue: (value: string) => boolean;
24
+ export declare const toBaseValue: (value: string) => string;
25
+ export declare const createAllItem: (label: string) => FilterDropdownSpecialItem;
26
+ export declare const createAliasItem: <T extends CollectionItem>(item: T, collection: ListCollection<T>) => FilterDropdownSpecialItem<T>;
27
+ interface ToInternalValueOptions {
28
+ multiple: boolean;
29
+ /** Base values that currently have an alias row in the "Selected" section. */
30
+ aliased: ReadonlySet<string>;
31
+ /**
32
+ * Single mode: the «All» row is in the collection. Without it an unset value stays `[]`, so Ark
33
+ * never selects or highlights a value it cannot find.
34
+ * @default true
35
+ */
36
+ hasAll?: boolean;
37
+ }
38
+ /**
39
+ * Consumer value → the value handed to Ark.
40
+ * - single: `[]` becomes the «All» sentinel, so «All» shows as picked;
41
+ * - multi: every picked value that has an alias row is doubled with its alias, so the copy in
42
+ * "Selected" and the original in the list tick together.
43
+ */
44
+ export declare const toInternalValue: (value: readonly string[], { multiple, aliased, hasAll }: ToInternalValueOptions) => string[];
45
+ interface ToConsumerValueOptions {
46
+ multiple: boolean;
47
+ /** The internal value Ark had before this change. */
48
+ previousInternal: readonly string[];
49
+ /** The consumer value before this change. */
50
+ previousValue: readonly string[];
51
+ }
52
+ /**
53
+ * Ark's next value → consumer value. Never returns the sentinel or an alias.
54
+ * - single: the sentinel (or nothing) becomes `[]`;
55
+ * - multi: Ark only ever toggles, so the change is read as a diff against what Ark had — an alias
56
+ * toggles its base value, which is how unticking a copy in "Selected" unticks the original.
57
+ */
58
+ export declare const toConsumerValue: (next: readonly string[], { multiple, previousInternal, previousValue }: ToConsumerValueOptions) => string[];
59
+ export {};
@@ -0,0 +1,58 @@
1
+ const ALL_VALUE = '__all__';
2
+ const SELECTED_PREFIX = '__selected__:';
3
+ const SPECIAL = Symbol('filter-dropdown-special-item');
4
+ const isSpecialItem = (item)=>'object' == typeof item && null !== item && SPECIAL in item;
5
+ const toAliasValue = (value)=>`${SELECTED_PREFIX}${value}`;
6
+ const isAliasValue = (value)=>value.startsWith(SELECTED_PREFIX);
7
+ const toBaseValue = (value)=>isAliasValue(value) ? value.slice(SELECTED_PREFIX.length) : value;
8
+ const createAllItem = (label)=>({
9
+ [SPECIAL]: true,
10
+ value: ALL_VALUE,
11
+ label
12
+ });
13
+ const createAliasItem = (item, collection)=>({
14
+ [SPECIAL]: true,
15
+ value: toAliasValue(collection.getItemValue(item) ?? ''),
16
+ label: collection.stringifyItem(item) ?? '',
17
+ source: item
18
+ });
19
+ const toInternalValue = (value, { multiple, aliased, hasAll = true })=>{
20
+ if (!multiple) {
21
+ const [first] = value;
22
+ if (void 0 === first) return hasAll ? [
23
+ ALL_VALUE
24
+ ] : [];
25
+ return [
26
+ first
27
+ ];
28
+ }
29
+ return [
30
+ ...value,
31
+ ...value.filter((v)=>aliased.has(v)).map(toAliasValue)
32
+ ];
33
+ };
34
+ const toConsumerValue = (next, { multiple, previousInternal, previousValue })=>{
35
+ if (!multiple) {
36
+ const [first] = next;
37
+ return void 0 === first || first === ALL_VALUE ? [] : [
38
+ toBaseValue(first)
39
+ ];
40
+ }
41
+ const before = new Set(previousInternal);
42
+ const after = new Set(next);
43
+ let result = [
44
+ ...previousValue
45
+ ];
46
+ for (const v of next){
47
+ if (before.has(v) || v === ALL_VALUE) continue;
48
+ const base = toBaseValue(v);
49
+ if (!result.includes(base)) result.push(base);
50
+ }
51
+ for (const v of previousInternal){
52
+ if (after.has(v)) continue;
53
+ const base = toBaseValue(v);
54
+ result = result.filter((r)=>r !== base);
55
+ }
56
+ return result;
57
+ };
58
+ export { ALL_VALUE, SELECTED_PREFIX, createAliasItem, createAllItem, isAliasValue, isSpecialItem, toAliasValue, toBaseValue, toConsumerValue, toInternalValue };
@@ -10,7 +10,7 @@ export interface NavRailItemProps extends AnchorHTMLAttributes<HTMLAnchorElement
10
10
  active?: boolean;
11
11
  /** Seats the icon on a soft plate, for the signed-in user's item at the foot of the rail. */
12
12
  avatar?: boolean;
13
- /** User photo for the plate (implies `avatar`). The icon stays underneath and returns if the photo fails to load. */
13
+ /** User photo for the plate (implies `avatar`). The icon shows while it loads and if it fails. */
14
14
  avatarSrc?: string;
15
15
  }
16
16
  export declare const NavRailItem: FC<NavRailItemProps>;
@@ -1,9 +1,10 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
- import { Fragment, useRef, useState } from "react";
2
+ import { Fragment, useRef } from "react";
3
3
  import { composeRefs } from "@radix-ui/react-compose-refs";
4
4
  import { Slot, Slottable } from "@radix-ui/react-slot";
5
5
  import { cn } from "../../utils/cn.js";
6
6
  import { useTestId } from "../../utils/testId.js";
7
+ import { Avatar, AvatarFallback, AvatarImage } from "../Avatar/index.js";
7
8
  import { Kbd } from "../Kbd/index.js";
8
9
  import { Tooltip } from "../Tooltip/index.js";
9
10
  import { TooltipContent } from "../Tooltip/TooltipContent.js";
@@ -16,8 +17,6 @@ const NavRailItem = ({ ref, asChild = false, icon: Icon, label, shortcut, active
16
17
  const testId = useTestId('item', testIdProp);
17
18
  const Comp = asChild ? Slot : 'a';
18
19
  const internalRef = useRef(null);
19
- const [failedSrc, setFailedSrc] = useState();
20
- const photo = avatarSrc && avatarSrc !== failedSrc ? avatarSrc : void 0;
21
20
  const hasPlate = avatar || void 0 !== avatarSrc;
22
21
  const showsLabel = 'expanded' === mode || 'compact' === mode && !hasPlate;
23
22
  const fallbackName = showsLabel || 'string' != typeof label ? void 0 : label;
@@ -37,18 +36,16 @@ const NavRailItem = ({ ref, asChild = false, icon: Icon, label, shortcut, active
37
36
  children: [
38
37
  /*#__PURE__*/ jsx("span", {
39
38
  className: "flex shrink-0 items-center justify-center",
40
- children: hasPlate ? /*#__PURE__*/ jsxs("span", {
39
+ children: hasPlate ? /*#__PURE__*/ jsxs(Avatar, {
40
+ size: "xs",
41
41
  "data-slot": "nav-rail-item-avatar",
42
- className: cn('-m-4 grid size-24 place-items-center overflow-hidden rounded-8 bg-states-primary-hover branded:bg-states-brand-hover branded:text-icon-brand *:col-start-1 *:row-start-1', !photo && 'border border-border-primary branded:border-border-brand'),
42
+ className: "-m-4",
43
43
  children: [
44
- /*#__PURE__*/ jsx(Icon, {
45
- size: "md"
44
+ /*#__PURE__*/ jsx(AvatarImage, {
45
+ src: avatarSrc
46
46
  }),
47
- photo && /*#__PURE__*/ jsx("img", {
48
- src: photo,
49
- alt: "",
50
- className: "size-full object-cover",
51
- onError: ()=>setFailedSrc(photo)
47
+ /*#__PURE__*/ jsx(AvatarFallback, {
48
+ icon: Icon
52
49
  })
53
50
  ]
54
51
  }) : /*#__PURE__*/ jsx(Icon, {
@@ -6,7 +6,7 @@ export interface SelectBaseProps {
6
6
  /** Override default floating positioning (merged with DS defaults). */
7
7
  positioning?: SelectRootProps<CollectionItem>['positioning'];
8
8
  }
9
- type SelectProps<T extends CollectionItem> = SelectNativeProps<T> & SelectBaseProps & TestableProps;
9
+ export type SelectProps<T extends CollectionItem> = SelectNativeProps<T> & SelectBaseProps & TestableProps;
10
10
  export declare function Select<T extends CollectionItem>({ children, loading, disabled, positioning: positioningOverride, 'data-testid': testId, ...props }: SelectProps<T>): import("react").JSX.Element;
11
11
  export declare namespace Select {
12
12
  var displayName: string;
@@ -1,5 +1,6 @@
1
1
  import { type FC } from 'react';
2
2
  import { Select as ArkUiSelect } from '@ark-ui/react/select';
3
- type SelectContentProps = Omit<ArkUiSelect.ContentProps, 'className'>;
3
+ import { type TestableProps } from '../../utils/testId';
4
+ type SelectContentProps = Omit<ArkUiSelect.ContentProps, 'className'> & TestableProps;
4
5
  export declare const SelectContent: FC<SelectContentProps>;
5
6
  export {};
@@ -5,8 +5,8 @@ import { cn } from "../../utils/cn.js";
5
5
  import { useTestId } from "../../utils/testId.js";
6
6
  import { ScrollArea, ScrollAreaContent, ScrollAreaCorner, ScrollAreaScrollbar, ScrollAreaViewport } from "../ScrollArea/index.js";
7
7
  import { SelectEmptyState } from "./SelectEmptyState.js";
8
- const SelectContent = ({ children, ...props })=>{
9
- const testId = useTestId('content');
8
+ const SelectContent = ({ children, 'data-testid': testIdProp, ...props })=>{
9
+ const testId = useTestId('content', testIdProp);
10
10
  const isEmpty = 0 === Children.count(children);
11
11
  return /*#__PURE__*/ jsx(Select.List, {
12
12
  ...props,
@@ -16,6 +16,7 @@ const SelectContent = ({ children, ...props })=>{
16
16
  children: /*#__PURE__*/ jsxs(ScrollArea, {
17
17
  children: [
18
18
  /*#__PURE__*/ jsx(ScrollAreaViewport, {
19
+ "data-no-autofocus": "",
19
20
  children: /*#__PURE__*/ jsx(ScrollAreaContent, {
20
21
  className: "flex flex-col gap-1",
21
22
  children: isEmpty ? /*#__PURE__*/ jsx(SelectEmptyState, {}) : children
@@ -1,5 +1,6 @@
1
1
  import type { FC, ReactNode } from 'react';
2
2
  export interface SelectEmptyStateProps {
3
3
  description?: ReactNode;
4
+ className?: string;
4
5
  }
5
6
  export declare const SelectEmptyState: FC<SelectEmptyStateProps>;
@@ -1,7 +1,8 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import { EmptyState, EmptyStateDescription, EmptyStateMessage } from "../EmptyState/index.js";
3
- const SelectEmptyState = ({ description = 'No results' })=>/*#__PURE__*/ jsx(EmptyState, {
3
+ const SelectEmptyState = ({ description = 'No results', className })=>/*#__PURE__*/ jsx(EmptyState, {
4
4
  type: "no-results",
5
+ className: className,
5
6
  children: /*#__PURE__*/ jsx(EmptyStateMessage, {
6
7
  children: /*#__PURE__*/ jsx(EmptyStateDescription, {
7
8
  children: description
@@ -1,3 +1,8 @@
1
- import type { FC, HTMLAttributes } from 'react';
2
- export type SelectFooterProps = Omit<HTMLAttributes<HTMLDivElement>, 'className'>;
1
+ import type { FC, HTMLAttributes, Ref } from 'react';
2
+ import type { VariantProps } from 'class-variance-authority';
3
+ import { type TestableProps } from '../../utils/testId';
4
+ import { selectFooterVariants } from './classes';
5
+ export type SelectFooterProps = Omit<HTMLAttributes<HTMLDivElement>, 'className'> & VariantProps<typeof selectFooterVariants> & TestableProps & {
6
+ ref?: Ref<HTMLDivElement>;
7
+ };
3
8
  export declare const SelectFooter: FC<SelectFooterProps>;
@@ -1,12 +1,15 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import { cn } from "../../utils/cn.js";
3
3
  import { useTestId } from "../../utils/testId.js";
4
- const SelectFooter = (props)=>{
5
- const testId = useTestId('footer');
4
+ import { selectFooterVariants } from "./classes.js";
5
+ const SelectFooter = ({ variant = 'default', 'data-testid': testIdProp, ...props })=>{
6
+ const testId = useTestId('footer', testIdProp);
6
7
  return /*#__PURE__*/ jsx("div", {
7
8
  ...props,
8
9
  "data-testid": testId,
9
- className: cn('bg-component-outline-button-bg py-8 px-16 shrink-0 border-t border-border-primary')
10
+ className: cn(selectFooterVariants({
11
+ variant
12
+ }))
10
13
  });
11
14
  };
12
15
  SelectFooter.displayName = 'SelectFooter';
@@ -1,2 +1,8 @@
1
- import type { FC, PropsWithChildren } from 'react';
2
- export declare const SelectGroup: FC<PropsWithChildren>;
1
+ import type { FC, Ref } from 'react';
2
+ import { Select as ArkUiSelect } from '@ark-ui/react/select';
3
+ import { type TestableProps } from '../../utils/testId';
4
+ type SelectGroupProps = Omit<ArkUiSelect.ItemGroupProps, 'className'> & TestableProps & {
5
+ ref?: Ref<HTMLDivElement>;
6
+ };
7
+ export declare const SelectGroup: FC<SelectGroupProps>;
8
+ export {};
@@ -2,9 +2,10 @@ import { jsx } from "react/jsx-runtime";
2
2
  import { Select } from "@ark-ui/react/select";
3
3
  import { cn } from "../../utils/cn.js";
4
4
  import { useTestId } from "../../utils/testId.js";
5
- const SelectGroup = ({ children })=>{
6
- const testId = useTestId('group');
5
+ const SelectGroup = ({ children, 'data-testid': testIdProp, ...props })=>{
6
+ const testId = useTestId('group', testIdProp);
7
7
  return /*#__PURE__*/ jsx(Select.ItemGroup, {
8
+ ...props,
8
9
  "data-testid": testId,
9
10
  className: cn('flex flex-col gap-1'),
10
11
  children: children
@@ -1,5 +1,8 @@
1
- import type { FC } from 'react';
1
+ import type { FC, Ref } from 'react';
2
2
  import { Select as ArkUiSelect } from '@ark-ui/react/select';
3
- type SelectGroupLabelProps = ArkUiSelect.ItemGroupLabelProps;
3
+ import { type TestableProps } from '../../utils/testId';
4
+ type SelectGroupLabelProps = ArkUiSelect.ItemGroupLabelProps & TestableProps & {
5
+ ref?: Ref<HTMLDivElement>;
6
+ };
4
7
  export declare const SelectGroupLabel: FC<SelectGroupLabelProps>;
5
8
  export {};
@@ -3,8 +3,8 @@ import { Select } from "@ark-ui/react/select";
3
3
  import { cn } from "../../utils/cn.js";
4
4
  import { useTestId } from "../../utils/testId.js";
5
5
  import { dropdownMenuLabelVariants } from "../DropdownMenu/index.js";
6
- const SelectGroupLabel = (props)=>{
7
- const testId = useTestId('group-label');
6
+ const SelectGroupLabel = ({ 'data-testid': testIdProp, ...props })=>{
7
+ const testId = useTestId('group-label', testIdProp);
8
8
  return /*#__PURE__*/ jsx(Select.ItemGroupLabel, {
9
9
  ...props,
10
10
  "data-testid": testId,
@@ -12,7 +12,7 @@ const SelectOption = ({ variant = 'default', 'data-testid': testIdProp, ...props
12
12
  className: cn(dropdownMenuItemVariants({
13
13
  variant,
14
14
  inset: false
15
- }), 'flex-wrap relative gap-y-0 gap-x-8 pr-32', 'data-[state=checked]:bg-states-primary-active', 'data-highlighted:bg-states-primary-hover')
15
+ }), 'flex-wrap relative gap-y-0 gap-x-8 pr-32', 'has-[>[data-slot=select-option-hint]]:flex-nowrap', 'data-[state=checked]:bg-states-primary-active', 'data-highlighted:bg-states-primary-hover')
16
16
  });
17
17
  };
18
18
  SelectOption.displayName = 'SelectOption';
@@ -0,0 +1,11 @@
1
+ import type { FC, HTMLAttributes, Ref } from 'react';
2
+ import { type TestableProps } from '../../utils/testId';
3
+ export interface SelectOptionHintProps extends HTMLAttributes<HTMLSpanElement>, TestableProps {
4
+ ref?: Ref<HTMLSpanElement>;
5
+ }
6
+ /**
7
+ * Secondary text at the right end of an option, such as a count. It sits before the indicator
8
+ * rather than under it: the option stops wrapping while a hint is present, so the label wraps
9
+ * inside its own box and the hint keeps its place on the first line.
10
+ */
11
+ export declare const SelectOptionHint: FC<SelectOptionHintProps>;
@@ -0,0 +1,15 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { cn } from "../../utils/cn.js";
3
+ import { useTestId } from "../../utils/testId.js";
4
+ const SelectOptionHint = ({ ref, className, 'data-testid': testIdProp, ...props })=>{
5
+ const testId = useTestId('option-hint', testIdProp);
6
+ return /*#__PURE__*/ jsx("span", {
7
+ ...props,
8
+ ref: ref,
9
+ "data-slot": "select-option-hint",
10
+ "data-testid": testId,
11
+ className: cn('ml-auto shrink-0 self-start font-sans text-sm text-text-secondary tabular-nums', className)
12
+ });
13
+ };
14
+ SelectOptionHint.displayName = 'SelectOptionHint';
15
+ export { SelectOptionHint };
@@ -1,5 +1,15 @@
1
- import type { FC } from 'react';
1
+ import type { FC, Ref } from 'react';
2
2
  import { Select as ArkUiSelect } from '@ark-ui/react/select';
3
- type SelectPositionerProps = ArkUiSelect.PositionerProps;
3
+ export interface SelectPositionerProps extends ArkUiSelect.PositionerProps {
4
+ /**
5
+ * Props for the content element (the `listbox` panel inside the positioner) — for a ref, an
6
+ * inline measurement such as a locked width, or `data-*` attributes. `className` on the
7
+ * positioner itself already lands on the content, and overrides its default sizes
8
+ * (`min-w-240 max-w-320 max-h-(--available-height)`) through tailwind-merge.
9
+ */
10
+ contentProps?: Omit<ArkUiSelect.ContentProps, 'className' | 'children' | 'asChild'> & {
11
+ ref?: Ref<HTMLDivElement>;
12
+ [dataAttribute: `data-${string}`]: string | undefined;
13
+ };
14
+ }
4
15
  export declare const SelectPositioner: FC<SelectPositionerProps>;
5
- export {};
@@ -3,11 +3,12 @@ import { Portal } from "@ark-ui/react/portal";
3
3
  import { Select } from "@ark-ui/react/select";
4
4
  import { cn } from "../../utils/cn.js";
5
5
  import { dropdownMenuClassNames } from "../DropdownMenu/index.js";
6
- const SelectPositioner = ({ className, children, ...props })=>/*#__PURE__*/ jsx(Portal, {
6
+ const SelectPositioner = ({ className, children, contentProps, ...props })=>/*#__PURE__*/ jsx(Portal, {
7
7
  children: /*#__PURE__*/ jsx(Select.Positioner, {
8
8
  ...props,
9
9
  className: "outline-none",
10
10
  children: /*#__PURE__*/ jsx(Select.Content, {
11
+ ...contentProps,
11
12
  className: cn(dropdownMenuClassNames, 'flex flex-col', 'h-full', 'min-w-240', 'max-w-320', 'max-h-(--available-height)', 'p-0', 'origin-[--transform-origin]', className),
12
13
  children: children
13
14
  })