@performant-software/semantic-components 1.0.5 → 1.0.6-beta.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/build/index.js +1 -1
- package/build/index.js.map +1 -1
- package/package.json +2 -2
- package/src/components/Selectize.js +49 -5
- package/src/i18n/en.json +7 -1
- package/types/components/Selectize.js.flow +49 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@performant-software/semantic-components",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.6-beta.0",
|
|
4
4
|
"description": "A package of shared components based on the Semantic UI Framework.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "./build/index.js",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"build": "webpack --mode production && flow-copy-source -v src types"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@performant-software/shared-components": "^1.0.
|
|
15
|
+
"@performant-software/shared-components": "^1.0.6-beta.0",
|
|
16
16
|
"@react-google-maps/api": "^2.8.1",
|
|
17
17
|
"axios": "^0.26.1",
|
|
18
18
|
"citeproc": "^2.4.62",
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import React, {
|
|
4
4
|
useCallback,
|
|
5
5
|
useEffect,
|
|
6
|
+
useMemo,
|
|
6
7
|
useState,
|
|
7
8
|
type ComponentType,
|
|
8
9
|
type Element
|
|
@@ -12,6 +13,7 @@ import {
|
|
|
12
13
|
Form,
|
|
13
14
|
Grid,
|
|
14
15
|
Icon,
|
|
16
|
+
Message,
|
|
15
17
|
Modal,
|
|
16
18
|
Table
|
|
17
19
|
} from 'semantic-ui-react';
|
|
@@ -35,7 +37,7 @@ type Props = {
|
|
|
35
37
|
modal?: {
|
|
36
38
|
onSave: (item: any) => Promise<any>
|
|
37
39
|
},
|
|
38
|
-
multiple?: boolean,
|
|
40
|
+
multiple?: boolean | number,
|
|
39
41
|
onClose: () => void,
|
|
40
42
|
onLoad: (params: any) => Promise<any>,
|
|
41
43
|
onSave: (items: any) => void,
|
|
@@ -48,8 +50,13 @@ type GridProps = ListProps & {
|
|
|
48
50
|
onInit: () => void,
|
|
49
51
|
onItemSelection: (item: any) => void,
|
|
50
52
|
onSelect: (item: any) => void,
|
|
51
|
-
renderHeader
|
|
52
|
-
renderItem
|
|
53
|
+
renderHeader?: (params: any) => Element<any>,
|
|
54
|
+
renderItem?: (item: any) => Element<any>,
|
|
55
|
+
renderItems?: ({
|
|
56
|
+
isSelected: (item: any) => boolean,
|
|
57
|
+
items: any,
|
|
58
|
+
onSelect: () => void
|
|
59
|
+
}) => Element<any>,
|
|
53
60
|
selectedItem: any,
|
|
54
61
|
selectedItems: Array<any>
|
|
55
62
|
};
|
|
@@ -113,6 +120,14 @@ const SelectizeGrid = useDataList(useList((props: GridProps) => {
|
|
|
113
120
|
return null;
|
|
114
121
|
}
|
|
115
122
|
|
|
123
|
+
if (props.renderItems) {
|
|
124
|
+
return props.renderItems({
|
|
125
|
+
isSelected: props.isSelected,
|
|
126
|
+
items: props.items,
|
|
127
|
+
onSelect: props.onSelect
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
|
|
116
131
|
return (
|
|
117
132
|
<Table
|
|
118
133
|
basic
|
|
@@ -161,7 +176,7 @@ const SelectizeGrid = useDataList(useList((props: GridProps) => {
|
|
|
161
176
|
/>
|
|
162
177
|
</Grid.Row>
|
|
163
178
|
<Grid.Row>
|
|
164
|
-
{ i18n.t('Selectize.noRecords') }
|
|
179
|
+
{ i18n.t('Selectize.messages.noRecords') }
|
|
165
180
|
</Grid.Row>
|
|
166
181
|
</Grid.Column>
|
|
167
182
|
</Grid>
|
|
@@ -182,9 +197,27 @@ const SelectizeGrid = useDataList(useList((props: GridProps) => {
|
|
|
182
197
|
}));
|
|
183
198
|
|
|
184
199
|
const Selectize = (props: Props) => {
|
|
200
|
+
const [error, setError] = useState(false);
|
|
185
201
|
const [selectedItem, setSelectedItem] = useState();
|
|
186
202
|
const [selectedItems, setSelectedItems] = useState(props.selectedItems || []);
|
|
187
203
|
|
|
204
|
+
/**
|
|
205
|
+
* Sets the allowMultiple prop to "true" if the multiple prop is a boolean or non-zero integer.
|
|
206
|
+
*
|
|
207
|
+
* @type {boolean}
|
|
208
|
+
*/
|
|
209
|
+
const allowMultiple = useMemo(() => !!props.multiple, [props.multiple]);
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Sets the allowed number of items that can be selected. If the multiple prop is a boolean, this will be
|
|
213
|
+
* and unlimited amount.
|
|
214
|
+
*
|
|
215
|
+
* @type {boolean|number}
|
|
216
|
+
*/
|
|
217
|
+
const allowedCount = useMemo(() => (
|
|
218
|
+
_.isNumber(props.multiple) ? props.multiple : Number.MAX_SAFE_INTEGER
|
|
219
|
+
), [props.multiple]);
|
|
220
|
+
|
|
188
221
|
/**
|
|
189
222
|
* Returns true if the passed item is selected.
|
|
190
223
|
*
|
|
@@ -196,13 +229,17 @@ const Selectize = (props: Props) => {
|
|
|
196
229
|
* If the passed item is selected, deselect the item. If we're not allowing multiple select, replace the selected
|
|
197
230
|
* items with the passed item. Otherwise, append the passed item to the list of selected items.
|
|
198
231
|
*
|
|
232
|
+
* If the user has already selected the maximum number allowed, display an error message.
|
|
233
|
+
*
|
|
199
234
|
* @type {(function(*=): void)|*}
|
|
200
235
|
*/
|
|
201
236
|
const onSelect = useCallback((item) => {
|
|
202
237
|
if (isSelected(item)) {
|
|
203
238
|
setSelectedItems((prevItems) => _.filter(prevItems, (i) => i.id !== item.id));
|
|
204
|
-
} else if (!
|
|
239
|
+
} else if (!allowMultiple) {
|
|
205
240
|
setSelectedItems([item]);
|
|
241
|
+
} else if (selectedItems.length >= allowedCount) {
|
|
242
|
+
setError(true);
|
|
206
243
|
} else {
|
|
207
244
|
setSelectedItems((prevItems) => [
|
|
208
245
|
...prevItems,
|
|
@@ -254,6 +291,13 @@ const Selectize = (props: Props) => {
|
|
|
254
291
|
content={props.title}
|
|
255
292
|
/>
|
|
256
293
|
<Modal.Content>
|
|
294
|
+
<Message
|
|
295
|
+
content={i18n.t('Selectize.messages.maxSelected.content')}
|
|
296
|
+
error
|
|
297
|
+
header={i18n.t('Selectize.messages.maxSelected.header')}
|
|
298
|
+
onDismiss={() => setError(false)}
|
|
299
|
+
visible={error}
|
|
300
|
+
/>
|
|
257
301
|
<SelectizeGrid
|
|
258
302
|
{...props}
|
|
259
303
|
actions={[]}
|
package/src/i18n/en.json
CHANGED
|
@@ -259,7 +259,13 @@
|
|
|
259
259
|
}
|
|
260
260
|
},
|
|
261
261
|
"Selectize": {
|
|
262
|
-
"
|
|
262
|
+
"messages": {
|
|
263
|
+
"maxSelected": {
|
|
264
|
+
"content": "You have already selected the maximum number of items allowed.",
|
|
265
|
+
"header": "Maximum items selected"
|
|
266
|
+
},
|
|
267
|
+
"noRecords": "No matching records."
|
|
268
|
+
}
|
|
263
269
|
},
|
|
264
270
|
"VideoFrameSelector": {
|
|
265
271
|
"buttons": {
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import React, {
|
|
4
4
|
useCallback,
|
|
5
5
|
useEffect,
|
|
6
|
+
useMemo,
|
|
6
7
|
useState,
|
|
7
8
|
type ComponentType,
|
|
8
9
|
type Element
|
|
@@ -12,6 +13,7 @@ import {
|
|
|
12
13
|
Form,
|
|
13
14
|
Grid,
|
|
14
15
|
Icon,
|
|
16
|
+
Message,
|
|
15
17
|
Modal,
|
|
16
18
|
Table
|
|
17
19
|
} from 'semantic-ui-react';
|
|
@@ -35,7 +37,7 @@ type Props = {
|
|
|
35
37
|
modal?: {
|
|
36
38
|
onSave: (item: any) => Promise<any>
|
|
37
39
|
},
|
|
38
|
-
multiple?: boolean,
|
|
40
|
+
multiple?: boolean | number,
|
|
39
41
|
onClose: () => void,
|
|
40
42
|
onLoad: (params: any) => Promise<any>,
|
|
41
43
|
onSave: (items: any) => void,
|
|
@@ -48,8 +50,13 @@ type GridProps = ListProps & {
|
|
|
48
50
|
onInit: () => void,
|
|
49
51
|
onItemSelection: (item: any) => void,
|
|
50
52
|
onSelect: (item: any) => void,
|
|
51
|
-
renderHeader
|
|
52
|
-
renderItem
|
|
53
|
+
renderHeader?: (params: any) => Element<any>,
|
|
54
|
+
renderItem?: (item: any) => Element<any>,
|
|
55
|
+
renderItems?: ({
|
|
56
|
+
isSelected: (item: any) => boolean,
|
|
57
|
+
items: any,
|
|
58
|
+
onSelect: () => void
|
|
59
|
+
}) => Element<any>,
|
|
53
60
|
selectedItem: any,
|
|
54
61
|
selectedItems: Array<any>
|
|
55
62
|
};
|
|
@@ -113,6 +120,14 @@ const SelectizeGrid = useDataList(useList((props: GridProps) => {
|
|
|
113
120
|
return null;
|
|
114
121
|
}
|
|
115
122
|
|
|
123
|
+
if (props.renderItems) {
|
|
124
|
+
return props.renderItems({
|
|
125
|
+
isSelected: props.isSelected,
|
|
126
|
+
items: props.items,
|
|
127
|
+
onSelect: props.onSelect
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
|
|
116
131
|
return (
|
|
117
132
|
<Table
|
|
118
133
|
basic
|
|
@@ -161,7 +176,7 @@ const SelectizeGrid = useDataList(useList((props: GridProps) => {
|
|
|
161
176
|
/>
|
|
162
177
|
</Grid.Row>
|
|
163
178
|
<Grid.Row>
|
|
164
|
-
{ i18n.t('Selectize.noRecords') }
|
|
179
|
+
{ i18n.t('Selectize.messages.noRecords') }
|
|
165
180
|
</Grid.Row>
|
|
166
181
|
</Grid.Column>
|
|
167
182
|
</Grid>
|
|
@@ -182,9 +197,27 @@ const SelectizeGrid = useDataList(useList((props: GridProps) => {
|
|
|
182
197
|
}));
|
|
183
198
|
|
|
184
199
|
const Selectize = (props: Props) => {
|
|
200
|
+
const [error, setError] = useState(false);
|
|
185
201
|
const [selectedItem, setSelectedItem] = useState();
|
|
186
202
|
const [selectedItems, setSelectedItems] = useState(props.selectedItems || []);
|
|
187
203
|
|
|
204
|
+
/**
|
|
205
|
+
* Sets the allowMultiple prop to "true" if the multiple prop is a boolean or non-zero integer.
|
|
206
|
+
*
|
|
207
|
+
* @type {boolean}
|
|
208
|
+
*/
|
|
209
|
+
const allowMultiple = useMemo(() => !!props.multiple, [props.multiple]);
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Sets the allowed number of items that can be selected. If the multiple prop is a boolean, this will be
|
|
213
|
+
* and unlimited amount.
|
|
214
|
+
*
|
|
215
|
+
* @type {boolean|number}
|
|
216
|
+
*/
|
|
217
|
+
const allowedCount = useMemo(() => (
|
|
218
|
+
_.isNumber(props.multiple) ? props.multiple : Number.MAX_SAFE_INTEGER
|
|
219
|
+
), [props.multiple]);
|
|
220
|
+
|
|
188
221
|
/**
|
|
189
222
|
* Returns true if the passed item is selected.
|
|
190
223
|
*
|
|
@@ -196,13 +229,17 @@ const Selectize = (props: Props) => {
|
|
|
196
229
|
* If the passed item is selected, deselect the item. If we're not allowing multiple select, replace the selected
|
|
197
230
|
* items with the passed item. Otherwise, append the passed item to the list of selected items.
|
|
198
231
|
*
|
|
232
|
+
* If the user has already selected the maximum number allowed, display an error message.
|
|
233
|
+
*
|
|
199
234
|
* @type {(function(*=): void)|*}
|
|
200
235
|
*/
|
|
201
236
|
const onSelect = useCallback((item) => {
|
|
202
237
|
if (isSelected(item)) {
|
|
203
238
|
setSelectedItems((prevItems) => _.filter(prevItems, (i) => i.id !== item.id));
|
|
204
|
-
} else if (!
|
|
239
|
+
} else if (!allowMultiple) {
|
|
205
240
|
setSelectedItems([item]);
|
|
241
|
+
} else if (selectedItems.length >= allowedCount) {
|
|
242
|
+
setError(true);
|
|
206
243
|
} else {
|
|
207
244
|
setSelectedItems((prevItems) => [
|
|
208
245
|
...prevItems,
|
|
@@ -254,6 +291,13 @@ const Selectize = (props: Props) => {
|
|
|
254
291
|
content={props.title}
|
|
255
292
|
/>
|
|
256
293
|
<Modal.Content>
|
|
294
|
+
<Message
|
|
295
|
+
content={i18n.t('Selectize.messages.maxSelected.content')}
|
|
296
|
+
error
|
|
297
|
+
header={i18n.t('Selectize.messages.maxSelected.header')}
|
|
298
|
+
onDismiss={() => setError(false)}
|
|
299
|
+
visible={error}
|
|
300
|
+
/>
|
|
257
301
|
<SelectizeGrid
|
|
258
302
|
{...props}
|
|
259
303
|
actions={[]}
|