@synerise/ds-select 2.0.3 → 2.1.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.
- package/CHANGELOG.md +10 -0
- package/dist/components/OptionList.js +19 -59
- package/package.json +9 -9
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
|
+
# [2.1.0](https://github.com/synerise/synerise-design/compare/@synerise/ds-select@2.0.4...@synerise/ds-select@2.1.0) (2026-09-16)
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
- **list-item:** add content-fitting size="auto" ([e269f0a](https://github.com/synerise/synerise-design/commit/e269f0a48ca7472f4766a50a957e22d7988c5e13))
|
|
11
|
+
|
|
12
|
+
## [2.0.4](https://github.com/synerise/synerise-design/compare/@synerise/ds-select@2.0.3...@synerise/ds-select@2.0.4) (2026-09-08)
|
|
13
|
+
|
|
14
|
+
**Note:** Version bump only for package @synerise/ds-select
|
|
15
|
+
|
|
6
16
|
## [2.0.3](https://github.com/synerise/synerise-design/compare/@synerise/ds-select@2.0.2...@synerise/ds-select@2.0.3) (2026-09-07)
|
|
7
17
|
|
|
8
18
|
**Note:** Version bump only for package @synerise/ds-select
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
|
-
import { forwardRef, memo, useRef,
|
|
2
|
+
import { forwardRef, memo, useRef, useCallback, useMemo, useEffect } from "react";
|
|
3
3
|
import { VariableSizeList } from "react-window";
|
|
4
4
|
import Loader from "@synerise/ds-loader";
|
|
5
5
|
import Scrollbar from "@synerise/ds-scrollbar";
|
|
6
|
+
import { useMeasuredRow, useMeasuredRowHeights } from "@synerise/ds-utils";
|
|
6
7
|
import { VirtualRow, OptionItem, DropdownWrapper, Loading, NotFound, ScrollList, Inner } from "../Select.styles.js";
|
|
7
8
|
import { cx, DEFAULT_LIST_ITEM_HEIGHT, MAX_MEASURED_ROWS, DEFAULT_LIST_HEIGHT, OVERSCAN_COUNT } from "../utils/helpers.js";
|
|
8
9
|
const LIST_STYLE = {
|
|
@@ -26,20 +27,7 @@ const OptionRow = memo(({
|
|
|
26
27
|
measureRow
|
|
27
28
|
} = data;
|
|
28
29
|
const option = options[index];
|
|
29
|
-
const rowRef =
|
|
30
|
-
useLayoutEffect(() => {
|
|
31
|
-
const height = rowRef.current?.offsetHeight ?? 0;
|
|
32
|
-
measureRow(index, height);
|
|
33
|
-
});
|
|
34
|
-
useLayoutEffect(() => {
|
|
35
|
-
const node = rowRef.current;
|
|
36
|
-
if (!node || typeof ResizeObserver === "undefined") {
|
|
37
|
-
return void 0;
|
|
38
|
-
}
|
|
39
|
-
const observer = new ResizeObserver(() => measureRow(index, node.offsetHeight));
|
|
40
|
-
observer.observe(node);
|
|
41
|
-
return () => observer.disconnect();
|
|
42
|
-
}, [index, measureRow]);
|
|
30
|
+
const rowRef = useMeasuredRow(index, measureRow);
|
|
43
31
|
const isSelected = selectedValues.includes(option.value);
|
|
44
32
|
const optionAttrs = Object.fromEntries(Object.entries(option).filter(([key]) => key.startsWith("data-") || key.startsWith("aria-")));
|
|
45
33
|
return /* @__PURE__ */ jsx(
|
|
@@ -93,60 +81,32 @@ const OptionList = ({
|
|
|
93
81
|
onOptionSelect,
|
|
94
82
|
onPopupScroll
|
|
95
83
|
}) => {
|
|
96
|
-
const listRef = useRef(null);
|
|
97
84
|
const scrollRef = useRef(null);
|
|
98
85
|
const scrollOffsetRef = useRef(0);
|
|
99
|
-
const sizeCacheRef = useRef(/* @__PURE__ */ new Map());
|
|
100
86
|
const windowHeight = Number(listHeight) || DEFAULT_LIST_HEIGHT;
|
|
101
87
|
const rowHeight = listItemHeight && listItemHeight > 0 ? listItemHeight : DEFAULT_LIST_ITEM_HEIGHT;
|
|
102
88
|
const keyFor = useCallback((option) => rowKey ? rowKey(option) : option.key ?? option.value, [rowKey]);
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
sizeCacheRef.current.set(key, height);
|
|
120
|
-
listRef.current?.resetAfterIndex(index);
|
|
121
|
-
}, [options, keyFor]);
|
|
122
|
-
const prevRowHeightRef = useRef(rowHeight);
|
|
123
|
-
useLayoutEffect(() => {
|
|
124
|
-
if (prevRowHeightRef.current === rowHeight) {
|
|
125
|
-
return;
|
|
126
|
-
}
|
|
127
|
-
prevRowHeightRef.current = rowHeight;
|
|
128
|
-
sizeCacheRef.current.clear();
|
|
129
|
-
listRef.current?.resetAfterIndex(0);
|
|
130
|
-
}, [rowHeight]);
|
|
131
|
-
useEffect(() => {
|
|
132
|
-
const cache = sizeCacheRef.current;
|
|
133
|
-
if (cache.size > MAX_MEASURED_ROWS) {
|
|
134
|
-
const live = new Set(options.map(keyFor));
|
|
135
|
-
cache.forEach((_height, key) => {
|
|
136
|
-
if (!live.has(key)) {
|
|
137
|
-
cache.delete(key);
|
|
138
|
-
}
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
listRef.current?.resetAfterIndex(0, false);
|
|
142
|
-
}, [options, keyFor]);
|
|
89
|
+
const rowKeys = useMemo(() => options.map(keyFor), [options, keyFor]);
|
|
90
|
+
const estimateRowHeight = useCallback(() => rowHeight, [rowHeight]);
|
|
91
|
+
const {
|
|
92
|
+
listRef,
|
|
93
|
+
getItemSize,
|
|
94
|
+
measureRow
|
|
95
|
+
} = useMeasuredRowHeights({
|
|
96
|
+
keys: rowKeys,
|
|
97
|
+
estimate: estimateRowHeight,
|
|
98
|
+
// `listItemHeight` can change under a stable option list; every cached
|
|
99
|
+
// measurement was taken against the old value, so they all have to go.
|
|
100
|
+
estimateVersion: rowHeight,
|
|
101
|
+
maxCachedRows: MAX_MEASURED_ROWS
|
|
102
|
+
});
|
|
143
103
|
const scrollTo = useCallback((offset) => {
|
|
144
104
|
scrollOffsetRef.current = offset;
|
|
145
105
|
if (scrollRef.current) {
|
|
146
106
|
scrollRef.current.scrollTop = offset;
|
|
147
107
|
}
|
|
148
108
|
listRef.current?.scrollTo(offset);
|
|
149
|
-
}, []);
|
|
109
|
+
}, [listRef]);
|
|
150
110
|
const isFirstQuery = useRef(true);
|
|
151
111
|
useEffect(() => {
|
|
152
112
|
if (isFirstQuery.current) {
|
|
@@ -183,7 +143,7 @@ const OptionList = ({
|
|
|
183
143
|
scrollOffsetRef.current = scrollTop;
|
|
184
144
|
listRef.current?.scrollTo(scrollTop);
|
|
185
145
|
onPopupScroll?.(event);
|
|
186
|
-
}, [onPopupScroll]);
|
|
146
|
+
}, [listRef, onPopupScroll]);
|
|
187
147
|
const itemData = useMemo(() => ({
|
|
188
148
|
options,
|
|
189
149
|
selectedValues,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@synerise/ds-select",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "Select UI Component for the Synerise Design System",
|
|
5
5
|
"license": "ISC",
|
|
6
6
|
"repository": "synerise/synerise-design",
|
|
@@ -42,14 +42,14 @@
|
|
|
42
42
|
],
|
|
43
43
|
"types": "dist/index.d.ts",
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@synerise/ds-dropdown": "^2.0
|
|
46
|
-
"@synerise/ds-form-field": "^2.0.
|
|
47
|
-
"@synerise/ds-icon": "^2.1.
|
|
48
|
-
"@synerise/ds-list-item": "^2.0
|
|
45
|
+
"@synerise/ds-dropdown": "^2.1.0",
|
|
46
|
+
"@synerise/ds-form-field": "^2.0.3",
|
|
47
|
+
"@synerise/ds-icon": "^2.1.1",
|
|
48
|
+
"@synerise/ds-list-item": "^2.1.0",
|
|
49
49
|
"@synerise/ds-loader": "^2.0.0",
|
|
50
|
-
"@synerise/ds-scrollbar": "^2.0.
|
|
51
|
-
"@synerise/ds-tooltip": "^2.0.
|
|
52
|
-
"@synerise/ds-utils": "^2.
|
|
50
|
+
"@synerise/ds-scrollbar": "^2.0.2",
|
|
51
|
+
"@synerise/ds-tooltip": "^2.0.3",
|
|
52
|
+
"@synerise/ds-utils": "^2.1.0",
|
|
53
53
|
"classnames": "^2.5.1",
|
|
54
54
|
"react-window": "^1.8.11"
|
|
55
55
|
},
|
|
@@ -59,5 +59,5 @@
|
|
|
59
59
|
"styled-components": "^5.3.3",
|
|
60
60
|
"vitest": "4"
|
|
61
61
|
},
|
|
62
|
-
"gitHead": "
|
|
62
|
+
"gitHead": "71f08fdaba8e7b80731e29a03883dc6a33f2b9db"
|
|
63
63
|
}
|