@canonical/react-components 0.47.4 → 0.49.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 +1 -1
- package/dist/components/ContextualMenu/ContextualMenuDropdown/ContextualMenuDropdown.js +50 -7
- package/dist/components/MultiSelect/FadeInDown/FadeInDown.d.ts +10 -0
- package/dist/components/MultiSelect/FadeInDown/FadeInDown.js +33 -0
- package/dist/components/MultiSelect/FadeInDown/FadeInDown.scss +22 -0
- package/dist/components/MultiSelect/FadeInDown/index.d.ts +1 -0
- package/dist/components/MultiSelect/FadeInDown/index.js +16 -0
- package/dist/components/MultiSelect/MultiSelect.d.ts +52 -0
- package/dist/components/MultiSelect/MultiSelect.js +280 -0
- package/dist/components/MultiSelect/MultiSelect.scss +158 -0
- package/dist/components/MultiSelect/MultiSelect.stories.d.ts +67 -0
- package/dist/components/MultiSelect/MultiSelect.stories.js +71 -0
- package/dist/components/MultiSelect/index.d.ts +1 -0
- package/dist/components/MultiSelect/index.js +16 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +87 -0
- package/package.json +26 -28
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# React components for Vanilla Framework
|
|
2
|
-

|
|
2
|
+

|
|
3
3
|
|
|
4
4
|
This is a collection of components designed to be the way to consume [Vanilla Framework](http://vanillaframework.io) when using React.
|
|
5
5
|
|
|
@@ -30,7 +30,7 @@ let Label = exports.Label = /*#__PURE__*/function (Label) {
|
|
|
30
30
|
* @param positionCoords - The coordinates of the position node.
|
|
31
31
|
* @param constrainPanelWidth - Whether the menu width should be constrained to the position width.
|
|
32
32
|
*/
|
|
33
|
-
const getPositionStyle = (position, positionCoords, constrainPanelWidth) => {
|
|
33
|
+
const getPositionStyle = (position, verticalPosition, positionCoords, constrainPanelWidth) => {
|
|
34
34
|
if (!positionCoords) {
|
|
35
35
|
return null;
|
|
36
36
|
}
|
|
@@ -40,7 +40,7 @@ const getPositionStyle = (position, positionCoords, constrainPanelWidth) => {
|
|
|
40
40
|
top,
|
|
41
41
|
width
|
|
42
42
|
} = positionCoords;
|
|
43
|
-
const topPos = top + height + (window.scrollY || 0);
|
|
43
|
+
const topPos = verticalPosition === "bottom" ? top + height + (window.scrollY || 0) : top + (window.scrollY || 0);
|
|
44
44
|
let leftPos = left;
|
|
45
45
|
switch (position) {
|
|
46
46
|
case "left":
|
|
@@ -120,6 +120,20 @@ const generateLink = (link, key, handleClose) => {
|
|
|
120
120
|
} : null
|
|
121
121
|
}, props), children);
|
|
122
122
|
};
|
|
123
|
+
const getClosestScrollableParent = node => {
|
|
124
|
+
let currentNode = node;
|
|
125
|
+
while (currentNode && currentNode !== document.body) {
|
|
126
|
+
const {
|
|
127
|
+
overflowY,
|
|
128
|
+
overflowX
|
|
129
|
+
} = window.getComputedStyle(currentNode);
|
|
130
|
+
if (["auto", "scroll", "overlay"].includes(overflowY) && ["auto", "scroll", "overlay"].includes(overflowX)) {
|
|
131
|
+
return currentNode;
|
|
132
|
+
}
|
|
133
|
+
currentNode = currentNode.parentElement;
|
|
134
|
+
}
|
|
135
|
+
return document.body;
|
|
136
|
+
};
|
|
123
137
|
const ContextualMenuDropdown = _ref => {
|
|
124
138
|
let {
|
|
125
139
|
adjustedPosition,
|
|
@@ -140,23 +154,46 @@ const ContextualMenuDropdown = _ref => {
|
|
|
140
154
|
...props
|
|
141
155
|
} = _ref;
|
|
142
156
|
const dropdown = (0, _react.useRef)();
|
|
143
|
-
const [
|
|
157
|
+
const [verticalPosition, setVerticalPosition] = (0, _react.useState)("bottom");
|
|
158
|
+
const [positionStyle, setPositionStyle] = (0, _react.useState)(getPositionStyle(adjustedPosition, verticalPosition, positionCoords, constrainPanelWidth));
|
|
144
159
|
const [maxHeight, setMaxHeight] = (0, _react.useState)();
|
|
145
|
-
|
|
146
160
|
// Update the styles to position the menu.
|
|
147
161
|
const updatePositionStyle = (0, _react.useCallback)(() => {
|
|
148
|
-
setPositionStyle(getPositionStyle(adjustedPosition, positionCoords, constrainPanelWidth));
|
|
149
|
-
}, [adjustedPosition, positionCoords, constrainPanelWidth]);
|
|
162
|
+
setPositionStyle(getPositionStyle(adjustedPosition, verticalPosition, positionCoords, constrainPanelWidth));
|
|
163
|
+
}, [adjustedPosition, positionCoords, verticalPosition, constrainPanelWidth]);
|
|
164
|
+
const updateVerticalPosition = (0, _react.useCallback)(() => {
|
|
165
|
+
if (!positionNode) {
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
const scrollableParent = getClosestScrollableParent(positionNode);
|
|
169
|
+
if (!scrollableParent) {
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
172
|
+
const scrollableParentRect = scrollableParent.getBoundingClientRect();
|
|
173
|
+
const rect = positionNode.getBoundingClientRect();
|
|
174
|
+
|
|
175
|
+
// Calculate the rect in relation to the scrollableParent
|
|
176
|
+
const relativeRect = {
|
|
177
|
+
top: rect.top - scrollableParentRect.top,
|
|
178
|
+
bottom: rect.bottom - scrollableParentRect.top,
|
|
179
|
+
height: rect.height
|
|
180
|
+
};
|
|
181
|
+
const spaceBelow = scrollableParentRect.height - relativeRect.bottom;
|
|
182
|
+
const spaceAbove = relativeRect.top;
|
|
183
|
+
const dropdownHeight = relativeRect.height;
|
|
184
|
+
setVerticalPosition(spaceBelow >= dropdownHeight || spaceBelow > spaceAbove ? "bottom" : "top");
|
|
185
|
+
}, [positionNode]);
|
|
150
186
|
|
|
151
187
|
// Update the position when the window fitment info changes.
|
|
152
188
|
const onUpdateWindowFitment = (0, _react.useCallback)(fitsWindow => {
|
|
153
189
|
if (autoAdjust) {
|
|
154
190
|
setAdjustedPosition(adjustForWindow(position, fitsWindow));
|
|
191
|
+
updateVerticalPosition();
|
|
155
192
|
}
|
|
156
193
|
if (scrollOverflow) {
|
|
157
194
|
setMaxHeight(fitsWindow.fromBottom.spaceBelow - 16);
|
|
158
195
|
}
|
|
159
|
-
}, [autoAdjust, position, scrollOverflow, setAdjustedPosition]);
|
|
196
|
+
}, [autoAdjust, position, scrollOverflow, setAdjustedPosition, updateVerticalPosition]);
|
|
160
197
|
|
|
161
198
|
// Handle adjusting the horizontal position and scrolling of the dropdown so that it remains on screen.
|
|
162
199
|
(0, _hooks.useWindowFitment)(dropdown.current, positionNode, onUpdateWindowFitment, 0, isOpen && (autoAdjust || scrollOverflow));
|
|
@@ -165,6 +202,9 @@ const ContextualMenuDropdown = _ref => {
|
|
|
165
202
|
(0, _react.useEffect)(() => {
|
|
166
203
|
updatePositionStyle();
|
|
167
204
|
}, [adjustedPosition, updatePositionStyle]);
|
|
205
|
+
(0, _react.useEffect)(() => {
|
|
206
|
+
updateVerticalPosition();
|
|
207
|
+
}, [updateVerticalPosition]);
|
|
168
208
|
return (
|
|
169
209
|
/*#__PURE__*/
|
|
170
210
|
// Vanilla Framework uses .p-contextual-menu parent modifier classnames to determine the correct position of the .p-contextual-menu__dropdown dropdown (left, center, right).
|
|
@@ -188,6 +228,9 @@ const ContextualMenuDropdown = _ref => {
|
|
|
188
228
|
maxHeight,
|
|
189
229
|
minHeight: "2rem",
|
|
190
230
|
overflowX: "auto"
|
|
231
|
+
} : {}),
|
|
232
|
+
...(verticalPosition === "top" ? {
|
|
233
|
+
bottom: "0"
|
|
191
234
|
} : {})
|
|
192
235
|
}
|
|
193
236
|
}, props), dropdownContent ? typeof dropdownContent === "function" ? dropdownContent(handleClose) : dropdownContent : links.map((item, i) => {
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { FC, PropsWithChildren } from "react";
|
|
2
|
+
import "./FadeInDown.scss";
|
|
3
|
+
export interface FadeInDownProps extends PropsWithChildren {
|
|
4
|
+
isVisible: boolean;
|
|
5
|
+
className?: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* EXPERIMENTAL: This component is experimental and should be used internally only.
|
|
9
|
+
*/
|
|
10
|
+
export declare const FadeInDown: FC<FadeInDownProps>;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.FadeInDown = void 0;
|
|
7
|
+
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
8
|
+
var _react = _interopRequireDefault(require("react"));
|
|
9
|
+
var _classnames = _interopRequireDefault(require("classnames"));
|
|
10
|
+
require("./FadeInDown.scss");
|
|
11
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
12
|
+
/**
|
|
13
|
+
* EXPERIMENTAL: This component is experimental and should be used internally only.
|
|
14
|
+
*/
|
|
15
|
+
const FadeInDown = _ref => {
|
|
16
|
+
let {
|
|
17
|
+
children,
|
|
18
|
+
className,
|
|
19
|
+
isVisible
|
|
20
|
+
} = _ref;
|
|
21
|
+
return /*#__PURE__*/_react.default.createElement("div", {
|
|
22
|
+
className: (0, _classnames.default)("fade-in--down", className),
|
|
23
|
+
"aria-hidden": isVisible ? "false" : "true",
|
|
24
|
+
style: {
|
|
25
|
+
visibility: isVisible ? "visible" : "hidden"
|
|
26
|
+
}
|
|
27
|
+
}, children);
|
|
28
|
+
};
|
|
29
|
+
exports.FadeInDown = FadeInDown;
|
|
30
|
+
FadeInDown.propTypes = {
|
|
31
|
+
isVisible: _propTypes.default.bool.isRequired,
|
|
32
|
+
className: _propTypes.default.string
|
|
33
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
@import "vanilla-framework";
|
|
2
|
+
|
|
3
|
+
.fade-in--down {
|
|
4
|
+
@include vf-transition(#{transform, opacity, visibility}, fast);
|
|
5
|
+
|
|
6
|
+
position: relative;
|
|
7
|
+
z-index: 1;
|
|
8
|
+
|
|
9
|
+
&[aria-hidden="true"] {
|
|
10
|
+
height: 0;
|
|
11
|
+
opacity: 0;
|
|
12
|
+
transform: translate3d(0, -0.5rem, 0);
|
|
13
|
+
visibility: hidden;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
&[aria-hidden="false"] {
|
|
17
|
+
height: auto;
|
|
18
|
+
opacity: 1;
|
|
19
|
+
transform: translate3d(0, 0, 0);
|
|
20
|
+
visibility: visible;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./FadeInDown";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
var _FadeInDown = require("./FadeInDown");
|
|
7
|
+
Object.keys(_FadeInDown).forEach(function (key) {
|
|
8
|
+
if (key === "default" || key === "__esModule") return;
|
|
9
|
+
if (key in exports && exports[key] === _FadeInDown[key]) return;
|
|
10
|
+
Object.defineProperty(exports, key, {
|
|
11
|
+
enumerable: true,
|
|
12
|
+
get: function () {
|
|
13
|
+
return _FadeInDown[key];
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
});
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { ReactNode } from "react";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import "./MultiSelect.scss";
|
|
4
|
+
export type MultiSelectItem = {
|
|
5
|
+
label: string;
|
|
6
|
+
value: string | number;
|
|
7
|
+
group?: string;
|
|
8
|
+
};
|
|
9
|
+
export type MultiSelectProps = {
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
error?: string;
|
|
12
|
+
selectedItems?: MultiSelectItem[];
|
|
13
|
+
help?: string;
|
|
14
|
+
label?: string | null;
|
|
15
|
+
onItemsUpdate?: (items: MultiSelectItem[]) => void;
|
|
16
|
+
placeholder?: string;
|
|
17
|
+
required?: boolean;
|
|
18
|
+
items: MultiSelectItem[];
|
|
19
|
+
disabledItems?: MultiSelectItem[];
|
|
20
|
+
renderItem?: (item: MultiSelectItem) => ReactNode;
|
|
21
|
+
dropdownHeader?: ReactNode;
|
|
22
|
+
dropdownFooter?: ReactNode;
|
|
23
|
+
variant?: "condensed" | "search";
|
|
24
|
+
};
|
|
25
|
+
type GroupFn = (items: Parameters<typeof getGroupedItems>[0]) => ReturnType<typeof getGroupedItems>;
|
|
26
|
+
type SortFn = typeof sortAlphabetically;
|
|
27
|
+
type MultiSelectDropdownProps = {
|
|
28
|
+
isOpen: boolean;
|
|
29
|
+
items: MultiSelectItem[];
|
|
30
|
+
selectedItems: MultiSelectItem[];
|
|
31
|
+
disabledItems: MultiSelectItem[];
|
|
32
|
+
header?: ReactNode;
|
|
33
|
+
updateItems: (newItems: MultiSelectItem[]) => void;
|
|
34
|
+
footer?: ReactNode;
|
|
35
|
+
groupFn?: GroupFn;
|
|
36
|
+
sortFn?: SortFn;
|
|
37
|
+
shouldPinSelectedItems?: boolean;
|
|
38
|
+
} & React.HTMLAttributes<HTMLDivElement>;
|
|
39
|
+
declare const sortAlphabetically: (a: MultiSelectItem, b: MultiSelectItem) => number;
|
|
40
|
+
declare const getGroupedItems: (items: MultiSelectItem[]) => {
|
|
41
|
+
group: string;
|
|
42
|
+
items: MultiSelectItem[];
|
|
43
|
+
}[];
|
|
44
|
+
export declare const MultiSelectDropdown: React.FC<MultiSelectDropdownProps>;
|
|
45
|
+
/**
|
|
46
|
+
* Component allowing to select multiple items from a list of options.
|
|
47
|
+
*
|
|
48
|
+
* `MultiSelectDropdown` displays the dropdown with options which are grouped and sorted alphabetically.
|
|
49
|
+
* `SearchBox` or `Button` is used to trigger the dropdown depending on the variant.
|
|
50
|
+
*/
|
|
51
|
+
export declare const MultiSelect: React.FC<MultiSelectProps>;
|
|
52
|
+
export {};
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.MultiSelectDropdown = exports.MultiSelect = void 0;
|
|
7
|
+
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
8
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
9
|
+
require("./MultiSelect.scss");
|
|
10
|
+
var _index = require("../../index");
|
|
11
|
+
var _FadeInDown = require("./FadeInDown");
|
|
12
|
+
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
13
|
+
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
14
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
15
|
+
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
|
16
|
+
const sortAlphabetically = (a, b) => {
|
|
17
|
+
return a.label.localeCompare(b.label, "en", {
|
|
18
|
+
numeric: true
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
const createSortSelectedItems = previouslySelectedItemValues => (a, b) => {
|
|
22
|
+
if (previouslySelectedItemValues) {
|
|
23
|
+
const aIsPreviouslySelected = previouslySelectedItemValues.has(a.value);
|
|
24
|
+
const bIsPreviouslySelected = previouslySelectedItemValues.has(b.value);
|
|
25
|
+
if (aIsPreviouslySelected && !bIsPreviouslySelected) return -1;
|
|
26
|
+
if (!aIsPreviouslySelected && bIsPreviouslySelected) return 1;
|
|
27
|
+
}
|
|
28
|
+
return 0;
|
|
29
|
+
};
|
|
30
|
+
const getGroupedItems = items => {
|
|
31
|
+
const groups = new Map();
|
|
32
|
+
items.forEach(item => {
|
|
33
|
+
const group = item.group || "Ungrouped";
|
|
34
|
+
const groupItems = groups.get(group) || [];
|
|
35
|
+
groupItems.push(item);
|
|
36
|
+
groups.set(group, groupItems);
|
|
37
|
+
});
|
|
38
|
+
return Array.from(groups, _ref => {
|
|
39
|
+
let [group, items] = _ref;
|
|
40
|
+
return {
|
|
41
|
+
group,
|
|
42
|
+
items
|
|
43
|
+
};
|
|
44
|
+
});
|
|
45
|
+
};
|
|
46
|
+
const MultiSelectDropdown = _ref2 => {
|
|
47
|
+
let {
|
|
48
|
+
items,
|
|
49
|
+
selectedItems,
|
|
50
|
+
disabledItems,
|
|
51
|
+
header,
|
|
52
|
+
updateItems,
|
|
53
|
+
isOpen,
|
|
54
|
+
footer,
|
|
55
|
+
sortFn = sortAlphabetically,
|
|
56
|
+
groupFn = getGroupedItems,
|
|
57
|
+
...props
|
|
58
|
+
} = _ref2;
|
|
59
|
+
const selectedItemValues = (0, _react.useMemo)(() => new Set(selectedItems.map(item => item.value)), [selectedItems]);
|
|
60
|
+
const disabledItemValues = (0, _react.useMemo)(() => new Set(disabledItems.map(item => item.value)), [disabledItems]);
|
|
61
|
+
const [previouslySelectedItemValues, setPreviouslySelectedItemValues] = (0, _react.useState)(new Set(selectedItemValues));
|
|
62
|
+
(0, _react.useEffect)(() => {
|
|
63
|
+
if (isOpen) {
|
|
64
|
+
setPreviouslySelectedItemValues(new Set(selectedItemValues));
|
|
65
|
+
}
|
|
66
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
67
|
+
}, [isOpen]);
|
|
68
|
+
const hasGroup = (0, _react.useMemo)(() => items.some(item => item.group), [items]);
|
|
69
|
+
const groupedItems = (0, _react.useMemo)(() => hasGroup ? groupFn(items) : [{
|
|
70
|
+
group: "Ungrouped",
|
|
71
|
+
items
|
|
72
|
+
}],
|
|
73
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
74
|
+
[items, groupFn]);
|
|
75
|
+
const handleOnChange = event => {
|
|
76
|
+
const {
|
|
77
|
+
checked,
|
|
78
|
+
value
|
|
79
|
+
} = event.target;
|
|
80
|
+
const foundItem = items.find(item => "".concat(item.value) === value);
|
|
81
|
+
if (foundItem) {
|
|
82
|
+
var _selectedItems$filter;
|
|
83
|
+
const newSelectedItems = checked ? [...selectedItems, foundItem] : (_selectedItems$filter = selectedItems.filter(item => "".concat(item.value) !== value)) !== null && _selectedItems$filter !== void 0 ? _selectedItems$filter : [];
|
|
84
|
+
updateItems(newSelectedItems);
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
return /*#__PURE__*/_react.default.createElement(_FadeInDown.FadeInDown, {
|
|
88
|
+
isVisible: isOpen
|
|
89
|
+
}, /*#__PURE__*/_react.default.createElement("div", _extends({
|
|
90
|
+
className: "multi-select__dropdown",
|
|
91
|
+
role: "listbox"
|
|
92
|
+
}, props), header ? header : null, groupedItems.map(_ref3 => {
|
|
93
|
+
let {
|
|
94
|
+
group,
|
|
95
|
+
items
|
|
96
|
+
} = _ref3;
|
|
97
|
+
return /*#__PURE__*/_react.default.createElement("div", {
|
|
98
|
+
className: "multi-select__group",
|
|
99
|
+
key: group
|
|
100
|
+
}, hasGroup ? /*#__PURE__*/_react.default.createElement("h5", {
|
|
101
|
+
className: "multi-select__dropdown-header"
|
|
102
|
+
}, group) : null, /*#__PURE__*/_react.default.createElement("ul", {
|
|
103
|
+
className: "multi-select__dropdown-list",
|
|
104
|
+
"aria-label": group
|
|
105
|
+
}, items.sort(sortFn).sort(createSortSelectedItems(previouslySelectedItemValues)).map(item => /*#__PURE__*/_react.default.createElement("li", {
|
|
106
|
+
key: item.value,
|
|
107
|
+
className: "multi-select__dropdown-item"
|
|
108
|
+
}, /*#__PURE__*/_react.default.createElement(_index.CheckboxInput, {
|
|
109
|
+
disabled: disabledItemValues.has(item.value),
|
|
110
|
+
label: item.label,
|
|
111
|
+
checked: selectedItemValues.has(item.value),
|
|
112
|
+
value: item.value,
|
|
113
|
+
onChange: handleOnChange,
|
|
114
|
+
key: item.value
|
|
115
|
+
})))));
|
|
116
|
+
}), footer ? /*#__PURE__*/_react.default.createElement("div", {
|
|
117
|
+
className: "multi-select__footer"
|
|
118
|
+
}, footer) : null));
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Component allowing to select multiple items from a list of options.
|
|
123
|
+
*
|
|
124
|
+
* `MultiSelectDropdown` displays the dropdown with options which are grouped and sorted alphabetically.
|
|
125
|
+
* `SearchBox` or `Button` is used to trigger the dropdown depending on the variant.
|
|
126
|
+
*/
|
|
127
|
+
exports.MultiSelectDropdown = MultiSelectDropdown;
|
|
128
|
+
MultiSelectDropdown.propTypes = {
|
|
129
|
+
isOpen: _propTypes.default.bool.isRequired,
|
|
130
|
+
items: _propTypes.default.arrayOf(_propTypes.default.shape({
|
|
131
|
+
label: _propTypes.default.string.isRequired,
|
|
132
|
+
value: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number]).isRequired,
|
|
133
|
+
group: _propTypes.default.string
|
|
134
|
+
})).isRequired,
|
|
135
|
+
selectedItems: _propTypes.default.arrayOf(_propTypes.default.shape({
|
|
136
|
+
label: _propTypes.default.string.isRequired,
|
|
137
|
+
value: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number]).isRequired,
|
|
138
|
+
group: _propTypes.default.string
|
|
139
|
+
})).isRequired,
|
|
140
|
+
disabledItems: _propTypes.default.arrayOf(_propTypes.default.shape({
|
|
141
|
+
label: _propTypes.default.string.isRequired,
|
|
142
|
+
value: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number]).isRequired,
|
|
143
|
+
group: _propTypes.default.string
|
|
144
|
+
})).isRequired,
|
|
145
|
+
header: _propTypes.default.node,
|
|
146
|
+
updateItems: _propTypes.default.func.isRequired,
|
|
147
|
+
footer: _propTypes.default.node,
|
|
148
|
+
groupFn: _propTypes.default.func,
|
|
149
|
+
sortFn: _propTypes.default.any,
|
|
150
|
+
shouldPinSelectedItems: _propTypes.default.bool
|
|
151
|
+
};
|
|
152
|
+
const MultiSelect = _ref4 => {
|
|
153
|
+
let {
|
|
154
|
+
disabled,
|
|
155
|
+
selectedItems: externalSelectedItems = [],
|
|
156
|
+
label,
|
|
157
|
+
onItemsUpdate,
|
|
158
|
+
placeholder,
|
|
159
|
+
required = false,
|
|
160
|
+
items = [],
|
|
161
|
+
disabledItems = [],
|
|
162
|
+
dropdownHeader,
|
|
163
|
+
dropdownFooter,
|
|
164
|
+
variant = "search"
|
|
165
|
+
} = _ref4;
|
|
166
|
+
const wrapperRef = (0, _index.useClickOutside)(() => {
|
|
167
|
+
setIsDropdownOpen(false);
|
|
168
|
+
setFilter("");
|
|
169
|
+
});
|
|
170
|
+
(0, _index.useOnEscapePressed)(() => {
|
|
171
|
+
setIsDropdownOpen(false);
|
|
172
|
+
setFilter("");
|
|
173
|
+
});
|
|
174
|
+
const [isDropdownOpen, setIsDropdownOpen] = (0, _react.useState)(false);
|
|
175
|
+
const [filter, setFilter] = (0, _react.useState)("");
|
|
176
|
+
(0, _react.useEffect)(() => {
|
|
177
|
+
if (!isDropdownOpen) {
|
|
178
|
+
setFilter("");
|
|
179
|
+
}
|
|
180
|
+
}, [isDropdownOpen]);
|
|
181
|
+
const [internalSelectedItems, setInternalSelectedItems] = (0, _react.useState)([]);
|
|
182
|
+
const selectedItems = externalSelectedItems || internalSelectedItems;
|
|
183
|
+
const updateItems = newItems => {
|
|
184
|
+
const uniqueItems = Array.from(new Set(newItems));
|
|
185
|
+
setInternalSelectedItems(uniqueItems);
|
|
186
|
+
onItemsUpdate && onItemsUpdate(uniqueItems);
|
|
187
|
+
};
|
|
188
|
+
const dropdownId = (0, _react.useId)();
|
|
189
|
+
const inputId = (0, _react.useId)();
|
|
190
|
+
const selectedItemsLabel = selectedItems.filter(selectedItem => items.some(item => item.value === selectedItem.value)).map(el => el.label).join(", ");
|
|
191
|
+
return /*#__PURE__*/_react.default.createElement("div", {
|
|
192
|
+
ref: wrapperRef
|
|
193
|
+
}, /*#__PURE__*/_react.default.createElement("div", {
|
|
194
|
+
className: "multi-select"
|
|
195
|
+
}, variant === "search" ? /*#__PURE__*/_react.default.createElement(_index.SearchBox, {
|
|
196
|
+
externallyControlled: true,
|
|
197
|
+
"aria-controls": dropdownId,
|
|
198
|
+
"aria-expanded": isDropdownOpen,
|
|
199
|
+
id: inputId,
|
|
200
|
+
role: "combobox",
|
|
201
|
+
"aria-label": label || placeholder || "Search",
|
|
202
|
+
disabled: disabled,
|
|
203
|
+
autoComplete: "off",
|
|
204
|
+
onChange: value => {
|
|
205
|
+
setFilter(value);
|
|
206
|
+
// reopen if dropdown has been closed via ESC
|
|
207
|
+
setIsDropdownOpen(true);
|
|
208
|
+
},
|
|
209
|
+
onFocus: () => setIsDropdownOpen(true),
|
|
210
|
+
placeholder: placeholder !== null && placeholder !== void 0 ? placeholder : "Search",
|
|
211
|
+
required: required,
|
|
212
|
+
type: "text",
|
|
213
|
+
value: filter,
|
|
214
|
+
className: "multi-select__input"
|
|
215
|
+
}) : /*#__PURE__*/_react.default.createElement("button", {
|
|
216
|
+
role: "combobox",
|
|
217
|
+
type: "button",
|
|
218
|
+
"aria-label": label || placeholder || "Select items",
|
|
219
|
+
"aria-controls": dropdownId,
|
|
220
|
+
"aria-expanded": isDropdownOpen,
|
|
221
|
+
className: "multi-select__select-button",
|
|
222
|
+
onClick: () => {
|
|
223
|
+
setIsDropdownOpen(isOpen => !isOpen);
|
|
224
|
+
}
|
|
225
|
+
}, /*#__PURE__*/_react.default.createElement("span", {
|
|
226
|
+
className: "multi-select__condensed-text"
|
|
227
|
+
}, selectedItems.length > 0 ? selectedItemsLabel : placeholder !== null && placeholder !== void 0 ? placeholder : "Select items")), /*#__PURE__*/_react.default.createElement(MultiSelectDropdown, {
|
|
228
|
+
id: dropdownId,
|
|
229
|
+
isOpen: isDropdownOpen,
|
|
230
|
+
items: filter.length > 0 ? items.filter(item => item.label.toLowerCase().includes(filter.toLowerCase())) : items,
|
|
231
|
+
selectedItems: selectedItems,
|
|
232
|
+
disabledItems: disabledItems,
|
|
233
|
+
header: dropdownHeader,
|
|
234
|
+
updateItems: updateItems,
|
|
235
|
+
footer: dropdownFooter ? dropdownFooter : /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_index.Button, {
|
|
236
|
+
appearance: "link",
|
|
237
|
+
onClick: () => {
|
|
238
|
+
const enabledItems = items.filter(item => !disabledItems.some(disabledItem => disabledItem.value === item.value));
|
|
239
|
+
updateItems([...selectedItems, ...enabledItems]);
|
|
240
|
+
},
|
|
241
|
+
type: "button"
|
|
242
|
+
}, "Select all"), /*#__PURE__*/_react.default.createElement(_index.Button, {
|
|
243
|
+
appearance: "link",
|
|
244
|
+
onClick: () => {
|
|
245
|
+
const disabledSelectedItems = selectedItems.filter(item => disabledItems.some(disabledItem => disabledItem.value === item.value));
|
|
246
|
+
updateItems(disabledSelectedItems);
|
|
247
|
+
},
|
|
248
|
+
type: "button"
|
|
249
|
+
}, "Clear"))
|
|
250
|
+
})));
|
|
251
|
+
};
|
|
252
|
+
exports.MultiSelect = MultiSelect;
|
|
253
|
+
MultiSelect.propTypes = {
|
|
254
|
+
disabled: _propTypes.default.bool,
|
|
255
|
+
error: _propTypes.default.string,
|
|
256
|
+
selectedItems: _propTypes.default.arrayOf(_propTypes.default.shape({
|
|
257
|
+
label: _propTypes.default.string.isRequired,
|
|
258
|
+
value: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number]).isRequired,
|
|
259
|
+
group: _propTypes.default.string
|
|
260
|
+
})),
|
|
261
|
+
help: _propTypes.default.string,
|
|
262
|
+
label: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.oneOf([null])]),
|
|
263
|
+
onItemsUpdate: _propTypes.default.func,
|
|
264
|
+
placeholder: _propTypes.default.string,
|
|
265
|
+
required: _propTypes.default.bool,
|
|
266
|
+
items: _propTypes.default.arrayOf(_propTypes.default.shape({
|
|
267
|
+
label: _propTypes.default.string.isRequired,
|
|
268
|
+
value: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number]).isRequired,
|
|
269
|
+
group: _propTypes.default.string
|
|
270
|
+
})).isRequired,
|
|
271
|
+
disabledItems: _propTypes.default.arrayOf(_propTypes.default.shape({
|
|
272
|
+
label: _propTypes.default.string.isRequired,
|
|
273
|
+
value: _propTypes.default.oneOfType([_propTypes.default.string, _propTypes.default.number]).isRequired,
|
|
274
|
+
group: _propTypes.default.string
|
|
275
|
+
})),
|
|
276
|
+
renderItem: _propTypes.default.func,
|
|
277
|
+
dropdownHeader: _propTypes.default.node,
|
|
278
|
+
dropdownFooter: _propTypes.default.node,
|
|
279
|
+
variant: _propTypes.default.oneOf(["condensed", "search"])
|
|
280
|
+
};
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
@use "sass:map";
|
|
2
|
+
@import "vanilla-framework";
|
|
3
|
+
@include vf-base;
|
|
4
|
+
@include vf-p-lists;
|
|
5
|
+
|
|
6
|
+
$dropdown-max-height: 20rem;
|
|
7
|
+
|
|
8
|
+
.multi-select {
|
|
9
|
+
position: relative;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.multi-select .p-form-validation__message {
|
|
13
|
+
margin-top: 0;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.multi-select__condensed-text {
|
|
17
|
+
margin-right: $sph--large + $sph--x-small;
|
|
18
|
+
overflow: hidden;
|
|
19
|
+
text-overflow: ellipsis;
|
|
20
|
+
white-space: nowrap;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.multi-select__input {
|
|
24
|
+
cursor: pointer;
|
|
25
|
+
position: relative;
|
|
26
|
+
|
|
27
|
+
&.items-selected {
|
|
28
|
+
border-top: 0;
|
|
29
|
+
box-shadow: none;
|
|
30
|
+
top: -#{$border-radius};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
&[disabled],
|
|
34
|
+
&[disabled="disabled"] {
|
|
35
|
+
opacity: 1;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.multi-select__dropdown {
|
|
40
|
+
@extend %vf-bg--x-light;
|
|
41
|
+
@extend %vf-has-box-shadow;
|
|
42
|
+
left: 0;
|
|
43
|
+
max-height: $dropdown-max-height;
|
|
44
|
+
overflow: auto;
|
|
45
|
+
|
|
46
|
+
padding-top: $spv--small;
|
|
47
|
+
position: absolute;
|
|
48
|
+
right: 0;
|
|
49
|
+
top: calc(100% - #{$input-margin-bottom});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.multi-select__dropdown--side-by-side {
|
|
53
|
+
display: flex;
|
|
54
|
+
flex-wrap: wrap;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.multi-select__group {
|
|
58
|
+
flex: 1 0 auto;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
.multi-select__dropdown-list {
|
|
62
|
+
@extend %vf-list;
|
|
63
|
+
|
|
64
|
+
margin-bottom: $sph--x-small;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.multi-select__footer {
|
|
68
|
+
background: white;
|
|
69
|
+
border-top: 1px solid $color-mid-light;
|
|
70
|
+
bottom: 0;
|
|
71
|
+
display: flex;
|
|
72
|
+
flex-wrap: wrap;
|
|
73
|
+
justify-content: space-between;
|
|
74
|
+
padding: $sph--small $sph--large 0 $sph--large;
|
|
75
|
+
position: sticky;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.multi-select__dropdown-header {
|
|
79
|
+
font-size: #{map.get($font-sizes, small)}rem;
|
|
80
|
+
letter-spacing: #{map.get($font-sizes, small)}px;
|
|
81
|
+
margin-bottom: 0;
|
|
82
|
+
padding: $spv--x-small $sph--large;
|
|
83
|
+
position: relative;
|
|
84
|
+
text-transform: uppercase;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.multi-select__dropdown-item {
|
|
88
|
+
padding: 0 $sph--large;
|
|
89
|
+
|
|
90
|
+
.p-checkbox {
|
|
91
|
+
padding-top: $sph--x-small;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
&,
|
|
95
|
+
.p-checkbox {
|
|
96
|
+
width: 100%;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.multi-select__dropdown-item-description {
|
|
101
|
+
@extend %small-text;
|
|
102
|
+
|
|
103
|
+
color: $color-mid-dark;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.multi-select__dropdown-button {
|
|
107
|
+
border: 0;
|
|
108
|
+
margin-bottom: 0;
|
|
109
|
+
padding-left: $sph--small;
|
|
110
|
+
padding-right: $sph--small;
|
|
111
|
+
text-align: left;
|
|
112
|
+
width: 100%;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.multi-select__selected-list {
|
|
116
|
+
background-color: $colors--light-theme--background-inputs;
|
|
117
|
+
border-bottom: 0;
|
|
118
|
+
margin: 0;
|
|
119
|
+
overflow: hidden;
|
|
120
|
+
padding: $spv--x-small $sph--small;
|
|
121
|
+
text-overflow: ellipsis;
|
|
122
|
+
white-space: nowrap;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.multi-select__select-button {
|
|
126
|
+
@extend %vf-input-elements;
|
|
127
|
+
align-items: center;
|
|
128
|
+
display: inline-flex;
|
|
129
|
+
height: 2.5rem;
|
|
130
|
+
justify-content: space-between;
|
|
131
|
+
overflow: auto;
|
|
132
|
+
|
|
133
|
+
position: relative;
|
|
134
|
+
z-index: 0;
|
|
135
|
+
|
|
136
|
+
&::after {
|
|
137
|
+
content: "";
|
|
138
|
+
margin-left: $sph--large;
|
|
139
|
+
position: absolute;
|
|
140
|
+
right: $sph--small;
|
|
141
|
+
top: 50%;
|
|
142
|
+
transform: translateY(-50%) rotate(-180deg);
|
|
143
|
+
|
|
144
|
+
@extend %icon;
|
|
145
|
+
@include vf-icon-chevron($color-mid-dark);
|
|
146
|
+
@include vf-transition($property: transform, $duration: fast);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
&[aria-expanded="true"] {
|
|
150
|
+
background-color: $colors--light-theme--background-hover;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
&[aria-expanded="false"] {
|
|
154
|
+
&::after {
|
|
155
|
+
transform: translateY(-50%) rotate(0);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { Meta } from "@storybook/react";
|
|
2
|
+
import { MultiSelect } from "./MultiSelect";
|
|
3
|
+
declare const meta: Meta<typeof MultiSelect>;
|
|
4
|
+
export default meta;
|
|
5
|
+
export declare const CondensedExample: {
|
|
6
|
+
args: {
|
|
7
|
+
items: ({
|
|
8
|
+
label: string;
|
|
9
|
+
value: string;
|
|
10
|
+
} | {
|
|
11
|
+
label: string;
|
|
12
|
+
value: number;
|
|
13
|
+
})[];
|
|
14
|
+
selectedItems: ({
|
|
15
|
+
label: string;
|
|
16
|
+
value: string;
|
|
17
|
+
} | {
|
|
18
|
+
label: string;
|
|
19
|
+
value: number;
|
|
20
|
+
})[];
|
|
21
|
+
variant: string;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
export declare const SearchExample: {
|
|
25
|
+
args: {
|
|
26
|
+
variant: string;
|
|
27
|
+
items: ({
|
|
28
|
+
group: string;
|
|
29
|
+
label: string;
|
|
30
|
+
value: string;
|
|
31
|
+
} | {
|
|
32
|
+
group: string;
|
|
33
|
+
label: string;
|
|
34
|
+
value: number;
|
|
35
|
+
})[];
|
|
36
|
+
selectedItems: ({
|
|
37
|
+
label: string;
|
|
38
|
+
value: string;
|
|
39
|
+
} | {
|
|
40
|
+
label: string;
|
|
41
|
+
value: number;
|
|
42
|
+
})[];
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
export declare const WithDisabledItems: {
|
|
46
|
+
args: {
|
|
47
|
+
disabledItems: {
|
|
48
|
+
label: string;
|
|
49
|
+
value: number;
|
|
50
|
+
}[];
|
|
51
|
+
items: ({
|
|
52
|
+
label: string;
|
|
53
|
+
value: string;
|
|
54
|
+
} | {
|
|
55
|
+
label: string;
|
|
56
|
+
value: number;
|
|
57
|
+
})[];
|
|
58
|
+
selectedItems: ({
|
|
59
|
+
label: string;
|
|
60
|
+
value: string;
|
|
61
|
+
} | {
|
|
62
|
+
label: string;
|
|
63
|
+
value: number;
|
|
64
|
+
})[];
|
|
65
|
+
variant: string;
|
|
66
|
+
};
|
|
67
|
+
};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = exports.WithDisabledItems = exports.SearchExample = exports.CondensedExample = void 0;
|
|
7
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
8
|
+
var _MultiSelect = require("./MultiSelect");
|
|
9
|
+
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
10
|
+
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
11
|
+
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
|
12
|
+
const Template = props => {
|
|
13
|
+
const [selectedItems, setSelectedItems] = (0, _react.useState)(props.selectedItems || []);
|
|
14
|
+
return /*#__PURE__*/_react.default.createElement(_MultiSelect.MultiSelect, _extends({}, props, {
|
|
15
|
+
selectedItems: selectedItems,
|
|
16
|
+
onItemsUpdate: setSelectedItems
|
|
17
|
+
}));
|
|
18
|
+
};
|
|
19
|
+
const meta = {
|
|
20
|
+
title: "MultiSelect",
|
|
21
|
+
component: _MultiSelect.MultiSelect,
|
|
22
|
+
render: Template,
|
|
23
|
+
tags: ["autodocs"],
|
|
24
|
+
parameters: {}
|
|
25
|
+
};
|
|
26
|
+
var _default = exports.default = meta;
|
|
27
|
+
const CondensedExample = exports.CondensedExample = {
|
|
28
|
+
args: {
|
|
29
|
+
items: [...Array.from({
|
|
30
|
+
length: 26
|
|
31
|
+
}, (_, i) => ({
|
|
32
|
+
label: "".concat(String.fromCharCode(i + 65)),
|
|
33
|
+
value: "".concat(String.fromCharCode(i + 65))
|
|
34
|
+
})), ...Array.from({
|
|
35
|
+
length: 26
|
|
36
|
+
}, (_, i) => ({
|
|
37
|
+
label: "Item ".concat(i + 1),
|
|
38
|
+
value: i + 1
|
|
39
|
+
}))],
|
|
40
|
+
selectedItems: [{
|
|
41
|
+
label: "A",
|
|
42
|
+
value: "A"
|
|
43
|
+
}, {
|
|
44
|
+
label: "Item 2",
|
|
45
|
+
value: 2
|
|
46
|
+
}],
|
|
47
|
+
variant: "condensed"
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
const SearchExample = exports.SearchExample = {
|
|
51
|
+
args: {
|
|
52
|
+
...CondensedExample.args,
|
|
53
|
+
variant: "search",
|
|
54
|
+
items: [...CondensedExample.args.items.map((item, i) => ({
|
|
55
|
+
...item,
|
|
56
|
+
group: i % 2 === 0 ? "Group 1" : "Group 2"
|
|
57
|
+
}))]
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
const WithDisabledItems = exports.WithDisabledItems = {
|
|
61
|
+
args: {
|
|
62
|
+
...CondensedExample.args,
|
|
63
|
+
disabledItems: [{
|
|
64
|
+
label: "Item 1",
|
|
65
|
+
value: 1
|
|
66
|
+
}, {
|
|
67
|
+
label: "Item 2",
|
|
68
|
+
value: 2
|
|
69
|
+
}]
|
|
70
|
+
}
|
|
71
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./MultiSelect";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
var _MultiSelect = require("./MultiSelect");
|
|
7
|
+
Object.keys(_MultiSelect).forEach(function (key) {
|
|
8
|
+
if (key === "default" || key === "__esModule") return;
|
|
9
|
+
if (key in exports && exports[key] === _MultiSelect[key]) return;
|
|
10
|
+
Object.defineProperty(exports, key, {
|
|
11
|
+
enumerable: true,
|
|
12
|
+
get: function () {
|
|
13
|
+
return _MultiSelect[key];
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
});
|
package/dist/index.d.ts
CHANGED
|
@@ -25,6 +25,7 @@ export { default as MainTable } from "./components/MainTable";
|
|
|
25
25
|
export { default as ModularTable } from "./components/ModularTable";
|
|
26
26
|
export { default as Navigation } from "./components/Navigation";
|
|
27
27
|
export { default as Modal } from "./components/Modal";
|
|
28
|
+
export * from "./components/MultiSelect";
|
|
28
29
|
export { default as Notification, NotificationSeverity, } from "./components/Notification";
|
|
29
30
|
export { NotificationConsumer, NotificationProvider, useNotify, info, success, failure, queue, } from "./components/NotificationProvider";
|
|
30
31
|
export { default as Pagination } from "./components/Pagination";
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,81 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
+
var _exportNames = {
|
|
7
|
+
Accordion: true,
|
|
8
|
+
ActionButton: true,
|
|
9
|
+
ArticlePagination: true,
|
|
10
|
+
Badge: true,
|
|
11
|
+
Button: true,
|
|
12
|
+
ButtonAppearance: true,
|
|
13
|
+
Card: true,
|
|
14
|
+
CheckboxInput: true,
|
|
15
|
+
Chip: true,
|
|
16
|
+
Code: true,
|
|
17
|
+
CodeSnippet: true,
|
|
18
|
+
CodeSnippetBlockAppearance: true,
|
|
19
|
+
Col: true,
|
|
20
|
+
ConfirmationButton: true,
|
|
21
|
+
ConfirmationModal: true,
|
|
22
|
+
ContextualMenu: true,
|
|
23
|
+
EmptyState: true,
|
|
24
|
+
Field: true,
|
|
25
|
+
Form: true,
|
|
26
|
+
Icon: true,
|
|
27
|
+
ICONS: true,
|
|
28
|
+
Input: true,
|
|
29
|
+
Label: true,
|
|
30
|
+
Link: true,
|
|
31
|
+
List: true,
|
|
32
|
+
Loader: true,
|
|
33
|
+
MainTable: true,
|
|
34
|
+
ModularTable: true,
|
|
35
|
+
Navigation: true,
|
|
36
|
+
Modal: true,
|
|
37
|
+
Notification: true,
|
|
38
|
+
NotificationSeverity: true,
|
|
39
|
+
NotificationConsumer: true,
|
|
40
|
+
NotificationProvider: true,
|
|
41
|
+
useNotify: true,
|
|
42
|
+
info: true,
|
|
43
|
+
success: true,
|
|
44
|
+
failure: true,
|
|
45
|
+
queue: true,
|
|
46
|
+
Pagination: true,
|
|
47
|
+
PasswordToggle: true,
|
|
48
|
+
RadioInput: true,
|
|
49
|
+
Row: true,
|
|
50
|
+
SearchAndFilter: true,
|
|
51
|
+
SearchBox: true,
|
|
52
|
+
Select: true,
|
|
53
|
+
Slider: true,
|
|
54
|
+
Switch: true,
|
|
55
|
+
Spinner: true,
|
|
56
|
+
StatusLabel: true,
|
|
57
|
+
StatusLabelAppearance: true,
|
|
58
|
+
Strip: true,
|
|
59
|
+
SummaryButton: true,
|
|
60
|
+
Table: true,
|
|
61
|
+
TableCell: true,
|
|
62
|
+
TableHeader: true,
|
|
63
|
+
TableRow: true,
|
|
64
|
+
Tabs: true,
|
|
65
|
+
Textarea: true,
|
|
66
|
+
Tooltip: true,
|
|
67
|
+
TablePagination: true,
|
|
68
|
+
useOnClickOutside: true,
|
|
69
|
+
useClickOutside: true,
|
|
70
|
+
useId: true,
|
|
71
|
+
useListener: true,
|
|
72
|
+
useOnEscapePressed: true,
|
|
73
|
+
usePagination: true,
|
|
74
|
+
usePrevious: true,
|
|
75
|
+
useThrottle: true,
|
|
76
|
+
useWindowFitment: true,
|
|
77
|
+
isNavigationAnchor: true,
|
|
78
|
+
isNavigationButton: true,
|
|
79
|
+
Theme: true
|
|
80
|
+
};
|
|
6
81
|
Object.defineProperty(exports, "Accordion", {
|
|
7
82
|
enumerable: true,
|
|
8
83
|
get: function () {
|
|
@@ -468,6 +543,18 @@ var _MainTable = _interopRequireDefault(require("./components/MainTable"));
|
|
|
468
543
|
var _ModularTable = _interopRequireDefault(require("./components/ModularTable"));
|
|
469
544
|
var _Navigation = _interopRequireDefault(require("./components/Navigation"));
|
|
470
545
|
var _Modal = _interopRequireDefault(require("./components/Modal"));
|
|
546
|
+
var _MultiSelect = require("./components/MultiSelect");
|
|
547
|
+
Object.keys(_MultiSelect).forEach(function (key) {
|
|
548
|
+
if (key === "default" || key === "__esModule") return;
|
|
549
|
+
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
|
550
|
+
if (key in exports && exports[key] === _MultiSelect[key]) return;
|
|
551
|
+
Object.defineProperty(exports, key, {
|
|
552
|
+
enumerable: true,
|
|
553
|
+
get: function () {
|
|
554
|
+
return _MultiSelect[key];
|
|
555
|
+
}
|
|
556
|
+
});
|
|
557
|
+
});
|
|
471
558
|
var _Notification = _interopRequireWildcard(require("./components/Notification"));
|
|
472
559
|
var _NotificationProvider = require("./components/NotificationProvider");
|
|
473
560
|
var _Pagination = _interopRequireDefault(require("./components/Pagination"));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@canonical/react-components",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.49.0",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"module": "dist/index.js",
|
|
6
6
|
"author": "Huw Wilkins <huw.wilkins@canonical.com>",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"@babel/eslint-parser": "7.23.3",
|
|
27
27
|
"@babel/preset-typescript": "7.23.3",
|
|
28
28
|
"@percy/cli": "1.27.6",
|
|
29
|
-
"@percy/storybook": "
|
|
29
|
+
"@percy/storybook": "5.0.1",
|
|
30
30
|
"@semantic-release/changelog": "6.0.3",
|
|
31
31
|
"@semantic-release/git": "10.0.1",
|
|
32
32
|
"@storybook/addon-a11y": "7.6.7",
|
|
@@ -38,64 +38,65 @@
|
|
|
38
38
|
"@storybook/blocks": "7.6.7",
|
|
39
39
|
"@storybook/react": "7.6.7",
|
|
40
40
|
"@storybook/react-webpack5": "7.6.7",
|
|
41
|
-
"@testing-library/cypress": "
|
|
41
|
+
"@testing-library/cypress": "10.0.1",
|
|
42
42
|
"@testing-library/dom": "9.3.3",
|
|
43
|
-
"@testing-library/jest-dom": "
|
|
43
|
+
"@testing-library/jest-dom": "6.2.1",
|
|
44
44
|
"@testing-library/react": "14.1.2",
|
|
45
45
|
"@testing-library/user-event": "14.5.2",
|
|
46
|
-
"@typescript-eslint/eslint-plugin": "
|
|
47
|
-
"@typescript-eslint/parser": "
|
|
48
|
-
"babel-jest": "
|
|
46
|
+
"@typescript-eslint/eslint-plugin": "6.19.1",
|
|
47
|
+
"@typescript-eslint/parser": "6.19.1",
|
|
48
|
+
"babel-jest": "29.7.0",
|
|
49
49
|
"babel-loader": "9.1.3",
|
|
50
50
|
"babel-plugin-module-resolver": "5.0.0",
|
|
51
51
|
"babel-plugin-typescript-to-proptypes": "2.1.0",
|
|
52
52
|
"concurrently": "8.2.2",
|
|
53
53
|
"css-loader": "6.8.1",
|
|
54
|
-
"cypress": "
|
|
54
|
+
"cypress": "13.6.3",
|
|
55
55
|
"deepmerge": "4.3.1",
|
|
56
56
|
"eslint": "8.56.0",
|
|
57
|
-
"eslint-config-prettier": "
|
|
57
|
+
"eslint-config-prettier": "9.1.0",
|
|
58
58
|
"eslint-config-react-app": "7.0.1",
|
|
59
59
|
"eslint-plugin-cypress": "2.15.1",
|
|
60
60
|
"eslint-plugin-flowtype": "8.0.3",
|
|
61
61
|
"eslint-plugin-import": "2.29.1",
|
|
62
62
|
"eslint-plugin-jsx-a11y": "6.8.0",
|
|
63
|
-
"eslint-plugin-prettier": "
|
|
63
|
+
"eslint-plugin-prettier": "5.1.3",
|
|
64
64
|
"eslint-plugin-react": "7.33.2",
|
|
65
65
|
"eslint-plugin-react-hooks": "4.6.0",
|
|
66
66
|
"eslint-plugin-storybook": "0.6.15",
|
|
67
|
-
"eslint-plugin-testing-library": "
|
|
68
|
-
"jest": "
|
|
69
|
-
"npm-package-json-lint": "
|
|
70
|
-
"prettier": "2.
|
|
67
|
+
"eslint-plugin-testing-library": "6.2.0",
|
|
68
|
+
"jest": "29.7.0",
|
|
69
|
+
"npm-package-json-lint": "7.1.0",
|
|
70
|
+
"prettier": "3.2.4",
|
|
71
71
|
"react": "18.2.0",
|
|
72
72
|
"react-docgen-typescript-loader": "3.7.2",
|
|
73
73
|
"react-dom": "18.2.0",
|
|
74
74
|
"sass": "1.69.7",
|
|
75
|
-
"sass-loader": "
|
|
75
|
+
"sass-loader": "14.0.0",
|
|
76
76
|
"semantic-release": "23.0.0",
|
|
77
77
|
"storybook": "7.6.7",
|
|
78
78
|
"style-loader": "3.3.3",
|
|
79
|
-
"stylelint": "
|
|
79
|
+
"stylelint": "16.2.0",
|
|
80
80
|
"stylelint-config-prettier": "9.0.5",
|
|
81
|
-
"stylelint-config-recommended-scss": "
|
|
82
|
-
"stylelint-order": "
|
|
83
|
-
"stylelint-prettier": "
|
|
84
|
-
"ts-jest": "
|
|
81
|
+
"stylelint-config-recommended-scss": "14.0.0",
|
|
82
|
+
"stylelint-order": "6.0.4",
|
|
83
|
+
"stylelint-prettier": "5.0.0",
|
|
84
|
+
"ts-jest": "29.1.2",
|
|
85
85
|
"tsc-alias": "1.8.8",
|
|
86
|
-
"typescript": "
|
|
86
|
+
"typescript": "5.3.3",
|
|
87
87
|
"vanilla-framework": "4.6.0",
|
|
88
|
-
"wait-on": "
|
|
88
|
+
"wait-on": "7.2.0",
|
|
89
89
|
"webpack": "5.89.0"
|
|
90
90
|
},
|
|
91
91
|
"dependencies": {
|
|
92
|
-
"@types/jest": "
|
|
92
|
+
"@types/jest": "29.5.11",
|
|
93
93
|
"@types/node": "18.19.4",
|
|
94
94
|
"@types/react": "18.2.46",
|
|
95
95
|
"@types/react-dom": "18.2.18",
|
|
96
96
|
"@types/react-table": "7.7.19",
|
|
97
97
|
"classnames": "2.5.1",
|
|
98
|
-
"
|
|
98
|
+
"jest-environment-jsdom": "29.7.0",
|
|
99
|
+
"nanoid": "5.0.4",
|
|
99
100
|
"prop-types": "15.8.1",
|
|
100
101
|
"react-table": "7.8.0",
|
|
101
102
|
"react-useportal": "1.0.19"
|
|
@@ -104,10 +105,7 @@
|
|
|
104
105
|
"@types/react": "18.2.46",
|
|
105
106
|
"@types/react-dom": "18.2.18",
|
|
106
107
|
"postcss": "^8.3.11",
|
|
107
|
-
"
|
|
108
|
-
"jackspeak": "^2",
|
|
109
|
-
"strip-ansi": "^6.0.0",
|
|
110
|
-
"strip-ansi-cjs": "^8.0.0"
|
|
108
|
+
"jackspeak": "2.1.1"
|
|
111
109
|
},
|
|
112
110
|
"peerDependencies": {
|
|
113
111
|
"@types/react": "^17.0.2 || ^18.0.0",
|