@canonical/react-components 1.7.2 → 1.8.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.
Files changed (33) hide show
  1. package/dist/components/CustomSelect/CustomSelect.d.ts +36 -0
  2. package/dist/components/CustomSelect/CustomSelect.js +145 -0
  3. package/dist/components/CustomSelect/CustomSelect.scss +82 -0
  4. package/dist/components/CustomSelect/CustomSelect.stories.d.ts +28 -0
  5. package/dist/components/CustomSelect/CustomSelect.stories.js +132 -0
  6. package/dist/components/CustomSelect/CustomSelect.test.d.ts +1 -0
  7. package/dist/components/CustomSelect/CustomSelectDropdown/CustomSelectDropdown.d.ts +25 -0
  8. package/dist/components/CustomSelect/CustomSelectDropdown/CustomSelectDropdown.js +300 -0
  9. package/dist/components/CustomSelect/CustomSelectDropdown/CustomSelectDropdown.test.d.ts +1 -0
  10. package/dist/components/CustomSelect/CustomSelectDropdown/index.d.ts +2 -0
  11. package/dist/components/CustomSelect/CustomSelectDropdown/index.js +20 -0
  12. package/dist/components/CustomSelect/index.d.ts +3 -0
  13. package/dist/components/CustomSelect/index.js +13 -0
  14. package/dist/components/MultiSelect/MultiSelect.scss +1 -0
  15. package/dist/esm/components/CustomSelect/CustomSelect.d.ts +36 -0
  16. package/dist/esm/components/CustomSelect/CustomSelect.js +139 -0
  17. package/dist/esm/components/CustomSelect/CustomSelect.scss +82 -0
  18. package/dist/esm/components/CustomSelect/CustomSelect.stories.d.ts +28 -0
  19. package/dist/esm/components/CustomSelect/CustomSelect.stories.js +126 -0
  20. package/dist/esm/components/CustomSelect/CustomSelect.test.d.ts +1 -0
  21. package/dist/esm/components/CustomSelect/CustomSelectDropdown/CustomSelectDropdown.d.ts +25 -0
  22. package/dist/esm/components/CustomSelect/CustomSelectDropdown/CustomSelectDropdown.js +285 -0
  23. package/dist/esm/components/CustomSelect/CustomSelectDropdown/CustomSelectDropdown.test.d.ts +1 -0
  24. package/dist/esm/components/CustomSelect/CustomSelectDropdown/index.d.ts +2 -0
  25. package/dist/esm/components/CustomSelect/CustomSelectDropdown/index.js +1 -0
  26. package/dist/esm/components/CustomSelect/index.d.ts +3 -0
  27. package/dist/esm/components/CustomSelect/index.js +1 -0
  28. package/dist/esm/components/MultiSelect/MultiSelect.scss +1 -0
  29. package/dist/esm/index.d.ts +2 -0
  30. package/dist/esm/index.js +1 -0
  31. package/dist/index.d.ts +2 -0
  32. package/dist/index.js +8 -0
  33. package/package.json +1 -1
@@ -0,0 +1,126 @@
1
+ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
2
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
3
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
4
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
5
+ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
6
+ function _objectDestructuringEmpty(t) { if (null == t) throw new TypeError("Cannot destructure " + t); }
7
+ function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
8
+ import CustomSelect from "./CustomSelect";
9
+ import React, { useState } from "react";
10
+ var generateStandardOptions = num => Array(num).fill(null).map((_, i) => ({
11
+ value: "option-".concat(i + 1),
12
+ label: "Option ".concat(i + 1),
13
+ text: "Option ".concat(i + 1),
14
+ disabled: false
15
+ }));
16
+ var generateCustomOptions = () => {
17
+ return [{
18
+ value: "smile",
19
+ label: /*#__PURE__*/React.createElement("div", null, "\uD83D\uDE00"),
20
+ text: "Smile",
21
+ disabled: false
22
+ }, {
23
+ value: "grin",
24
+ label: /*#__PURE__*/React.createElement("div", null, "\uD83D\uDE01"),
25
+ text: "Grin",
26
+ disabled: false
27
+ }, {
28
+ value: "cry",
29
+ label: /*#__PURE__*/React.createElement("div", null, "\uD83D\uDE2D"),
30
+ text: "Cry",
31
+ disabled: false
32
+ }, {
33
+ value: "angry",
34
+ label: /*#__PURE__*/React.createElement("div", null, "\uD83D\uDE21"),
35
+ text: "Angry",
36
+ disabled: false
37
+ }, {
38
+ value: "sad",
39
+ label: /*#__PURE__*/React.createElement("div", null, "\uD83D\uDE22"),
40
+ text: "Sad",
41
+ disabled: false
42
+ }];
43
+ };
44
+ var Template = _ref => {
45
+ var props = _extends({}, (_objectDestructuringEmpty(_ref), _ref));
46
+ var [selected, setSelected] = useState(props.value || "");
47
+ return /*#__PURE__*/React.createElement(CustomSelect, _extends({}, props, {
48
+ value: selected,
49
+ onChange: value => setSelected(value)
50
+ }));
51
+ };
52
+ var meta = {
53
+ component: CustomSelect,
54
+ render: Template,
55
+ tags: ["autodocs"],
56
+ args: {
57
+ name: "customSelect",
58
+ label: "Custom Select",
59
+ searchable: "auto",
60
+ initialPosition: "left"
61
+ },
62
+ argTypes: {
63
+ searchable: {
64
+ options: ["auto", "always", "never"],
65
+ control: {
66
+ type: "select"
67
+ }
68
+ },
69
+ initialPosition: {
70
+ options: ["left", "right"],
71
+ control: {
72
+ type: "select"
73
+ }
74
+ }
75
+ }
76
+ };
77
+ export default meta;
78
+ /**
79
+ * If `label` is of `string` type. You do not have to do anything extra to render it.
80
+ */
81
+ export var StandardOptions = {
82
+ args: {
83
+ options: generateStandardOptions(10)
84
+ }
85
+ };
86
+
87
+ /**
88
+ * If `label` is of `ReactNode` type. You can render custom content.
89
+ * In this case, the `text` property for each option is required and is used for display in the toggle, search and sort functionalities.
90
+ */
91
+ export var CustomOptions = {
92
+ args: {
93
+ options: generateCustomOptions()
94
+ }
95
+ };
96
+
97
+ /**
98
+ * For each option, if `disabled` is set to `true`, the option will be disabled.
99
+ */
100
+ export var DisabledOptions = {
101
+ args: {
102
+ options: generateStandardOptions(5).map((option, i) => _objectSpread(_objectSpread({}, option), {}, {
103
+ disabled: i % 2 === 0
104
+ }))
105
+ }
106
+ };
107
+
108
+ /**
109
+ * Search is enabled by default when there are 5 or more options.
110
+ */
111
+ export var AutoSearchable = {
112
+ args: {
113
+ options: generateStandardOptions(5),
114
+ searchable: "auto"
115
+ }
116
+ };
117
+
118
+ /**
119
+ * Search can be enabled manually by setting `searchable` to `always`.
120
+ */
121
+ export var ManualSearchable = {
122
+ args: {
123
+ options: generateStandardOptions(4),
124
+ searchable: "always"
125
+ }
126
+ };
@@ -0,0 +1,25 @@
1
+ import { FC, LiHTMLAttributes, ReactNode } from "react";
2
+ export type CustomSelectOption = LiHTMLAttributes<HTMLLIElement> & {
3
+ value: string;
4
+ label: ReactNode;
5
+ text?: string;
6
+ disabled?: boolean;
7
+ };
8
+ export type Props = {
9
+ searchable?: "auto" | "always" | "never";
10
+ name: string;
11
+ options: CustomSelectOption[];
12
+ onSelect: (value: string) => void;
13
+ onSearch?: (value: string) => void;
14
+ onClose: () => void;
15
+ header?: ReactNode;
16
+ toggleId: string;
17
+ };
18
+ export declare const adjustDropdownHeightBelow: (dropdown: HTMLUListElement) => void;
19
+ export declare const adjustDropdownHeightAbove: (dropdown: HTMLUListElement, search: HTMLInputElement | null) => void;
20
+ export declare const dropdownIsAbove: (dropdown: HTMLUListElement) => boolean;
21
+ export declare const adjustDropdownHeight: (dropdown: HTMLUListElement | null, search: HTMLInputElement | null) => void;
22
+ export declare const getNearestParentsZIndex: (element: HTMLElement | null) => string;
23
+ export declare const getOptionText: (option: CustomSelectOption) => string;
24
+ declare const CustomSelectDropdown: FC<Props>;
25
+ export default CustomSelectDropdown;
@@ -0,0 +1,285 @@
1
+ import _pt from "prop-types";
2
+ import React, { useEffect, useLayoutEffect, useRef, useState } from "react";
3
+ import classnames from "classnames";
4
+ import { useListener } from "../../../hooks";
5
+ import SearchBox from "../../SearchBox";
6
+ var DROPDOWN_MAX_HEIGHT = 16 * 30; // 30rem with base 16px
7
+ var DROPDOWN_MARGIN = 20;
8
+ export var adjustDropdownHeightBelow = dropdown => {
9
+ var _window$visualViewpor;
10
+ var dropdownRect = dropdown.getBoundingClientRect();
11
+ var dropdownHeight = dropdown.offsetHeight;
12
+ var viewportHeight = ((_window$visualViewpor = window.visualViewport) === null || _window$visualViewpor === void 0 ? void 0 : _window$visualViewpor.height) || window.innerHeight;
13
+
14
+ // If the dropdown is cut off at the bottom of the viewport
15
+ // adjust the height to fit within the viewport minus fixed margin.
16
+ // This usually becomes an issue when the dropdown is at the bottom of the viewport or screen getting smaller.
17
+ if (dropdownRect.bottom >= viewportHeight) {
18
+ var _adjustedHeight = dropdownHeight - dropdownRect.bottom + viewportHeight - DROPDOWN_MARGIN;
19
+ dropdown.style.height = "".concat(_adjustedHeight, "px");
20
+ dropdown.style.maxHeight = "".concat(_adjustedHeight, "px");
21
+ return;
22
+ }
23
+
24
+ // If the dropdown does not have overflow, the dropdown should fit its content.
25
+ var hasOverflow = dropdown.scrollHeight > dropdown.clientHeight;
26
+ if (!hasOverflow) {
27
+ dropdown.style.height = "auto";
28
+ dropdown.style.maxHeight = "";
29
+ return;
30
+ }
31
+
32
+ // If the dropdown is not cut off at the bottom of the viewport
33
+ // adjust the height of the dropdown so that its bottom edge is 20px from the bottom of the viewport
34
+ // until the dropdown max height is reached.
35
+ var adjustedHeight = Math.min(viewportHeight - dropdownRect.top - DROPDOWN_MARGIN, DROPDOWN_MAX_HEIGHT);
36
+ dropdown.style.height = "".concat(adjustedHeight, "px");
37
+ dropdown.style.maxHeight = "".concat(adjustedHeight, "px");
38
+ };
39
+ export var adjustDropdownHeightAbove = (dropdown, search) => {
40
+ // The search height is subtracted (if necessary) so that no options will be hidden behind the search input.
41
+ var searchRect = search === null || search === void 0 ? void 0 : search.getBoundingClientRect();
42
+ var searchHeight = (searchRect === null || searchRect === void 0 ? void 0 : searchRect.height) || 0;
43
+ var dropdownRect = dropdown.getBoundingClientRect();
44
+
45
+ // If the dropdown does not have overflow, do not adjust.
46
+ var hasOverflow = dropdown.scrollHeight > dropdown.clientHeight;
47
+ if (!hasOverflow) {
48
+ dropdown.style.height = "auto";
49
+ dropdown.style.maxHeight = "";
50
+ return;
51
+ }
52
+
53
+ // adjust the height of the dropdown so that its top edge is 20px from the top of the viewport.
54
+ // until the dropdown max height is reached.
55
+ // unlike the case where the dropdown is bellow the toggle, dropdown.bottom represents the available space above the toggle always.
56
+ // this makes the calculation simpler since we only need to work with dropdown.bottom regardless if the element is cut off or not.
57
+ var adjustedHeight = Math.min(dropdownRect.bottom - searchHeight - DROPDOWN_MARGIN, DROPDOWN_MAX_HEIGHT);
58
+ dropdown.style.height = "".concat(adjustedHeight, "px");
59
+ dropdown.style.maxHeight = "".concat(adjustedHeight, "px");
60
+ };
61
+ export var dropdownIsAbove = dropdown => {
62
+ var toggle = document.querySelector(".p-custom-select__toggle");
63
+ var dropdownRect = dropdown.getBoundingClientRect();
64
+ var toggleRect = toggle.getBoundingClientRect();
65
+ return toggleRect.top >= dropdownRect.bottom;
66
+ };
67
+ export var adjustDropdownHeight = (dropdown, search) => {
68
+ if (!dropdown) {
69
+ return;
70
+ }
71
+ if (dropdownIsAbove(dropdown)) {
72
+ adjustDropdownHeightAbove(dropdown, search);
73
+ return;
74
+ }
75
+ adjustDropdownHeightBelow(dropdown);
76
+ };
77
+ export var getNearestParentsZIndex = element => {
78
+ if (!document.defaultView || !element) {
79
+ return "0";
80
+ }
81
+ var zIndex = document.defaultView.getComputedStyle(element, null).getPropertyValue("z-index");
82
+ if (!element.parentElement) {
83
+ return zIndex;
84
+ }
85
+ if (zIndex === "auto" || zIndex === "0" || zIndex === "") {
86
+ return getNearestParentsZIndex(element.parentElement);
87
+ }
88
+ return zIndex;
89
+ };
90
+ export var getOptionText = option => {
91
+ if (option.text) {
92
+ return option.text;
93
+ }
94
+ if (typeof option.label === "string") {
95
+ return option.label;
96
+ }
97
+ throw new Error("CustomSelect: options must have a string label or a text property");
98
+ };
99
+ var CustomSelectDropdown = _ref => {
100
+ var {
101
+ searchable,
102
+ name,
103
+ options,
104
+ onSelect,
105
+ onSearch,
106
+ onClose,
107
+ header,
108
+ toggleId
109
+ } = _ref;
110
+ var [search, setSearch] = useState("");
111
+ // track highlighted option index for keyboard actions
112
+ var [highlightedOptionIndex, setHighlightedOptionIndex] = useState(0);
113
+ // use ref to keep a reference to all option HTML elements so we do not need to make DOM calls later for scrolling
114
+ var optionsRef = useRef([]);
115
+ var dropdownRef = useRef(null);
116
+ var searchRef = useRef(null);
117
+ var dropdownListRef = useRef(null);
118
+ var isSearchable = searchable !== "never" && options.length > 1 && (searchable === "always" || searchable === "auto" && options.length >= 5);
119
+ useEffect(() => {
120
+ if (dropdownRef.current) {
121
+ var _toggle$getBoundingCl, _toggle$getBoundingCl2;
122
+ var toggle = document.getElementById(toggleId);
123
+
124
+ // align width with wrapper toggle width
125
+ var toggleWidth = (_toggle$getBoundingCl = toggle === null || toggle === void 0 || (_toggle$getBoundingCl2 = toggle.getBoundingClientRect()) === null || _toggle$getBoundingCl2 === void 0 ? void 0 : _toggle$getBoundingCl2.width) !== null && _toggle$getBoundingCl !== void 0 ? _toggle$getBoundingCl : 0;
126
+ dropdownRef.current.style.setProperty("min-width", "".concat(toggleWidth, "px"));
127
+
128
+ // align z-index: when we are in a modal context, we want the dropdown to be above the modal
129
+ // apply the nearest parents z-index + 1
130
+ var zIndex = getNearestParentsZIndex(toggle);
131
+ if (parseInt(zIndex) > 0) {
132
+ var _dropdownRef$current$;
133
+ (_dropdownRef$current$ = dropdownRef.current.parentElement) === null || _dropdownRef$current$ === void 0 || _dropdownRef$current$.style.setProperty("z-index", zIndex + 1);
134
+ }
135
+ }
136
+ setTimeout(() => {
137
+ var _dropdownRef$current;
138
+ if (isSearchable) {
139
+ var _searchRef$current;
140
+ (_searchRef$current = searchRef.current) === null || _searchRef$current === void 0 || _searchRef$current.focus();
141
+ return;
142
+ }
143
+ (_dropdownRef$current = dropdownRef.current) === null || _dropdownRef$current === void 0 || _dropdownRef$current.focus();
144
+ }, 100);
145
+ }, [isSearchable, toggleId]);
146
+ var handleResize = () => {
147
+ adjustDropdownHeight(dropdownListRef.current, searchRef.current);
148
+ };
149
+ useLayoutEffect(handleResize, []);
150
+ useListener(window, handleResize, "resize");
151
+
152
+ // track selected index from key board action and scroll into view if needed
153
+ useEffect(() => {
154
+ var _optionsRef$current$h;
155
+ (_optionsRef$current$h = optionsRef.current[highlightedOptionIndex]) === null || _optionsRef$current$h === void 0 || _optionsRef$current$h.scrollIntoView({
156
+ block: "nearest",
157
+ inline: "nearest"
158
+ });
159
+ }, [highlightedOptionIndex]);
160
+ var filteredOptions = onSearch ? options : options === null || options === void 0 ? void 0 : options.filter(option => {
161
+ if (!search || option.disabled) return true;
162
+ var searchText = getOptionText(option) || option.value;
163
+ return searchText.toLowerCase().includes(search);
164
+ });
165
+ var getNextOptionIndex = (goingUp, prevIndex) => {
166
+ var increment = goingUp ? -1 : 1;
167
+ var currIndex = prevIndex + increment;
168
+ // skip disabled options for key board action
169
+ while (filteredOptions[currIndex] && (_filteredOptions$curr = filteredOptions[currIndex]) !== null && _filteredOptions$curr !== void 0 && _filteredOptions$curr.disabled) {
170
+ var _filteredOptions$curr;
171
+ currIndex += increment;
172
+ }
173
+
174
+ // consider upper bound for navigating down the list
175
+ if (increment > 0) {
176
+ return currIndex < filteredOptions.length ? currIndex : prevIndex;
177
+ }
178
+
179
+ // consider lower bound for navigating up the list
180
+ return currIndex >= 0 ? currIndex : prevIndex;
181
+ };
182
+
183
+ // handle keyboard actions for navigating the select dropdown
184
+ var handleKeyDown = event => {
185
+ var upDownKeys = ["ArrowUp", "ArrowDown"];
186
+
187
+ // prevent default browser actions for up, down, enter and escape keys
188
+ // also prevent any other event listeners from being called up the DOM tree
189
+ if ([...upDownKeys, "Enter", "Escape", "Tab"].includes(event.key)) {
190
+ event.preventDefault();
191
+ event.nativeEvent.stopImmediatePropagation();
192
+ }
193
+ if (upDownKeys.includes(event.key)) {
194
+ setHighlightedOptionIndex(prevIndex => {
195
+ var goingUp = event.key === "ArrowUp";
196
+ return getNextOptionIndex(goingUp, prevIndex);
197
+ });
198
+ }
199
+ if (event.key === "Enter" && filteredOptions[highlightedOptionIndex]) {
200
+ onSelect(filteredOptions[highlightedOptionIndex].value);
201
+ }
202
+ if (event.key === "Escape" || event.key === "Tab") {
203
+ onClose();
204
+ }
205
+ };
206
+ var handleSearch = value => {
207
+ setSearch(value.toLowerCase());
208
+ // reset selected index when search text changes
209
+ setHighlightedOptionIndex(0);
210
+ optionsRef.current = [];
211
+ if (onSearch) {
212
+ onSearch(value);
213
+ }
214
+ };
215
+ var handleSelect = option => {
216
+ if (option.disabled) {
217
+ return;
218
+ }
219
+ onSelect(option.value);
220
+ };
221
+ var optionItems = filteredOptions.map((option, idx) => {
222
+ return /*#__PURE__*/React.createElement("li", {
223
+ key: "".concat(option.value, "-").concat(idx),
224
+ onClick: () => handleSelect(option),
225
+ className: classnames("p-list__item", "p-custom-select__option", "u-truncate", {
226
+ disabled: option.disabled,
227
+ highlight: idx === highlightedOptionIndex && !option.disabled
228
+ })
229
+ // adding option elements to a ref array makes it easier to scroll the element later
230
+ // else we'd have to make a DOM call to find the element based on some identifier
231
+ ,
232
+ ref: el => {
233
+ if (!el) return;
234
+ optionsRef.current[idx] = el;
235
+ },
236
+ role: "option",
237
+ onMouseMove: () => setHighlightedOptionIndex(idx)
238
+ }, /*#__PURE__*/React.createElement("span", {
239
+ className: classnames({
240
+ "u-text--muted": option.disabled
241
+ })
242
+ }, option.label));
243
+ });
244
+ return /*#__PURE__*/React.createElement("div", {
245
+ className: "p-custom-select__dropdown u-no-padding",
246
+ role: "combobox",
247
+ onKeyDownCapture: handleKeyDown
248
+ // allow focus on the dropdown so that keyboard actions can be captured
249
+ ,
250
+ tabIndex: -1,
251
+ ref: dropdownRef,
252
+ onMouseDown: e => {
253
+ // when custom select is used in a modal, which is a portal, a dropdown click
254
+ // should not close the modal itself, so we stop the event right here.
255
+ e.stopPropagation();
256
+ }
257
+ }, isSearchable && /*#__PURE__*/React.createElement("div", {
258
+ className: "p-custom-select__search u-no-padding--bottom"
259
+ }, /*#__PURE__*/React.createElement(SearchBox, {
260
+ ref: searchRef,
261
+ id: "select-search-".concat(name),
262
+ name: "select-search-".concat(name),
263
+ type: "text",
264
+ "aria-label": "Search for ".concat(name),
265
+ className: "u-no-margin--bottom",
266
+ onChange: handleSearch,
267
+ value: search,
268
+ autocomplete: "off"
269
+ })), header, /*#__PURE__*/React.createElement("ul", {
270
+ className: "p-list u-no-margin--bottom",
271
+ role: "listbox",
272
+ ref: dropdownListRef
273
+ }, optionItems));
274
+ };
275
+ CustomSelectDropdown.propTypes = {
276
+ searchable: _pt.oneOf(["auto", "always", "never"]),
277
+ name: _pt.string.isRequired,
278
+ options: _pt.array.isRequired,
279
+ onSelect: _pt.func.isRequired,
280
+ onSearch: _pt.func,
281
+ onClose: _pt.func.isRequired,
282
+ header: _pt.node,
283
+ toggleId: _pt.string.isRequired
284
+ };
285
+ export default CustomSelectDropdown;
@@ -0,0 +1,2 @@
1
+ export { default, getOptionText } from "./CustomSelectDropdown";
2
+ export type { CustomSelectOption, Props as CustomSelectDropdownProps, } from "./CustomSelectDropdown";
@@ -0,0 +1 @@
1
+ export { default, getOptionText } from "./CustomSelectDropdown";
@@ -0,0 +1,3 @@
1
+ export { default } from "./CustomSelect";
2
+ export type { Props as CustomSelectProps } from "./CustomSelect";
3
+ export type { CustomSelectDropdownProps, CustomSelectOption, } from "./CustomSelectDropdown";
@@ -0,0 +1 @@
1
+ export { default } from "./CustomSelect";
@@ -56,6 +56,7 @@ $dropdown-max-height: 20rem;
56
56
  list-style: none;
57
57
  margin-bottom: $sph--x-small;
58
58
  margin-left: 0;
59
+ margin-top: $sph--x-small;
59
60
  padding-left: 0;
60
61
  }
61
62
 
@@ -67,6 +67,7 @@ export { default as Textarea } from "./components/Textarea";
67
67
  export { default as Tooltip } from "./components/Tooltip";
68
68
  export { default as TablePagination } from "./components/TablePagination";
69
69
  export { default as TablePaginationControls } from "./components/TablePagination/TablePaginationControls";
70
+ export { default as CustomSelect } from "./components/CustomSelect";
70
71
  export type { AccordionProps } from "./components/Accordion";
71
72
  export type { ActionButtonProps } from "./components/ActionButton";
72
73
  export type { ArticlePaginationProps } from "./components/ArticlePagination";
@@ -131,6 +132,7 @@ export type { TabsProps } from "./components/Tabs";
131
132
  export type { TextareaProps } from "./components/Textarea";
132
133
  export type { TooltipProps } from "./components/Tooltip";
133
134
  export type { TablePaginationProps } from "./components/TablePagination";
135
+ export type { CustomSelectProps, CustomSelectDropdownProps, CustomSelectOption, } from "./components/CustomSelect";
134
136
  export { useOnClickOutside, useClickOutside, useId, useListener, useOnEscapePressed, usePagination, usePrevious, useThrottle, useWindowFitment, } from "./hooks";
135
137
  export type { WindowFitment } from "./hooks";
136
138
  export { isNavigationAnchor, isNavigationButton } from "./utils";
package/dist/esm/index.js CHANGED
@@ -67,6 +67,7 @@ export { default as Textarea } from "./components/Textarea";
67
67
  export { default as Tooltip } from "./components/Tooltip";
68
68
  export { default as TablePagination } from "./components/TablePagination";
69
69
  export { default as TablePaginationControls } from "./components/TablePagination/TablePaginationControls";
70
+ export { default as CustomSelect } from "./components/CustomSelect";
70
71
  export { useOnClickOutside, useClickOutside, useId, useListener, useOnEscapePressed, usePagination, usePrevious, useThrottle, useWindowFitment } from "./hooks";
71
72
  export { isNavigationAnchor, isNavigationButton } from "./utils";
72
73
  export { Theme } from "./enums";
package/dist/index.d.ts CHANGED
@@ -67,6 +67,7 @@ export { default as Textarea } from "./components/Textarea";
67
67
  export { default as Tooltip } from "./components/Tooltip";
68
68
  export { default as TablePagination } from "./components/TablePagination";
69
69
  export { default as TablePaginationControls } from "./components/TablePagination/TablePaginationControls";
70
+ export { default as CustomSelect } from "./components/CustomSelect";
70
71
  export type { AccordionProps } from "./components/Accordion";
71
72
  export type { ActionButtonProps } from "./components/ActionButton";
72
73
  export type { ArticlePaginationProps } from "./components/ArticlePagination";
@@ -131,6 +132,7 @@ export type { TabsProps } from "./components/Tabs";
131
132
  export type { TextareaProps } from "./components/Textarea";
132
133
  export type { TooltipProps } from "./components/Tooltip";
133
134
  export type { TablePaginationProps } from "./components/TablePagination";
135
+ export type { CustomSelectProps, CustomSelectDropdownProps, CustomSelectOption, } from "./components/CustomSelect";
134
136
  export { useOnClickOutside, useClickOutside, useId, useListener, useOnEscapePressed, usePagination, usePrevious, useThrottle, useWindowFitment, } from "./hooks";
135
137
  export type { WindowFitment } from "./hooks";
136
138
  export { isNavigationAnchor, isNavigationButton } from "./utils";
package/dist/index.js CHANGED
@@ -84,6 +84,7 @@ var _exportNames = {
84
84
  Tooltip: true,
85
85
  TablePagination: true,
86
86
  TablePaginationControls: true,
87
+ CustomSelect: true,
87
88
  useOnClickOutside: true,
88
89
  useClickOutside: true,
89
90
  useId: true,
@@ -235,6 +236,12 @@ Object.defineProperty(exports, "ContextualMenu", {
235
236
  return _ContextualMenu.default;
236
237
  }
237
238
  });
239
+ Object.defineProperty(exports, "CustomSelect", {
240
+ enumerable: true,
241
+ get: function () {
242
+ return _CustomSelect.default;
243
+ }
244
+ });
238
245
  Object.defineProperty(exports, "DoughnutChart", {
239
246
  enumerable: true,
240
247
  get: function () {
@@ -729,6 +736,7 @@ var _Textarea = _interopRequireDefault(require("./components/Textarea"));
729
736
  var _Tooltip = _interopRequireDefault(require("./components/Tooltip"));
730
737
  var _TablePagination = _interopRequireDefault(require("./components/TablePagination"));
731
738
  var _TablePaginationControls = _interopRequireDefault(require("./components/TablePagination/TablePaginationControls"));
739
+ var _CustomSelect = _interopRequireDefault(require("./components/CustomSelect"));
732
740
  var _hooks = require("./hooks");
733
741
  var _utils = require("./utils");
734
742
  var _enums = require("./enums");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@canonical/react-components",
3
- "version": "1.7.2",
3
+ "version": "1.8.0",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.js",
6
6
  "author": {