etudes 2.6.0 → 3.0.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/lib/Dropdown.d.ts CHANGED
@@ -1,45 +1,20 @@
1
- import React, { type ComponentType, type HTMLAttributes, type PropsWithChildren, type ReactElement, type Ref } from 'react';
2
- import { type ListItemProps } from './List';
3
- type Orientation = 'horizontal' | 'vertical';
1
+ import React, { type HTMLAttributes, type PropsWithChildren, type ReactElement, type Ref } from 'react';
2
+ import { type ListItemProps, type ListProps } from './List';
4
3
  export type DropdownData = {
5
4
  label?: string;
6
5
  };
7
6
  export type DropdownItemProps<T extends DropdownData = DropdownData> = ListItemProps<T>;
8
- export type DropdownProps<T extends DropdownData = DropdownData> = HTMLAttributes<HTMLDivElement> & PropsWithChildren<{
9
- /**
10
- * Data of every item in the component. This is used to generate individual
11
- * menu items. Data type is generic.
12
- */
13
- data: T[];
7
+ export type DropdownProps<T extends DropdownData = DropdownData> = HTMLAttributes<HTMLDivElement> & ListProps<T> & PropsWithChildren<{
14
8
  /**
15
9
  * Indicates if the component is inverted (i.e. "dropup" instead of dropdown).
16
10
  * Supports all orientations.
17
11
  */
18
12
  isInverted?: boolean;
19
13
  /**
20
- * Indicates if items can be toggled, i.e. they can be deselected if selected
21
- * again.
22
- */
23
- isTogglable?: boolean;
24
- /**
25
- * Thickness of the border (in pixels) of every item and the dropdown button
26
- * itself. 0 indicates no borders.
14
+ * Specifies if the dropdown should be collapsed upon selection. This only
15
+ * works if `selectionMode` is `single`.
27
16
  */
28
- borderThickness?: number;
29
- /**
30
- * The index of the default selected item.
31
- */
32
- selectedIndex?: number;
33
- /**
34
- * Length (in pixels) of each item. This does not apply to the dropdown button
35
- * itself. Length refers to the height in vertical orientation and width in
36
- * horizontal orientation.
37
- */
38
- itemLength?: number;
39
- /**
40
- * Padding (in pixels) of each item.
41
- */
42
- itemPadding?: number;
17
+ collapsesOnSelect?: boolean;
43
18
  /**
44
19
  * Maximum number of items that are viside when the component expands. When a
45
20
  * value greater than or equal to 0 is specified, only that number of items
@@ -48,10 +23,6 @@ export type DropdownProps<T extends DropdownData = DropdownData> = HTMLAttribute
48
23
  * visible when the component expands.
49
24
  */
50
25
  maxVisibleItems?: number;
51
- /**
52
- * Orientation of the component.
53
- */
54
- orientation?: Orientation;
55
26
  /**
56
27
  * The label to appear on the dropdown button when no items are selected.
57
28
  */
@@ -61,13 +32,9 @@ export type DropdownProps<T extends DropdownData = DropdownData> = HTMLAttribute
61
32
  */
62
33
  expandIconSvg?: string;
63
34
  /**
64
- * React component type to be used for generating items inside the component.
65
- */
66
- itemComponentType: ComponentType<DropdownItemProps<T>>;
67
- /**
68
- * Handler invoked whenever the selected index changes.
35
+ * SVG markup to be put in the dropdown button as the collapse icon.
69
36
  */
70
- onIndexChange?: (index: number) => void;
37
+ collapseIconSvg?: string;
71
38
  }>;
72
39
  /**
73
40
  * A dropdown menu component that is invertible (i.e. can "dropup" instead) and
@@ -75,40 +42,29 @@ export type DropdownProps<T extends DropdownData = DropdownData> = HTMLAttribute
75
42
  * component type to this component to automatically generate menu items.
76
43
  */
77
44
  declare const _default: <T extends DropdownData = DropdownData>(props: React.HTMLAttributes<HTMLDivElement> & {
78
- /**
79
- * Data of every item in the component. This is used to generate individual
80
- * menu items. Data type is generic.
81
- */
45
+ borderThickness?: number | undefined;
82
46
  data: T[];
47
+ isTogglable?: boolean | undefined;
48
+ itemComponentType?: React.ComponentType<ListItemProps<T>> | undefined;
49
+ itemLength?: number | undefined;
50
+ itemPadding?: number | undefined;
51
+ orientation?: ("horizontal" | "vertical") | undefined;
52
+ selectedIndices?: number[] | undefined;
53
+ selectionMode?: "none" | "multiple" | "single" | undefined;
54
+ onActivateAt?: ((index: number) => void) | undefined;
55
+ onDeselectAt?: ((index: number) => void) | undefined;
56
+ onSelectAt?: ((index: number) => void) | undefined;
57
+ } & {
83
58
  /**
84
59
  * Indicates if the component is inverted (i.e. "dropup" instead of dropdown).
85
60
  * Supports all orientations.
86
61
  */
87
62
  isInverted?: boolean | undefined;
88
63
  /**
89
- * Indicates if items can be toggled, i.e. they can be deselected if selected
90
- * again.
91
- */
92
- isTogglable?: boolean | undefined;
93
- /**
94
- * Thickness of the border (in pixels) of every item and the dropdown button
95
- * itself. 0 indicates no borders.
64
+ * Specifies if the dropdown should be collapsed upon selection. This only
65
+ * works if `selectionMode` is `single`.
96
66
  */
97
- borderThickness?: number | undefined;
98
- /**
99
- * The index of the default selected item.
100
- */
101
- selectedIndex?: number | undefined;
102
- /**
103
- * Length (in pixels) of each item. This does not apply to the dropdown button
104
- * itself. Length refers to the height in vertical orientation and width in
105
- * horizontal orientation.
106
- */
107
- itemLength?: number | undefined;
108
- /**
109
- * Padding (in pixels) of each item.
110
- */
111
- itemPadding?: number | undefined;
67
+ collapsesOnSelect?: boolean | undefined;
112
68
  /**
113
69
  * Maximum number of items that are viside when the component expands. When a
114
70
  * value greater than or equal to 0 is specified, only that number of items
@@ -117,10 +73,6 @@ declare const _default: <T extends DropdownData = DropdownData>(props: React.HTM
117
73
  * visible when the component expands.
118
74
  */
119
75
  maxVisibleItems?: number | undefined;
120
- /**
121
- * Orientation of the component.
122
- */
123
- orientation?: Orientation | undefined;
124
76
  /**
125
77
  * The label to appear on the dropdown button when no items are selected.
126
78
  */
@@ -130,18 +82,15 @@ declare const _default: <T extends DropdownData = DropdownData>(props: React.HTM
130
82
  */
131
83
  expandIconSvg?: string | undefined;
132
84
  /**
133
- * React component type to be used for generating items inside the component.
134
- */
135
- itemComponentType: React.ComponentType<DropdownItemProps<T>>;
136
- /**
137
- * Handler invoked whenever the selected index changes.
85
+ * SVG markup to be put in the dropdown button as the collapse icon.
138
86
  */
139
- onIndexChange?: ((index: number) => void) | undefined;
87
+ collapseIconSvg?: string | undefined;
140
88
  } & {
141
89
  children?: React.ReactNode;
142
90
  } & {
143
91
  ref?: React.Ref<HTMLDivElement> | undefined;
144
92
  }) => ReactElement;
145
93
  export default _default;
146
- export declare const DropdownToggle: ({ ...props }: HTMLAttributes<HTMLButtonElement>) => React.JSX.Element;
147
- export declare const DropdownExpandIcon: ({ ...props }: HTMLAttributes<HTMLDivElement>) => React.JSX.Element;
94
+ export declare const DropdownToggle: ({ children, ...props }: HTMLAttributes<HTMLButtonElement> & PropsWithChildren) => React.JSX.Element;
95
+ export declare const DropdownExpandIcon: ({ children, ...props }: HTMLAttributes<HTMLDivElement> & PropsWithChildren) => React.JSX.Element;
96
+ export declare const DropdownCollapseIcon: ({ children, ...props }: HTMLAttributes<HTMLDivElement> & PropsWithChildren) => React.JSX.Element;
package/lib/Dropdown.js CHANGED
@@ -73,8 +73,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
73
73
  return (mod && mod.__esModule) ? mod : { "default": mod };
74
74
  };
75
75
  Object.defineProperty(exports, "__esModule", { value: true });
76
- exports.DropdownExpandIcon = exports.DropdownToggle = void 0;
76
+ exports.DropdownCollapseIcon = exports.DropdownExpandIcon = exports.DropdownToggle = void 0;
77
77
  var classnames_1 = __importDefault(require("classnames"));
78
+ var fast_deep_equal_1 = __importDefault(require("fast-deep-equal"));
78
79
  var react_1 = __importStar(require("react"));
79
80
  var FlatSVG_1 = __importDefault(require("./FlatSVG"));
80
81
  var List_1 = __importDefault(require("./List"));
@@ -91,20 +92,14 @@ var styles_1 = __importDefault(require("./utils/styles"));
91
92
  */
92
93
  exports.default = (0, react_1.forwardRef)(function (_a, ref) {
93
94
  var _b, _c, _d;
94
- var children = _a.children, className = _a.className, style = _a.style, _e = _a.borderThickness, borderThickness = _e === void 0 ? 0 : _e, data = _a.data, _f = _a.defaultLabel, defaultLabel = _f === void 0 ? 'Select' : _f, expandIconSvg = _a.expandIconSvg, _g = _a.isInverted, isInverted = _g === void 0 ? false : _g, _h = _a.isTogglable, isTogglable = _h === void 0 ? false : _h, itemComponentType = _a.itemComponentType, externalItemLength = _a.itemLength, _j = _a.itemPadding, itemPadding = _j === void 0 ? 0 : _j, _k = _a.maxVisibleItems, maxVisibleItems = _k === void 0 ? -1 : _k, _l = _a.orientation, orientation = _l === void 0 ? 'vertical' : _l, _m = _a.selectedIndex, externalSelectedIndex = _m === void 0 ? -1 : _m, onIndexChange = _a.onIndexChange, props = __rest(_a, ["children", "className", "style", "borderThickness", "data", "defaultLabel", "expandIconSvg", "isInverted", "isTogglable", "itemComponentType", "itemLength", "itemPadding", "maxVisibleItems", "orientation", "selectedIndex", "onIndexChange"]);
95
- var selectItemAt = function (index) {
96
- setSelectedIndex(index);
97
- setIsCollapsed(true);
98
- };
95
+ var children = _a.children, className = _a.className, style = _a.style, _e = _a.borderThickness, borderThickness = _e === void 0 ? 0 : _e, data = _a.data, _f = _a.collapsesOnSelect, collapsesOnSelect = _f === void 0 ? true : _f, _g = _a.defaultLabel, defaultLabel = _g === void 0 ? 'Select' : _g, expandIconSvg = _a.expandIconSvg, collapseIconSvg = _a.collapseIconSvg, _h = _a.isInverted, isInverted = _h === void 0 ? false : _h, _j = _a.isTogglable, isTogglable = _j === void 0 ? false : _j, itemComponentType = _a.itemComponentType, externalItemLength = _a.itemLength, _k = _a.itemPadding, itemPadding = _k === void 0 ? 0 : _k, _l = _a.maxVisibleItems, maxVisibleItems = _l === void 0 ? -1 : _l, _m = _a.orientation, orientation = _m === void 0 ? 'vertical' : _m, _o = _a.selectionMode, selectionMode = _o === void 0 ? 'single' : _o, _p = _a.selectedIndices, externalSelectedIndices = _p === void 0 ? [] : _p, onActivateAt = _a.onActivateAt, onDeselectAt = _a.onDeselectAt, onSelectAt = _a.onSelectAt, props = __rest(_a, ["children", "className", "style", "borderThickness", "data", "collapsesOnSelect", "defaultLabel", "expandIconSvg", "collapseIconSvg", "isInverted", "isTogglable", "itemComponentType", "itemLength", "itemPadding", "maxVisibleItems", "orientation", "selectionMode", "selectedIndices", "onActivateAt", "onDeselectAt", "onSelectAt"]);
99
96
  var expand = function () {
100
- if (!isCollapsed)
101
- return;
102
- setIsCollapsed(false);
97
+ if (isCollapsed)
98
+ setIsCollapsed(false);
103
99
  };
104
100
  var collapse = function () {
105
- if (isCollapsed)
106
- return;
107
- setIsCollapsed(true);
101
+ if (!isCollapsed)
102
+ setIsCollapsed(true);
108
103
  };
109
104
  var toggle = function () {
110
105
  if (isCollapsed) {
@@ -114,6 +109,11 @@ exports.default = (0, react_1.forwardRef)(function (_a, ref) {
114
109
  collapse();
115
110
  }
116
111
  };
112
+ var selectAtHandler = function (index) {
113
+ onSelectAt === null || onSelectAt === void 0 ? void 0 : onSelectAt(index);
114
+ if (selectionMode === 'single' && collapsesOnSelect)
115
+ collapse();
116
+ };
117
117
  var clickOutsideHandler = function (event) {
118
118
  if (isCollapsed)
119
119
  return;
@@ -135,8 +135,8 @@ exports.default = (0, react_1.forwardRef)(function (_a, ref) {
135
135
  collapse();
136
136
  };
137
137
  var bodyRef = (0, react_1.useRef)(null);
138
- var _o = __read((0, react_1.useState)(externalSelectedIndex), 2), selectedIndex = _o[0], setSelectedIndex = _o[1];
139
- var _p = __read((0, react_1.useState)(true), 2), isCollapsed = _p[0], setIsCollapsed = _p[1];
138
+ var _q = __read((0, react_1.useState)(externalSelectedIndices), 2), selectedIndices = _q[0], setSelectedIndices = _q[1];
139
+ var _r = __read((0, react_1.useState)(true), 2), isCollapsed = _r[0], setIsCollapsed = _r[1];
140
140
  var rect = (0, useElementRect_1.default)(bodyRef);
141
141
  (0, react_1.useEffect)(function () {
142
142
  window.addEventListener('click', clickOutsideHandler);
@@ -145,13 +145,10 @@ exports.default = (0, react_1.forwardRef)(function (_a, ref) {
145
145
  };
146
146
  }, [isCollapsed]);
147
147
  (0, react_1.useEffect)(function () {
148
- if (externalSelectedIndex === selectedIndex)
148
+ if ((0, fast_deep_equal_1.default)(externalSelectedIndices, selectedIndices))
149
149
  return;
150
- setSelectedIndex(externalSelectedIndex);
151
- }, [externalSelectedIndex]);
152
- (0, react_1.useEffect)(function () {
153
- onIndexChange === null || onIndexChange === void 0 ? void 0 : onIndexChange(selectedIndex);
154
- }, [selectedIndex]);
150
+ setSelectedIndices(externalSelectedIndices);
151
+ }, [JSON.stringify(externalSelectedIndices)]);
155
152
  var itemLength = externalItemLength !== null && externalItemLength !== void 0 ? externalItemLength : (orientation === 'vertical' ? rect.height : rect.width);
156
153
  var numItems = data.length;
157
154
  var numVisibleItems = maxVisibleItems < 0 ? numItems : Math.min(numItems, maxVisibleItems);
@@ -159,6 +156,7 @@ exports.default = (0, react_1.forwardRef)(function (_a, ref) {
159
156
  var components = (0, asComponentDict_1.default)(children, {
160
157
  toggle: exports.DropdownToggle,
161
158
  expandIcon: exports.DropdownExpandIcon,
159
+ collapseIcon: exports.DropdownCollapseIcon,
162
160
  });
163
161
  var fixedClassNames = (0, asClassNameDict_1.default)({
164
162
  root: (0, classnames_1.default)(orientation, {
@@ -176,6 +174,11 @@ exports.default = (0, react_1.forwardRef)(function (_a, ref) {
176
174
  collapsed: isCollapsed,
177
175
  expanded: !isCollapsed,
178
176
  }),
177
+ collapseIcon: (0, classnames_1.default)(orientation, {
178
+ togglable: isTogglable,
179
+ collapsed: isCollapsed,
180
+ expanded: !isCollapsed,
181
+ }),
179
182
  list: (0, classnames_1.default)({
180
183
  togglable: isTogglable,
181
184
  collapsed: isCollapsed,
@@ -211,6 +214,7 @@ exports.default = (0, react_1.forwardRef)(function (_a, ref) {
211
214
  lineHeight: 'inherit',
212
215
  },
213
216
  expandIcon: {},
217
+ collapseIcon: {},
214
218
  list: __assign({ position: 'absolute' }, orientation === 'vertical' ? __assign({ transition: 'height 100ms ease-out', width: '100%', height: isCollapsed ? '0px' : "".concat(menuLength, "px"), overflowY: maxVisibleItems === -1 ? 'hidden' : maxVisibleItems < numItems ? 'scroll' : 'hidden' }, isInverted ? {
215
219
  marginBottom: "".concat(itemPadding - borderThickness, "px"),
216
220
  bottom: '100%',
@@ -244,30 +248,44 @@ exports.default = (0, react_1.forwardRef)(function (_a, ref) {
244
248
  padding: '0',
245
249
  width: '15px',
246
250
  },
251
+ collapseIcon: {
252
+ height: '15px',
253
+ margin: '0',
254
+ padding: '0',
255
+ width: '15px',
256
+ },
247
257
  });
258
+ var toggleComponent = (_b = components.toggle) !== null && _b !== void 0 ? _b : react_1.default.createElement("button", { style: defaultStyles.toggle });
259
+ var expandIconComponent = (_c = components.expandIcon) !== null && _c !== void 0 ? _c : (expandIconSvg ? react_1.default.createElement(FlatSVG_1.default, { svg: expandIconSvg, style: defaultStyles.expandIcon }) : react_1.default.createElement(react_1.default.Fragment, null));
260
+ var collapseIconComponent = (_d = components.collapseIcon) !== null && _d !== void 0 ? _d : (collapseIconSvg ? react_1.default.createElement(FlatSVG_1.default, { svg: collapseIconSvg, style: defaultStyles.collapseIcon }) : expandIconComponent);
248
261
  return (react_1.default.createElement("div", __assign({}, props, { ref: ref, className: (0, classnames_1.default)(className, fixedClassNames.root), style: (0, styles_1.default)(style, fixedStyles.root) }),
249
262
  react_1.default.createElement("div", { ref: bodyRef, style: (0, styles_1.default)(fixedStyles.body) },
250
- cloneStyledElement_1.default.apply(void 0, __spreadArray([(_b = components.toggle) !== null && _b !== void 0 ? _b : react_1.default.createElement("button", { style: defaultStyles.toggle }), {
263
+ cloneStyledElement_1.default.apply(void 0, __spreadArray([toggleComponent, {
251
264
  className: (0, classnames_1.default)(fixedClassNames.toggle),
252
265
  style: (0, styles_1.default)(fixedStyles.toggle),
253
266
  onClick: function () { return toggle(); },
254
267
  }], [
255
- react_1.default.createElement("label", { style: fixedStyles.toggleLabel, dangerouslySetInnerHTML: { __html: selectedIndex === -1 ? defaultLabel : (_c = data[selectedIndex].label) !== null && _c !== void 0 ? _c : '' } }),
256
- (0, cloneStyledElement_1.default)((_d = components.expandIcon) !== null && _d !== void 0 ? _d : (expandIconSvg ? react_1.default.createElement(FlatSVG_1.default, { svg: expandIconSvg, style: defaultStyles.expandIcon }) : react_1.default.createElement(react_1.default.Fragment, null)), {
257
- className: (0, classnames_1.default)(fixedClassNames.expandIcon),
258
- style: (0, styles_1.default)(fixedStyles.expandIcon),
268
+ react_1.default.createElement("label", { style: fixedStyles.toggleLabel, dangerouslySetInnerHTML: { __html: selectedIndices.length > 0 ? selectedIndices.map(function (t) { return data[t].label; }).join(', ') : defaultLabel !== null && defaultLabel !== void 0 ? defaultLabel : '' } }),
269
+ (0, cloneStyledElement_1.default)(isCollapsed ? expandIconComponent : collapseIconComponent, {
270
+ className: (0, classnames_1.default)(isCollapsed ? fixedClassNames.expandIcon : fixedClassNames.collapseIcon),
271
+ style: (0, styles_1.default)(isCollapsed ? fixedStyles.expandIcon : fixedStyles.collapseIcon),
259
272
  }),
260
273
  ], false)),
261
- react_1.default.createElement(List_1.default, { className: fixedClassNames.list, style: (0, styles_1.default)(fixedStyles.list), borderThickness: borderThickness, data: data, isSelectable: true, isTogglable: false, itemComponentType: itemComponentType, itemLength: itemLength, itemPadding: itemPadding, orientation: orientation, selectedIndex: selectedIndex, onDeselectAt: function (idx) { return selectItemAt(-1); }, onSelectAt: function (idx) { return selectItemAt(idx); } }))));
274
+ react_1.default.createElement(List_1.default, { className: fixedClassNames.list, style: (0, styles_1.default)(fixedStyles.list), borderThickness: borderThickness, data: data, isTogglable: isTogglable, itemComponentType: itemComponentType, itemLength: itemLength, itemPadding: itemPadding, orientation: orientation, selectedIndices: selectedIndices, selectionMode: selectionMode, onActivateAt: onActivateAt, onDeselectAt: onDeselectAt, onSelectAt: selectAtHandler }))));
262
275
  });
263
276
  var DropdownToggle = function (_a) {
264
- var props = __rest(_a, []);
265
- return react_1.default.createElement("button", __assign({}, props));
277
+ var children = _a.children, props = __rest(_a, ["children"]);
278
+ return react_1.default.createElement("button", __assign({}, props), children);
266
279
  };
267
280
  exports.DropdownToggle = DropdownToggle;
268
281
  var DropdownExpandIcon = function (_a) {
269
- var props = __rest(_a, []);
270
- return react_1.default.createElement("div", __assign({}, props));
282
+ var children = _a.children, props = __rest(_a, ["children"]);
283
+ return react_1.default.createElement("div", __assign({}, props), children);
271
284
  };
272
285
  exports.DropdownExpandIcon = DropdownExpandIcon;
286
+ var DropdownCollapseIcon = function (_a) {
287
+ var children = _a.children, props = __rest(_a, ["children"]);
288
+ return react_1.default.createElement("div", __assign({}, props), children);
289
+ };
290
+ exports.DropdownCollapseIcon = DropdownCollapseIcon;
273
291
  //# sourceMappingURL=Dropdown.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Dropdown.js","sourceRoot":"/","sources":["Dropdown.tsx"],"names":[],"mappings":"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","sourcesContent":["import classNames from 'classnames'\nimport React, { forwardRef, useEffect, useRef, useState, type ComponentType, type HTMLAttributes, type PropsWithChildren, type ReactElement, type Ref } from 'react'\nimport FlatSVG from './FlatSVG'\nimport List, { type ListItemProps } from './List'\nimport useElementRect from './hooks/useElementRect'\nimport asClassNameDict from './utils/asClassNameDict'\nimport asComponentDict from './utils/asComponentDict'\nimport asStyleDict from './utils/asStyleDict'\nimport cloneStyledElement from './utils/cloneStyledElement'\nimport styles from './utils/styles'\n\ntype Orientation = 'horizontal' | 'vertical'\n\nexport type DropdownData = {\n label?: string\n}\n\nexport type DropdownItemProps<T extends DropdownData = DropdownData> = ListItemProps<T>\n\nexport type DropdownProps<T extends DropdownData = DropdownData> = HTMLAttributes<HTMLDivElement> & PropsWithChildren<{\n /**\n * Data of every item in the component. This is used to generate individual\n * menu items. Data type is generic.\n */\n data: T[]\n\n /**\n * Indicates if the component is inverted (i.e. \"dropup\" instead of dropdown).\n * Supports all orientations.\n */\n isInverted?: boolean\n\n /**\n * Indicates if items can be toggled, i.e. they can be deselected if selected\n * again.\n */\n isTogglable?: boolean\n\n /**\n * Thickness of the border (in pixels) of every item and the dropdown button\n * itself. 0 indicates no borders.\n */\n borderThickness?: number\n\n /**\n * The index of the default selected item.\n */\n selectedIndex?: number\n\n /**\n * Length (in pixels) of each item. This does not apply to the dropdown button\n * itself. Length refers to the height in vertical orientation and width in\n * horizontal orientation.\n */\n itemLength?: number\n\n /**\n * Padding (in pixels) of each item.\n */\n itemPadding?: number\n\n /**\n * Maximum number of items that are viside when the component expands. When a\n * value greater than or equal to 0 is specified, only that number of items\n * will be visible at a time, and a scrollbar will appear to scroll to\n * remaining items. Any value less than 0 indicates that all items will be\n * visible when the component expands.\n */\n maxVisibleItems?: number\n\n /**\n * Orientation of the component.\n */\n orientation?: Orientation\n\n /**\n * The label to appear on the dropdown button when no items are selected.\n */\n defaultLabel?: string\n\n /**\n * SVG markup to be put in the dropdown button as the expand icon.\n */\n expandIconSvg?: string\n\n /**\n * React component type to be used for generating items inside the component.\n */\n itemComponentType: ComponentType<DropdownItemProps<T>>\n\n /**\n * Handler invoked whenever the selected index changes.\n */\n onIndexChange?: (index: number) => void\n}>\n\n/**\n * A dropdown menu component that is invertible (i.e. can \"dropup\" instead) and\n * supports both horizontal and vertical orientations. Provide data and item\n * component type to this component to automatically generate menu items.\n */\nexport default forwardRef(({\n children,\n className,\n style,\n borderThickness = 0,\n data,\n defaultLabel = 'Select',\n expandIconSvg,\n isInverted = false,\n isTogglable = false,\n itemComponentType,\n itemLength: externalItemLength,\n itemPadding = 0,\n maxVisibleItems = -1,\n orientation = 'vertical',\n selectedIndex: externalSelectedIndex = -1,\n onIndexChange,\n ...props\n}, ref) => {\n const selectItemAt = (index: number) => {\n setSelectedIndex(index)\n setIsCollapsed(true)\n }\n\n const expand = () => {\n if (!isCollapsed) return\n setIsCollapsed(false)\n }\n\n const collapse = () => {\n if (isCollapsed) return\n setIsCollapsed(true)\n }\n\n const toggle = () => {\n if (isCollapsed) {\n expand()\n }\n else {\n collapse()\n }\n }\n\n const clickOutsideHandler = (event: MouseEvent) => {\n if (isCollapsed) return\n if (!(event.target instanceof Node)) return\n\n let isOutside = true\n let node = event.target\n\n while (node) {\n if (node === bodyRef.current) {\n isOutside = false\n break\n }\n\n if (!node.parentNode) break\n\n node = node.parentNode\n }\n\n if (!isOutside) return\n\n collapse()\n }\n\n const bodyRef = useRef<HTMLDivElement>(null)\n const [selectedIndex, setSelectedIndex] = useState(externalSelectedIndex)\n const [isCollapsed, setIsCollapsed] = useState(true)\n const rect = useElementRect(bodyRef)\n\n useEffect(() => {\n window.addEventListener('click', clickOutsideHandler)\n\n return () => {\n window.removeEventListener('click', clickOutsideHandler)\n }\n }, [isCollapsed])\n\n useEffect(() => {\n if (externalSelectedIndex === selectedIndex) return\n setSelectedIndex(externalSelectedIndex)\n }, [externalSelectedIndex])\n\n useEffect(() => {\n onIndexChange?.(selectedIndex)\n }, [selectedIndex])\n\n const itemLength = externalItemLength ?? (orientation === 'vertical' ? rect.height : rect.width)\n const numItems = data.length\n const numVisibleItems = maxVisibleItems < 0 ? numItems : Math.min(numItems, maxVisibleItems)\n const menuLength = (itemLength - borderThickness) * numVisibleItems + itemPadding * (numVisibleItems - 1) + borderThickness\n\n const components = asComponentDict(children, {\n toggle: DropdownToggle,\n expandIcon: DropdownExpandIcon,\n })\n\n const fixedClassNames = asClassNameDict({\n root: classNames(orientation, {\n togglable: isTogglable,\n collapsed: isCollapsed,\n expanded: !isCollapsed,\n }),\n toggle: classNames(orientation, {\n togglable: isTogglable,\n collapsed: isCollapsed,\n expanded: !isCollapsed,\n }),\n expandIcon: classNames(orientation, {\n togglable: isTogglable,\n collapsed: isCollapsed,\n expanded: !isCollapsed,\n }),\n list: classNames({\n togglable: isTogglable,\n collapsed: isCollapsed,\n expanded: !isCollapsed,\n }),\n })\n\n const fixedStyles = asStyleDict({\n root: {\n alignItems: 'center',\n display: 'flex',\n justifyContent: 'flex-start',\n overflow: 'visible',\n ...orientation === 'vertical' ? {\n flexDirection: isInverted ? 'column-reverse' : 'column',\n } : {\n flexDirection: isInverted ? 'row-reverse' : 'row',\n },\n },\n body: {\n height: '100%',\n width: '100%',\n },\n toggle: {\n borderWidth: `${borderThickness}px`,\n height: '100%',\n left: '0',\n margin: '0',\n outline: 'none',\n position: 'absolute',\n top: '0',\n width: '100%',\n zIndex: '1',\n },\n toggleLabel: {\n fontFamily: 'inherit',\n fontSize: 'inherit',\n fontWeight: 'inherit',\n letterSpacing: 'inherit',\n lineHeight: 'inherit',\n },\n expandIcon: {\n\n },\n list: {\n position: 'absolute',\n ...orientation === 'vertical' ? {\n transition: 'height 100ms ease-out',\n width: '100%',\n height: isCollapsed ? '0px' : `${menuLength}px`,\n overflowY: maxVisibleItems === -1 ? 'hidden' : maxVisibleItems < numItems ? 'scroll' : 'hidden',\n ...isInverted ? {\n marginBottom: `${itemPadding - borderThickness}px`,\n bottom: '100%',\n } : {\n top: '100%',\n marginTop: `${itemPadding - borderThickness}px`,\n },\n } : {\n transition: 'width 100ms ease-out',\n width: isCollapsed ? '0px' : `${menuLength}px`,\n height: '100%',\n overflowX: maxVisibleItems === -1 ? 'hidden' : maxVisibleItems < numItems ? 'scroll' : 'hidden',\n ...isInverted ? {\n marginRight: `${itemPadding - borderThickness}px`,\n right: '100%',\n } : {\n left: '100%',\n marginLeft: `${itemPadding - borderThickness}px`,\n },\n },\n },\n })\n\n const defaultStyles = asStyleDict({\n toggle: {\n alignItems: 'center',\n background: '#fff',\n boxSizing: 'border-box',\n color: '#000',\n display: 'flex',\n flexDirection: 'row',\n fontSize: '16px',\n justifyContent: 'space-between',\n margin: '0',\n padding: '0 10px',\n },\n expandIcon: {\n height: '15px',\n margin: '0',\n padding: '0',\n width: '15px',\n },\n })\n\n return (\n <div\n {...props}\n ref={ref}\n className={classNames(className, fixedClassNames.root)}\n style={styles(style, fixedStyles.root)}\n >\n <div ref={bodyRef} style={styles(fixedStyles.body)}>\n {cloneStyledElement(components.toggle ?? <button style={defaultStyles.toggle}/>, {\n className: classNames(fixedClassNames.toggle),\n style: styles(fixedStyles.toggle),\n onClick: () => toggle(),\n }, ...[\n <label style={fixedStyles.toggleLabel} dangerouslySetInnerHTML={{ __html: selectedIndex === -1 ? defaultLabel : data[selectedIndex].label ?? '' }}/>,\n cloneStyledElement(components.expandIcon ?? (expandIconSvg ? <FlatSVG svg={expandIconSvg} style={defaultStyles.expandIcon}/> : <></>), {\n className: classNames(fixedClassNames.expandIcon),\n style: styles(fixedStyles.expandIcon),\n }),\n ])}\n <List\n className={fixedClassNames.list}\n style={styles(fixedStyles.list)}\n borderThickness={borderThickness}\n data={data}\n isSelectable={true}\n isTogglable={false}\n itemComponentType={itemComponentType}\n itemLength={itemLength}\n itemPadding={itemPadding}\n orientation={orientation}\n selectedIndex={selectedIndex}\n onDeselectAt={idx => selectItemAt(-1)}\n onSelectAt={idx => selectItemAt(idx)}\n />\n </div>\n </div>\n )\n}) as <T extends DropdownData = DropdownData>(props: DropdownProps<T> & { ref?: Ref<HTMLDivElement> }) => ReactElement\n\nexport const DropdownToggle = ({ ...props }: HTMLAttributes<HTMLButtonElement>) => <button {...props}/>\n\nexport const DropdownExpandIcon = ({ ...props }: HTMLAttributes<HTMLDivElement>) => <div {...props}/>\n"]}
1
+ {"version":3,"file":"Dropdown.js","sourceRoot":"/","sources":["Dropdown.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,0DAAmC;AACnC,oEAAqC;AACrC,6CAAgJ;AAChJ,sDAA+B;AAC/B,gDAAiE;AACjE,0EAAmD;AACnD,4EAAqD;AACrD,4EAAqD;AACrD,oEAA6C;AAC7C,kFAA2D;AAC3D,0DAAmC;AA8CnC;;;;GAIG;AACH,kBAAe,IAAA,kBAAU,EAAC,UAAC,EAuB1B,EAAE,GAAG;;IAtBJ,IAAA,QAAQ,cAAA,EACR,SAAS,eAAA,EACT,KAAK,WAAA,EACL,uBAAmB,EAAnB,eAAe,mBAAG,CAAC,KAAA,EACnB,IAAI,UAAA,EACJ,yBAAwB,EAAxB,iBAAiB,mBAAG,IAAI,KAAA,EACxB,oBAAuB,EAAvB,YAAY,mBAAG,QAAQ,KAAA,EACvB,aAAa,mBAAA,EACb,eAAe,qBAAA,EACf,kBAAkB,EAAlB,UAAU,mBAAG,KAAK,KAAA,EAClB,mBAAmB,EAAnB,WAAW,mBAAG,KAAK,KAAA,EACnB,iBAAiB,uBAAA,EACL,kBAAkB,gBAAA,EAC9B,mBAAe,EAAf,WAAW,mBAAG,CAAC,KAAA,EACf,uBAAoB,EAApB,eAAe,mBAAG,CAAC,CAAC,KAAA,EACpB,mBAAwB,EAAxB,WAAW,mBAAG,UAAU,KAAA,EACxB,qBAAwB,EAAxB,aAAa,mBAAG,QAAQ,KAAA,EACxB,uBAA6C,EAA5B,uBAAuB,mBAAG,EAAE,KAAA,EAC7C,YAAY,kBAAA,EACZ,YAAY,kBAAA,EACZ,UAAU,gBAAA,EACP,KAAK,cAtBiB,yUAuB1B,CADS;IAER,IAAM,MAAM,GAAG;QACb,IAAI,WAAW;YAAE,cAAc,CAAC,KAAK,CAAC,CAAA;IACxC,CAAC,CAAA;IAED,IAAM,QAAQ,GAAG;QACf,IAAI,CAAC,WAAW;YAAE,cAAc,CAAC,IAAI,CAAC,CAAA;IACxC,CAAC,CAAA;IAED,IAAM,MAAM,GAAG;QACb,IAAI,WAAW,EAAE;YACf,MAAM,EAAE,CAAA;SACT;aACI;YACH,QAAQ,EAAE,CAAA;SACX;IACH,CAAC,CAAA;IAED,IAAM,eAAe,GAAG,UAAC,KAAa;QACpC,UAAU,aAAV,UAAU,uBAAV,UAAU,CAAG,KAAK,CAAC,CAAA;QAEnB,IAAI,aAAa,KAAK,QAAQ,IAAI,iBAAiB;YAAE,QAAQ,EAAE,CAAA;IACjE,CAAC,CAAA;IAED,IAAM,mBAAmB,GAAG,UAAC,KAAiB;QAC5C,IAAI,WAAW;YAAE,OAAM;QACvB,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,YAAY,IAAI,CAAC;YAAE,OAAM;QAE3C,IAAI,SAAS,GAAG,IAAI,CAAA;QACpB,IAAI,IAAI,GAAG,KAAK,CAAC,MAAM,CAAA;QAEvB,OAAO,IAAI,EAAE;YACX,IAAI,IAAI,KAAK,OAAO,CAAC,OAAO,EAAE;gBAC5B,SAAS,GAAG,KAAK,CAAA;gBACjB,MAAK;aACN;YAED,IAAI,CAAC,IAAI,CAAC,UAAU;gBAAE,MAAK;YAE3B,IAAI,GAAG,IAAI,CAAC,UAAU,CAAA;SACvB;QAED,IAAI,CAAC,SAAS;YAAE,OAAM;QAEtB,QAAQ,EAAE,CAAA;IACZ,CAAC,CAAA;IAED,IAAM,OAAO,GAAG,IAAA,cAAM,EAAiB,IAAI,CAAC,CAAA;IACtC,IAAA,KAAA,OAAwC,IAAA,gBAAQ,EAAC,uBAAuB,CAAC,IAAA,EAAxE,eAAe,QAAA,EAAE,kBAAkB,QAAqC,CAAA;IACzE,IAAA,KAAA,OAAgC,IAAA,gBAAQ,EAAC,IAAI,CAAC,IAAA,EAA7C,WAAW,QAAA,EAAE,cAAc,QAAkB,CAAA;IACpD,IAAM,IAAI,GAAG,IAAA,wBAAc,EAAC,OAAO,CAAC,CAAA;IAEpC,IAAA,iBAAS,EAAC;QACR,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAA;QAErD,OAAO;YACL,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAA;QAC1D,CAAC,CAAA;IACH,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAA;IAEjB,IAAA,iBAAS,EAAC;QACR,IAAI,IAAA,yBAAO,EAAC,uBAAuB,EAAE,eAAe,CAAC;YAAE,OAAM;QAE7D,kBAAkB,CAAC,uBAAuB,CAAC,CAAA;IAC7C,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAA;IAE7C,IAAM,UAAU,GAAG,kBAAkB,aAAlB,kBAAkB,cAAlB,kBAAkB,GAAI,CAAC,WAAW,KAAK,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAChG,IAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAA;IAC5B,IAAM,eAAe,GAAG,eAAe,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAA;IAC5F,IAAM,UAAU,GAAG,CAAC,UAAU,GAAG,eAAe,CAAC,GAAG,eAAe,GAAG,WAAW,GAAG,CAAC,eAAe,GAAG,CAAC,CAAC,GAAG,eAAe,CAAA;IAE3H,IAAM,UAAU,GAAG,IAAA,yBAAe,EAAC,QAAQ,EAAE;QAC3C,MAAM,EAAE,sBAAc;QACtB,UAAU,EAAE,0BAAkB;QAC9B,YAAY,EAAE,4BAAoB;KACnC,CAAC,CAAA;IAEF,IAAM,eAAe,GAAG,IAAA,yBAAe,EAAC;QACtC,IAAI,EAAE,IAAA,oBAAU,EAAC,WAAW,EAAE;YAC5B,SAAS,EAAE,WAAW;YACtB,SAAS,EAAE,WAAW;YACtB,QAAQ,EAAE,CAAC,WAAW;SACvB,CAAC;QACF,MAAM,EAAE,IAAA,oBAAU,EAAC,WAAW,EAAE;YAC9B,SAAS,EAAE,WAAW;YACtB,SAAS,EAAE,WAAW;YACtB,QAAQ,EAAE,CAAC,WAAW;SACvB,CAAC;QACF,UAAU,EAAE,IAAA,oBAAU,EAAC,WAAW,EAAE;YAClC,SAAS,EAAE,WAAW;YACtB,SAAS,EAAE,WAAW;YACtB,QAAQ,EAAE,CAAC,WAAW;SACvB,CAAC;QACF,YAAY,EAAE,IAAA,oBAAU,EAAC,WAAW,EAAE;YACpC,SAAS,EAAE,WAAW;YACtB,SAAS,EAAE,WAAW;YACtB,QAAQ,EAAE,CAAC,WAAW;SACvB,CAAC;QACF,IAAI,EAAE,IAAA,oBAAU,EAAC;YACf,SAAS,EAAE,WAAW;YACtB,SAAS,EAAE,WAAW;YACtB,QAAQ,EAAE,CAAC,WAAW;SACvB,CAAC;KACH,CAAC,CAAA;IAEF,IAAM,WAAW,GAAG,IAAA,qBAAW,EAAC;QAC9B,IAAI,aACF,UAAU,EAAE,QAAQ,EACpB,OAAO,EAAE,MAAM,EACf,cAAc,EAAE,YAAY,EAC5B,QAAQ,EAAE,SAAS,IAChB,WAAW,KAAK,UAAU,CAAC,CAAC,CAAC;YAC9B,aAAa,EAAE,UAAU,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ;SACxD,CAAC,CAAC,CAAC;YACF,aAAa,EAAE,UAAU,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK;SAClD,CACF;QACD,IAAI,EAAE;YACJ,MAAM,EAAE,MAAM;YACd,KAAK,EAAE,MAAM;SACd;QACD,MAAM,EAAE;YACN,WAAW,EAAE,UAAG,eAAe,OAAI;YACnC,MAAM,EAAE,MAAM;YACd,IAAI,EAAE,GAAG;YACT,MAAM,EAAE,GAAG;YACX,OAAO,EAAE,MAAM;YACf,QAAQ,EAAE,UAAU;YACpB,GAAG,EAAE,GAAG;YACR,KAAK,EAAE,MAAM;YACb,MAAM,EAAE,GAAG;SACZ;QACD,WAAW,EAAE;YACX,UAAU,EAAE,SAAS;YACrB,QAAQ,EAAE,SAAS;YACnB,UAAU,EAAE,SAAS;YACrB,aAAa,EAAE,SAAS;YACxB,UAAU,EAAE,SAAS;SACtB;QACD,UAAU,EAAE,EAEX;QACD,YAAY,EAAE,EAEb;QACD,IAAI,aACF,QAAQ,EAAE,UAAU,IACjB,WAAW,KAAK,UAAU,CAAC,CAAC,YAC7B,UAAU,EAAE,uBAAuB,EACnC,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,UAAG,UAAU,OAAI,EAC/C,SAAS,EAAE,eAAe,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,eAAe,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,IAC5F,UAAU,CAAC,CAAC,CAAC;YACd,YAAY,EAAE,UAAG,WAAW,GAAG,eAAe,OAAI;YAClD,MAAM,EAAE,MAAM;SACf,CAAC,CAAC,CAAC;YACF,GAAG,EAAE,MAAM;YACX,SAAS,EAAE,UAAG,WAAW,GAAG,eAAe,OAAI;SAChD,EACD,CAAC,YACD,UAAU,EAAE,sBAAsB,EAClC,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,UAAG,UAAU,OAAI,EAC9C,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,eAAe,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,eAAe,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,IAC5F,UAAU,CAAC,CAAC,CAAC;YACd,WAAW,EAAE,UAAG,WAAW,GAAG,eAAe,OAAI;YACjD,KAAK,EAAE,MAAM;SACd,CAAC,CAAC,CAAC;YACF,IAAI,EAAE,MAAM;YACZ,UAAU,EAAE,UAAG,WAAW,GAAG,eAAe,OAAI;SACjD,CACF,CACF;KACF,CAAC,CAAA;IAEF,IAAM,aAAa,GAAG,IAAA,qBAAW,EAAC;QAChC,MAAM,EAAE;YACN,UAAU,EAAE,QAAQ;YACpB,UAAU,EAAE,MAAM;YAClB,SAAS,EAAE,YAAY;YACvB,KAAK,EAAE,MAAM;YACb,OAAO,EAAE,MAAM;YACf,aAAa,EAAE,KAAK;YACpB,QAAQ,EAAE,MAAM;YAChB,cAAc,EAAE,eAAe;YAC/B,MAAM,EAAE,GAAG;YACX,OAAO,EAAE,QAAQ;SAClB;QACD,UAAU,EAAE;YACV,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,GAAG;YACX,OAAO,EAAE,GAAG;YACZ,KAAK,EAAE,MAAM;SACd;QACD,YAAY,EAAE;YACZ,MAAM,EAAE,MAAM;YACd,MAAM,EAAE,GAAG;YACX,OAAO,EAAE,GAAG;YACZ,KAAK,EAAE,MAAM;SACd;KACF,CAAC,CAAA;IAEF,IAAM,eAAe,GAAG,MAAA,UAAU,CAAC,MAAM,mCAAI,0CAAQ,KAAK,EAAE,aAAa,CAAC,MAAM,GAAG,CAAA;IACnF,IAAM,mBAAmB,GAAG,MAAA,UAAU,CAAC,UAAU,mCAAI,CAAC,aAAa,CAAC,CAAC,CAAC,8BAAC,iBAAO,IAAC,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,aAAa,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,6DAAK,CAAC,CAAA;IAC9I,IAAM,qBAAqB,GAAG,MAAA,UAAU,CAAC,YAAY,mCAAI,CAAC,eAAe,CAAC,CAAC,CAAC,8BAAC,iBAAO,IAAC,GAAG,EAAE,eAAe,EAAE,KAAK,EAAE,aAAa,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAA;IAEtK,OAAO,CACL,kDACM,KAAK,IACT,GAAG,EAAE,GAAG,EACR,SAAS,EAAE,IAAA,oBAAU,EAAC,SAAS,EAAE,eAAe,CAAC,IAAI,CAAC,EACtD,KAAK,EAAE,IAAA,gBAAM,EAAC,KAAK,EAAE,WAAW,CAAC,IAAI,CAAC;QAEtC,uCAAK,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,IAAA,gBAAM,EAAC,WAAW,CAAC,IAAI,CAAC;YAC/C,4BAAkB,8BAAC,eAAe,EAAE;oBACnC,SAAS,EAAE,IAAA,oBAAU,EAAC,eAAe,CAAC,MAAM,CAAC;oBAC7C,KAAK,EAAE,IAAA,gBAAM,EAAC,WAAW,CAAC,MAAM,CAAC;oBACjC,OAAO,EAAE,cAAM,OAAA,MAAM,EAAE,EAAR,CAAQ;iBACxB,GAAK;gBACJ,yCAAO,KAAK,EAAE,WAAW,CAAC,WAAW,EAAE,uBAAuB,EAAE,EAAE,MAAM,EAAE,eAAe,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,GAAG,CAAC,UAAA,CAAC,IAAI,OAAA,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,EAAb,CAAa,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,YAAY,aAAZ,YAAY,cAAZ,YAAY,GAAI,EAAE,EAAE,GAAG;gBACnL,IAAA,4BAAkB,EAAC,WAAW,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,qBAAqB,EAAE;oBAC5E,SAAS,EAAE,IAAA,oBAAU,EAAC,WAAW,CAAC,CAAC,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,CAAC,eAAe,CAAC,YAAY,CAAC;oBAC9F,KAAK,EAAE,IAAA,gBAAM,EAAC,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC,YAAY,CAAC;iBAC/E,CAAC;aACH;YACD,8BAAC,cAAI,IACH,SAAS,EAAE,eAAe,CAAC,IAAI,EAC/B,KAAK,EAAE,IAAA,gBAAM,EAAC,WAAW,CAAC,IAAI,CAAC,EAC/B,eAAe,EAAE,eAAe,EAChC,IAAI,EAAE,IAAI,EACV,WAAW,EAAE,WAAW,EACxB,iBAAiB,EAAE,iBAAiB,EACpC,UAAU,EAAE,UAAU,EACtB,WAAW,EAAE,WAAW,EACxB,WAAW,EAAE,WAAW,EACxB,eAAe,EAAE,eAAe,EAChC,aAAa,EAAE,aAAa,EAC5B,YAAY,EAAE,YAAY,EAC1B,YAAY,EAAE,YAAY,EAC1B,UAAU,EAAE,eAAe,GAC3B,CACE,CACF,CACP,CAAA;AACH,CAAC,CAAqH,CAAA;AAE/G,IAAM,cAAc,GAAG,UAAC,EAA6E;IAA3E,IAAA,QAAQ,cAAA,EAAK,KAAK,cAApB,YAAsB,CAAF;IAA8D,OAAA,qDAAY,KAAK,GAAG,QAAQ,CAAU,CAAA;CAAA,CAAA;AAA1I,QAAA,cAAc,kBAA4H;AAEhJ,IAAM,kBAAkB,GAAG,UAAC,EAA0E;IAAxE,IAAA,QAAQ,cAAA,EAAK,KAAK,cAApB,YAAsB,CAAF;IAA2D,OAAA,kDAAS,KAAK,GAAG,QAAQ,CAAO,CAAA;CAAA,CAAA;AAArI,QAAA,kBAAkB,sBAAmH;AAE3I,IAAM,oBAAoB,GAAG,UAAC,EAA0E;IAAxE,IAAA,QAAQ,cAAA,EAAK,KAAK,cAApB,YAAsB,CAAF;IAA2D,OAAA,kDAAS,KAAK,GAAG,QAAQ,CAAO,CAAA;CAAA,CAAA;AAAvI,QAAA,oBAAoB,wBAAmH","sourcesContent":["import classNames from 'classnames'\nimport isEqual from 'fast-deep-equal'\nimport React, { forwardRef, useEffect, useRef, useState, type HTMLAttributes, type PropsWithChildren, type ReactElement, type Ref } from 'react'\nimport FlatSVG from './FlatSVG'\nimport List, { type ListItemProps, type ListProps } from './List'\nimport useElementRect from './hooks/useElementRect'\nimport asClassNameDict from './utils/asClassNameDict'\nimport asComponentDict from './utils/asComponentDict'\nimport asStyleDict from './utils/asStyleDict'\nimport cloneStyledElement from './utils/cloneStyledElement'\nimport styles from './utils/styles'\n\nexport type DropdownData = {\n label?: string\n}\n\nexport type DropdownItemProps<T extends DropdownData = DropdownData> = ListItemProps<T>\n\nexport type DropdownProps<T extends DropdownData = DropdownData> = HTMLAttributes<HTMLDivElement> & ListProps<T> & PropsWithChildren<{\n /**\n * Indicates if the component is inverted (i.e. \"dropup\" instead of dropdown).\n * Supports all orientations.\n */\n isInverted?: boolean\n\n /**\n * Specifies if the dropdown should be collapsed upon selection. This only\n * works if `selectionMode` is `single`.\n */\n collapsesOnSelect?: boolean\n\n /**\n * Maximum number of items that are viside when the component expands. When a\n * value greater than or equal to 0 is specified, only that number of items\n * will be visible at a time, and a scrollbar will appear to scroll to\n * remaining items. Any value less than 0 indicates that all items will be\n * visible when the component expands.\n */\n maxVisibleItems?: number\n\n /**\n * The label to appear on the dropdown button when no items are selected.\n */\n defaultLabel?: string\n\n /**\n * SVG markup to be put in the dropdown button as the expand icon.\n */\n expandIconSvg?: string\n\n /**\n * SVG markup to be put in the dropdown button as the collapse icon.\n */\n collapseIconSvg?: string\n}>\n\n/**\n * A dropdown menu component that is invertible (i.e. can \"dropup\" instead) and\n * supports both horizontal and vertical orientations. Provide data and item\n * component type to this component to automatically generate menu items.\n */\nexport default forwardRef(({\n children,\n className,\n style,\n borderThickness = 0,\n data,\n collapsesOnSelect = true,\n defaultLabel = 'Select',\n expandIconSvg,\n collapseIconSvg,\n isInverted = false,\n isTogglable = false,\n itemComponentType,\n itemLength: externalItemLength,\n itemPadding = 0,\n maxVisibleItems = -1,\n orientation = 'vertical',\n selectionMode = 'single',\n selectedIndices: externalSelectedIndices = [],\n onActivateAt,\n onDeselectAt,\n onSelectAt,\n ...props\n}, ref) => {\n const expand = () => {\n if (isCollapsed) setIsCollapsed(false)\n }\n\n const collapse = () => {\n if (!isCollapsed) setIsCollapsed(true)\n }\n\n const toggle = () => {\n if (isCollapsed) {\n expand()\n }\n else {\n collapse()\n }\n }\n\n const selectAtHandler = (index: number) => {\n onSelectAt?.(index)\n\n if (selectionMode === 'single' && collapsesOnSelect) collapse()\n }\n\n const clickOutsideHandler = (event: MouseEvent) => {\n if (isCollapsed) return\n if (!(event.target instanceof Node)) return\n\n let isOutside = true\n let node = event.target\n\n while (node) {\n if (node === bodyRef.current) {\n isOutside = false\n break\n }\n\n if (!node.parentNode) break\n\n node = node.parentNode\n }\n\n if (!isOutside) return\n\n collapse()\n }\n\n const bodyRef = useRef<HTMLDivElement>(null)\n const [selectedIndices, setSelectedIndices] = useState(externalSelectedIndices)\n const [isCollapsed, setIsCollapsed] = useState(true)\n const rect = useElementRect(bodyRef)\n\n useEffect(() => {\n window.addEventListener('click', clickOutsideHandler)\n\n return () => {\n window.removeEventListener('click', clickOutsideHandler)\n }\n }, [isCollapsed])\n\n useEffect(() => {\n if (isEqual(externalSelectedIndices, selectedIndices)) return\n\n setSelectedIndices(externalSelectedIndices)\n }, [JSON.stringify(externalSelectedIndices)])\n\n const itemLength = externalItemLength ?? (orientation === 'vertical' ? rect.height : rect.width)\n const numItems = data.length\n const numVisibleItems = maxVisibleItems < 0 ? numItems : Math.min(numItems, maxVisibleItems)\n const menuLength = (itemLength - borderThickness) * numVisibleItems + itemPadding * (numVisibleItems - 1) + borderThickness\n\n const components = asComponentDict(children, {\n toggle: DropdownToggle,\n expandIcon: DropdownExpandIcon,\n collapseIcon: DropdownCollapseIcon,\n })\n\n const fixedClassNames = asClassNameDict({\n root: classNames(orientation, {\n togglable: isTogglable,\n collapsed: isCollapsed,\n expanded: !isCollapsed,\n }),\n toggle: classNames(orientation, {\n togglable: isTogglable,\n collapsed: isCollapsed,\n expanded: !isCollapsed,\n }),\n expandIcon: classNames(orientation, {\n togglable: isTogglable,\n collapsed: isCollapsed,\n expanded: !isCollapsed,\n }),\n collapseIcon: classNames(orientation, {\n togglable: isTogglable,\n collapsed: isCollapsed,\n expanded: !isCollapsed,\n }),\n list: classNames({\n togglable: isTogglable,\n collapsed: isCollapsed,\n expanded: !isCollapsed,\n }),\n })\n\n const fixedStyles = asStyleDict({\n root: {\n alignItems: 'center',\n display: 'flex',\n justifyContent: 'flex-start',\n overflow: 'visible',\n ...orientation === 'vertical' ? {\n flexDirection: isInverted ? 'column-reverse' : 'column',\n } : {\n flexDirection: isInverted ? 'row-reverse' : 'row',\n },\n },\n body: {\n height: '100%',\n width: '100%',\n },\n toggle: {\n borderWidth: `${borderThickness}px`,\n height: '100%',\n left: '0',\n margin: '0',\n outline: 'none',\n position: 'absolute',\n top: '0',\n width: '100%',\n zIndex: '1',\n },\n toggleLabel: {\n fontFamily: 'inherit',\n fontSize: 'inherit',\n fontWeight: 'inherit',\n letterSpacing: 'inherit',\n lineHeight: 'inherit',\n },\n expandIcon: {\n\n },\n collapseIcon: {\n\n },\n list: {\n position: 'absolute',\n ...orientation === 'vertical' ? {\n transition: 'height 100ms ease-out',\n width: '100%',\n height: isCollapsed ? '0px' : `${menuLength}px`,\n overflowY: maxVisibleItems === -1 ? 'hidden' : maxVisibleItems < numItems ? 'scroll' : 'hidden',\n ...isInverted ? {\n marginBottom: `${itemPadding - borderThickness}px`,\n bottom: '100%',\n } : {\n top: '100%',\n marginTop: `${itemPadding - borderThickness}px`,\n },\n } : {\n transition: 'width 100ms ease-out',\n width: isCollapsed ? '0px' : `${menuLength}px`,\n height: '100%',\n overflowX: maxVisibleItems === -1 ? 'hidden' : maxVisibleItems < numItems ? 'scroll' : 'hidden',\n ...isInverted ? {\n marginRight: `${itemPadding - borderThickness}px`,\n right: '100%',\n } : {\n left: '100%',\n marginLeft: `${itemPadding - borderThickness}px`,\n },\n },\n },\n })\n\n const defaultStyles = asStyleDict({\n toggle: {\n alignItems: 'center',\n background: '#fff',\n boxSizing: 'border-box',\n color: '#000',\n display: 'flex',\n flexDirection: 'row',\n fontSize: '16px',\n justifyContent: 'space-between',\n margin: '0',\n padding: '0 10px',\n },\n expandIcon: {\n height: '15px',\n margin: '0',\n padding: '0',\n width: '15px',\n },\n collapseIcon: {\n height: '15px',\n margin: '0',\n padding: '0',\n width: '15px',\n },\n })\n\n const toggleComponent = components.toggle ?? <button style={defaultStyles.toggle}/>\n const expandIconComponent = components.expandIcon ?? (expandIconSvg ? <FlatSVG svg={expandIconSvg} style={defaultStyles.expandIcon}/> : <></>)\n const collapseIconComponent = components.collapseIcon ?? (collapseIconSvg ? <FlatSVG svg={collapseIconSvg} style={defaultStyles.collapseIcon}/> : expandIconComponent)\n\n return (\n <div\n {...props}\n ref={ref}\n className={classNames(className, fixedClassNames.root)}\n style={styles(style, fixedStyles.root)}\n >\n <div ref={bodyRef} style={styles(fixedStyles.body)}>\n {cloneStyledElement(toggleComponent, {\n className: classNames(fixedClassNames.toggle),\n style: styles(fixedStyles.toggle),\n onClick: () => toggle(),\n }, ...[\n <label style={fixedStyles.toggleLabel} dangerouslySetInnerHTML={{ __html: selectedIndices.length > 0 ? selectedIndices.map(t => data[t].label).join(', ') : defaultLabel ?? '' }}/>,\n cloneStyledElement(isCollapsed ? expandIconComponent : collapseIconComponent, {\n className: classNames(isCollapsed ? fixedClassNames.expandIcon : fixedClassNames.collapseIcon),\n style: styles(isCollapsed ? fixedStyles.expandIcon : fixedStyles.collapseIcon),\n }),\n ])}\n <List\n className={fixedClassNames.list}\n style={styles(fixedStyles.list)}\n borderThickness={borderThickness}\n data={data}\n isTogglable={isTogglable}\n itemComponentType={itemComponentType}\n itemLength={itemLength}\n itemPadding={itemPadding}\n orientation={orientation}\n selectedIndices={selectedIndices}\n selectionMode={selectionMode}\n onActivateAt={onActivateAt}\n onDeselectAt={onDeselectAt}\n onSelectAt={selectAtHandler}\n />\n </div>\n </div>\n )\n}) as <T extends DropdownData = DropdownData>(props: DropdownProps<T> & { ref?: Ref<HTMLDivElement> }) => ReactElement\n\nexport const DropdownToggle = ({ children, ...props }: HTMLAttributes<HTMLButtonElement> & PropsWithChildren) => <button {...props}>{children}</button>\n\nexport const DropdownExpandIcon = ({ children, ...props }: HTMLAttributes<HTMLDivElement> & PropsWithChildren) => <div {...props}>{children}</div>\n\nexport const DropdownCollapseIcon = ({ children, ...props }: HTMLAttributes<HTMLDivElement> & PropsWithChildren) => <div {...props}>{children}</div>\n"]}
package/lib/List.d.ts CHANGED
@@ -16,16 +16,17 @@ export type ListProps<T> = HTMLAttributes<HTMLDivElement> & {
16
16
  */
17
17
  data: T[];
18
18
  /**
19
- * The selected index. Any value below 0 indicates that nothing is
20
- * selected.
19
+ * Indicates if items can be toggled, i.e. they can be deselected if selected
20
+ * again.
21
21
  */
22
- selectedIndex?: number;
22
+ isTogglable?: boolean;
23
23
  /**
24
24
  * React component type to be used to generate items for this list.
25
25
  */
26
26
  itemComponentType?: ComponentType<ListItemProps<T>>;
27
27
  /**
28
- * Optional length of each item.
28
+ * Optional length (in pixels) of each item. Length refers to the height in
29
+ * vertical orientation and width in horizontal orientation.
29
30
  */
30
31
  itemLength?: number;
31
32
  /**
@@ -33,34 +34,37 @@ export type ListProps<T> = HTMLAttributes<HTMLDivElement> & {
33
34
  */
34
35
  itemPadding?: number;
35
36
  /**
36
- * Indicates whether selections are retained. For example, in the case of a
37
- * vertical list of clickable rows, being able to retain a selection means
38
- * when the row is clicked, it becomes and stays selected. Being unable to
39
- * retain a selection means when the row is clicked, it does not become
40
- * selected. It is simply clicked and the subsequent event is dispatched.
37
+ * Orientation of the component.
41
38
  */
42
- isSelectable?: boolean;
39
+ orientation?: Orientation;
43
40
  /**
44
- * Indicates whether selections can be toggled. For example, in the case of a
45
- * vertical list of selectable rows, being able to toggle a row means it gets
46
- * deselected when selected again. Being unable to toggle the row means it
47
- * does not get deselected when selected again.
41
+ * The selected indices. If `selectionMode` is `single`, only only the first
42
+ * value will be used.
48
43
  */
49
- isTogglable?: boolean;
44
+ selectedIndices?: number[];
50
45
  /**
51
- * Orientation of the list.
46
+ * Indicates the selection behavior:
47
+ * - `none`: No selection at all.
48
+ * - `single`: Only one item can be selected at a time.
49
+ * - `multiple`: Multiple items can be selected at the same time.
52
50
  */
53
- orientation?: Orientation;
51
+ selectionMode?: 'none' | 'single' | 'multiple';
54
52
  /**
55
- * Handler invoked when an index is activated.
53
+ * Handler invoked when an item is activated.
54
+ *
55
+ * @param index Item index.
56
56
  */
57
- onActivate?: (index: number) => void;
57
+ onActivateAt?: (index: number) => void;
58
58
  /**
59
- * Handler invoked when an index is deselected.
59
+ * Handler invoked when an item is deselected.
60
+ *
61
+ * @param index Item index.
60
62
  */
61
63
  onDeselectAt?: (index: number) => void;
62
64
  /**
63
- * Handler invoked when an index is selected.
65
+ * Handler invoked when an item is selected.
66
+ *
67
+ * @param index Item index.
64
68
  */
65
69
  onSelectAt?: (index: number) => void;
66
70
  };
@@ -79,16 +83,17 @@ declare const _default: <T>(props: React.HTMLAttributes<HTMLDivElement> & {
79
83
  */
80
84
  data: T[];
81
85
  /**
82
- * The selected index. Any value below 0 indicates that nothing is
83
- * selected.
86
+ * Indicates if items can be toggled, i.e. they can be deselected if selected
87
+ * again.
84
88
  */
85
- selectedIndex?: number | undefined;
89
+ isTogglable?: boolean | undefined;
86
90
  /**
87
91
  * React component type to be used to generate items for this list.
88
92
  */
89
93
  itemComponentType?: React.ComponentType<ListItemProps<T>> | undefined;
90
94
  /**
91
- * Optional length of each item.
95
+ * Optional length (in pixels) of each item. Length refers to the height in
96
+ * vertical orientation and width in horizontal orientation.
92
97
  */
93
98
  itemLength?: number | undefined;
94
99
  /**
@@ -96,34 +101,37 @@ declare const _default: <T>(props: React.HTMLAttributes<HTMLDivElement> & {
96
101
  */
97
102
  itemPadding?: number | undefined;
98
103
  /**
99
- * Indicates whether selections are retained. For example, in the case of a
100
- * vertical list of clickable rows, being able to retain a selection means
101
- * when the row is clicked, it becomes and stays selected. Being unable to
102
- * retain a selection means when the row is clicked, it does not become
103
- * selected. It is simply clicked and the subsequent event is dispatched.
104
+ * Orientation of the component.
104
105
  */
105
- isSelectable?: boolean | undefined;
106
+ orientation?: Orientation | undefined;
106
107
  /**
107
- * Indicates whether selections can be toggled. For example, in the case of a
108
- * vertical list of selectable rows, being able to toggle a row means it gets
109
- * deselected when selected again. Being unable to toggle the row means it
110
- * does not get deselected when selected again.
108
+ * The selected indices. If `selectionMode` is `single`, only only the first
109
+ * value will be used.
111
110
  */
112
- isTogglable?: boolean | undefined;
111
+ selectedIndices?: number[] | undefined;
113
112
  /**
114
- * Orientation of the list.
113
+ * Indicates the selection behavior:
114
+ * - `none`: No selection at all.
115
+ * - `single`: Only one item can be selected at a time.
116
+ * - `multiple`: Multiple items can be selected at the same time.
115
117
  */
116
- orientation?: Orientation | undefined;
118
+ selectionMode?: "none" | "multiple" | "single" | undefined;
117
119
  /**
118
- * Handler invoked when an index is activated.
120
+ * Handler invoked when an item is activated.
121
+ *
122
+ * @param index Item index.
119
123
  */
120
- onActivate?: ((index: number) => void) | undefined;
124
+ onActivateAt?: ((index: number) => void) | undefined;
121
125
  /**
122
- * Handler invoked when an index is deselected.
126
+ * Handler invoked when an item is deselected.
127
+ *
128
+ * @param index Item index.
123
129
  */
124
130
  onDeselectAt?: ((index: number) => void) | undefined;
125
131
  /**
126
- * Handler invoked when an index is selected.
132
+ * Handler invoked when an item is selected.
133
+ *
134
+ * @param index Item index.
127
135
  */
128
136
  onSelectAt?: ((index: number) => void) | undefined;
129
137
  } & {