@sb1/ffe-searchable-dropdown-react 100.8.2 → 100.9.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/README.md +175 -33
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -1,58 +1,200 @@
|
|
|
1
|
-
# ffe-searchable-dropdown-react
|
|
1
|
+
# @sb1/ffe-searchable-dropdown-react
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
## Beskrivelse
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Søkbar nedtrekksliste for store eller dynamiske lister. Tilgjengelig som enkeltvalg (`SearchableDropdown`) og flervalg (`SearchableDropdownMultiSelect`).
|
|
6
|
+
|
|
7
|
+
## Installasjon
|
|
6
8
|
|
|
7
9
|
```bash
|
|
8
|
-
npm install --save ffe-searchable-dropdown-react
|
|
10
|
+
npm install --save @sb1/ffe-searchable-dropdown-react
|
|
9
11
|
```
|
|
10
12
|
|
|
11
|
-
##
|
|
12
|
-
|
|
13
|
-
Full documentation on searchable dropdown usage is available at https://design.sparebank1.no/komponenter/dropdown/#searchabledropdown.
|
|
13
|
+
## Bruk
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
Make sure you import the less-files.
|
|
15
|
+
Full dokumentasjon: https://sparebank1.github.io/designsystem/
|
|
17
16
|
|
|
18
|
-
|
|
19
|
-
import { SearchableDropdown } from '@sb1/ffe-searchable-dropdown-react';
|
|
20
|
-
```
|
|
17
|
+
Avhengigheter: `@sb1/ffe-form-react`, `@sb1/ffe-icons-react`, `@sb1/ffe-chips-react`, `@sb1/ffe-spinner-react`.
|
|
21
18
|
|
|
22
|
-
|
|
19
|
+
### Importere kompilert CSS
|
|
23
20
|
|
|
24
|
-
```
|
|
25
|
-
@import
|
|
21
|
+
```css
|
|
22
|
+
@import '@sb1/ffe-searchable-dropdown-react/css/searchable-dropdown.css';
|
|
26
23
|
```
|
|
27
24
|
|
|
28
|
-
|
|
25
|
+
## Eksempler
|
|
29
26
|
|
|
30
|
-
|
|
27
|
+
### Enkeltvalg
|
|
31
28
|
|
|
32
|
-
```
|
|
33
|
-
|
|
29
|
+
```tsx
|
|
30
|
+
import { useState } from 'react';
|
|
31
|
+
import { SearchableDropdown } from '@sb1/ffe-searchable-dropdown-react';
|
|
32
|
+
import { InputGroup } from '@sb1/ffe-form-react';
|
|
33
|
+
|
|
34
|
+
interface Company {
|
|
35
|
+
organizationName: string;
|
|
36
|
+
organizationNumber: string;
|
|
37
|
+
balance: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function MyComponent() {
|
|
41
|
+
const [selected, setSelected] = useState<Company | null>(null);
|
|
42
|
+
|
|
43
|
+
const companies: Company[] = [
|
|
44
|
+
{
|
|
45
|
+
organizationName: 'Bedriften AS',
|
|
46
|
+
organizationNumber: '912602370',
|
|
47
|
+
balance: '12 345,00 kr',
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
organizationName: 'Firma AS',
|
|
51
|
+
organizationNumber: '812602372',
|
|
52
|
+
balance: '45 678,00 kr',
|
|
53
|
+
},
|
|
54
|
+
];
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<InputGroup
|
|
58
|
+
label="Velg bedrift"
|
|
59
|
+
labelId="company-label"
|
|
60
|
+
inputId="company-dropdown"
|
|
61
|
+
>
|
|
62
|
+
<SearchableDropdown<Company>
|
|
63
|
+
id="company-dropdown"
|
|
64
|
+
labelledById="company-label"
|
|
65
|
+
dropdownList={companies}
|
|
66
|
+
dropdownAttributes={['organizationName', 'organizationNumber']}
|
|
67
|
+
searchAttributes={['organizationName', 'organizationNumber']}
|
|
68
|
+
selectedItem={selected}
|
|
69
|
+
onChange={item => setSelected(item)}
|
|
70
|
+
noMatch={{ text: 'Ingen treff' }}
|
|
71
|
+
inputProps={{ placeholder: 'Søk etter bedrift' }}
|
|
72
|
+
locale="nb"
|
|
73
|
+
/>
|
|
74
|
+
</InputGroup>
|
|
75
|
+
);
|
|
76
|
+
}
|
|
34
77
|
```
|
|
35
78
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
79
|
+
### Flervalg
|
|
80
|
+
|
|
81
|
+
Valgte elementer vises som chips. `onChange` kalles med elementet og `actionType` ('selected' | 'removed').
|
|
82
|
+
|
|
83
|
+
```tsx
|
|
84
|
+
import { useState } from 'react';
|
|
85
|
+
import { SearchableDropdownMultiSelect } from '@sb1/ffe-searchable-dropdown-react';
|
|
86
|
+
import { InputGroup } from '@sb1/ffe-form-react';
|
|
87
|
+
|
|
88
|
+
interface Fruit {
|
|
89
|
+
displayName: string;
|
|
90
|
+
color: string;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function MyComponent() {
|
|
94
|
+
const [selectedFruits, setSelectedFruits] = useState<Fruit[]>([]);
|
|
95
|
+
|
|
96
|
+
const fruits: Fruit[] = [
|
|
97
|
+
{ displayName: 'Banan', color: 'Gul' },
|
|
98
|
+
{ displayName: 'Eple', color: 'Rød' },
|
|
99
|
+
];
|
|
100
|
+
|
|
101
|
+
const handleChange = (item: Fruit, actionType: 'selected' | 'removed') => {
|
|
102
|
+
if (actionType === 'selected') {
|
|
103
|
+
setSelectedFruits(prev => [...prev, item]);
|
|
104
|
+
} else {
|
|
105
|
+
setSelectedFruits(prev =>
|
|
106
|
+
prev.filter(f => f.displayName !== item.displayName),
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
return (
|
|
112
|
+
<InputGroup
|
|
113
|
+
label="Velg frukt"
|
|
114
|
+
labelId="fruit-label"
|
|
115
|
+
inputId="fruit-multiselect"
|
|
116
|
+
>
|
|
117
|
+
<SearchableDropdownMultiSelect<Fruit>
|
|
118
|
+
id="fruit-multiselect"
|
|
119
|
+
labelledById="fruit-label"
|
|
120
|
+
dropdownList={fruits}
|
|
121
|
+
dropdownAttributes={['displayName', 'color']}
|
|
122
|
+
searchAttributes={['displayName', 'color']}
|
|
123
|
+
selectedItems={selectedFruits}
|
|
124
|
+
onChange={handleChange}
|
|
125
|
+
noMatch={{ text: 'Ingen frukt funnet' }}
|
|
126
|
+
locale="nb"
|
|
127
|
+
/>
|
|
128
|
+
</InputGroup>
|
|
129
|
+
);
|
|
130
|
+
}
|
|
40
131
|
```
|
|
41
132
|
|
|
42
|
-
|
|
133
|
+
### Egendefinert optionBody
|
|
134
|
+
|
|
135
|
+
```tsx
|
|
136
|
+
import type { Locale } from '@sb1/ffe-searchable-dropdown-react';
|
|
137
|
+
|
|
138
|
+
// For SearchableDropdown
|
|
139
|
+
const CustomOptionBody = ({
|
|
140
|
+
item,
|
|
141
|
+
isHighlighted,
|
|
142
|
+
}: {
|
|
143
|
+
item: Company;
|
|
144
|
+
isHighlighted: boolean;
|
|
145
|
+
dropdownAttributes: (keyof Company)[];
|
|
146
|
+
locale: Locale;
|
|
147
|
+
}) => (
|
|
148
|
+
<div style={{ background: isHighlighted ? '#e0e0e0' : 'white' }}>
|
|
149
|
+
<strong>{item.organizationName}</strong>
|
|
150
|
+
<div>{item.organizationNumber}</div>
|
|
151
|
+
</div>
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
// For SearchableDropdownMultiSelect - har ekstra `isSelected`-prop
|
|
155
|
+
```
|
|
43
156
|
|
|
44
|
-
|
|
157
|
+
### Egendefinert søkefunksjon
|
|
158
|
+
|
|
159
|
+
```tsx
|
|
160
|
+
const customSearchMatcher = (
|
|
161
|
+
inputValue: string,
|
|
162
|
+
searchAttributes: string[],
|
|
163
|
+
) => {
|
|
164
|
+
const cleanedInput = inputValue.toLowerCase().replace(/\s/g, '');
|
|
165
|
+
return (item: Record<string, any>) =>
|
|
166
|
+
searchAttributes.some(attr =>
|
|
167
|
+
String(item[attr])
|
|
168
|
+
.toLowerCase()
|
|
169
|
+
.replace(/\s/g, '')
|
|
170
|
+
.includes(cleanedInput),
|
|
171
|
+
);
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
<SearchableDropdown searchMatcher={customSearchMatcher} /* ... */ />;
|
|
175
|
+
```
|
|
45
176
|
|
|
46
|
-
|
|
177
|
+
### Vis alternativt innhold ved ingen treff
|
|
178
|
+
|
|
179
|
+
```tsx
|
|
180
|
+
<SearchableDropdown
|
|
181
|
+
noMatch={{
|
|
182
|
+
text: 'Fant ingen treff',
|
|
183
|
+
dropdownList: [
|
|
184
|
+
{
|
|
185
|
+
organizationName: 'Foreslått bedrift',
|
|
186
|
+
organizationNumber: '123456789',
|
|
187
|
+
balance: '0 kr',
|
|
188
|
+
},
|
|
189
|
+
],
|
|
190
|
+
}}
|
|
191
|
+
/>
|
|
192
|
+
```
|
|
47
193
|
|
|
48
|
-
|
|
194
|
+
## Utvikling
|
|
49
195
|
|
|
50
196
|
```bash
|
|
51
|
-
npm install
|
|
52
|
-
npm run build
|
|
53
|
-
npm start
|
|
197
|
+
npm install && npm run build && npm start
|
|
54
198
|
```
|
|
55
199
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
Example implementations using the latest versions of all components are also available at https://sparebank1.github.io/designsystem.
|
|
200
|
+
Lokal Storybook kjører på http://localhost:6006/.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sb1/ffe-searchable-dropdown-react",
|
|
3
|
-
"version": "100.
|
|
3
|
+
"version": "100.9.0",
|
|
4
4
|
"description": "Dropdown with search option",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "SpareBank 1",
|
|
@@ -27,11 +27,11 @@
|
|
|
27
27
|
"test:watch": "ffe-buildtool jest --watch"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@sb1/ffe-chips-react": "^100.
|
|
31
|
-
"@sb1/ffe-core-react": "^100.
|
|
32
|
-
"@sb1/ffe-form": "^100.
|
|
33
|
-
"@sb1/ffe-icons-react": "^100.
|
|
34
|
-
"@sb1/ffe-spinner-react": "^100.
|
|
30
|
+
"@sb1/ffe-chips-react": "^100.9.0",
|
|
31
|
+
"@sb1/ffe-core-react": "^100.9.0",
|
|
32
|
+
"@sb1/ffe-form": "^100.9.0",
|
|
33
|
+
"@sb1/ffe-icons-react": "^100.9.0",
|
|
34
|
+
"@sb1/ffe-spinner-react": "^100.9.0",
|
|
35
35
|
"@types/lodash.isequal": "^4.5.8",
|
|
36
36
|
"classnames": "^2.3.1",
|
|
37
37
|
"compute-scroll-into-view": "^3.1.0",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"react-custom-scrollbars-4": "^4.5.1"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
|
-
"@sb1/ffe-buildtool": "^100.
|
|
43
|
+
"@sb1/ffe-buildtool": "^100.9.0",
|
|
44
44
|
"eslint": "^9.22.0",
|
|
45
45
|
"react": "^18.2.0",
|
|
46
46
|
"react-dom": "^18.2.0"
|
|
@@ -51,5 +51,5 @@
|
|
|
51
51
|
"publishConfig": {
|
|
52
52
|
"access": "public"
|
|
53
53
|
},
|
|
54
|
-
"gitHead": "
|
|
54
|
+
"gitHead": "41f20cf10bec5ebe53036c282690983d2114fb45"
|
|
55
55
|
}
|