etudes 3.3.1 → 3.5.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
@@ -3,7 +3,9 @@ import { type ListItemProps, type ListProps } from './List';
3
3
  export type DropdownData = {
4
4
  label?: string;
5
5
  };
6
- export type DropdownToggleProps = HTMLAttributes<HTMLElement> & PropsWithChildren;
6
+ export type DropdownToggleProps = HTMLAttributes<HTMLElement> & {
7
+ onCustomEvent?: (name: string, info?: any) => void;
8
+ };
7
9
  export type DropdownItemProps<T extends DropdownData = DropdownData> = ListItemProps<T>;
8
10
  export type DropdownProps<T extends DropdownData = DropdownData> = HTMLAttributes<HTMLDivElement> & ListProps<T> & PropsWithChildren<{
9
11
  /**
@@ -41,6 +43,13 @@ export type DropdownProps<T extends DropdownData = DropdownData> = HTMLAttribute
41
43
  * the component. When absent, one will be generated automatically.
42
44
  */
43
45
  toggleComponentType?: ComponentType<DropdownToggleProps>;
46
+ /**
47
+ * Handler invoked when the toggle dispatches a custom event.
48
+ *
49
+ * @param eventName Name of the dispatched custom event.
50
+ * @param eventInfo Optional info of the dispatched custom event.
51
+ */
52
+ onToggleCustomEvent?: (eventName: string, eventInfo?: any) => void;
44
53
  }>;
45
54
  /**
46
55
  * A dropdown menu component that is invertible (i.e. can "dropup" instead) and
@@ -50,25 +59,16 @@ export type DropdownProps<T extends DropdownData = DropdownData> = HTMLAttribute
50
59
  declare const _default: <T extends DropdownData = DropdownData>(props: React.HTMLAttributes<HTMLDivElement> & {
51
60
  borderThickness?: number | undefined;
52
61
  data: T[];
53
- isTogglable?: boolean | undefined;
54
- itemComponentType?: React.ComponentType<ListItemProps<T>> | undefined;
62
+ isSelectionTogglable?: boolean | undefined;
55
63
  itemLength?: number | undefined;
56
64
  itemPadding?: number | undefined;
57
- orientation?: ("horizontal" | "vertical") | undefined; /**
58
- * Indicates if the component is inverted (i.e. "dropup" instead of dropdown).
59
- * Supports all orientations.
60
- */
65
+ orientation?: ("horizontal" | "vertical") | undefined;
61
66
  selectedIndices?: number[] | undefined;
62
- /**
63
- * Maximum number of items that are viside when the component expands. When a
64
- * value greater than or equal to 0 is specified, only that number of items
65
- * will be visible at a time, and a scrollbar will appear to scroll to
66
- * remaining items. Any value less than 0 indicates that all items will be
67
- * visible when the component expands.
68
- */
69
67
  selectionMode?: "none" | "multiple" | "single" | undefined;
68
+ itemComponentType?: React.ComponentType<ListItemProps<T>> | undefined;
70
69
  onActivateAt?: ((index: number) => void) | undefined;
71
70
  onDeselectAt?: ((index: number) => void) | undefined;
71
+ onItemCustomEvent?: ((index: number, eventName: string, eventInfo?: any) => void) | undefined;
72
72
  onSelectAt?: ((index: number) => void) | undefined;
73
73
  onSelectionChange?: ((indices: number[]) => void) | undefined;
74
74
  } & {
@@ -107,6 +107,13 @@ declare const _default: <T extends DropdownData = DropdownData>(props: React.HTM
107
107
  * the component. When absent, one will be generated automatically.
108
108
  */
109
109
  toggleComponentType?: React.ComponentType<DropdownToggleProps> | undefined;
110
+ /**
111
+ * Handler invoked when the toggle dispatches a custom event.
112
+ *
113
+ * @param eventName Name of the dispatched custom event.
114
+ * @param eventInfo Optional info of the dispatched custom event.
115
+ */
116
+ onToggleCustomEvent?: ((eventName: string, eventInfo?: any) => void) | undefined;
110
117
  } & {
111
118
  children?: React.ReactNode;
112
119
  } & {
package/lib/Dropdown.js CHANGED
@@ -65,8 +65,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
65
65
  };
66
66
  Object.defineProperty(exports, "__esModule", { value: true });
67
67
  var classnames_1 = __importDefault(require("classnames"));
68
- var fast_deep_equal_1 = __importDefault(require("fast-deep-equal"));
69
- var react_1 = __importStar(require("react"));
68
+ var react_1 = __importDefault(require("fast-deep-equal/react"));
69
+ var react_2 = __importStar(require("react"));
70
70
  var FlatSVG_1 = __importDefault(require("./FlatSVG"));
71
71
  var List_1 = __importDefault(require("./List"));
72
72
  var useElementRect_1 = __importDefault(require("./hooks/useElementRect"));
@@ -79,8 +79,16 @@ var styles_1 = __importDefault(require("./utils/styles"));
79
79
  * supports both horizontal and vertical orientations. Provide data and item
80
80
  * component type to this component to automatically generate menu items.
81
81
  */
82
- exports.default = (0, react_1.forwardRef)(function (_a, ref) {
83
- var children = _a.children, className = _a.className, style = _a.style, _b = _a.borderThickness, borderThickness = _b === void 0 ? 0 : _b, collapseIconSvg = _a.collapseIconSvg, _c = _a.collapsesOnSelect, collapsesOnSelect = _c === void 0 ? true : _c, data = _a.data, _d = _a.defaultLabel, defaultLabel = _d === void 0 ? 'Select' : _d, expandIconSvg = _a.expandIconSvg, _e = _a.isInverted, isInverted = _e === void 0 ? false : _e, _f = _a.isTogglable, isTogglable = _f === void 0 ? false : _f, itemComponentType = _a.itemComponentType, externalItemLength = _a.itemLength, _g = _a.itemPadding, itemPadding = _g === void 0 ? 0 : _g, _h = _a.maxVisibleItems, maxVisibleItems = _h === void 0 ? -1 : _h, _j = _a.orientation, orientation = _j === void 0 ? 'vertical' : _j, _k = _a.selectedIndices, externalSelectedIndices = _k === void 0 ? [] : _k, _l = _a.selectionMode, selectionMode = _l === void 0 ? 'single' : _l, ToggleComponent = _a.toggleComponentType, onActivateAt = _a.onActivateAt, onDeselectAt = _a.onDeselectAt, onSelectAt = _a.onSelectAt, onSelectionChange = _a.onSelectionChange, props = __rest(_a, ["children", "className", "style", "borderThickness", "collapseIconSvg", "collapsesOnSelect", "data", "defaultLabel", "expandIconSvg", "isInverted", "isTogglable", "itemComponentType", "itemLength", "itemPadding", "maxVisibleItems", "orientation", "selectedIndices", "selectionMode", "toggleComponentType", "onActivateAt", "onDeselectAt", "onSelectAt", "onSelectionChange"]);
82
+ exports.default = (0, react_2.forwardRef)(function (_a, ref) {
83
+ var children = _a.children, className = _a.className, style = _a.style, _b = _a.borderThickness, borderThickness = _b === void 0 ? 0 : _b, collapseIconSvg = _a.collapseIconSvg, _c = _a.collapsesOnSelect, collapsesOnSelect = _c === void 0 ? true : _c, data = _a.data, _d = _a.defaultLabel, defaultLabel = _d === void 0 ? 'Select' : _d, expandIconSvg = _a.expandIconSvg, _e = _a.isInverted, isInverted = _e === void 0 ? false : _e, _f = _a.isSelectionTogglable, isSelectionTogglable = _f === void 0 ? false : _f, itemComponentType = _a.itemComponentType, externalItemLength = _a.itemLength, _g = _a.itemPadding, itemPadding = _g === void 0 ? 0 : _g, _h = _a.maxVisibleItems, maxVisibleItems = _h === void 0 ? -1 : _h, _j = _a.orientation, orientation = _j === void 0 ? 'vertical' : _j, _k = _a.selectedIndices, externalSelectedIndices = _k === void 0 ? [] : _k, _l = _a.selectionMode, selectionMode = _l === void 0 ? 'single' : _l, ToggleComponent = _a.toggleComponentType, onActivateAt = _a.onActivateAt, onDeselectAt = _a.onDeselectAt, onSelectAt = _a.onSelectAt, onSelectionChange = _a.onSelectionChange, onToggleCustomEvent = _a.onToggleCustomEvent, props = __rest(_a, ["children", "className", "style", "borderThickness", "collapseIconSvg", "collapsesOnSelect", "data", "defaultLabel", "expandIconSvg", "isInverted", "isSelectionTogglable", "itemComponentType", "itemLength", "itemPadding", "maxVisibleItems", "orientation", "selectedIndices", "selectionMode", "toggleComponentType", "onActivateAt", "onDeselectAt", "onSelectAt", "onSelectionChange", "onToggleCustomEvent"]);
84
+ var isIndexOutOfRange = function (index) {
85
+ if (index >= data.length)
86
+ return true;
87
+ if (index < 0)
88
+ return true;
89
+ return false;
90
+ };
91
+ var sanitizeSelectedIndices = function (indices) { return indices.sort().filter(function (t) { return !isIndexOutOfRange(t); }); };
84
92
  var expand = function () {
85
93
  if (isCollapsed)
86
94
  setIsCollapsed(false);
@@ -102,6 +110,12 @@ exports.default = (0, react_1.forwardRef)(function (_a, ref) {
102
110
  if (selectionMode === 'single' && collapsesOnSelect)
103
111
  collapse();
104
112
  };
113
+ var selectionChangeHandler = function (selection) {
114
+ var newValue = selection.sort();
115
+ if ((0, react_1.default)(newValue, selectedIndices))
116
+ return;
117
+ setSelectedIndices(newValue);
118
+ };
105
119
  var clickOutsideHandler = function (event) {
106
120
  if (isCollapsed)
107
121
  return;
@@ -122,48 +136,52 @@ exports.default = (0, react_1.forwardRef)(function (_a, ref) {
122
136
  return;
123
137
  collapse();
124
138
  };
125
- var bodyRef = (0, react_1.useRef)(null);
126
- var _m = __read((0, react_1.useState)(externalSelectedIndices), 2), selectedIndices = _m[0], setSelectedIndices = _m[1];
127
- var _o = __read((0, react_1.useState)(true), 2), isCollapsed = _o[0], setIsCollapsed = _o[1];
139
+ var bodyRef = (0, react_2.useRef)(null);
140
+ var _m = __read((0, react_2.useState)(sanitizeSelectedIndices(externalSelectedIndices)), 2), selectedIndices = _m[0], setSelectedIndices = _m[1];
141
+ var _o = __read((0, react_2.useState)(true), 2), isCollapsed = _o[0], setIsCollapsed = _o[1];
128
142
  var rect = (0, useElementRect_1.default)(bodyRef);
129
- (0, react_1.useEffect)(function () {
143
+ (0, react_2.useEffect)(function () {
130
144
  window.addEventListener('click', clickOutsideHandler);
131
145
  return function () {
132
146
  window.removeEventListener('click', clickOutsideHandler);
133
147
  };
134
148
  }, [isCollapsed]);
135
- (0, react_1.useEffect)(function () {
136
- if ((0, fast_deep_equal_1.default)(externalSelectedIndices, selectedIndices))
149
+ (0, react_2.useEffect)(function () {
150
+ var newValue = sanitizeSelectedIndices(externalSelectedIndices);
151
+ if ((0, react_1.default)(newValue, selectedIndices))
137
152
  return;
138
- setSelectedIndices(externalSelectedIndices);
139
- }, [JSON.stringify(externalSelectedIndices)]);
153
+ setSelectedIndices(newValue);
154
+ }, [JSON.stringify(sanitizeSelectedIndices(externalSelectedIndices))]);
155
+ (0, react_2.useEffect)(function () {
156
+ onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange(selectedIndices);
157
+ }, [JSON.stringify(sanitizeSelectedIndices(selectedIndices))]);
140
158
  var itemLength = externalItemLength !== null && externalItemLength !== void 0 ? externalItemLength : (orientation === 'vertical' ? rect.height : rect.width);
141
159
  var numItems = data.length;
142
160
  var numVisibleItems = maxVisibleItems < 0 ? numItems : Math.min(numItems, maxVisibleItems);
143
161
  var menuLength = (itemLength - borderThickness) * numVisibleItems + itemPadding * (numVisibleItems - 1) + borderThickness;
144
162
  var fixedClassNames = (0, asClassNameDict_1.default)({
145
163
  root: (0, classnames_1.default)(orientation, {
146
- togglable: isTogglable,
164
+ togglable: isSelectionTogglable,
147
165
  collapsed: isCollapsed,
148
166
  expanded: !isCollapsed,
149
167
  }),
150
168
  toggle: (0, classnames_1.default)(orientation, {
151
- togglable: isTogglable,
169
+ togglable: isSelectionTogglable,
152
170
  collapsed: isCollapsed,
153
171
  expanded: !isCollapsed,
154
172
  }),
155
173
  expandIcon: (0, classnames_1.default)(orientation, {
156
- togglable: isTogglable,
174
+ togglable: isSelectionTogglable,
157
175
  collapsed: isCollapsed,
158
176
  expanded: !isCollapsed,
159
177
  }),
160
178
  collapseIcon: (0, classnames_1.default)(orientation, {
161
- togglable: isTogglable,
179
+ togglable: isSelectionTogglable,
162
180
  collapsed: isCollapsed,
163
181
  expanded: !isCollapsed,
164
182
  }),
165
183
  list: (0, classnames_1.default)({
166
- togglable: isTogglable,
184
+ togglable: isSelectionTogglable,
167
185
  collapsed: isCollapsed,
168
186
  expanded: !isCollapsed,
169
187
  }),
@@ -240,16 +258,16 @@ exports.default = (0, react_1.forwardRef)(function (_a, ref) {
240
258
  width: '15px',
241
259
  },
242
260
  });
243
- var expandIconComponent = expandIconSvg ? react_1.default.createElement(FlatSVG_1.default, { svg: expandIconSvg, style: defaultStyles.expandIcon }) : react_1.default.createElement(react_1.default.Fragment, null);
244
- var collapseIconComponent = collapseIconSvg ? react_1.default.createElement(FlatSVG_1.default, { svg: collapseIconSvg, style: defaultStyles.collapseIcon }) : expandIconComponent;
245
- 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) }),
246
- react_1.default.createElement("div", { ref: bodyRef, style: (0, styles_1.default)(fixedStyles.body) },
247
- ToggleComponent ? (react_1.default.createElement(ToggleComponent, { className: (0, classnames_1.default)(fixedClassNames.toggle), style: (0, styles_1.default)(fixedStyles.toggle), onClick: function () { return toggle(); } })) : (react_1.default.createElement("button", { className: (0, classnames_1.default)(fixedClassNames.toggle), style: (0, styles_1.default)(fixedStyles.toggle, defaultStyles.toggle), onClick: function () { return toggle(); } },
248
- 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 : '' } }),
261
+ var expandIconComponent = expandIconSvg ? react_2.default.createElement(FlatSVG_1.default, { svg: expandIconSvg, style: defaultStyles.expandIcon }) : react_2.default.createElement(react_2.default.Fragment, null);
262
+ var collapseIconComponent = collapseIconSvg ? react_2.default.createElement(FlatSVG_1.default, { svg: collapseIconSvg, style: defaultStyles.collapseIcon }) : expandIconComponent;
263
+ return (react_2.default.createElement("div", __assign({}, props, { ref: ref, className: (0, classnames_1.default)(className, fixedClassNames.root), style: (0, styles_1.default)(style, fixedStyles.root) }),
264
+ react_2.default.createElement("div", { ref: bodyRef, style: (0, styles_1.default)(fixedStyles.body) },
265
+ ToggleComponent ? (react_2.default.createElement(ToggleComponent, { className: (0, classnames_1.default)(fixedClassNames.toggle), style: (0, styles_1.default)(fixedStyles.toggle), onClick: function () { return toggle(); }, onCustomEvent: function (name, info) { return onToggleCustomEvent === null || onToggleCustomEvent === void 0 ? void 0 : onToggleCustomEvent(name, info); } })) : (react_2.default.createElement("button", { className: (0, classnames_1.default)(fixedClassNames.toggle), style: (0, styles_1.default)(fixedStyles.toggle, defaultStyles.toggle), onClick: function () { return toggle(); } },
266
+ react_2.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 : '' } }),
249
267
  (0, cloneStyledElement_1.default)(isCollapsed ? expandIconComponent : collapseIconComponent, {
250
268
  className: (0, classnames_1.default)(isCollapsed ? fixedClassNames.expandIcon : fixedClassNames.collapseIcon),
251
269
  style: (0, styles_1.default)(isCollapsed ? fixedStyles.expandIcon : fixedStyles.collapseIcon),
252
270
  }))),
253
- 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, onSelectionChange: onSelectionChange }))));
271
+ react_2.default.createElement(List_1.default, { className: fixedClassNames.list, style: (0, styles_1.default)(fixedStyles.list), borderThickness: borderThickness, data: data, isSelectionTogglable: isSelectionTogglable, itemComponentType: itemComponentType, itemLength: itemLength, itemPadding: itemPadding, orientation: orientation, selectedIndices: selectedIndices, selectionMode: selectionMode, onActivateAt: onActivateAt, onDeselectAt: onDeselectAt, onSelectAt: selectAtHandler, onSelectionChange: selectionChangeHandler }))));
254
272
  });
255
273
  //# 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 isEqual from 'fast-deep-equal'\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, type ListProps } from './List'\nimport useElementRect from './hooks/useElementRect'\nimport asClassNameDict from './utils/asClassNameDict'\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 DropdownToggleProps = HTMLAttributes<HTMLElement> & PropsWithChildren\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 * SVG markup to be put in the dropdown button as the collapse icon.\n */\n collapseIconSvg?: string\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 * 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 * Indicates if the component is inverted (i.e. \"dropup\" instead of dropdown).\n * Supports all orientations.\n */\n isInverted?: 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 * React component type to be used for generating the toggle element inside\n * the component. When absent, one will be generated automatically.\n */\n toggleComponentType?: ComponentType<DropdownToggleProps>\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 collapseIconSvg,\n collapsesOnSelect = true,\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 selectedIndices: externalSelectedIndices = [],\n selectionMode = 'single',\n toggleComponentType: ToggleComponent,\n onActivateAt,\n onDeselectAt,\n onSelectAt,\n onSelectionChange,\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 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 cursor: 'pointer',\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 pointerEvents: 'none',\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 expandIconComponent = expandIconSvg ? <FlatSVG svg={expandIconSvg} style={defaultStyles.expandIcon}/> : <></>\n const collapseIconComponent = 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 {ToggleComponent ? (\n <ToggleComponent\n className={classNames(fixedClassNames.toggle)}\n style={styles(fixedStyles.toggle)}\n onClick={() => toggle()}\n />\n ) : (\n <button\n className={classNames(fixedClassNames.toggle)}\n style={styles(fixedStyles.toggle, defaultStyles.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 </button>\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 onSelectionChange={onSelectionChange}\n />\n </div>\n </div>\n )\n}) as <T extends DropdownData = DropdownData>(props: DropdownProps<T> & { ref?: Ref<HTMLDivElement> }) => ReactElement\n"]}
1
+ {"version":3,"file":"Dropdown.js","sourceRoot":"/","sources":["Dropdown.tsx"],"names":[],"mappings":"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","sourcesContent":["import classNames from 'classnames'\nimport isDeepEqual from 'fast-deep-equal/react'\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, type ListProps } from './List'\nimport useElementRect from './hooks/useElementRect'\nimport asClassNameDict from './utils/asClassNameDict'\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 DropdownToggleProps = HTMLAttributes<HTMLElement> & {\n onCustomEvent?: (name: string, info?: any) => void\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 * SVG markup to be put in the dropdown button as the collapse icon.\n */\n collapseIconSvg?: string\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 * 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 * Indicates if the component is inverted (i.e. \"dropup\" instead of dropdown).\n * Supports all orientations.\n */\n isInverted?: 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 * React component type to be used for generating the toggle element inside\n * the component. When absent, one will be generated automatically.\n */\n toggleComponentType?: ComponentType<DropdownToggleProps>\n\n /**\n * Handler invoked when the toggle dispatches a custom event.\n *\n * @param eventName Name of the dispatched custom event.\n * @param eventInfo Optional info of the dispatched custom event.\n */\n onToggleCustomEvent?: (eventName: string, eventInfo?: any) => 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 collapseIconSvg,\n collapsesOnSelect = true,\n data,\n defaultLabel = 'Select',\n expandIconSvg,\n isInverted = false,\n isSelectionTogglable = false,\n itemComponentType,\n itemLength: externalItemLength,\n itemPadding = 0,\n maxVisibleItems = -1,\n orientation = 'vertical',\n selectedIndices: externalSelectedIndices = [],\n selectionMode = 'single',\n toggleComponentType: ToggleComponent,\n onActivateAt,\n onDeselectAt,\n onSelectAt,\n onSelectionChange,\n onToggleCustomEvent,\n ...props\n}, ref) => {\n const isIndexOutOfRange = (index: number) => {\n if (index >= data.length) return true\n if (index < 0) return true\n\n return false\n }\n\n const sanitizeSelectedIndices = (indices: number[]) => indices.sort().filter(t => !isIndexOutOfRange(t))\n\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 selectionChangeHandler = (selection: number[]) => {\n const newValue = selection.sort()\n\n if (isDeepEqual(newValue, selectedIndices)) return\n\n setSelectedIndices(newValue)\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(sanitizeSelectedIndices(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 const newValue = sanitizeSelectedIndices(externalSelectedIndices)\n\n if (isDeepEqual(newValue, selectedIndices)) return\n\n setSelectedIndices(newValue)\n }, [JSON.stringify(sanitizeSelectedIndices(externalSelectedIndices))])\n\n useEffect(() => {\n onSelectionChange?.(selectedIndices)\n }, [JSON.stringify(sanitizeSelectedIndices(selectedIndices))])\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 fixedClassNames = asClassNameDict({\n root: classNames(orientation, {\n togglable: isSelectionTogglable,\n collapsed: isCollapsed,\n expanded: !isCollapsed,\n }),\n toggle: classNames(orientation, {\n togglable: isSelectionTogglable,\n collapsed: isCollapsed,\n expanded: !isCollapsed,\n }),\n expandIcon: classNames(orientation, {\n togglable: isSelectionTogglable,\n collapsed: isCollapsed,\n expanded: !isCollapsed,\n }),\n collapseIcon: classNames(orientation, {\n togglable: isSelectionTogglable,\n collapsed: isCollapsed,\n expanded: !isCollapsed,\n }),\n list: classNames({\n togglable: isSelectionTogglable,\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 cursor: 'pointer',\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 pointerEvents: 'none',\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 expandIconComponent = expandIconSvg ? <FlatSVG svg={expandIconSvg} style={defaultStyles.expandIcon}/> : <></>\n const collapseIconComponent = 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 {ToggleComponent ? (\n <ToggleComponent\n className={classNames(fixedClassNames.toggle)}\n style={styles(fixedStyles.toggle)}\n onClick={() => toggle()}\n onCustomEvent={(name, info) => onToggleCustomEvent?.(name, info)}\n />\n ) : (\n <button\n className={classNames(fixedClassNames.toggle)}\n style={styles(fixedStyles.toggle, defaultStyles.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 </button>\n )}\n <List\n className={fixedClassNames.list}\n style={styles(fixedStyles.list)}\n borderThickness={borderThickness}\n data={data}\n isSelectionTogglable={isSelectionTogglable}\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 onSelectionChange={selectionChangeHandler}\n />\n </div>\n </div>\n )\n}) as <T extends DropdownData = DropdownData>(props: DropdownProps<T> & { ref?: Ref<HTMLDivElement> }) => ReactElement\n"]}
package/lib/List.d.ts CHANGED
@@ -5,6 +5,7 @@ export type ListItemProps<T> = HTMLAttributes<HTMLElement> & {
5
5
  index: number;
6
6
  isSelected: boolean;
7
7
  orientation: Orientation;
8
+ onCustomEvent?: (name: string, info?: any) => void;
8
9
  };
9
10
  export type ListProps<T> = HTMLAttributes<HTMLDivElement> & {
10
11
  /**
@@ -16,14 +17,10 @@ export type ListProps<T> = HTMLAttributes<HTMLDivElement> & {
16
17
  */
17
18
  data: T[];
18
19
  /**
19
- * Indicates if items can be toggled, i.e. they can be deselected if selected
20
- * again.
20
+ * Indicates if item selection can be toggled, i.e. they can be deselected if
21
+ * selected again.
21
22
  */
22
- isTogglable?: boolean;
23
- /**
24
- * React component type to be used to generate items for this list.
25
- */
26
- itemComponentType?: ComponentType<ListItemProps<T>>;
23
+ isSelectionTogglable?: boolean;
27
24
  /**
28
25
  * Optional length (in pixels) of each item. Length refers to the height in
29
26
  * vertical orientation and width in horizontal orientation.
@@ -49,6 +46,10 @@ export type ListProps<T> = HTMLAttributes<HTMLDivElement> & {
49
46
  * - `multiple`: Multiple items can be selected at the same time.
50
47
  */
51
48
  selectionMode?: 'none' | 'single' | 'multiple';
49
+ /**
50
+ * React component type to be used to generate items for this list.
51
+ */
52
+ itemComponentType?: ComponentType<ListItemProps<T>>;
52
53
  /**
53
54
  * Handler invoked when an item is activated.
54
55
  *
@@ -61,6 +62,14 @@ export type ListProps<T> = HTMLAttributes<HTMLDivElement> & {
61
62
  * @param index Item index.
62
63
  */
63
64
  onDeselectAt?: (index: number) => void;
65
+ /**
66
+ * Handler invoked when a custom event is dispatched from the item.
67
+ *
68
+ * @param index Index of the item.
69
+ * @param eventName Name of the dispatched custom event.
70
+ * @param eventInfo Optional info of the dispatched custom event.
71
+ */
72
+ onItemCustomEvent?: (index: number, eventName: string, eventInfo?: any) => void;
64
73
  /**
65
74
  * Handler invoked when an item is selected.
66
75
  *
@@ -89,14 +98,10 @@ declare const _default: <T>(props: React.HTMLAttributes<HTMLDivElement> & {
89
98
  */
90
99
  data: T[];
91
100
  /**
92
- * Indicates if items can be toggled, i.e. they can be deselected if selected
93
- * again.
101
+ * Indicates if item selection can be toggled, i.e. they can be deselected if
102
+ * selected again.
94
103
  */
95
- isTogglable?: boolean | undefined;
96
- /**
97
- * React component type to be used to generate items for this list.
98
- */
99
- itemComponentType?: React.ComponentType<ListItemProps<T>> | undefined;
104
+ isSelectionTogglable?: boolean | undefined;
100
105
  /**
101
106
  * Optional length (in pixels) of each item. Length refers to the height in
102
107
  * vertical orientation and width in horizontal orientation.
@@ -122,6 +127,10 @@ declare const _default: <T>(props: React.HTMLAttributes<HTMLDivElement> & {
122
127
  * - `multiple`: Multiple items can be selected at the same time.
123
128
  */
124
129
  selectionMode?: "none" | "multiple" | "single" | undefined;
130
+ /**
131
+ * React component type to be used to generate items for this list.
132
+ */
133
+ itemComponentType?: React.ComponentType<ListItemProps<T>> | undefined;
125
134
  /**
126
135
  * Handler invoked when an item is activated.
127
136
  *
@@ -134,6 +143,14 @@ declare const _default: <T>(props: React.HTMLAttributes<HTMLDivElement> & {
134
143
  * @param index Item index.
135
144
  */
136
145
  onDeselectAt?: ((index: number) => void) | undefined;
146
+ /**
147
+ * Handler invoked when a custom event is dispatched from the item.
148
+ *
149
+ * @param index Index of the item.
150
+ * @param eventName Name of the dispatched custom event.
151
+ * @param eventInfo Optional info of the dispatched custom event.
152
+ */
153
+ onItemCustomEvent?: ((index: number, eventName: string, eventInfo?: any) => void) | undefined;
137
154
  /**
138
155
  * Handler invoked when an item is selected.
139
156
  *
package/lib/List.js CHANGED
@@ -74,8 +74,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
74
74
  };
75
75
  Object.defineProperty(exports, "__esModule", { value: true });
76
76
  var classnames_1 = __importDefault(require("classnames"));
77
- var fast_deep_equal_1 = __importDefault(require("fast-deep-equal"));
78
- var react_1 = __importStar(require("react"));
77
+ var react_1 = __importDefault(require("fast-deep-equal/react"));
78
+ var react_2 = __importStar(require("react"));
79
79
  var Each_1 = __importDefault(require("./Each"));
80
80
  var usePrevious_1 = __importDefault(require("./hooks/usePrevious"));
81
81
  var asClassNameDict_1 = __importDefault(require("./utils/asClassNameDict"));
@@ -86,8 +86,8 @@ var styles_1 = __importDefault(require("./utils/styles"));
86
86
  * provided React component type. The type of data passed to each item is
87
87
  * generic. This component supports both horizontal and vertical orientations.
88
88
  */
89
- exports.default = (0, react_1.forwardRef)(function (_a, ref) {
90
- var className = _a.className, style = _a.style, _b = _a.borderThickness, borderThickness = _b === void 0 ? 0 : _b, data = _a.data, _c = _a.selectionMode, selectionMode = _c === void 0 ? 'none' : _c, isTogglable = _a.isTogglable, ItemComponent = _a.itemComponentType, itemLength = _a.itemLength, _d = _a.itemPadding, itemPadding = _d === void 0 ? 0 : _d, _e = _a.orientation, orientation = _e === void 0 ? 'vertical' : _e, _f = _a.selectedIndices, externalSelectedIndices = _f === void 0 ? [] : _f, onActivateAt = _a.onActivateAt, onDeselectAt = _a.onDeselectAt, onSelectAt = _a.onSelectAt, onSelectionChange = _a.onSelectionChange, props = __rest(_a, ["className", "style", "borderThickness", "data", "selectionMode", "isTogglable", "itemComponentType", "itemLength", "itemPadding", "orientation", "selectedIndices", "onActivateAt", "onDeselectAt", "onSelectAt", "onSelectionChange"]);
89
+ exports.default = (0, react_2.forwardRef)(function (_a, ref) {
90
+ var className = _a.className, style = _a.style, _b = _a.borderThickness, borderThickness = _b === void 0 ? 0 : _b, data = _a.data, _c = _a.selectionMode, selectionMode = _c === void 0 ? 'none' : _c, _d = _a.isSelectionTogglable, isSelectionTogglable = _d === void 0 ? false : _d, itemLength = _a.itemLength, _e = _a.itemPadding, itemPadding = _e === void 0 ? 0 : _e, _f = _a.orientation, orientation = _f === void 0 ? 'vertical' : _f, _g = _a.selectedIndices, externalSelectedIndices = _g === void 0 ? [] : _g, ItemComponent = _a.itemComponentType, onActivateAt = _a.onActivateAt, onDeselectAt = _a.onDeselectAt, onItemCustomEvent = _a.onItemCustomEvent, onSelectAt = _a.onSelectAt, onSelectionChange = _a.onSelectionChange, props = __rest(_a, ["className", "style", "borderThickness", "data", "selectionMode", "isSelectionTogglable", "itemLength", "itemPadding", "orientation", "selectedIndices", "itemComponentType", "onActivateAt", "onDeselectAt", "onItemCustomEvent", "onSelectAt", "onSelectionChange"]);
91
91
  var isIndexOutOfRange = function (index) {
92
92
  if (index >= data.length)
93
93
  return true;
@@ -95,6 +95,7 @@ exports.default = (0, react_1.forwardRef)(function (_a, ref) {
95
95
  return true;
96
96
  return false;
97
97
  };
98
+ var sanitizeSelectedIndices = function (indices) { return indices.sort().filter(function (t) { return !isIndexOutOfRange(t); }); };
98
99
  var isSelectedAt = function (index) { return selectedIndices.indexOf(index) >= 0; };
99
100
  var toggleAt = function (index) {
100
101
  if (isSelectedAt(index)) {
@@ -105,11 +106,11 @@ exports.default = (0, react_1.forwardRef)(function (_a, ref) {
105
106
  }
106
107
  };
107
108
  var selectAt = function (index) {
108
- if (isSelectedAt(index))
109
+ if (isIndexOutOfRange(index) || isSelectedAt(index))
109
110
  return;
110
111
  switch (selectionMode) {
111
112
  case 'multiple':
112
- setSelectedIndices(function (prev) { return __spreadArray(__spreadArray([], __read(prev.filter(function (t) { return t !== index; })), false), [index], false); });
113
+ setSelectedIndices(function (prev) { return __spreadArray(__spreadArray([], __read(prev.filter(function (t) { return t !== index; })), false), [index], false).sort(); });
113
114
  break;
114
115
  case 'single':
115
116
  setSelectedIndices([index]);
@@ -119,13 +120,13 @@ exports.default = (0, react_1.forwardRef)(function (_a, ref) {
119
120
  }
120
121
  };
121
122
  var deselectAt = function (index) {
122
- if (!isSelectedAt(index))
123
+ if (isIndexOutOfRange(index) || !isSelectedAt(index))
123
124
  return;
124
125
  setSelectedIndices(function (prev) { return prev.filter(function (t) { return t !== index; }); });
125
126
  };
126
127
  var activateAt = function (index) {
127
128
  if (selectionMode !== 'none') {
128
- if (isTogglable) {
129
+ if (isSelectionTogglable) {
129
130
  toggleAt(index);
130
131
  }
131
132
  else {
@@ -134,29 +135,30 @@ exports.default = (0, react_1.forwardRef)(function (_a, ref) {
134
135
  }
135
136
  onActivateAt === null || onActivateAt === void 0 ? void 0 : onActivateAt(index);
136
137
  };
137
- var _g = __read((0, react_1.useState)(externalSelectedIndices), 2), selectedIndices = _g[0], setSelectedIndices = _g[1];
138
+ var _h = __read((0, react_2.useState)(sanitizeSelectedIndices(externalSelectedIndices)), 2), selectedIndices = _h[0], setSelectedIndices = _h[1];
138
139
  var prevSelectedIndices = (0, usePrevious_1.default)(selectedIndices);
139
- (0, react_1.useEffect)(function () {
140
- if ((0, fast_deep_equal_1.default)(externalSelectedIndices, selectedIndices))
140
+ (0, react_2.useEffect)(function () {
141
+ var newValue = sanitizeSelectedIndices(externalSelectedIndices);
142
+ if ((0, react_1.default)(newValue, selectedIndices))
141
143
  return;
142
- setSelectedIndices(externalSelectedIndices);
143
- }, [JSON.stringify(externalSelectedIndices)]);
144
- (0, react_1.useEffect)(function () {
144
+ setSelectedIndices(newValue);
145
+ }, [JSON.stringify(sanitizeSelectedIndices(externalSelectedIndices))]);
146
+ (0, react_2.useEffect)(function () {
145
147
  var _a;
146
148
  if (selectionMode === 'none')
147
149
  return;
148
- var deselected = (_a = prevSelectedIndices === null || prevSelectedIndices === void 0 ? void 0 : prevSelectedIndices.filter(function (t) { return !isIndexOutOfRange(t) && selectedIndices.indexOf(t) === -1; })) !== null && _a !== void 0 ? _a : [];
149
- var selected = selectedIndices.filter(function (t) { return !isIndexOutOfRange(t) && (prevSelectedIndices === null || prevSelectedIndices === void 0 ? void 0 : prevSelectedIndices.indexOf(t)) === -1; });
150
+ var deselected = (_a = prevSelectedIndices === null || prevSelectedIndices === void 0 ? void 0 : prevSelectedIndices.filter(function (t) { return selectedIndices.indexOf(t) === -1; })) !== null && _a !== void 0 ? _a : [];
151
+ var selected = selectedIndices.filter(function (t) { return (prevSelectedIndices === null || prevSelectedIndices === void 0 ? void 0 : prevSelectedIndices.indexOf(t)) === -1; });
150
152
  deselected.map(function (t) { return onDeselectAt === null || onDeselectAt === void 0 ? void 0 : onDeselectAt(t); });
151
153
  selected.map(function (t) { return onSelectAt === null || onSelectAt === void 0 ? void 0 : onSelectAt(t); });
152
154
  onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange(selectedIndices);
153
- }, [JSON.stringify(selectedIndices)]);
155
+ }, [JSON.stringify(sanitizeSelectedIndices(selectedIndices))]);
154
156
  var fixedClassNames = (0, asClassNameDict_1.default)({
155
157
  root: (0, classnames_1.default)(orientation, {
156
- togglable: isTogglable,
158
+ togglable: isSelectionTogglable,
157
159
  }),
158
160
  item: (0, classnames_1.default)(orientation, {
159
- togglable: isTogglable,
161
+ togglable: isSelectionTogglable,
160
162
  }),
161
163
  });
162
164
  var fixedStyles = (0, asStyleDict_1.default)({
@@ -175,9 +177,9 @@ exports.default = (0, react_1.forwardRef)(function (_a, ref) {
175
177
  height: '100%',
176
178
  }),
177
179
  });
178
- 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) }), ItemComponent && (react_1.default.createElement(Each_1.default, { in: data }, function (val, idx) { return (react_1.default.createElement(ItemComponent, { className: (0, classnames_1.default)(fixedClassNames.item, {
180
+ return (react_2.default.createElement("div", __assign({}, props, { ref: ref, className: (0, classnames_1.default)(className, fixedClassNames.root), style: (0, styles_1.default)(style, fixedStyles.root) }), ItemComponent && (react_2.default.createElement(Each_1.default, { in: data }, function (val, idx) { return (react_2.default.createElement(ItemComponent, { className: (0, classnames_1.default)(fixedClassNames.item, {
179
181
  selected: isSelectedAt(idx),
180
- }), style: (0, styles_1.default)(fixedStyles.item, __assign(__assign({ pointerEvents: isTogglable !== true && isSelectedAt(idx) ? 'none' : 'auto' }, orientation === 'vertical' ? {
182
+ }), style: (0, styles_1.default)(fixedStyles.item, __assign(__assign({ pointerEvents: isSelectionTogglable !== true && isSelectedAt(idx) ? 'none' : 'auto' }, orientation === 'vertical' ? {
181
183
  height: itemLength !== undefined ? "".concat(itemLength, "px") : undefined,
182
184
  marginTop: "".concat(idx === 0 ? 0 : -borderThickness, "px"),
183
185
  } : {
@@ -187,6 +189,6 @@ exports.default = (0, react_1.forwardRef)(function (_a, ref) {
187
189
  marginBottom: "".concat(itemPadding, "px"),
188
190
  } : {
189
191
  marginRight: "".concat(itemPadding, "px"),
190
- }))), "data-index": idx, data: val, index: idx, isSelected: isSelectedAt(idx), orientation: orientation, onClick: function () { return activateAt(idx); } })); }))));
192
+ }))), "data-index": idx, data: val, index: idx, isSelected: isSelectedAt(idx), orientation: orientation, onCustomEvent: function (name, info) { return onItemCustomEvent === null || onItemCustomEvent === void 0 ? void 0 : onItemCustomEvent(idx, name, info); }, onClick: function () { return activateAt(idx); } })); }))));
191
193
  });
192
194
  //# sourceMappingURL=List.js.map
package/lib/List.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"List.js","sourceRoot":"/","sources":["List.tsx"],"names":[],"mappings":"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","sourcesContent":["import classNames from 'classnames'\nimport isEqual from 'fast-deep-equal'\nimport React, { forwardRef, useEffect, useState, type ComponentType, type HTMLAttributes, type ReactElement, type Ref } from 'react'\nimport Each from './Each'\nimport usePrevious from './hooks/usePrevious'\nimport asClassNameDict from './utils/asClassNameDict'\nimport asStyleDict from './utils/asStyleDict'\nimport styles from './utils/styles'\n\ntype Orientation = 'horizontal' | 'vertical'\n\nexport type ListItemProps<T> = HTMLAttributes<HTMLElement> & {\n data: T\n index: number\n isSelected: boolean\n orientation: Orientation\n}\n\nexport type ListProps<T> = HTMLAttributes<HTMLDivElement> & {\n /**\n * Thickness of item borders (in pixels). 0 indicates no borders.\n */\n borderThickness?: number\n\n /**\n * Generically typed data of each item.\n */\n data: T[]\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 * React component type to be used to generate items for this list.\n */\n itemComponentType?: ComponentType<ListItemProps<T>>\n\n /**\n * Optional length (in pixels) of each item. Length refers to the height in\n * vertical orientation and width in horizontal orientation.\n */\n itemLength?: number\n\n /**\n * Padding between every item (in pixels).\n */\n itemPadding?: number\n\n /**\n * Orientation of the component.\n */\n orientation?: Orientation\n\n /**\n * The selected indices. If `selectionMode` is `single`, only only the first\n * value will be used.\n */\n selectedIndices?: number[]\n\n /**\n * Indicates the selection behavior:\n * - `none`: No selection at all.\n * - `single`: Only one item can be selected at a time.\n * - `multiple`: Multiple items can be selected at the same time.\n */\n selectionMode?: 'none' | 'single' | 'multiple'\n\n /**\n * Handler invoked when an item is activated.\n *\n * @param index Item index.\n */\n onActivateAt?: (index: number) => void\n\n /**\n * Handler invoked when an item is deselected.\n *\n * @param index Item index.\n */\n onDeselectAt?: (index: number) => void\n\n /**\n * Handler invoked when an item is selected.\n *\n * @param index Item index.\n */\n onSelectAt?: (index: number) => void\n\n /**\n * Handler invoked when the selected items changed.\n *\n * @param indices Indices of selected items.\n */\n onSelectionChange?: (indices: number[]) => void\n}\n\n/**\n * A scrollable list of selectable items. Items are generated based on the\n * provided React component type. The type of data passed to each item is\n * generic. This component supports both horizontal and vertical orientations.\n */\nexport default forwardRef(({\n className,\n style,\n borderThickness = 0,\n data,\n selectionMode = 'none',\n isTogglable,\n itemComponentType: ItemComponent,\n itemLength,\n itemPadding = 0,\n orientation = 'vertical',\n selectedIndices: externalSelectedIndices = [],\n onActivateAt,\n onDeselectAt,\n onSelectAt,\n onSelectionChange,\n ...props\n}, ref) => {\n const isIndexOutOfRange = (index: number) => {\n if (index >= data.length) return true\n if (index < 0) return true\n\n return false\n }\n\n const isSelectedAt = (index: number) => selectedIndices.indexOf(index) >= 0\n\n const toggleAt = (index: number) => {\n if (isSelectedAt(index)) {\n deselectAt(index)\n }\n else {\n selectAt(index)\n }\n }\n\n const selectAt = (index: number) => {\n if (isSelectedAt(index)) return\n\n switch (selectionMode) {\n case 'multiple':\n setSelectedIndices(prev => [...prev.filter(t => t !== index), index])\n\n break\n case 'single':\n setSelectedIndices([index])\n\n break\n default:\n break\n }\n }\n\n const deselectAt = (index: number) => {\n if (!isSelectedAt(index)) return\n\n setSelectedIndices(prev => prev.filter(t => t !== index))\n }\n\n const activateAt = (index: number) => {\n if (selectionMode !== 'none') {\n if (isTogglable) {\n toggleAt(index)\n }\n else {\n selectAt(index)\n }\n }\n\n onActivateAt?.(index)\n }\n\n const [selectedIndices, setSelectedIndices] = useState(externalSelectedIndices)\n const prevSelectedIndices = usePrevious(selectedIndices)\n\n useEffect(() => {\n if (isEqual(externalSelectedIndices, selectedIndices)) return\n\n setSelectedIndices(externalSelectedIndices)\n }, [JSON.stringify(externalSelectedIndices)])\n\n useEffect(() => {\n if (selectionMode === 'none') return\n\n const deselected = prevSelectedIndices?.filter(t => !isIndexOutOfRange(t) && selectedIndices.indexOf(t) === -1) ?? []\n const selected = selectedIndices.filter(t => !isIndexOutOfRange(t) && prevSelectedIndices?.indexOf(t) === -1)\n\n deselected.map(t => onDeselectAt?.(t))\n selected.map(t => onSelectAt?.(t))\n\n onSelectionChange?.(selectedIndices)\n }, [JSON.stringify(selectedIndices)])\n\n const fixedClassNames = asClassNameDict({\n root: classNames(orientation, {\n togglable: isTogglable,\n }),\n item: classNames(orientation, {\n togglable: isTogglable,\n }),\n })\n\n const fixedStyles = asStyleDict({\n root: {\n alignItems: 'flex-start',\n counterReset: 'item-counter',\n display: 'flex',\n flex: '0 0 auto',\n flexDirection: orientation === 'horizontal' ? 'row' : 'column',\n justifyContent: 'flex-start',\n listStyle: 'none',\n },\n item: {\n borderWidth: `${borderThickness}px`,\n counterIncrement: 'item-counter',\n flex: '0 0 auto',\n ...orientation === 'vertical' ? {\n width: '100%',\n } : {\n height: '100%',\n },\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 {ItemComponent && (\n <Each in={data}>\n {(val, idx) => (\n <ItemComponent\n className={classNames(fixedClassNames.item, {\n selected: isSelectedAt(idx),\n })}\n style={styles(fixedStyles.item, {\n pointerEvents: isTogglable !== true && isSelectedAt(idx) ? 'none' : 'auto',\n ...orientation === 'vertical' ? {\n height: itemLength !== undefined ? `${itemLength}px` : undefined,\n marginTop: `${idx === 0 ? 0 : -borderThickness}px`,\n } : {\n marginLeft: `${idx === 0 ? 0 : -borderThickness}px`,\n width: itemLength !== undefined ? `${itemLength}px` : undefined,\n },\n ...idx >= data.length - 1 ? {} : {\n ...orientation === 'vertical' ? {\n marginBottom: `${itemPadding}px`,\n } : {\n marginRight: `${itemPadding}px`,\n },\n },\n })}\n data-index={idx}\n data={val}\n index={idx}\n isSelected={isSelectedAt(idx)}\n orientation={orientation}\n onClick={() => activateAt(idx)}\n />\n )}\n </Each>\n )}\n </div>\n )\n}) as <T>(props: ListProps<T> & { ref?: Ref<HTMLDivElement> }) => ReactElement\n"]}
1
+ {"version":3,"file":"List.js","sourceRoot":"/","sources":["List.tsx"],"names":[],"mappings":"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","sourcesContent":["import classNames from 'classnames'\nimport isDeepEqual from 'fast-deep-equal/react'\nimport React, { forwardRef, useEffect, useState, type ComponentType, type HTMLAttributes, type ReactElement, type Ref } from 'react'\nimport Each from './Each'\nimport usePrevious from './hooks/usePrevious'\nimport asClassNameDict from './utils/asClassNameDict'\nimport asStyleDict from './utils/asStyleDict'\nimport styles from './utils/styles'\n\ntype Orientation = 'horizontal' | 'vertical'\n\nexport type ListItemProps<T> = HTMLAttributes<HTMLElement> & {\n data: T\n index: number\n isSelected: boolean\n orientation: Orientation\n onCustomEvent?: (name: string, info?: any) => void\n}\n\nexport type ListProps<T> = HTMLAttributes<HTMLDivElement> & {\n /**\n * Thickness of item borders (in pixels). 0 indicates no borders.\n */\n borderThickness?: number\n\n /**\n * Generically typed data of each item.\n */\n data: T[]\n\n /**\n * Indicates if item selection can be toggled, i.e. they can be deselected if\n * selected again.\n */\n isSelectionTogglable?: boolean\n\n /**\n * Optional length (in pixels) of each item. Length refers to the height in\n * vertical orientation and width in horizontal orientation.\n */\n itemLength?: number\n\n /**\n * Padding between every item (in pixels).\n */\n itemPadding?: number\n\n /**\n * Orientation of the component.\n */\n orientation?: Orientation\n\n /**\n * The selected indices. If `selectionMode` is `single`, only only the first\n * value will be used.\n */\n selectedIndices?: number[]\n\n /**\n * Indicates the selection behavior:\n * - `none`: No selection at all.\n * - `single`: Only one item can be selected at a time.\n * - `multiple`: Multiple items can be selected at the same time.\n */\n selectionMode?: 'none' | 'single' | 'multiple'\n\n /**\n * React component type to be used to generate items for this list.\n */\n itemComponentType?: ComponentType<ListItemProps<T>>\n\n /**\n * Handler invoked when an item is activated.\n *\n * @param index Item index.\n */\n onActivateAt?: (index: number) => void\n\n /**\n * Handler invoked when an item is deselected.\n *\n * @param index Item index.\n */\n onDeselectAt?: (index: number) => void\n\n /**\n * Handler invoked when a custom event is dispatched from the item.\n *\n * @param index Index of the item.\n * @param eventName Name of the dispatched custom event.\n * @param eventInfo Optional info of the dispatched custom event.\n */\n onItemCustomEvent?: (index: number, eventName: string, eventInfo?: any) => void\n\n /**\n * Handler invoked when an item is selected.\n *\n * @param index Item index.\n */\n onSelectAt?: (index: number) => void\n\n /**\n * Handler invoked when the selected items changed.\n *\n * @param indices Indices of selected items.\n */\n onSelectionChange?: (indices: number[]) => void\n}\n\n/**\n * A scrollable list of selectable items. Items are generated based on the\n * provided React component type. The type of data passed to each item is\n * generic. This component supports both horizontal and vertical orientations.\n */\nexport default forwardRef(({\n className,\n style,\n borderThickness = 0,\n data,\n selectionMode = 'none',\n isSelectionTogglable = false,\n itemLength,\n itemPadding = 0,\n orientation = 'vertical',\n selectedIndices: externalSelectedIndices = [],\n itemComponentType: ItemComponent,\n onActivateAt,\n onDeselectAt,\n onItemCustomEvent,\n onSelectAt,\n onSelectionChange,\n ...props\n}, ref) => {\n const isIndexOutOfRange = (index: number) => {\n if (index >= data.length) return true\n if (index < 0) return true\n\n return false\n }\n\n const sanitizeSelectedIndices = (indices: number[]) => indices.sort().filter(t => !isIndexOutOfRange(t))\n\n const isSelectedAt = (index: number) => selectedIndices.indexOf(index) >= 0\n\n const toggleAt = (index: number) => {\n if (isSelectedAt(index)) {\n deselectAt(index)\n }\n else {\n selectAt(index)\n }\n }\n\n const selectAt = (index: number) => {\n if (isIndexOutOfRange(index) || isSelectedAt(index)) return\n\n switch (selectionMode) {\n case 'multiple':\n setSelectedIndices(prev => [...prev.filter(t => t !== index), index].sort())\n\n break\n case 'single':\n setSelectedIndices([index])\n\n break\n default:\n break\n }\n }\n\n const deselectAt = (index: number) => {\n if (isIndexOutOfRange(index) || !isSelectedAt(index)) return\n\n setSelectedIndices(prev => prev.filter(t => t !== index))\n }\n\n const activateAt = (index: number) => {\n if (selectionMode !== 'none') {\n if (isSelectionTogglable) {\n toggleAt(index)\n }\n else {\n selectAt(index)\n }\n }\n\n onActivateAt?.(index)\n }\n\n const [selectedIndices, setSelectedIndices] = useState(sanitizeSelectedIndices(externalSelectedIndices))\n const prevSelectedIndices = usePrevious(selectedIndices)\n\n useEffect(() => {\n const newValue = sanitizeSelectedIndices(externalSelectedIndices)\n\n if (isDeepEqual(newValue, selectedIndices)) return\n\n setSelectedIndices(newValue)\n }, [JSON.stringify(sanitizeSelectedIndices(externalSelectedIndices))])\n\n useEffect(() => {\n if (selectionMode === 'none') return\n\n const deselected = prevSelectedIndices?.filter(t => selectedIndices.indexOf(t) === -1) ?? []\n const selected = selectedIndices.filter(t => prevSelectedIndices?.indexOf(t) === -1)\n\n deselected.map(t => onDeselectAt?.(t))\n selected.map(t => onSelectAt?.(t))\n\n onSelectionChange?.(selectedIndices)\n }, [JSON.stringify(sanitizeSelectedIndices(selectedIndices))])\n\n const fixedClassNames = asClassNameDict({\n root: classNames(orientation, {\n togglable: isSelectionTogglable,\n }),\n item: classNames(orientation, {\n togglable: isSelectionTogglable,\n }),\n })\n\n const fixedStyles = asStyleDict({\n root: {\n alignItems: 'flex-start',\n counterReset: 'item-counter',\n display: 'flex',\n flex: '0 0 auto',\n flexDirection: orientation === 'horizontal' ? 'row' : 'column',\n justifyContent: 'flex-start',\n listStyle: 'none',\n },\n item: {\n borderWidth: `${borderThickness}px`,\n counterIncrement: 'item-counter',\n flex: '0 0 auto',\n ...orientation === 'vertical' ? {\n width: '100%',\n } : {\n height: '100%',\n },\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 {ItemComponent && (\n <Each in={data}>\n {(val, idx) => (\n <ItemComponent\n className={classNames(fixedClassNames.item, {\n selected: isSelectedAt(idx),\n })}\n style={styles(fixedStyles.item, {\n pointerEvents: isSelectionTogglable !== true && isSelectedAt(idx) ? 'none' : 'auto',\n ...orientation === 'vertical' ? {\n height: itemLength !== undefined ? `${itemLength}px` : undefined,\n marginTop: `${idx === 0 ? 0 : -borderThickness}px`,\n } : {\n marginLeft: `${idx === 0 ? 0 : -borderThickness}px`,\n width: itemLength !== undefined ? `${itemLength}px` : undefined,\n },\n ...idx >= data.length - 1 ? {} : {\n ...orientation === 'vertical' ? {\n marginBottom: `${itemPadding}px`,\n } : {\n marginRight: `${itemPadding}px`,\n },\n },\n })}\n data-index={idx}\n data={val}\n index={idx}\n isSelected={isSelectedAt(idx)}\n orientation={orientation}\n onCustomEvent={(name, info) => onItemCustomEvent?.(idx, name, info)}\n onClick={() => activateAt(idx)}\n />\n )}\n </Each>\n )}\n </div>\n )\n}) as <T>(props: ListProps<T> & { ref?: Ref<HTMLDivElement> }) => ReactElement\n"]}