Skip to content

Commit 8d47f80

Browse files
Merge pull request #53 from infinum/release/5.2.1
5.2.1
2 parents 9af8766 + a6d511e commit 8d47f80

File tree

5 files changed

+64
-44
lines changed

5 files changed

+64
-44
lines changed

CHANGELOG.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ All notable changes to this project will be documented in this file.
33

44
This projects adheres to [Semantic Versioning](https://semver.org/) and [Keep a CHANGELOG](https://keepachangelog.com/).
55

6+
## [5.2.1] - 2025-07-28
7+
- Added the option for custom fetch functions in `AsyncSelectNext` and `__AsyncMultiSelectNext`.
8+
69
## [5.2.0] - 2025-07-23
710
- Updated dependencies.
811
- Added experimental MultiSelect and async MultiSelect components (`__MultiSelectNext` and `__AsyncMultiSelectNext`).
@@ -390,7 +393,8 @@ Co-authored with @piqusy
390393
- Initial release
391394

392395
[Unreleased]: https://github.com/infinum/eightshift-ui-components/compare/master...HEAD
393-
[5.1.4]: https://github.com/infinum/eightshift-ui-components/compare/5.1.4...5.2.0
396+
[5.2.1]: https://github.com/infinum/eightshift-ui-components/compare/5.2.0...5.2.1
397+
[5.2.0]: https://github.com/infinum/eightshift-ui-components/compare/5.1.4...5.2.0
394398
[5.1.4]: https://github.com/infinum/eightshift-ui-components/compare/5.1.3...5.1.4
395399
[5.1.3]: https://github.com/infinum/eightshift-ui-components/compare/5.1.2...5.1.3
396400
[5.1.2]: https://github.com/infinum/eightshift-ui-components/compare/5.1.1...5.1.2

lib/components/select/v2/async-multi-select.jsx

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ import { moveArrayItem } from '../shared';
3333
* @param {Function} [props.getIcon] - Function to get the icon for the item from the fetched data. `(item: Object<string, any>) => JSX.Element | string`
3434
* @param {Function} [props.getSubtitle] - Function to get the subtitle for the item from the fetched data. `(item: Object<string, any>) => string`
3535
* @param {Function} [props.getData] - Function to pre-process the fetched data before it is used in the select. `(data: Object<string, any>[]) => Object<string, any>[]`
36+
* @param {Function} [props.fetchUrl] - Function to get the URL for fetching data. Provides typed search text if entered. `(searchText: string) => string`
37+
* @param {Object} [props.fetchConfig] - Configuration object for the fetch request, passed to the `fetch` function.
38+
* @param {Function} [props.fetchFunction] - Allows overriding the default fetch function. `fetchFunction: (url: string, fetchOptions: Object<string, any>, searchText?: string) => Promise<Object<string, any>>`
39+
* @param {Function} [props.processLoadedOptions] - Allows processing the options fetched from the source. `(options: Object<string, any>[]) => Object<string, any>[]`
3640
* @param {JSX.Element} [props.customMenuOption] - If provided, replaces the default item in the dropdown menu. `({ value: string, label: string, subtitle: string, metadata: any }) => JSX.Element`
3741
* @param {JSX.Element} [props.customValueDisplay] - If provided, replaces the default current value display of each selected item. `({ value: string, label: string, subtitle: string, metadata: any }) => JSX.Element`
3842
* @param {JSX.Element} [props.customDropdownArrow] - If provided, replaces the default dropdown arrow indicator.
@@ -76,9 +80,10 @@ export const __AsyncMultiSelectNext = (props) => {
7680

7781
fetchUrl,
7882
fetchConfig = {},
83+
fetchFunction,
7984

80-
getLabel,
81-
getValue,
85+
getLabel = (item) => item?.label,
86+
getValue = (item) => item?.value,
8287
getMeta,
8388
getIcon,
8489
getSubtitle,
@@ -103,8 +108,15 @@ export const __AsyncMultiSelectNext = (props) => {
103108
initialSelectedKeys: Array.isArray(value) ? value.map((item) => item?.value) : [],
104109
getKey: (item) => item.value,
105110
async load({ signal, filterText }) {
106-
const res = await fetch(fetchUrl(filterText), { ...fetchConfig, signal });
107-
const json = processLoadedOptions(getData(await res.json()));
111+
let json = [];
112+
113+
if (fetchFunction) {
114+
const res = await fetchFunction(filterText, signal);
115+
json = processLoadedOptions ? processLoadedOptions(getData(res)) : getData(res);
116+
} else {
117+
const res = await fetch(fetchUrl(filterText), { ...fetchConfig, signal });
118+
json = processLoadedOptions ? processLoadedOptions(getData(await res.json())) : getData(res);
119+
}
108120

109121
const output = json?.map((item, index) => {
110122
const id = getValue?.(item) ?? index;

lib/components/select/v2/async-select.jsx

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ import clsx from 'clsx';
3232
* @param {Function} [props.getIcon] - Function to get the icon for the item from the fetched data. `(item: Object<string, any>) => JSX.Element | string`
3333
* @param {Function} [props.getSubtitle] - Function to get the subtitle for the item from the fetched data. `(item: Object<string, any>) => string`
3434
* @param {Function} [props.getData] - Function to pre-process the fetched data before it is used in the select. `(data: Object<string, any>[]) => Object<string, any>[]`
35+
* @param {Function} [props.fetchUrl] - Function to get the URL for fetching data. Provides typed search text if entered. `(searchText: string) => string`
36+
* @param {Object} [props.fetchConfig] - Configuration object for the fetch request, passed to the `fetch` function.
37+
* @param {Function} [props.fetchFunction] - Allows overriding the default fetch function. `fetchFunction: (url: string, fetchOptions: Object<string, any>, searchText?: string) => Promise<Object<string, any>>`
38+
* @param {Function} [props.processLoadedOptions] - Allows processing the options fetched from the source. `(options: Object<string, any>[]) => Object<string, any>[]`
3539
* @param {JSX.Element} [props.customMenuOption] - If provided, replaces the default item in the dropdown menu. `({ value: string, label: string, subtitle: string, metadata: any }) => JSX.Element`
3640
* @param {JSX.Element} [props.customValueDisplay] - If provided, replaces the default current value display of each selected item. `({ value: string, label: string, subtitle: string, metadata: any }) => JSX.Element`
3741
* @param {JSX.Element} [props.customDropdownArrow] - If provided, replaces the default dropdown arrow indicator.
@@ -81,9 +85,10 @@ export const AsyncSelectNext = (props) => {
8185

8286
fetchUrl,
8387
fetchConfig = {},
88+
fetchFunction,
8489

85-
getLabel,
86-
getValue,
90+
getLabel = (item) => item?.label,
91+
getValue = (item) => item?.value,
8792
getMeta,
8893
getIcon,
8994
getSubtitle,
@@ -99,8 +104,15 @@ export const AsyncSelectNext = (props) => {
99104
const list = useAsyncList({
100105
getKey: (item) => item.value,
101106
async load({ signal, filterText }) {
102-
const res = await fetch(fetchUrl(filterText), { ...fetchConfig, signal });
103-
const json = processLoadedOptions(getData(await res.json()));
107+
let json = [];
108+
109+
if (fetchFunction) {
110+
const res = await fetchFunction(filterText, signal);
111+
json = processLoadedOptions ? processLoadedOptions(getData(res)) : getData(res);
112+
} else {
113+
const res = await fetch(fetchUrl(filterText), { ...fetchConfig, signal });
114+
json = processLoadedOptions ? processLoadedOptions(getData(await res.json())) : getData(res);
115+
}
104116

105117
const output = json?.map((item, index) => {
106118
const id = getValue?.(item) ?? index;

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@eightshift/ui-components",
3-
"version": "5.2.0",
3+
"version": "5.2.1",
44
"type": "module",
55
"main": "./dist/index.js",
66
"module": "./dist/index.js",

src/App.jsx

Lines changed: 26 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,21 @@ function App() {
242242
}
243243

244244
resolve(data.filter(filterData));
245-
}, 30);
245+
}, 300);
246+
});
247+
};
248+
249+
const getDataNew = (searchText) => {
250+
const filterData = ({ label }) => label.toLowerCase().includes(searchText?.toLowerCase());
251+
252+
return new Promise((resolve) => {
253+
setTimeout(() => {
254+
if ((searchText ?? '').length < 3) {
255+
resolve(data);
256+
}
257+
258+
resolve(data.filter(filterData));
259+
}, 300);
246260
});
247261
};
248262

@@ -1908,7 +1922,6 @@ function App() {
19081922
getData={(data) => data?.jokes}
19091923
customDropdownArrow={icons.experiment}
19101924
/>
1911-
19121925
<AsyncSelectNext
19131926
label='Async single select'
19141927
value={sinASel2}
@@ -1925,7 +1938,6 @@ function App() {
19251938
getData={(data) => data?.jokes}
19261939
disabled
19271940
/>
1928-
19291941
<AsyncSelectNext
19301942
label='Async single select - clearable'
19311943
value={sinASel3}
@@ -1950,26 +1962,21 @@ function App() {
19501962
)}
19511963
clearable
19521964
/>
1953-
19541965
<hr />
1955-
19561966
<SelectNext
19571967
label='Single basic'
19581968
value={sinSel}
19591969
onChange={setSinSel}
19601970
options={data}
19611971
/>
1962-
19631972
<hr />
1964-
19651973
<SelectNext
19661974
label='Single basic - simpleValue'
19671975
value={sinSelSimple}
19681976
onChange={setSinSelSimple}
19691977
options={data}
19701978
simpleValue
19711979
/>
1972-
19731980
<SelectNext
19741981
label='Single basic - simpleValue SRCH'
19751982
value={sinSelSimple}
@@ -1978,9 +1985,7 @@ function App() {
19781985
simpleValue
19791986
searchable
19801987
/>
1981-
19821988
<pre>{JSON.stringify(sinSelSimple, null, 2)}</pre>
1983-
19841989
<SelectNext
19851990
label='Single basic - simpleValue with clear'
19861991
value={sinSelSimple}
@@ -1989,9 +1994,7 @@ function App() {
19891994
simpleValue
19901995
clearable
19911996
/>
1992-
19931997
<hr />
1994-
19951998
<SelectNext
19961999
label='Single basic - simpleValue with custom value display'
19972000
value={sinSelSimple}
@@ -2000,7 +2003,6 @@ function App() {
20002003
simpleValue
20012004
customValueDisplay={(item) => <span className='es:font-bold es:text-blue-400'>{item?.label}</span>}
20022005
/>
2003-
20042006
<SelectNext
20052007
label='Single basic - simpleValue with custom menu item'
20062008
value={sinSelSimple}
@@ -2009,14 +2011,12 @@ function App() {
20092011
simpleValue
20102012
customMenuOption={(item) => <span className='es:font-bold es:text-blue-400'>{item?.label}</span>}
20112013
/>
2012-
20132014
<SelectNext
20142015
label='Single basic'
20152016
value={sinSel}
20162017
onChange={setSinSel}
20172018
options={data}
20182019
/>
2019-
20202020
<AsyncSelectNext
20212021
label='Async single select PROD'
20222022
value={sinASel2}
@@ -2030,7 +2030,6 @@ function App() {
20302030
getIcon={() => icons.emptyCircle}
20312031
processLoadedOptions={(items) => items.map((item) => ({ ...item, value: slugify(item?.name) }))}
20322032
/>
2033-
20342033
<AsyncSelectNext
20352034
label='Async single select PROD'
20362035
value={sinASel2}
@@ -2057,7 +2056,6 @@ function App() {
20572056
processLoadedOptions={(items) => items.map((item) => ({ ...item, value: slugify(item?.name) }))}
20582057
clearable
20592058
/>
2060-
20612059
<AsyncSelectNext
20622060
label='Async single select PROD'
20632061
value={sinASel2}
@@ -2071,7 +2069,6 @@ function App() {
20712069
processLoadedOptions={(items) => items.map((item) => ({ ...item, value: slugify(item?.name) }))}
20722070
clearable
20732071
/>
2074-
20752072
<AsyncSelectNext
20762073
label='Async single select PROD LOGGEr2'
20772074
value={sinASel2}
@@ -2089,23 +2086,18 @@ function App() {
20892086
processLoadedOptions={(items) => items.map((item) => ({ ...item, value: slugify(item?.name) }))}
20902087
clearable
20912088
/>
2092-
20932089
{JSON.stringify(sinASel2)}
2094-
20952090
<hr />
2096-
20972091
<AsyncMultiSelect
20982092
label='Multi async'
20992093
value={mulASel}
21002094
onChange={setMulASel}
21012095
loadOptions={getDataAlt}
21022096
/>
2103-
21042097
<__AsyncMultiSelectNext
21052098
label='Multi async NEXT'
21062099
value={mulASel}
21072100
onChange={setMulASel}
2108-
// loadOptions={getData}
21092101
fetchUrl={(searchText) =>
21102102
searchText?.length >= 3 ? `http://universities.hipolabs.com/search?limit=5&name=${searchText}` : 'http://universities.hipolabs.com/search?limit=5&country=croatia'
21112103
}
@@ -2114,21 +2106,21 @@ function App() {
21142106
getSubtitle={(item) => item?.country}
21152107
getIcon={() => icons.emptyCircle}
21162108
processLoadedOptions={(items) => items.map((item) => ({ ...item, value: slugify(item?.name) }))}
2109+
clearable
21172110
/>
2118-
2111+
<hr />
2112+
Custom
21192113
<__AsyncMultiSelectNext
2120-
label='Multi async NEXT'
2114+
label='Multi async NEXT CSTM'
21212115
value={mulASel}
21222116
onChange={setMulASel}
2123-
fetchUrl={(searchText) =>
2124-
searchText?.length >= 3 ? `http://universities.hipolabs.com/search?limit=5&name=${searchText}` : 'http://universities.hipolabs.com/search?limit=5&country=croatia'
2125-
}
2126-
getLabel={(item) => item?.name}
2127-
getValue={(item) => item?.value}
2128-
getSubtitle={(item) => item?.country}
2129-
getIcon={() => icons.emptyCircle}
2130-
processLoadedOptions={(items) => items.map((item) => ({ ...item, value: slugify(item?.name) }))}
2131-
clearable
2117+
fetchFunction={getDataNew}
2118+
/>
2119+
<AsyncSelectNext
2120+
label='Async single select NEXT CSTM'
2121+
value={sinASel2}
2122+
onChange={setSinASel2}
2123+
fetchFunction={getDataNew}
21322124
/>
21332125
</TabPanel>
21342126
<TabPanel className='es:m-5 es:w-96 es:space-y-4 es:p-5!'>

0 commit comments

Comments
 (0)