@wallarm-org/design-system 0.86.0 → 0.87.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,12 +1,11 @@
1
- import { jsx, jsxs } from "react/jsx-runtime";
1
+ import { jsx } from "react/jsx-runtime";
2
2
  import { useMemo } from "react";
3
3
  import { Popover, usePopoverContext } from "@ark-ui/react";
4
4
  import { Portal } from "@ark-ui/react/portal";
5
5
  import { cn } from "../../utils/cn.js";
6
6
  import { useTestId } from "../../utils/testId.js";
7
- import { ScrollArea, ScrollAreaContent, ScrollAreaScrollbar, ScrollAreaViewport } from "../ScrollArea/index.js";
8
- import { POPOVER_MAX_HEIGHT, POPOVER_MAX_WIDTH, POPOVER_MIN_HEIGHT, POPOVER_MIN_WIDTH } from "./constants.js";
9
- const PopoverContent = ({ children, minHeight = POPOVER_MIN_HEIGHT, maxHeight = POPOVER_MAX_HEIGHT, minWidth = POPOVER_MIN_WIDTH, maxWidth = POPOVER_MAX_WIDTH, className, 'data-testid': testIdProp, ...rest })=>{
7
+ import { POPOVER_MAX_HEIGHT, POPOVER_MAX_WIDTH, POPOVER_MIN_WIDTH } from "./constants.js";
8
+ const PopoverContent = ({ children, minHeight, maxHeight = POPOVER_MAX_HEIGHT, minWidth = POPOVER_MIN_WIDTH, maxWidth = POPOVER_MAX_WIDTH, className, 'data-testid': testIdProp, ...rest })=>{
10
9
  const testId = useTestId('content', testIdProp);
11
10
  const { getContentProps } = usePopoverContext();
12
11
  const { id } = getContentProps();
@@ -28,21 +27,8 @@ const PopoverContent = ({ children, minHeight = POPOVER_MIN_HEIGHT, maxHeight =
28
27
  id: id,
29
28
  "data-testid": testId,
30
29
  style: style,
31
- className: cn('flex flex-col', 'min-w-(--popover-min-width)', 'max-w-[clamp(var(--popover-min-width),var(--available-width),var(--popover-max-width))]', 'min-h-(--popover-min-height)', 'max-h-[clamp(var(--popover-min-height),var(--available-height),var(--popover-max-height))]', 'p-12 bg-bg-surface-2 rounded-12 border border-border-primary-light shadow-md text-text-primary', 'z-[calc(var(--drawer-positioner-z-index)+(var(--layer-index,0)*var(--drawer-level-ratio)))]', '[&_[data-part=viewport]]:overscroll-contain', 'animate-in fade-in-0 zoom-in-95 origin-[--radix-tooltip-content-transform-origin]', 'data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95', 'data-[side=bottom]:slide-in-from-top-2', 'data-[side=left]:slide-in-from-right-2', 'data-[side=right]:slide-in-from-left-2', 'data-[side=top]:slide-in-from-bottom-2', className),
32
- asChild: true,
33
- children: /*#__PURE__*/ jsxs(ScrollArea, {
34
- ids: {
35
- root: id
36
- },
37
- children: [
38
- /*#__PURE__*/ jsx(ScrollAreaViewport, {
39
- children: /*#__PURE__*/ jsx(ScrollAreaContent, {
40
- children: children
41
- })
42
- }),
43
- /*#__PURE__*/ jsx(ScrollAreaScrollbar, {})
44
- ]
45
- })
30
+ className: cn('flex flex-col overflow-auto', 'min-w-(--popover-min-width)', 'max-w-[clamp(var(--popover-min-width),var(--available-width),var(--popover-max-width))]', 'min-h-(--popover-min-height)', 'max-h-[clamp(var(--popover-min-height,0px),var(--available-height),var(--popover-max-height))]', 'p-12 bg-bg-surface-2 rounded-12 border border-border-primary-light shadow-md text-text-primary', 'z-[calc(var(--drawer-positioner-z-index)+(var(--layer-index,0)*var(--drawer-level-ratio)))]', 'overscroll-contain', 'animate-in fade-in-0 zoom-in-95 origin-[--radix-tooltip-content-transform-origin]', 'data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95', 'data-[side=bottom]:slide-in-from-top-2', 'data-[side=left]:slide-in-from-right-2', 'data-[side=right]:slide-in-from-left-2', 'data-[side=top]:slide-in-from-bottom-2', className),
31
+ children: children
46
32
  })
47
33
  })
48
34
  });
@@ -1,5 +1,4 @@
1
1
  import type { PopoverSizeDimension } from './types';
2
- export declare const POPOVER_MIN_HEIGHT: PopoverSizeDimension;
3
2
  export declare const POPOVER_MAX_HEIGHT: PopoverSizeDimension;
4
3
  export declare const POPOVER_MIN_WIDTH: PopoverSizeDimension;
5
4
  export declare const POPOVER_MAX_WIDTH: PopoverSizeDimension;
@@ -1,5 +1,4 @@
1
- const POPOVER_MIN_HEIGHT = '156px';
2
1
  const POPOVER_MAX_HEIGHT = '560px';
3
2
  const POPOVER_MIN_WIDTH = '256px';
4
3
  const POPOVER_MAX_WIDTH = '560px';
5
- export { POPOVER_MAX_HEIGHT, POPOVER_MAX_WIDTH, POPOVER_MIN_HEIGHT, POPOVER_MIN_WIDTH };
4
+ export { POPOVER_MAX_HEIGHT, POPOVER_MAX_WIDTH, POPOVER_MIN_WIDTH };
@@ -1,2 +1,5 @@
1
- import type { FC } from 'react';
2
- export declare const SelectEmptyState: FC;
1
+ import type { FC, ReactNode } from 'react';
2
+ export interface SelectEmptyStateProps {
3
+ description?: ReactNode;
4
+ }
5
+ export declare const SelectEmptyState: FC<SelectEmptyStateProps>;
@@ -1,10 +1,10 @@
1
1
  import { jsx } from "react/jsx-runtime";
2
2
  import { EmptyState, EmptyStateDescription, EmptyStateMessage } from "../EmptyState/index.js";
3
- const SelectEmptyState = ()=>/*#__PURE__*/ jsx(EmptyState, {
3
+ const SelectEmptyState = ({ description = 'No results' })=>/*#__PURE__*/ jsx(EmptyState, {
4
4
  type: "no-results",
5
5
  children: /*#__PURE__*/ jsx(EmptyStateMessage, {
6
6
  children: /*#__PURE__*/ jsx(EmptyStateDescription, {
7
- children: "No results"
7
+ children: description
8
8
  })
9
9
  })
10
10
  });
@@ -4,6 +4,7 @@ export { SelectButton } from './SelectButton';
4
4
  export { SelectButtonTag, SelectButtonTagValue } from './SelectButtonTag';
5
5
  export { SelectClearTrigger } from './SelectClearTrigger';
6
6
  export { SelectContent } from './SelectContent';
7
+ export { SelectEmptyState, type SelectEmptyStateProps } from './SelectEmptyState';
7
8
  export { SelectFooter } from './SelectFooter';
8
9
  export { SelectGroup } from './SelectGroup';
9
10
  export { SelectGroupLabel } from './SelectGroupLabel';
@@ -17,3 +18,4 @@ export { SelectPositioner } from './SelectPositioner';
17
18
  export { SelectSearchInput, type SelectSearchInputProps } from './SelectSearchInput';
18
19
  export { SelectSeparator, type SelectSeparatorProps } from './SelectSeparator';
19
20
  export type { SelectDataItem } from './types';
21
+ export { type UseSelectSearchOptions, type UseSelectSearchResult, useSelectSearch, } from './useSelectSearch';
@@ -4,6 +4,7 @@ export { SelectButton } from "./SelectButton.js";
4
4
  export { SelectButtonTag, SelectButtonTagValue } from "./SelectButtonTag/index.js";
5
5
  export { SelectClearTrigger } from "./SelectClearTrigger.js";
6
6
  export { SelectContent } from "./SelectContent.js";
7
+ export { SelectEmptyState } from "./SelectEmptyState.js";
7
8
  export { SelectFooter } from "./SelectFooter.js";
8
9
  export { SelectGroup } from "./SelectGroup.js";
9
10
  export { SelectGroupLabel } from "./SelectGroupLabel.js";
@@ -16,3 +17,4 @@ export { SelectOptionText } from "./SelectOptionText.js";
16
17
  export { SelectPositioner } from "./SelectPositioner.js";
17
18
  export { SelectSearchInput } from "./SelectSearchInput.js";
18
19
  export { SelectSeparator } from "./SelectSeparator.js";
20
+ export { useSelectSearch } from "./useSelectSearch.js";
@@ -0,0 +1,16 @@
1
+ import type { CollectionItem, ListCollection } from '@ark-ui/react/collection';
2
+ export interface UseSelectSearchOptions<T extends CollectionItem> {
3
+ /**
4
+ * Overrides the default case-insensitive substring match against the
5
+ * item's stringified label. Receives the same `itemString` `collection`
6
+ * already computes via `itemToString`, plus the raw item for matching on
7
+ * other fields (e.g. `description`).
8
+ */
9
+ filterFn?: (itemString: string, item: T, query: string) => boolean;
10
+ }
11
+ export interface UseSelectSearchResult<T extends CollectionItem> {
12
+ searchValue: string;
13
+ onSearchChange: (value: string) => void;
14
+ filteredCollection: ListCollection<T>;
15
+ }
16
+ export declare const useSelectSearch: <T extends CollectionItem>(collection: ListCollection<T>, options?: UseSelectSearchOptions<T>) => UseSelectSearchResult<T>;
@@ -0,0 +1,20 @@
1
+ import { useMemo, useState } from "react";
2
+ const defaultFilterFn = (itemString, query)=>itemString.toLowerCase().includes(query.toLowerCase());
3
+ const useSelectSearch = (collection, options)=>{
4
+ const [searchValue, setSearchValue] = useState('');
5
+ const filterFn = options?.filterFn;
6
+ const filteredCollection = useMemo(()=>{
7
+ if (!searchValue) return collection;
8
+ return collection.filter((itemString, _index, item)=>filterFn ? filterFn(itemString, item, searchValue) : defaultFilterFn(itemString, searchValue));
9
+ }, [
10
+ collection,
11
+ searchValue,
12
+ filterFn
13
+ ]);
14
+ return {
15
+ searchValue,
16
+ onSearchChange: setSearchValue,
17
+ filteredCollection
18
+ };
19
+ };
20
+ export { useSelectSearch };
package/dist/index.d.ts CHANGED
@@ -62,7 +62,7 @@ export { getResponseCodeCategory, RESPONSE_CODE_COLOR, ResponseCode, type Respon
62
62
  export { ScrollArea, ScrollAreaContent, type ScrollAreaContentProps, ScrollAreaCorner, type ScrollAreaProps, ScrollAreaScrollbar, type ScrollAreaScrollbarProps, ScrollAreaViewport, type ScrollAreaViewportProps, } from './components/ScrollArea';
63
63
  export { SegmentedControl, SegmentedControlButton, type SegmentedControlButtonProps, SegmentedControlItem, type SegmentedControlItemProps, type SegmentedControlProps, SegmentedControlSeparator, type SegmentedControlSeparatorProps, } from './components/SegmentedControl';
64
64
  export { SegmentedTabs, SegmentedTabsButton, SegmentedTabsContent, SegmentedTabsList, SegmentedTabsSeparator, SegmentedTabsTrigger, SegmentedTabsTriggerButton, } from './components/SegmentedTabs';
65
- export { createListCollection, Select, SelectButton, SelectClearTrigger, SelectContent, type SelectDataItem, SelectFooter, SelectGroup, SelectGroupLabel, SelectHeader, SelectInput, SelectOption, SelectOptionDescription, SelectOptionIndicator, SelectOptionText, SelectPositioner, SelectSearchInput, SelectSeparator, } from './components/Select';
65
+ export { createListCollection, Select, SelectButton, SelectClearTrigger, SelectContent, type SelectDataItem, SelectEmptyState, type SelectEmptyStateProps, SelectFooter, SelectGroup, SelectGroupLabel, SelectHeader, SelectInput, SelectOption, SelectOptionDescription, SelectOptionIndicator, SelectOptionText, SelectPositioner, SelectSearchInput, SelectSeparator, type UseSelectSearchOptions, type UseSelectSearchResult, useSelectSearch, } from './components/Select';
66
66
  export { Selection, SelectionAll, type SelectionAllProps, SelectionBulkBar, type SelectionBulkBarPlacement, type SelectionBulkBarProps, type SelectionContextValue, SelectionItem, type SelectionItemProps, type SelectionProps, useSelectionContext, } from './components/Selection';
67
67
  export { Separator, type SeparatorProps } from './components/Separator';
68
68
  export { Skeleton, type SkeletonProps } from './components/Skeleton';
package/dist/index.js CHANGED
@@ -51,7 +51,7 @@ export { RESPONSE_CODE_COLOR, ResponseCode, getResponseCodeCategory } from "./co
51
51
  export { ScrollArea, ScrollAreaContent, ScrollAreaCorner, ScrollAreaScrollbar, ScrollAreaViewport } from "./components/ScrollArea/index.js";
52
52
  export { SegmentedControl, SegmentedControlButton, SegmentedControlItem, SegmentedControlSeparator } from "./components/SegmentedControl/index.js";
53
53
  export { SegmentedTabs, SegmentedTabsButton, SegmentedTabsContent, SegmentedTabsList, SegmentedTabsSeparator, SegmentedTabsTrigger, SegmentedTabsTriggerButton } from "./components/SegmentedTabs/index.js";
54
- export { Select, SelectButton, SelectClearTrigger, SelectContent, SelectFooter, SelectGroup, SelectGroupLabel, SelectHeader, SelectInput, SelectOption, SelectOptionDescription, SelectOptionIndicator, SelectOptionText, SelectPositioner, SelectSearchInput, SelectSeparator, createListCollection } from "./components/Select/index.js";
54
+ export { Select, SelectButton, SelectClearTrigger, SelectContent, SelectEmptyState, SelectFooter, SelectGroup, SelectGroupLabel, SelectHeader, SelectInput, SelectOption, SelectOptionDescription, SelectOptionIndicator, SelectOptionText, SelectPositioner, SelectSearchInput, SelectSeparator, createListCollection, useSelectSearch } from "./components/Select/index.js";
55
55
  export { Selection, SelectionAll, SelectionBulkBar, SelectionItem, useSelectionContext } from "./components/Selection/index.js";
56
56
  export { Separator } from "./components/Separator/index.js";
57
57
  export { Skeleton } from "./components/Skeleton/index.js";
@@ -1,6 +1,6 @@
1
1
  {
2
- "version": "0.85.1",
3
- "generatedAt": "2026-08-07T06:49:22.264Z",
2
+ "version": "0.87.0",
3
+ "generatedAt": "2026-08-07T08:50:50.859Z",
4
4
  "components": [
5
5
  {
6
6
  "name": "Accordion",
@@ -47718,8 +47718,7 @@
47718
47718
  {
47719
47719
  "name": "minHeight",
47720
47720
  "type": "PopoverSizeDimension | undefined",
47721
- "required": false,
47722
- "defaultValue": "POPOVER_MIN_HEIGHT"
47721
+ "required": false
47723
47722
  },
47724
47723
  {
47725
47724
  "name": "maxHeight",
@@ -53952,6 +53951,17 @@
53952
53951
  "props": [],
53953
53952
  "variants": [],
53954
53953
  "subComponents": [
53954
+ {
53955
+ "name": "SelectEmptyState",
53956
+ "props": [
53957
+ {
53958
+ "name": "description",
53959
+ "type": "ReactNode",
53960
+ "required": false,
53961
+ "defaultValue": "No results"
53962
+ }
53963
+ ]
53964
+ },
53955
53965
  {
53956
53966
  "name": "SelectSearchInput",
53957
53967
  "props": [
@@ -54554,7 +54564,7 @@
54554
54564
  },
54555
54565
  {
54556
54566
  "name": "WithSearch",
54557
- "code": "() => {\n const [searchValue, setSearchValue] = useState<string>('');\n\n const collection = createListCollection({\n items: skillsWithoutIcons,\n groupBy: item => item.category ?? '',\n itemToString: item => item.label,\n });\n\n return (\n <div className='w-300'>\n <Select collection={collection}>\n <SelectButton />\n\n <SelectPositioner>\n <SelectHeader>\n <SelectSearchInput value={searchValue} onChange={setSearchValue} />\n </SelectHeader>\n\n <SelectContent>\n {collection\n .filter(skill => skill.toLowerCase().includes(searchValue.toLowerCase()))\n .group()\n .map(([category, group], index) => (\n <SelectGroup key={category}>\n <SelectGroupLabel>\n {category}\n {index === 0 && <SelectClearTrigger>Clear all</SelectClearTrigger>}\n </SelectGroupLabel>\n {group.map(skill => (\n <SelectOption key={skill.value} item={skill}>\n <SelectOptionText>{skill.label}</SelectOptionText>\n {skill.description && (\n <SelectOptionDescription>{skill.description}</SelectOptionDescription>\n )}\n <SelectOptionIndicator />\n </SelectOption>\n ))}\n </SelectGroup>\n ))}\n </SelectContent>\n\n <SelectFooter>\n <HStack justify='between'>\n <Button variant='ghost' color='neutral' size='small'>\n <SquareArrowOutUpRight />\n See all\n </Button>\n\n <HStack justify='end'>\n <Button variant='ghost' color='neutral' size='small'>\n Cancel\n </Button>\n\n <Button variant='primary' color='brand' size='small'>\n Apply\n </Button>\n </HStack>\n </HStack>\n </SelectFooter>\n </SelectPositioner>\n </Select>\n </div>\n );\n}"
54567
+ "code": "() => {\n const collection = createListCollection({\n items: skillsWithoutIcons,\n groupBy: item => item.category ?? '',\n itemToString: item => item.label,\n });\n\n const { searchValue, onSearchChange, filteredCollection } = useSelectSearch(collection);\n\n return (\n <div className='w-300'>\n <Select collection={collection}>\n <SelectButton />\n\n <SelectPositioner>\n <SelectHeader>\n <SelectSearchInput value={searchValue} onChange={onSearchChange} />\n </SelectHeader>\n\n <SelectContent>\n {filteredCollection.size === 0 ? (\n <SelectEmptyState description={`No results for \"${searchValue}\"`} />\n ) : (\n filteredCollection.group().map(([category, group], index) => (\n <SelectGroup key={category}>\n <SelectGroupLabel>\n {category}\n {index === 0 && <SelectClearTrigger>Clear all</SelectClearTrigger>}\n </SelectGroupLabel>\n {group.map(skill => (\n <SelectOption key={skill.value} item={skill}>\n <SelectOptionText>{skill.label}</SelectOptionText>\n {skill.description && (\n <SelectOptionDescription>{skill.description}</SelectOptionDescription>\n )}\n <SelectOptionIndicator />\n </SelectOption>\n ))}\n </SelectGroup>\n ))\n )}\n </SelectContent>\n\n <SelectFooter>\n <HStack justify='between'>\n <Button variant='ghost' color='neutral' size='small'>\n <SquareArrowOutUpRight />\n See all\n </Button>\n\n <HStack justify='end'>\n <Button variant='ghost' color='neutral' size='small'>\n Cancel\n </Button>\n\n <Button variant='primary' color='brand' size='small'>\n Apply\n </Button>\n </HStack>\n </HStack>\n </SelectFooter>\n </SelectPositioner>\n </Select>\n </div>\n );\n}"
54558
54568
  },
54559
54569
  {
54560
54570
  "name": "WithFormField",
@@ -35,6 +35,28 @@
35
35
  }
36
36
  }
37
37
 
38
+ /**
39
+ * Global native-scrollbar styling, matching the ScrollArea component's look
40
+ * (thin slate thumb, transparent track) for every plain `overflow:
41
+ * auto/scroll` element that isn't opting into ScrollArea's own JS-drawn
42
+ * thumb (excluded above via higher-specificity attribute selector). The
43
+ * thumb is permanently visible: `overflow: auto` already only renders a
44
+ * scrollbar when content overflows, so that's the only "show it when
45
+ * scrollable" gate this needs.
46
+ *
47
+ * Deliberately uses only the standard `scrollbar-width`/`scrollbar-color`
48
+ * properties, not `::-webkit-scrollbar-*`. The legacy pseudo-elements would
49
+ * allow a fully custom (rounded, inset) thumb, but their hover-driven state
50
+ * changes only repaint reliably when the pointer is over the scrollbar
51
+ * widget itself, not the rest of the scrollable container — unreliable
52
+ * enough that a permanently-visible thumb sidesteps the issue entirely.
53
+ */
54
+ * {
55
+ scrollbar-width: thin;
56
+ scrollbar-color: color-mix(in srgb, var(--color-badge-slate-dark-alt) 50%, transparent)
57
+ transparent;
58
+ }
59
+
38
60
  /** Remove when old DS will be removed **/
39
61
  :where(:root) {
40
62
  cursor: default;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wallarm-org/design-system",
3
- "version": "0.86.0",
3
+ "version": "0.87.1",
4
4
  "description": "Core design system library with React components and Storybook documentation",
5
5
  "publishConfig": {
6
6
  "access": "public",