@synerise/ds-context-selector 0.24.6 → 0.24.8

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/CHANGELOG.md CHANGED
@@ -3,6 +3,26 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [0.24.8](https://github.com/Synerise/synerise-design/compare/@synerise/ds-context-selector@0.24.7...@synerise/ds-context-selector@0.24.8) (2024-09-11)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * **context-selector:** updated search logic ([dfadc02](https://github.com/Synerise/synerise-design/commit/dfadc02928651905f31c58a374d48368b8375eb3))
12
+ * **factors:** make all dropdowns same fixed height ([40e86d1](https://github.com/Synerise/synerise-design/commit/40e86d183dddb925c2b75c499615c1455b93b7c4))
13
+
14
+
15
+
16
+
17
+
18
+ ## [0.24.7](https://github.com/Synerise/synerise-design/compare/@synerise/ds-context-selector@0.24.6...@synerise/ds-context-selector@0.24.7) (2024-09-03)
19
+
20
+ **Note:** Version bump only for package @synerise/ds-context-selector
21
+
22
+
23
+
24
+
25
+
6
26
  ## [0.24.6](https://github.com/Synerise/synerise-design/compare/@synerise/ds-context-selector@0.24.5...@synerise/ds-context-selector@0.24.6) (2024-08-30)
7
27
 
8
28
 
@@ -1,4 +1,4 @@
1
1
  import React from 'react';
2
2
  import { ContextProps } from './ContextSelector.types';
3
- declare const ContextSelector: ({ defaultDropdownVisibility, selectedItem, onSelectItem, onSetGroup, groups, items, texts, opened, addMode, loading, customTriggerComponent, trigger, menuItemHeight, dropdownWrapperStyles, onClickOutsideEvents, onClickOutside, onSearch, hideSearchField, hasMoreItems, onFetchData, onActivate, onDeactivate, onOpen, getPopupContainerOverride, type, dropdownProps, disabled, errorText, readOnly, getMenuEntryProps, }: ContextProps) => React.JSX.Element;
3
+ declare const ContextSelector: ({ defaultDropdownVisibility, selectedItem, onSelectItem, onSetGroup, groups, items, texts, opened, addMode, loading, customTriggerComponent, trigger, menuItemHeight, dropdownWrapperStyles, onClickOutsideEvents, onClickOutside, onSearch, hideSearchField, hasMoreItems, onFetchData, onActivate, onDeactivate, onOpen, getPopupContainerOverride, type, dropdownProps, disabled, errorText, readOnly, getMenuEntryProps, dropdownDimensionsConfig, }: ContextProps) => React.JSX.Element;
4
4
  export default ContextSelector;
@@ -15,6 +15,7 @@ import InformationCard from '@synerise/ds-information-card';
15
15
  import { getPopupContainer } from '@synerise/ds-utils';
16
16
  import ContextSelectorDropdown from './ContextSelectorDropdown/ContextSelectorDropdown';
17
17
  import { ItemWrapper, ErrorWrapper } from './ContextSelector.styles';
18
+ import { DROPDOWN_HEIGHT, DROPDOWN_HEIGHT_BELOW_THRESHOLD, DROPDOWN_HEIGHT_THRESHOLD } from './constants';
18
19
 
19
20
  var ContextSelector = function ContextSelector(_ref) {
20
21
  var defaultDropdownVisibility = _ref.defaultDropdownVisibility,
@@ -49,12 +50,34 @@ var ContextSelector = function ContextSelector(_ref) {
49
50
  errorText = _ref.errorText,
50
51
  _ref$readOnly = _ref.readOnly,
51
52
  readOnly = _ref$readOnly === void 0 ? false : _ref$readOnly,
52
- getMenuEntryProps = _ref.getMenuEntryProps;
53
+ getMenuEntryProps = _ref.getMenuEntryProps,
54
+ dropdownDimensionsConfig = _ref.dropdownDimensionsConfig;
53
55
 
54
56
  var _useState = useState(defaultDropdownVisibility != null ? defaultDropdownVisibility : false),
55
57
  dropdownVisible = _useState[0],
56
58
  setDropdownVisible = _useState[1];
57
59
 
60
+ var dimensionsConfig = _objectSpread({
61
+ defaultHeight: DROPDOWN_HEIGHT,
62
+ lowerHeight: DROPDOWN_HEIGHT_BELOW_THRESHOLD,
63
+ threshold: DROPDOWN_HEIGHT_THRESHOLD
64
+ }, dropdownDimensionsConfig);
65
+
66
+ var _useState2 = useState(dimensionsConfig.defaultHeight),
67
+ outerHeight = _useState2[0],
68
+ setOuterHeight = _useState2[1];
69
+
70
+ useEffect(function () {
71
+ var checkViewportHeight = function checkViewportHeight() {
72
+ return setOuterHeight(window.innerHeight < dimensionsConfig.threshold ? dimensionsConfig.lowerHeight : dimensionsConfig.defaultHeight);
73
+ };
74
+
75
+ checkViewportHeight();
76
+ window.addEventListener('resize', checkViewportHeight);
77
+ return function () {
78
+ window.removeEventListener('resize', checkViewportHeight);
79
+ };
80
+ }, [dimensionsConfig.defaultHeight, dimensionsConfig.lowerHeight, dimensionsConfig.threshold]);
58
81
  useEffect(function () {
59
82
  setDropdownVisible(defaultDropdownVisibility != null ? defaultDropdownVisibility : false);
60
83
  }, [defaultDropdownVisibility]);
@@ -169,7 +192,8 @@ var ContextSelector = function ContextSelector(_ref) {
169
192
  onSearch: onSearch,
170
193
  hideSearchField: hideSearchField,
171
194
  hasMoreItems: hasMoreItems,
172
- onFetchData: onFetchData
195
+ onFetchData: onFetchData,
196
+ outerHeight: outerHeight
173
197
  })
174
198
  }), customTriggerComponent != null ? customTriggerComponent : triggerButton)), errorText && /*#__PURE__*/React.createElement(ErrorWrapper, null, errorText));
175
199
  };
@@ -1,8 +1,15 @@
1
+ /// <reference types="react" />
1
2
  export declare const TabsWrapper: import("styled-components").StyledComponent<"div", any, {}, never>;
2
3
  export declare const ContentPlaceholder: import("styled-components").StyledComponent<"div", any, {}, never>;
3
- export declare const ItemsList: import("styled-components").StyledComponent<"div", any, {}, never>;
4
+ export declare const ItemsList: import("styled-components").StyledComponent<"div", any, {
5
+ contentHeight?: number | undefined;
6
+ }, never>;
4
7
  export declare const SearchResult: import("styled-components").StyledComponent<"span", any, {}, never>;
5
8
  export declare const SearchResultHighlight: import("styled-components").StyledComponent<"span", any, {}, never>;
6
9
  export declare const Title: import("styled-components").StyledComponent<"div", any, {}, never>;
7
10
  export declare const ItemWrapper: import("styled-components").StyledComponent<"span", any, {}, never>;
11
+ export declare const ShowMoreItem: import("styled-components").StyledComponent<"div", any, {}, never>;
8
12
  export declare const ErrorWrapper: import("styled-components").StyledComponent<"div", any, {}, never>;
13
+ export declare const Skeleton: import("styled-components").StyledComponent<({ size, numberOfSkeletons, width, height, className }: import("@synerise/ds-skeleton").SkeletonProps) => import("react").JSX.Element, any, {
14
+ contentHeight?: number | undefined;
15
+ }, never>;
@@ -1,4 +1,5 @@
1
1
  import styled from 'styled-components';
2
+ import DropdownSkeleton from '@synerise/ds-skeleton';
2
3
  export var TabsWrapper = styled.div.withConfig({
3
4
  displayName: "ContextSelectorstyles__TabsWrapper",
4
5
  componentId: "sc-1tuu6xk-0"
@@ -10,8 +11,10 @@ export var ContentPlaceholder = styled.div.withConfig({
10
11
  export var ItemsList = styled.div.withConfig({
11
12
  displayName: "ContextSelectorstyles__ItemsList",
12
13
  componentId: "sc-1tuu6xk-2"
13
- })(["width:100%;background:", ";.ds-context-selector-list{height:auto !important;max-height:300px;}"], function (props) {
14
+ })(["width:100%;background:", ";.ds-context-selector-list{height:auto !important;max-height:300px;}", ""], function (props) {
14
15
  return props.theme.palette.white;
16
+ }, function (props) {
17
+ return props.contentHeight !== undefined && "height: " + props.contentHeight + "px;";
15
18
  });
16
19
  export var SearchResult = styled.span.withConfig({
17
20
  displayName: "ContextSelectorstyles__SearchResult",
@@ -35,9 +38,19 @@ export var ItemWrapper = styled.span.withConfig({
35
38
  displayName: "ContextSelectorstyles__ItemWrapper",
36
39
  componentId: "sc-1tuu6xk-6"
37
40
  })(["max-width:170px;overflow:hidden;text-overflow:ellipsis;"]);
41
+ export var ShowMoreItem = styled.div.withConfig({
42
+ displayName: "ContextSelectorstyles__ShowMoreItem",
43
+ componentId: "sc-1tuu6xk-7"
44
+ })(["font-weight:500;"]);
38
45
  export var ErrorWrapper = styled.div.withConfig({
39
46
  displayName: "ContextSelectorstyles__ErrorWrapper",
40
- componentId: "sc-1tuu6xk-7"
47
+ componentId: "sc-1tuu6xk-8"
41
48
  })(["color:", ";margin-top:8px;"], function (props) {
42
49
  return props.theme.palette['red-600'];
50
+ });
51
+ export var Skeleton = styled(DropdownSkeleton).withConfig({
52
+ displayName: "ContextSelectorstyles__Skeleton",
53
+ componentId: "sc-1tuu6xk-9"
54
+ })(["", ""], function (props) {
55
+ return props.contentHeight !== undefined && "height: " + props.contentHeight + "px;";
43
56
  });
@@ -1,15 +1,15 @@
1
- import { CSSProperties, ReactNode, ReactText } from 'react';
2
- import { HandledEventsType } from '@synerise/ds-utils';
3
- import { ItemSize } from '@synerise/ds-menu';
4
- import { DropdownProps } from '@synerise/ds-dropdown/dist/Dropdown';
1
+ import type { CSSProperties, ReactNode, ReactText } from 'react';
2
+ import type { HandledEventsType } from '@synerise/ds-utils';
3
+ import type { DropdownProps } from '@synerise/ds-dropdown';
5
4
  import type { FactorsProps } from '@synerise/ds-factors';
6
- import { InformationCardProps } from '@synerise/ds-information-card';
7
- import { ListItemProps } from '@synerise/ds-list-item';
5
+ import type { InformationCardProps } from '@synerise/ds-information-card';
6
+ import type { ListItemProps, ItemSize } from '@synerise/ds-list-item';
8
7
  export type ContextTexts = {
9
8
  buttonLabel: string;
10
9
  searchPlaceholder: string;
11
10
  loadingResults: string;
12
11
  noResults: string;
12
+ showMore: string;
13
13
  };
14
14
  export type ContextItem = Pick<ListItemProps, 'renderHoverTooltip' | 'hoverTooltipProps' | 'disabled'> & {
15
15
  id: ReactText | null;
@@ -71,6 +71,11 @@ export type ContextProps = {
71
71
  dropdownProps?: Omit<DropdownProps, 'trigger' | 'getPopupContainer' | 'onVisibleChange' | 'visible' | 'overlay'>;
72
72
  errorText?: ReactNode | string;
73
73
  getMenuEntryProps?: FactorsProps['getMenuEntryProps'];
74
+ dropdownDimensionsConfig?: {
75
+ defaultHeight?: number;
76
+ lowerHeight?: number;
77
+ threshold?: number;
78
+ };
74
79
  };
75
80
  export type ContextDropdownProps = {
76
81
  setDropdownVisible: (show: boolean) => void;
@@ -91,30 +96,23 @@ export type ContextDropdownProps = {
91
96
  onFetchData?: () => void;
92
97
  hasMoreItems?: boolean;
93
98
  style?: CSSProperties;
99
+ outerHeight?: number;
100
+ maxSearchResultsInGroup?: number;
94
101
  };
95
102
  export type ContextSelectorDropdownItemProps = {
96
- item: ContextItem | ContextGroup;
97
- searchQuery: string;
103
+ className: string;
98
104
  clearSearch?: () => void;
99
105
  hideDropdown?: () => void;
100
- select: (item: ContextItem | ContextGroup) => void;
101
- selected?: boolean;
102
- className: string;
103
- menuItemHeight?: ItemSize;
104
- style?: CSSProperties;
105
- };
106
- export type ListItem = {
107
- className: string;
108
106
  item: ContextItem | ContextGroup;
109
- searchQuery: string;
110
- select: (item: ContextItem | ContextGroup) => void;
111
107
  menuItemHeight?: ItemSize;
108
+ searchQuery?: string;
109
+ select: (item: ContextItem | ContextGroup) => void;
112
110
  selected?: boolean;
113
- clearSearch?: () => void;
114
- hideDropdown?: () => void;
111
+ style?: CSSProperties;
112
+ label?: ReactNode;
115
113
  };
116
114
  export type ListTitle = {
117
115
  title?: string;
118
116
  type?: string;
119
117
  };
120
- export type DropdownItemProps = ListTitle | ListItem;
118
+ export type DropdownItemProps = ListTitle | ContextSelectorDropdownItemProps;
@@ -1,4 +1,4 @@
1
- import * as React from 'react';
1
+ import React from 'react';
2
2
  import { ContextDropdownProps } from '../ContextSelector.types';
3
- declare const ContextSelectorDropdown: React.FC<ContextDropdownProps>;
3
+ declare const ContextSelectorDropdown: ({ texts, setSelected, onSetGroup, groups, items, setDropdownVisible, value, visible, hideSearchField, loading, menuItemHeight, dropdownWrapperStyles, onClickOutsideEvents, onClickOutside, onSearch, onFetchData, hasMoreItems, outerHeight, maxSearchResultsInGroup, }: ContextDropdownProps) => React.JSX.Element;
4
4
  export default ContextSelectorDropdown;
@@ -1,5 +1,3 @@
1
- var _ITEM_SIZE;
2
-
3
1
  function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
4
2
 
5
3
  function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
@@ -8,30 +6,21 @@ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { va
8
6
 
9
7
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
10
8
 
11
- import * as React from 'react';
9
+ import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
10
+ import { v4 as uuid } from 'uuid';
11
+ import { VariableSizeList } from 'react-window';
12
12
  import Dropdown from '@synerise/ds-dropdown';
13
- import Icon, { SearchM } from '@synerise/ds-icon';
13
+ import Icon, { ArrowRightCircleM, SearchM } from '@synerise/ds-icon';
14
14
  import Tabs from '@synerise/ds-tabs';
15
- import { focusWithArrowKeys, getClosest, useOnClickOutside } from '@synerise/ds-utils';
15
+ import { focusWithArrowKeys, getClosest, useOnClickOutside, useSearchResults, getActiveTabGroup, getGroupName } from '@synerise/ds-utils';
16
16
  import Result from '@synerise/ds-result';
17
17
  import Scrollbar from '@synerise/ds-scrollbar';
18
18
  import { theme } from '@synerise/ds-core';
19
- import { v4 as uuid } from 'uuid';
20
- import { VariableSizeList as List } from 'react-window';
21
- import { ItemSize } from '@synerise/ds-menu';
22
- import DropdownSkeleton from '@synerise/ds-skeleton';
19
+ import { itemSizes } from '@synerise/ds-list-item';
23
20
  import * as S from '../ContextSelector.styles';
24
21
  import ContextSelectorDropdownItem from './ContextSelectorDropdownItem';
25
- var NO_GROUP_NAME = 'NO_GROUP_NAME';
26
- var ITEM_SIZE = (_ITEM_SIZE = {}, _ITEM_SIZE[ItemSize.LARGE] = 50, _ITEM_SIZE[ItemSize.DEFAULT] = 32, _ITEM_SIZE.title = 32, _ITEM_SIZE);
27
-
28
- function isListTitle(element) {
29
- return element.title !== undefined;
30
- }
31
-
32
- function isGroup(item) {
33
- return 'isGroup' in item;
34
- }
22
+ import { NO_GROUP_NAME, ITEM_SIZE, DROPDOWN_HEIGHT, TABS_HEIGHT, SUBGROUP_HEADER_HEIGHT, SEARCH_HEIGHT } from '../constants';
23
+ import { isGroup, isListTitle } from './utils';
35
24
 
36
25
  var ContextSelectorDropdown = function ContextSelectorDropdown(_ref) {
37
26
  var texts = _ref.texts,
@@ -51,44 +40,49 @@ var ContextSelectorDropdown = function ContextSelectorDropdown(_ref) {
51
40
  onClickOutside = _ref.onClickOutside,
52
41
  onSearch = _ref.onSearch,
53
42
  onFetchData = _ref.onFetchData,
54
- hasMoreItems = _ref.hasMoreItems;
55
- var listRef = React.createRef();
43
+ hasMoreItems = _ref.hasMoreItems,
44
+ _ref$outerHeight = _ref.outerHeight,
45
+ outerHeight = _ref$outerHeight === void 0 ? DROPDOWN_HEIGHT : _ref$outerHeight,
46
+ _ref$maxSearchResults = _ref.maxSearchResultsInGroup,
47
+ maxSearchResultsInGroup = _ref$maxSearchResults === void 0 ? 4 : _ref$maxSearchResults;
56
48
  var listStyle = {
57
49
  overflowX: 'unset',
58
50
  overflowY: 'unset'
59
51
  };
60
- var defaultTab = React.useMemo(function () {
52
+ var defaultTab = useMemo(function () {
61
53
  var defaultIndex = groups == null ? void 0 : groups.findIndex(function (group) {
62
54
  return group.defaultGroup;
63
55
  });
64
56
  return defaultIndex || 0;
65
57
  }, [groups]);
66
- var overlayRef = React.useRef(null);
58
+ var listRef = useRef(null);
59
+ var overlayRef = useRef(null);
60
+ var scrollBarRef = useRef(null);
67
61
 
68
- var _React$useState = React.useState(),
69
- searchInputHandle = _React$useState[0],
70
- setSearchInputHandle = _React$useState[1];
62
+ var _useState = useState(),
63
+ searchInputHandle = _useState[0],
64
+ setSearchInputHandle = _useState[1];
71
65
 
72
- var _React$useState2 = React.useState(''),
73
- searchQuery = _React$useState2[0],
74
- setSearchQuery = _React$useState2[1];
66
+ var _useState2 = useState(''),
67
+ searchQuery = _useState2[0],
68
+ setSearchQuery = _useState2[1];
75
69
 
76
- var _React$useState3 = React.useState(defaultTab),
77
- activeTab = _React$useState3[0],
78
- setActiveTab = _React$useState3[1];
70
+ var _useState3 = useState(defaultTab),
71
+ activeTab = _useState3[0],
72
+ setActiveTab = _useState3[1];
79
73
 
80
- var _React$useState4 = React.useState(undefined),
81
- activeGroup = _React$useState4[0],
82
- setActiveGroup = _React$useState4[1];
74
+ var _useState4 = useState(undefined),
75
+ activeGroup = _useState4[0],
76
+ setActiveGroup = _useState4[1];
83
77
 
84
- var _React$useState5 = React.useState(true),
85
- searchInputCanBeFocused = _React$useState5[0],
86
- setSearchInputFocus = _React$useState5[1];
78
+ var _useState5 = useState(true),
79
+ searchInputCanBeFocused = _useState5[0],
80
+ setSearchInputFocus = _useState5[1];
87
81
 
88
- var classNames = React.useMemo(function () {
82
+ var classNames = useMemo(function () {
89
83
  return "ds-context-item ds-context-item-" + uuid();
90
84
  }, []);
91
- var handleOnSetGroup = React.useCallback(function (item) {
85
+ var handleOnSetGroup = useCallback(function (item) {
92
86
  if (isGroup(item)) {
93
87
  onSetGroup && onSetGroup(item);
94
88
  setActiveGroup(item);
@@ -100,23 +94,22 @@ var ContextSelectorDropdown = function ContextSelectorDropdown(_ref) {
100
94
  setDropdownVisible(false);
101
95
  }
102
96
  }, onClickOutsideEvents);
103
- var clearSearch = React.useCallback(function () {
97
+ var clearSearch = useCallback(function () {
104
98
  setSearchQuery('');
105
99
  }, []);
106
- var hideDropdown = React.useCallback(function () {
100
+ var hideDropdown = useCallback(function () {
107
101
  setDropdownVisible(false);
108
102
  }, [setDropdownVisible]);
109
- var currentTabItems = React.useMemo(function () {
110
- return groups == null ? void 0 : groups.find(function (group, index) {
111
- return activeTab === index;
112
- });
103
+ var currentTabItems = useMemo(function () {
104
+ return groups ? getActiveTabGroup(activeTab, groups) : undefined;
113
105
  }, [groups, activeTab]);
114
- var groupByGroupName = React.useCallback(function (activeItems) {
115
- var itemsNumber = activeItems.length;
106
+ var groupByGroupName = useCallback(function (dropdownItems, maxItemsInGroup) {
107
+ var itemsNumber = dropdownItems == null ? void 0 : dropdownItems.length;
116
108
  var groupedItems = {};
117
109
 
118
110
  for (var i = 0; i < itemsNumber; i += 1) {
119
- var item = activeItems[i];
111
+ var item = dropdownItems[i]; // @ts-ignore
112
+
120
113
  var groupName = item.groupName || NO_GROUP_NAME;
121
114
  var group = groupedItems[groupName] || [];
122
115
  group.push(item);
@@ -132,7 +125,8 @@ var ContextSelectorDropdown = function ContextSelectorDropdown(_ref) {
132
125
  });
133
126
  }
134
127
 
135
- groupedItems[key].forEach(function (item) {
128
+ var groupItems = maxItemsInGroup ? groupedItems[key].slice(0, maxItemsInGroup) : groupedItems[key];
129
+ groupItems.forEach(function (item) {
136
130
  var resultItem = item.isGroup ? {
137
131
  className: classNames,
138
132
  item: item,
@@ -143,6 +137,7 @@ var ContextSelectorDropdown = function ContextSelectorDropdown(_ref) {
143
137
  className: classNames,
144
138
  item: item,
145
139
  searchQuery: searchQuery,
140
+ clearSearch: clearSearch,
146
141
  hideDropdown: hideDropdown,
147
142
  select: setSelected,
148
143
  selected: Boolean(value) && item.id === (value == null ? void 0 : value.id),
@@ -150,42 +145,33 @@ var ContextSelectorDropdown = function ContextSelectorDropdown(_ref) {
150
145
  };
151
146
  resultItems.push(resultItem);
152
147
  });
153
- });
154
- return resultItems;
155
- }, [activeGroup, classNames, searchQuery, handleOnSetGroup, menuItemHeight, hideDropdown, setSelected, value]);
156
- var searchResults = React.useMemo(function () {
157
- var result = [];
158
- var itemsNumber = items.length;
159
148
 
160
- for (var i = 0; i < itemsNumber; i += 1) {
161
- var _item$name, _item$subtitle;
162
-
163
- var item = items[i];
164
- var searchQueryInLowerCase = searchQuery.toLowerCase();
165
- var isMatchingName = (_item$name = item.name) == null ? void 0 : _item$name.toLowerCase().includes(searchQueryInLowerCase);
166
- var isMatchingSubtitle = (_item$subtitle = item.subtitle) == null ? void 0 : _item$subtitle.toLowerCase().includes(searchQueryInLowerCase);
167
- var matching = !searchQuery || isMatchingName || isMatchingSubtitle;
168
-
169
- if (matching) {
170
- result.push({
149
+ if (maxItemsInGroup && groupedItems[key].length > maxItemsInGroup) {
150
+ var anyItem = groupItems[0];
151
+ resultItems.push({
171
152
  className: classNames,
172
- item: item,
173
- searchQuery: searchQuery,
174
- clearSearch: clearSearch,
175
- hideDropdown: hideDropdown,
176
- select: setSelected,
177
- selected: Boolean(value) && item.id === (value == null ? void 0 : value.id),
178
- menuItemHeight: menuItemHeight
153
+ select: handleOnSetGroup,
154
+ menuItemHeight: menuItemHeight,
155
+ label: /*#__PURE__*/React.createElement(S.ShowMoreItem, null, texts.showMore),
156
+ item: {
157
+ isGroup: true,
158
+ id: anyItem.groupId,
159
+ name: getGroupName(anyItem.groupId, groups) || '',
160
+ icon: /*#__PURE__*/React.createElement(ArrowRightCircleM, null)
161
+ }
179
162
  });
180
163
  }
181
- }
164
+ });
165
+ return resultItems;
166
+ }, [activeGroup, classNames, searchQuery, handleOnSetGroup, menuItemHeight, clearSearch, hideDropdown, setSelected, value, texts.showMore, groups]);
182
167
 
183
- return result;
184
- }, [classNames, clearSearch, hideDropdown, items, menuItemHeight, searchQuery, setSelected, value]);
185
- var hasSubgroups = React.useMemo(function () {
168
+ var _useSearchResults = useSearchResults(items, groups, activeTab, groupByGroupName, activeGroup, searchQuery, maxSearchResultsInGroup),
169
+ searchResults = _useSearchResults.searchResults;
170
+
171
+ var hasSubgroups = useMemo(function () {
186
172
  return Boolean(currentTabItems == null ? void 0 : currentTabItems.subGroups);
187
173
  }, [currentTabItems]);
188
- var activeItems = React.useMemo(function () {
174
+ var activeItems = useMemo(function () {
189
175
  if (!onSearch && searchQuery) {
190
176
  return searchResults;
191
177
  }
@@ -193,7 +179,7 @@ var ContextSelectorDropdown = function ContextSelectorDropdown(_ref) {
193
179
  if (hasSubgroups && !activeGroup) {
194
180
  var _currentTabItems$subG;
195
181
 
196
- var subGroups = currentTabItems != null && currentTabItems.subGroups ? currentTabItems == null || (_currentTabItems$subG = currentTabItems.subGroups) == null ? void 0 : _currentTabItems$subG.map(function (group) {
182
+ var subGroups = hasSubgroups ? currentTabItems == null || (_currentTabItems$subG = currentTabItems.subGroups) == null ? void 0 : _currentTabItems$subG.map(function (group) {
197
183
  return _objectSpread({}, group, {
198
184
  isGroup: true
199
185
  });
@@ -207,7 +193,7 @@ var ContextSelectorDropdown = function ContextSelectorDropdown(_ref) {
207
193
 
208
194
  return prev;
209
195
  }, []);
210
- return groupByGroupName([].concat(subGroups, subItems));
196
+ return groupByGroupName([].concat(subGroups || [], subItems));
211
197
  }
212
198
 
213
199
  if (activeGroup) {
@@ -223,25 +209,26 @@ var ContextSelectorDropdown = function ContextSelectorDropdown(_ref) {
223
209
  }
224
210
 
225
211
  return groupByGroupName(items);
226
- }, [activeGroup, activeTab, currentTabItems, groupByGroupName, groups, hasSubgroups, items, onSearch, searchQuery, searchResults]);
227
- React.useEffect(function () {
212
+ }, [onSearch, searchQuery, hasSubgroups, activeGroup, activeTab, groups, groupByGroupName, items, searchResults, currentTabItems == null ? void 0 : currentTabItems.subGroups, currentTabItems == null ? void 0 : currentTabItems.id]);
213
+ useEffect(function () {
228
214
  var _listRef$current;
229
215
 
230
216
  // eslint-disable-next-line no-unused-expressions
231
217
  (_listRef$current = listRef.current) == null || _listRef$current.resetAfterIndex(0, false);
232
218
  }, [activeItems, listRef]);
233
- var handleSearch = React.useCallback(function (val) {
219
+ var handleSearch = useCallback(function (val) {
234
220
  setSearchQuery(val);
235
221
  onSearch && onSearch(val);
236
222
  }, [onSearch]);
237
- var getTabs = React.useMemo(function () {
223
+ var getTabs = useMemo(function () {
238
224
  return (groups == null ? void 0 : groups.map(function (group) {
239
225
  return {
240
226
  label: group.name
241
227
  };
242
228
  })) || [];
243
229
  }, [groups]);
244
- var getNoResultContainer = React.useMemo(function () {
230
+ var hasTabs = getTabs.length > 1;
231
+ var getNoResultContainer = useMemo(function () {
245
232
  return /*#__PURE__*/React.createElement(Result, {
246
233
  noSearchResults: true,
247
234
  type: "no-results",
@@ -261,22 +248,33 @@ var ContextSelectorDropdown = function ContextSelectorDropdown(_ref) {
261
248
  var getItemSize = function getItemSize(index) {
262
249
  var item = activeItems[index];
263
250
  if (isListTitle(item)) return ITEM_SIZE.title;
264
- return menuItemHeight ? ITEM_SIZE[menuItemHeight] : ITEM_SIZE[ItemSize.DEFAULT];
251
+ return menuItemHeight ? ITEM_SIZE[menuItemHeight] : ITEM_SIZE[itemSizes.DEFAULT];
265
252
  };
266
253
 
254
+ var dropdownContentHeight = useMemo(function () {
255
+ return outerHeight - (hasTabs && !searchQuery ? TABS_HEIGHT : 0) - (activeGroup ? SUBGROUP_HEADER_HEIGHT : 0) - SEARCH_HEIGHT;
256
+ }, [activeGroup, hasTabs, outerHeight, searchQuery]);
257
+ useEffect(function () {
258
+ if (scrollBarRef.current && listRef.current) {
259
+ scrollBarRef.current.scrollTo({
260
+ top: 0
261
+ });
262
+ listRef.current.resetAfterIndex(0);
263
+ }
264
+ }, [searchQuery, activeGroup, activeTab]);
267
265
  return /*#__PURE__*/React.createElement(Dropdown.Wrapper, {
268
266
  style: _objectSpread({
269
267
  width: '300px'
270
268
  }, dropdownWrapperStyles),
271
269
  ref: overlayRef,
272
- onKeyDown: function onKeyDown(e) {
270
+ onKeyDown: function onKeyDown(event) {
273
271
  var _document;
274
272
 
275
273
  if (((_document = document) == null ? void 0 : _document.activeElement) === (searchInputHandle == null ? void 0 : searchInputHandle.current)) {
276
274
  setSearchInputFocus(false);
277
275
  }
278
276
 
279
- searchQuery && focusWithArrowKeys(e, classNames.split(' ')[1], function () {
277
+ searchQuery && focusWithArrowKeys(event, classNames.split(' ')[1], function () {
280
278
  setSearchInputFocus(true);
281
279
  });
282
280
  }
@@ -297,7 +295,7 @@ var ContextSelectorDropdown = function ContextSelectorDropdown(_ref) {
297
295
  component: /*#__PURE__*/React.createElement(SearchM, null),
298
296
  color: theme.palette['grey-600']
299
297
  })
300
- }), searchQuery === '' && getTabs.length > 1 && /*#__PURE__*/React.createElement(S.TabsWrapper, null, /*#__PURE__*/React.createElement(Tabs, {
298
+ }), hasTabs && /*#__PURE__*/React.createElement(S.TabsWrapper, null, /*#__PURE__*/React.createElement(Tabs, {
301
299
  block: true,
302
300
  tabs: getTabs,
303
301
  activeTab: activeTab,
@@ -306,14 +304,18 @@ var ContextSelectorDropdown = function ContextSelectorDropdown(_ref) {
306
304
  setActiveGroup(undefined);
307
305
  },
308
306
  visible: visible
309
- })), activeGroup && !searchQuery && /*#__PURE__*/React.createElement(Dropdown.BackAction, {
307
+ })), activeGroup && /*#__PURE__*/React.createElement(Dropdown.BackAction, {
310
308
  label: activeGroup.name,
311
309
  onClick: function onClick() {
312
310
  return setActiveGroup(undefined);
313
311
  }
314
- }), loading ? /*#__PURE__*/React.createElement(DropdownSkeleton, {
315
- size: "M"
316
- }) : /*#__PURE__*/React.createElement(S.ItemsList, null, activeItems != null && activeItems.length ? /*#__PURE__*/React.createElement(Scrollbar, {
312
+ }), loading ? /*#__PURE__*/React.createElement(S.Skeleton, {
313
+ contentHeight: dropdownContentHeight,
314
+ size: "M",
315
+ numberOfSkeletons: 3
316
+ }) : /*#__PURE__*/React.createElement(S.ItemsList, {
317
+ contentHeight: dropdownContentHeight
318
+ }, activeItems != null && activeItems.length ? /*#__PURE__*/React.createElement(Scrollbar, {
317
319
  absolute: true,
318
320
  style: {
319
321
  padding: 8
@@ -321,8 +323,9 @@ var ContextSelectorDropdown = function ContextSelectorDropdown(_ref) {
321
323
  loading: loading,
322
324
  hasMore: hasMoreItems,
323
325
  onYReachEnd: onFetchData,
324
- onScroll: handleScroll
325
- }, /*#__PURE__*/React.createElement(List, {
326
+ onScroll: handleScroll,
327
+ ref: scrollBarRef
328
+ }, /*#__PURE__*/React.createElement(VariableSizeList, {
326
329
  className: "ds-context-selector-list",
327
330
  key: "list-" + activeGroup + "-" + activeTab,
328
331
  width: "100%",
@@ -1,4 +1,4 @@
1
1
  import React from 'react';
2
2
  import { ContextSelectorDropdownItemProps } from '../ContextSelector.types';
3
- declare const ContextSelectorDropdownItem: ({ item, clearSearch, searchQuery, hideDropdown, select, selected, className, menuItemHeight, style, }: ContextSelectorDropdownItemProps) => React.JSX.Element;
3
+ declare const ContextSelectorDropdownItem: ({ item, clearSearch, searchQuery, hideDropdown, select, selected, className, menuItemHeight, style, label, }: ContextSelectorDropdownItemProps) => React.JSX.Element;
4
4
  export default ContextSelectorDropdownItem;
@@ -18,7 +18,8 @@ var ContextSelectorDropdownItem = function ContextSelectorDropdownItem(_ref) {
18
18
  selected = _ref.selected,
19
19
  className = _ref.className,
20
20
  menuItemHeight = _ref.menuItemHeight,
21
- style = _ref.style;
21
+ style = _ref.style,
22
+ label = _ref.label;
22
23
 
23
24
  var id = item.id,
24
25
  _ = item.icon,
@@ -43,7 +44,7 @@ var ContextSelectorDropdownItem = function ContextSelectorDropdownItem(_ref) {
43
44
  },
44
45
  size: menuItemHeight,
45
46
  description: item.description
46
- }, itemProps), item.name);
47
+ }, itemProps), label || item.name);
47
48
  };
48
49
 
49
50
  export default ContextSelectorDropdownItem;
@@ -0,0 +1,3 @@
1
+ import type { ContextGroup, ContextItem, DropdownItemProps, ListTitle } from '../ContextSelector.types';
2
+ export declare const isListTitle: (element: DropdownItemProps) => element is ListTitle;
3
+ export declare const isGroup: (item: ContextItem | ContextGroup) => item is ContextGroup;
@@ -0,0 +1,6 @@
1
+ export var isListTitle = function isListTitle(element) {
2
+ return element.title !== undefined;
3
+ };
4
+ export var isGroup = function isGroup(item) {
5
+ return 'isGroup' in item;
6
+ };
@@ -0,0 +1,12 @@
1
+ export declare const NO_GROUP_NAME = "NO_GROUP_NAME";
2
+ export declare const ITEM_SIZE: {
3
+ large: number;
4
+ default: number;
5
+ title: number;
6
+ };
7
+ export declare const DROPDOWN_HEIGHT = 420;
8
+ export declare const DROPDOWN_HEIGHT_BELOW_THRESHOLD = 350;
9
+ export declare const DROPDOWN_HEIGHT_THRESHOLD = 900;
10
+ export declare const SEARCH_HEIGHT = 53;
11
+ export declare const TABS_HEIGHT = 50;
12
+ export declare const SUBGROUP_HEADER_HEIGHT = 53;
@@ -0,0 +1,11 @@
1
+ var _ITEM_SIZE;
2
+
3
+ import { ItemSize } from '@synerise/ds-menu';
4
+ export var NO_GROUP_NAME = 'NO_GROUP_NAME';
5
+ export var ITEM_SIZE = (_ITEM_SIZE = {}, _ITEM_SIZE[ItemSize.LARGE] = 50, _ITEM_SIZE[ItemSize.DEFAULT] = 32, _ITEM_SIZE.title = 32, _ITEM_SIZE);
6
+ export var DROPDOWN_HEIGHT = 420;
7
+ export var DROPDOWN_HEIGHT_BELOW_THRESHOLD = 350;
8
+ export var DROPDOWN_HEIGHT_THRESHOLD = 900;
9
+ export var SEARCH_HEIGHT = 53;
10
+ export var TABS_HEIGHT = 50;
11
+ export var SUBGROUP_HEADER_HEIGHT = 53;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@synerise/ds-context-selector",
3
- "version": "0.24.6",
3
+ "version": "0.24.8",
4
4
  "description": "ContextSelector UI Component for the Synerise Design System",
5
5
  "license": "ISC",
6
6
  "repository": "Synerise/synerise-design",
@@ -27,25 +27,25 @@
27
27
  "test:watch": "npm run test -- --watchAll",
28
28
  "types": "tsc --noEmit"
29
29
  },
30
- "gitHead": "d5df67eecdc1cbcb56def8c17d04b7d883876fbf",
30
+ "gitHead": "fcf3fa64e906cf9fefb37a61ee28218c8eed9b73",
31
31
  "sideEffects": [
32
32
  "dist/style/*",
33
33
  "*.less"
34
34
  ],
35
35
  "types": "dist/index.d.ts",
36
36
  "dependencies": {
37
- "@synerise/ds-button": "^0.21.7",
38
- "@synerise/ds-dropdown": "^0.18.11",
39
- "@synerise/ds-factors": "^0.24.0",
40
- "@synerise/ds-icon": "^0.65.2",
41
- "@synerise/ds-information-card": "^0.5.5",
42
- "@synerise/ds-list-item": "^0.4.7",
43
- "@synerise/ds-menu": "^0.19.11",
44
- "@synerise/ds-result": "^0.7.1",
45
- "@synerise/ds-scrollbar": "^0.11.7",
46
- "@synerise/ds-skeleton": "^0.6.5",
47
- "@synerise/ds-tabs": "^0.15.4",
48
- "@synerise/ds-utils": "^0.28.2",
37
+ "@synerise/ds-button": "^0.21.9",
38
+ "@synerise/ds-dropdown": "^0.18.13",
39
+ "@synerise/ds-factors": "^0.25.1",
40
+ "@synerise/ds-icon": "^0.65.4",
41
+ "@synerise/ds-information-card": "^0.5.7",
42
+ "@synerise/ds-list-item": "^0.4.9",
43
+ "@synerise/ds-menu": "^0.19.13",
44
+ "@synerise/ds-result": "^0.7.3",
45
+ "@synerise/ds-scrollbar": "^0.11.9",
46
+ "@synerise/ds-skeleton": "^0.6.7",
47
+ "@synerise/ds-tabs": "^0.15.6",
48
+ "@synerise/ds-utils": "^0.29.1",
49
49
  "react-window": "1.8.5",
50
50
  "uuid": "^8.3.2"
51
51
  },