@synerise/ds-search 1.5.14 → 1.5.16

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,16 @@
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
+ ## [1.5.16](https://github.com/Synerise/synerise-design/compare/@synerise/ds-search@1.5.15...@synerise/ds-search@1.5.16) (2026-04-22)
7
+
8
+ **Note:** Version bump only for package @synerise/ds-search
9
+
10
+ ## [1.5.15](https://github.com/Synerise/synerise-design/compare/@synerise/ds-search@1.5.14...@synerise/ds-search@1.5.15) (2026-04-22)
11
+
12
+ ### Bug Fixes
13
+
14
+ - **search:** update click outside logic ([e23b44b](https://github.com/Synerise/synerise-design/commit/e23b44b073337580cabae5ed834cfdf9b45ad383))
15
+
6
16
  ## [1.5.14](https://github.com/Synerise/synerise-design/compare/@synerise/ds-search@1.5.13...@synerise/ds-search@1.5.14) (2026-04-21)
7
17
 
8
18
  **Note:** Version bump only for package @synerise/ds-search
package/README.md CHANGED
@@ -88,7 +88,7 @@ return (
88
88
 
89
89
  ## Demo
90
90
 
91
- <iframe src="/storybook-static/iframe.html?id=components-search--default"></iframe>
91
+ <iframe src="/storybook-static/iframe.html?id=components-search-search--with-dropdown"></iframe>
92
92
 
93
93
  ## API
94
94
 
@@ -157,7 +157,7 @@ return (
157
157
  | alwaysHighlight | When set, the input always has blue border when expanded | boolean | `false` |
158
158
  | alwaysExpanded | Boolean value to force expanded state of the input | boolean | `false` |
159
159
  | clearTooltip | Clear button tooltip text | ReactNode | - |
160
- | closeOnClickOutside | Boolean value to prevent / force toggling the input when clicking outside | boolean | `false` |
160
+ | closeOnClickOutside | Collapses the input when clicking outside. The decision fires on `mousedown`/`touchstart`, but the collapse animation is deferred to the matching `mouseup`/`touchend` so clicks on adjacent layout-shifting content stay reliable | boolean | `false` |
161
161
  | disabled | Disables the entire component including the search button | boolean | - |
162
162
  | disableInput | Disables only the text input; search button remains active | boolean | - |
163
163
  | filterLabel | Label displayed on the left-hand side of the input caret | `{ icon?: ReactNode; [key: string]: any }` or null | - |
@@ -1,6 +1,6 @@
1
1
  import { jsxs, jsx } from "react/jsx-runtime";
2
2
  import Icon, { InfoFillS } from "@synerise/ds-icon";
3
- import Tooltip from "@synerise/ds-tooltip/dist/Tooltip";
3
+ import Tooltip from "@synerise/ds-tooltip";
4
4
  import { MenuHeader, HeaderIconWrapper } from "../../Search.styles.js";
5
5
  const SearchHeader = ({
6
6
  headerText,
@@ -48,11 +48,25 @@ const SearchInput = ({
48
48
  toggleOpen();
49
49
  }
50
50
  });
51
- useOnClickOutside(wrapperRef, () => {
52
- if (closeOnClickOutside && !alwaysExpanded) {
53
- setIsInputOpen(false);
54
- onToggle && onToggle(false);
51
+ const pendingCloseCleanupRef = useRef(null);
52
+ useEffect(() => () => {
53
+ pendingCloseCleanupRef.current?.();
54
+ }, []);
55
+ useOnClickOutside(wrapperRef, (event) => {
56
+ if (!closeOnClickOutside || alwaysExpanded) {
57
+ return;
55
58
  }
59
+ pendingCloseCleanupRef.current?.();
60
+ const endEventName = event.type === "touchstart" ? "touchend" : "mouseup";
61
+ const close = () => {
62
+ pendingCloseCleanupRef.current = null;
63
+ setIsInputOpen(false);
64
+ onToggle?.(false);
65
+ };
66
+ document.addEventListener(endEventName, close, {
67
+ once: true
68
+ });
69
+ pendingCloseCleanupRef.current = () => document.removeEventListener(endEventName, close);
56
70
  });
57
71
  const focusInput = () => {
58
72
  inputRef.current && inputRef.current.focus();
@@ -2,8 +2,9 @@ import { AnyObject } from '../../Search.types';
2
2
  export declare const getAllElementsFiltered: <T extends AnyObject>(data: T[] | undefined | null, value: string, elementTextLookupKey: keyof T) => T[];
3
3
  export declare const hasSomeElementFiltered: <T extends AnyObject>(data: T[] | undefined | null, currentValue: string, elementTextLookupKey: keyof T) => boolean;
4
4
  export declare const hasSomeElement: (data: Record<string, unknown>[] | undefined) => boolean;
5
- export declare const getParametersScrollTop: ({ scrollTop, rowHeight, recent, }: {
5
+ export declare const getParametersScrollTop: ({ scrollTop, rowHeight, recent, hasRecentTitle, }: {
6
6
  scrollTop: number;
7
7
  rowHeight: number;
8
8
  recent: AnyObject[];
9
+ hasRecentTitle?: boolean;
9
10
  }) => number;
@@ -9,8 +9,9 @@ const hasSomeElement = (data) => !!data && data.length > 0;
9
9
  const getParametersScrollTop = ({
10
10
  scrollTop,
11
11
  rowHeight,
12
- recent
13
- }) => scrollTop - LIST_HEADER_HEIGHT - (hasSomeElement(recent) ? recent.length * rowHeight : 0);
12
+ recent,
13
+ hasRecentTitle
14
+ }) => scrollTop - (hasSomeElement(recent) && hasRecentTitle ? LIST_HEADER_HEIGHT : 0) - (hasSomeElement(recent) ? recent.length * rowHeight : 0);
14
15
  export {
15
16
  getAllElementsFiltered,
16
17
  getParametersScrollTop,
package/dist/Search.js CHANGED
@@ -4,7 +4,7 @@ import Scrollbar from "@synerise/ds-scrollbar";
4
4
  import { useOnClickOutside, focusWithArrowKeys } from "@synerise/ds-utils";
5
5
  import SearchInput from "./Elements/SearchInput/SearchInput.js";
6
6
  import "@synerise/ds-icon";
7
- import "@synerise/ds-tooltip/dist/Tooltip";
7
+ import "@synerise/ds-tooltip";
8
8
  import { SearchWrapper, SearchDropdownWrapper, SearchDropdownContent } from "./Search.styles.js";
9
9
  import "react-window";
10
10
  import "@synerise/ds-list-item";
@@ -132,13 +132,26 @@ function Search({
132
132
  return 0;
133
133
  };
134
134
  const [isOpen, setIsOpen] = useState(false);
135
- useOnClickOutside(wrapperRef, () => {
136
- if (isOpen && !value && !label && !alwaysExpanded) {
137
- setToggleInputTrigger((prev) => !prev);
138
- }
139
- setIsOpen(false);
140
- setIsListVisible(false);
141
- setScrollbarScrollTop(0);
135
+ const pendingCloseCleanupRef = useRef(null);
136
+ useEffect(() => () => {
137
+ pendingCloseCleanupRef.current?.();
138
+ }, []);
139
+ useOnClickOutside(wrapperRef, (event) => {
140
+ pendingCloseCleanupRef.current?.();
141
+ const endEventName = event.type === "touchstart" ? "touchend" : "mouseup";
142
+ const close = () => {
143
+ pendingCloseCleanupRef.current = null;
144
+ if (isOpen && !value && !label && !alwaysExpanded) {
145
+ setToggleInputTrigger((prev) => !prev);
146
+ }
147
+ setIsOpen(false);
148
+ setIsListVisible(false);
149
+ setScrollbarScrollTop(0);
150
+ };
151
+ document.addEventListener(endEventName, close, {
152
+ once: true
153
+ });
154
+ pendingCloseCleanupRef.current = () => document.removeEventListener(endEventName, close);
142
155
  });
143
156
  const handleClearValue = () => {
144
157
  onClear?.();
@@ -227,7 +240,8 @@ function Search({
227
240
  scrollTop: getParametersScrollTop({
228
241
  scrollTop: scrollbarScrollTop,
229
242
  recent: filteredRecent,
230
- rowHeight: recentDisplayProps.rowHeight
243
+ rowHeight: recentDisplayProps.rowHeight,
244
+ hasRecentTitle: !!recentDisplayProps.title
231
245
  }),
232
246
  ...parametersDisplayProps.listProps || {}
233
247
  }, onItemClick: (item) => selectFilter(item), ...parametersDisplayProps }),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@synerise/ds-search",
3
- "version": "1.5.14",
3
+ "version": "1.5.16",
4
4
  "description": "Search UI Component for the Synerise Design System",
5
5
  "license": "ISC",
6
6
  "repository": "Synerise/synerise-design",
@@ -32,12 +32,12 @@
32
32
  ],
33
33
  "types": "dist/index.d.ts",
34
34
  "dependencies": {
35
- "@synerise/ds-button": "^1.5.21",
35
+ "@synerise/ds-button": "^1.5.22",
36
36
  "@synerise/ds-icon": "^1.16.0",
37
- "@synerise/ds-list-item": "^1.4.14",
38
- "@synerise/ds-menu": "^1.4.16",
39
- "@synerise/ds-scrollbar": "^1.2.20",
40
- "@synerise/ds-tooltip": "^1.4.13",
37
+ "@synerise/ds-list-item": "^1.4.15",
38
+ "@synerise/ds-menu": "^1.4.17",
39
+ "@synerise/ds-scrollbar": "^1.3.0",
40
+ "@synerise/ds-tooltip": "^1.4.14",
41
41
  "@synerise/ds-utils": "^1.8.0",
42
42
  "react-onclickoutside": "^6.9.0",
43
43
  "react-window": "^1.8.11"
@@ -49,5 +49,5 @@
49
49
  "styled-components": "^5.3.3",
50
50
  "vitest": "4"
51
51
  },
52
- "gitHead": "16b12f75e97d9c416a5cb9ca38864e97ef4f1530"
52
+ "gitHead": "6d4f42c9a899ff73f582a7405a5a2470a4b07083"
53
53
  }