dce-reactkit 5.0.6 → 5.0.8
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/dist/cjs/index.js +96 -68
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/types/components/ItemPicker/NestableItemList.d.ts +1 -0
- package/dist/cjs/types/components/ItemPicker/index.d.ts +1 -0
- package/dist/cjs/types/components/ItemPicker/types/PickableItem.d.ts +4 -1
- package/dist/cjs/types/helpers/visitServerEndpoint.d.ts +5 -0
- package/dist/esm/index.js +96 -68
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types/components/ItemPicker/NestableItemList.d.ts +1 -0
- package/dist/esm/types/components/ItemPicker/index.d.ts +1 -0
- package/dist/esm/types/components/ItemPicker/types/PickableItem.d.ts +4 -1
- package/dist/esm/types/helpers/visitServerEndpoint.d.ts +5 -0
- package/dist/index.d.ts +9 -1
- package/package.json +1 -1
- package/src/components/ItemPicker/NestableItemList.tsx +42 -15
- package/src/components/ItemPicker/index.tsx +4 -0
- package/src/components/ItemPicker/types/PickableItem.tsx +7 -1
- package/src/components/Tooltip.tsx +17 -0
- package/src/helpers/visitServerEndpoint.tsx +5 -0
|
@@ -1,11 +1,14 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
1
2
|
/**
|
|
2
3
|
* An item that can be chosen (for use within ItemPicker)
|
|
3
4
|
* @author Gabe Abrams
|
|
4
5
|
*/
|
|
5
6
|
type PickableItem = ({
|
|
6
7
|
id: number | string;
|
|
7
|
-
name:
|
|
8
|
+
name: React.ReactNode;
|
|
9
|
+
ariaLabel?: string;
|
|
8
10
|
link?: string;
|
|
11
|
+
tooltip?: string;
|
|
9
12
|
} & ({
|
|
10
13
|
isGroup: false;
|
|
11
14
|
checked: boolean;
|
|
@@ -22,6 +22,8 @@ export declare const _setStubResponse: (opts: {
|
|
|
22
22
|
* @param opts.path - the path of the server endpoint
|
|
23
23
|
* @param [opts.method=GET] - the method of the endpoint
|
|
24
24
|
* @param [opts.params] - query/body parameters to include
|
|
25
|
+
* @param [opts.headers] - custom headers to include; values must already be
|
|
26
|
+
* string to avoid issue with header serialization
|
|
25
27
|
* @returns response from server
|
|
26
28
|
*/
|
|
27
29
|
declare const visitServerEndpoint: (opts: {
|
|
@@ -30,5 +32,8 @@ declare const visitServerEndpoint: (opts: {
|
|
|
30
32
|
params?: {
|
|
31
33
|
[x: string]: any;
|
|
32
34
|
} | undefined;
|
|
35
|
+
headers?: {
|
|
36
|
+
[x: string]: string;
|
|
37
|
+
} | undefined;
|
|
33
38
|
}) => Promise<any>;
|
|
34
39
|
export default visitServerEndpoint;
|
package/dist/index.d.ts
CHANGED
|
@@ -442,8 +442,10 @@ declare const CopiableBox: React$1.FC<Props$c>;
|
|
|
442
442
|
*/
|
|
443
443
|
type PickableItem = ({
|
|
444
444
|
id: number | string;
|
|
445
|
-
name:
|
|
445
|
+
name: React.ReactNode;
|
|
446
|
+
ariaLabel?: string;
|
|
446
447
|
link?: string;
|
|
448
|
+
tooltip?: string;
|
|
447
449
|
} & ({
|
|
448
450
|
isGroup: false;
|
|
449
451
|
checked: boolean;
|
|
@@ -468,6 +470,7 @@ type Props$b = {
|
|
|
468
470
|
onChanged: (updatedItems: PickableItem[]) => void;
|
|
469
471
|
noBottomMargin?: boolean;
|
|
470
472
|
hideSelectAllOrNoneButtons?: boolean;
|
|
473
|
+
startWithGroupsExpanded?: boolean;
|
|
471
474
|
};
|
|
472
475
|
declare const ItemPicker: React$1.FC<Props$b>;
|
|
473
476
|
|
|
@@ -862,6 +865,8 @@ declare const initClient: (opts: ({
|
|
|
862
865
|
* @param opts.path - the path of the server endpoint
|
|
863
866
|
* @param [opts.method=GET] - the method of the endpoint
|
|
864
867
|
* @param [opts.params] - query/body parameters to include
|
|
868
|
+
* @param [opts.headers] - custom headers to include; values must already be
|
|
869
|
+
* string to avoid issue with header serialization
|
|
865
870
|
* @returns response from server
|
|
866
871
|
*/
|
|
867
872
|
declare const visitServerEndpoint: (opts: {
|
|
@@ -870,6 +875,9 @@ declare const visitServerEndpoint: (opts: {
|
|
|
870
875
|
params?: {
|
|
871
876
|
[x: string]: any;
|
|
872
877
|
} | undefined;
|
|
878
|
+
headers?: {
|
|
879
|
+
[x: string]: string;
|
|
880
|
+
} | undefined;
|
|
873
881
|
}) => Promise<any>;
|
|
874
882
|
|
|
875
883
|
/**
|
package/package.json
CHANGED
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
|
|
17
17
|
// Import shared components
|
|
18
18
|
import CheckboxButton from '../CheckboxButton';
|
|
19
|
+
import Tooltip from '../Tooltip';
|
|
19
20
|
import Variant from '../../types/Variant';
|
|
20
21
|
|
|
21
22
|
// Import types
|
|
@@ -35,6 +36,8 @@ type Props = {
|
|
|
35
36
|
* values updated
|
|
36
37
|
*/
|
|
37
38
|
onChanged: (updatedItems: PickableItem[]) => void,
|
|
39
|
+
// If true, groups start expanded instead of collapsed
|
|
40
|
+
startWithGroupsExpanded?: boolean,
|
|
38
41
|
};
|
|
39
42
|
|
|
40
43
|
/*------------------------------------------------------------------------*/
|
|
@@ -106,6 +109,7 @@ const NestableItemList: React.FC<Props> = (props) => {
|
|
|
106
109
|
const {
|
|
107
110
|
items,
|
|
108
111
|
onChanged,
|
|
112
|
+
startWithGroupsExpanded,
|
|
109
113
|
} = props;
|
|
110
114
|
|
|
111
115
|
/* -------------- State ------------- */
|
|
@@ -113,7 +117,7 @@ const NestableItemList: React.FC<Props> = (props) => {
|
|
|
113
117
|
// Create initial map of child expanded booleans
|
|
114
118
|
const initChildExpanded: { [k: string]: boolean } = {};
|
|
115
119
|
items.forEach((item) => {
|
|
116
|
-
initChildExpanded[String(item.id)] =
|
|
120
|
+
initChildExpanded[String(item.id)] = !!startWithGroupsExpanded;
|
|
117
121
|
});
|
|
118
122
|
|
|
119
123
|
// Initial state
|
|
@@ -229,6 +233,29 @@ const NestableItemList: React.FC<Props> = (props) => {
|
|
|
229
233
|
<div>
|
|
230
234
|
{
|
|
231
235
|
items.map((item) => {
|
|
236
|
+
// Human-readable label for accessibility. Prefer the explicit
|
|
237
|
+
// ariaLabel, then fall back to the name if it is a plain string
|
|
238
|
+
const accessibleName = (
|
|
239
|
+
item.ariaLabel
|
|
240
|
+
?? (typeof item.name === 'string' ? item.name : '')
|
|
241
|
+
);
|
|
242
|
+
|
|
243
|
+
// Checkbox and Text
|
|
244
|
+
const checkbox = (
|
|
245
|
+
<CheckboxButton
|
|
246
|
+
className={`NestableItemList-CheckboxButton-${item.id}`}
|
|
247
|
+
text={item.name}
|
|
248
|
+
checked={item.isGroup ? allChecked(item.children) : item.checked}
|
|
249
|
+
dashed={item.isGroup ? !noneChecked(item.children) : false}
|
|
250
|
+
onChanged={(checked) => {
|
|
251
|
+
onChanged(changeChecked(item.id, checked, items));
|
|
252
|
+
}}
|
|
253
|
+
ariaLabel={`Select ${accessibleName}`}
|
|
254
|
+
checkedVariant={Variant.Light}
|
|
255
|
+
uncheckedVariant={Variant.Light}
|
|
256
|
+
/>
|
|
257
|
+
);
|
|
258
|
+
|
|
232
259
|
return (
|
|
233
260
|
<div key={item.id}>
|
|
234
261
|
{/* Dropdown Button */}
|
|
@@ -252,7 +279,7 @@ const NestableItemList: React.FC<Props> = (props) => {
|
|
|
252
279
|
id: item.id,
|
|
253
280
|
});
|
|
254
281
|
}}
|
|
255
|
-
aria-label={`${childExpanded[item.id] ? 'Hide' : 'Show'} items in ${
|
|
282
|
+
aria-label={`${childExpanded[item.id] ? 'Hide' : 'Show'} items in ${accessibleName}`}
|
|
256
283
|
>
|
|
257
284
|
<FontAwesomeIcon
|
|
258
285
|
icon={childExpanded[item.id] ? faChevronDown : faChevronRight}
|
|
@@ -261,19 +288,18 @@ const NestableItemList: React.FC<Props> = (props) => {
|
|
|
261
288
|
)}
|
|
262
289
|
</span>
|
|
263
290
|
|
|
264
|
-
{/* Checkbox and Text */}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
/>
|
|
291
|
+
{/* Checkbox and Text (optionally wrapped in a tooltip) */}
|
|
292
|
+
{
|
|
293
|
+
item.tooltip
|
|
294
|
+
? (
|
|
295
|
+
<Tooltip text={item.tooltip}>
|
|
296
|
+
<span className="d-inline-block">
|
|
297
|
+
{checkbox}
|
|
298
|
+
</span>
|
|
299
|
+
</Tooltip>
|
|
300
|
+
)
|
|
301
|
+
: checkbox
|
|
302
|
+
}
|
|
277
303
|
|
|
278
304
|
{/* Children */}
|
|
279
305
|
{(item.isGroup && childExpanded[item.id]) && (
|
|
@@ -288,6 +314,7 @@ const NestableItemList: React.FC<Props> = (props) => {
|
|
|
288
314
|
onChanged={(updatedItems) => {
|
|
289
315
|
onChanged(changeItems(item.id, updatedItems));
|
|
290
316
|
}}
|
|
317
|
+
startWithGroupsExpanded={startWithGroupsExpanded}
|
|
291
318
|
/>
|
|
292
319
|
</div>
|
|
293
320
|
)}
|
|
@@ -35,6 +35,8 @@ type Props = {
|
|
|
35
35
|
noBottomMargin?: boolean,
|
|
36
36
|
// If true, hide select all or none buttons
|
|
37
37
|
hideSelectAllOrNoneButtons?: boolean,
|
|
38
|
+
// If true, groups start expanded instead of collapsed
|
|
39
|
+
startWithGroupsExpanded?: boolean,
|
|
38
40
|
};
|
|
39
41
|
|
|
40
42
|
/*------------------------------------------------------------------------*/
|
|
@@ -55,6 +57,7 @@ const ItemPicker: React.FC<Props> = (props) => {
|
|
|
55
57
|
onChanged,
|
|
56
58
|
noBottomMargin,
|
|
57
59
|
hideSelectAllOrNoneButtons,
|
|
60
|
+
startWithGroupsExpanded,
|
|
58
61
|
} = props;
|
|
59
62
|
|
|
60
63
|
/*------------------------------------------------------------------------*/
|
|
@@ -171,6 +174,7 @@ const ItemPicker: React.FC<Props> = (props) => {
|
|
|
171
174
|
<NestableItemList
|
|
172
175
|
items={items}
|
|
173
176
|
onChanged={onChanged}
|
|
177
|
+
startWithGroupsExpanded={startWithGroupsExpanded}
|
|
174
178
|
/>
|
|
175
179
|
</div>
|
|
176
180
|
</TabBox>
|
|
@@ -7,9 +7,15 @@ type PickableItem = (
|
|
|
7
7
|
// Unique id of the item
|
|
8
8
|
id: number | string,
|
|
9
9
|
// Name of the item (human readable)
|
|
10
|
-
name:
|
|
10
|
+
name: React.ReactNode,
|
|
11
|
+
// Accessible label for the item, used for screen readers. Required when
|
|
12
|
+
// "name" is not a plain string (e.g. a custom ReactNode); when "name" is
|
|
13
|
+
// a string, it is used as the label if this is not provided
|
|
14
|
+
ariaLabel?: string,
|
|
11
15
|
// Link to view the item in the browser
|
|
12
16
|
link?: string,
|
|
17
|
+
// If included, show this text in a tooltip when hovering over the item
|
|
18
|
+
tooltip?: string,
|
|
13
19
|
}
|
|
14
20
|
& (
|
|
15
21
|
| {
|
|
@@ -63,6 +63,14 @@ const Tooltip: React.FC<Props> = (props) => {
|
|
|
63
63
|
// Import bootstrap tooltip
|
|
64
64
|
const BSTooltip = (await import('bootstrap')).Tooltip;
|
|
65
65
|
|
|
66
|
+
// The child may have unmounted while the dynamic import above was
|
|
67
|
+
// resolving (React nulls the ref on unmount). Constructing a
|
|
68
|
+
// Bootstrap tooltip with a null element causes an error,
|
|
69
|
+
// so bail out instead
|
|
70
|
+
if (!childRef.current) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
66
74
|
// Initialize
|
|
67
75
|
t = new BSTooltip(
|
|
68
76
|
childRef.current,
|
|
@@ -78,6 +86,15 @@ const Tooltip: React.FC<Props> = (props) => {
|
|
|
78
86
|
return () => {
|
|
79
87
|
if (t) {
|
|
80
88
|
t.dispose();
|
|
89
|
+
// Bootstrap's hide() queues a transition-end callback that can
|
|
90
|
+
// fire AFTER dispose and touch the (now null) trigger map and
|
|
91
|
+
// element (twbs/bootstrap issue #37474). Point those private
|
|
92
|
+
// fields at harmless stand-ins so the late callback is a no-op
|
|
93
|
+
// instead of a crash.
|
|
94
|
+
/* eslint-disable no-underscore-dangle */
|
|
95
|
+
t._activeTrigger = {};
|
|
96
|
+
t._element = document.createElement('noscript');
|
|
97
|
+
/* eslint-enable no-underscore-dangle */
|
|
81
98
|
}
|
|
82
99
|
};
|
|
83
100
|
},
|
|
@@ -96,6 +96,8 @@ export const _setStubResponse = (
|
|
|
96
96
|
* @param opts.path - the path of the server endpoint
|
|
97
97
|
* @param [opts.method=GET] - the method of the endpoint
|
|
98
98
|
* @param [opts.params] - query/body parameters to include
|
|
99
|
+
* @param [opts.headers] - custom headers to include; values must already be
|
|
100
|
+
* string to avoid issue with header serialization
|
|
99
101
|
* @returns response from server
|
|
100
102
|
*/
|
|
101
103
|
const visitServerEndpoint = async (
|
|
@@ -103,6 +105,8 @@ const visitServerEndpoint = async (
|
|
|
103
105
|
path: string,
|
|
104
106
|
method?: ('GET' | 'POST' | 'DELETE' | 'PUT'),
|
|
105
107
|
params?: { [key in string]: any },
|
|
108
|
+
// Headers have no serialization layer, so use string
|
|
109
|
+
headers?: { [key in string]: string },
|
|
106
110
|
},
|
|
107
111
|
): Promise<any> => {
|
|
108
112
|
// Set default method
|
|
@@ -159,6 +163,7 @@ const visitServerEndpoint = async (
|
|
|
159
163
|
path: opts.path,
|
|
160
164
|
method: opts.method ?? 'GET',
|
|
161
165
|
params,
|
|
166
|
+
headers: opts.headers,
|
|
162
167
|
});
|
|
163
168
|
|
|
164
169
|
// Check for failure
|