@spaced-out/ui-design-system 0.1.93 → 0.1.94-beta.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.
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.Menu = void 0;
7
7
  var React = _interopRequireWildcard(require("react"));
8
+ var _reactWindow = require("react-window");
8
9
  var _classify = require("../../utils/classify");
9
10
  var _menu = require("../../utils/menu");
10
11
  var _SearchInput = require("../SearchInput");
@@ -15,6 +16,10 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
15
16
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
16
17
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
17
18
  function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
19
+ const menuSizeMedium = 276,
20
+ menuSizeSmall = 228;
21
+ const buttonSizeMedium = 40,
22
+ buttonSizeSmall = 32;
18
23
  const RenderOption = _ref => {
19
24
  let {
20
25
  options,
@@ -25,15 +30,45 @@ const RenderOption = _ref => {
25
30
  ...restProps
26
31
  } = _ref;
27
32
  const {
28
- allowSearch
33
+ allowSearch,
34
+ size,
35
+ virtualization = {
36
+ enable: false,
37
+ menuHeight: null,
38
+ itemHeight: null
39
+ }
29
40
  } = restProps;
30
41
  if (options && Array.isArray(options) && options.length) {
31
42
  const optionsFiltered = !allowSearch ? options : (0, _menu.getFilteredOptionsFromSearchText)(options, searchText);
32
43
  const resultText = !allowSearch ? '' : (0, _menu.getFilteredOptionsResultText)(optionsFiltered);
44
+ const {
45
+ enable: isVirtualizationEnabled,
46
+ menuHeight,
47
+ itemHeight
48
+ } = virtualization;
33
49
  return /*#__PURE__*/React.createElement(React.Fragment, null, allowSearch && /*#__PURE__*/React.createElement(_Text.FormLabelSmall, {
34
50
  className: _MenuModule.default.filterOptionsResultText,
35
51
  color: "tertiary"
36
- }, resultText), optionsFiltered.map((option, idx) => /*#__PURE__*/React.createElement(React.Fragment, {
52
+ }, resultText), virtualization && isVirtualizationEnabled ? /*#__PURE__*/React.createElement(_reactWindow.FixedSizeList, {
53
+ height: menuHeight || (size === 'medium' ? menuSizeMedium : menuSizeSmall),
54
+ itemSize: itemHeight || (size === 'medium' ? buttonSizeMedium : buttonSizeSmall),
55
+ itemCount: optionsFiltered.length
56
+ }, _ref2 => {
57
+ let {
58
+ index: idx,
59
+ style
60
+ } = _ref2;
61
+ const buttonOption = optionsFiltered[idx];
62
+ return /*#__PURE__*/React.createElement(React.Fragment, {
63
+ key: buttonOption.key
64
+ }, /*#__PURE__*/React.createElement(_MenuOptionButton.MenuOptionButton, _extends({
65
+ option: buttonOption,
66
+ classNames: classNames,
67
+ style: style
68
+ }, restProps, {
69
+ isLastItem: idx === optionsFiltered.length - 1
70
+ })));
71
+ }) : optionsFiltered.map((option, idx) => /*#__PURE__*/React.createElement(React.Fragment, {
37
72
  key: option.key
38
73
  }, /*#__PURE__*/React.createElement(_MenuOptionButton.MenuOptionButton, _extends({
39
74
  option: option,
@@ -93,9 +128,17 @@ const Menu = /*#__PURE__*/React.forwardRef((props, ref) => {
93
128
  size = 'medium',
94
129
  width,
95
130
  isFluid = true,
96
- allowSearch
131
+ allowSearch,
132
+ virtualization = {
133
+ enable: false,
134
+ menuHeight: null,
135
+ itemHeight: null
136
+ }
97
137
  } = props;
98
138
  const [searchText, setSearchText] = React.useState('');
139
+ const {
140
+ menuHeight
141
+ } = virtualization;
99
142
  return /*#__PURE__*/React.createElement("div", {
100
143
  className: (0, _classify.classify)(_MenuModule.default.menuCard, {
101
144
  [_MenuModule.default.fluid]: isFluid,
@@ -103,7 +146,8 @@ const Menu = /*#__PURE__*/React.forwardRef((props, ref) => {
103
146
  [_MenuModule.default.small]: size === 'small'
104
147
  }, classNames?.wrapper),
105
148
  style: {
106
- width
149
+ width,
150
+ maxHeight: menuHeight ? menuHeight + 'px' : ''
107
151
  },
108
152
  ref: ref
109
153
  }, allowSearch && /*#__PURE__*/React.createElement(_SearchInput.SearchInput, {
@@ -1,5 +1,7 @@
1
1
  // @flow strict
2
2
  import * as React from 'react';
3
+ // $FlowIssue[nonstrict-import] react-window
4
+ import {FixedSizeList} from 'react-window';
3
5
 
4
6
  import {classify} from '../../utils/classify';
5
7
  import {
@@ -31,6 +33,12 @@ type OptionClassNames = $ReadOnly<{
31
33
  wrapper?: string,
32
34
  }>;
33
35
 
36
+ export type Virtualization = $ReadOnly<{
37
+ enable: boolean,
38
+ itemHeight?: number,
39
+ menuHeight?: number,
40
+ }>;
41
+
34
42
  export type MenuOption = {
35
43
  key: string,
36
44
  classNames?: OptionClassNames,
@@ -68,6 +76,8 @@ export type BaseMenuProps = {
68
76
  // A function that resolves the secondaryLabel for a MenuOption.
69
77
  // It takes a MenuOption as a parameter and returns either a string or a React Node.
70
78
  resolveSecondaryLabel?: (option: MenuOption) => string | React.Node,
79
+ // When virtualization is enabled, the MenuOptionButtons will be rendered only when they are present in the Menu's viewport
80
+ virtualization?: Virtualization,
71
81
  };
72
82
 
73
83
  export type MenuOptionTypes = {
@@ -95,6 +105,12 @@ export type RenderOptionProps = {
95
105
  searchText?: string,
96
106
  };
97
107
 
108
+ const menuSizeMedium = 276,
109
+ menuSizeSmall = 228;
110
+
111
+ const buttonSizeMedium = 40,
112
+ buttonSizeSmall = 32;
113
+
98
114
  const RenderOption = ({
99
115
  options,
100
116
  composeOptions,
@@ -103,7 +119,15 @@ const RenderOption = ({
103
119
  searchText = '',
104
120
  ...restProps
105
121
  }: RenderOptionProps): React.Node => {
106
- const {allowSearch} = restProps;
122
+ const {
123
+ allowSearch,
124
+ size,
125
+ virtualization = {
126
+ enable: false,
127
+ menuHeight: null,
128
+ itemHeight: null,
129
+ },
130
+ } = restProps;
107
131
  if (options && Array.isArray(options) && options.length) {
108
132
  const optionsFiltered = !allowSearch
109
133
  ? options
@@ -112,6 +136,12 @@ const RenderOption = ({
112
136
  ? ''
113
137
  : getFilteredOptionsResultText(optionsFiltered);
114
138
 
139
+ const {
140
+ enable: isVirtualizationEnabled,
141
+ menuHeight,
142
+ itemHeight,
143
+ } = virtualization;
144
+
115
145
  return (
116
146
  <>
117
147
  {allowSearch && (
@@ -122,16 +152,44 @@ const RenderOption = ({
122
152
  {resultText}
123
153
  </FormLabelSmall>
124
154
  )}
125
- {optionsFiltered.map((option, idx) => (
126
- <React.Fragment key={option.key}>
127
- <MenuOptionButton
128
- option={option}
129
- classNames={classNames}
130
- {...restProps}
131
- isLastItem={idx === optionsFiltered.length - 1}
132
- />
133
- </React.Fragment>
134
- ))}
155
+ {virtualization && isVirtualizationEnabled ? (
156
+ <FixedSizeList
157
+ height={
158
+ menuHeight || (size === 'medium' ? menuSizeMedium : menuSizeSmall)
159
+ }
160
+ itemSize={
161
+ itemHeight ||
162
+ (size === 'medium' ? buttonSizeMedium : buttonSizeSmall)
163
+ }
164
+ itemCount={optionsFiltered.length}
165
+ >
166
+ {({index: idx, style}) => {
167
+ const buttonOption = optionsFiltered[idx];
168
+ return (
169
+ <React.Fragment key={buttonOption.key}>
170
+ <MenuOptionButton
171
+ option={buttonOption}
172
+ classNames={classNames}
173
+ style={style}
174
+ {...restProps}
175
+ isLastItem={idx === optionsFiltered.length - 1}
176
+ />
177
+ </React.Fragment>
178
+ );
179
+ }}
180
+ </FixedSizeList>
181
+ ) : (
182
+ optionsFiltered.map((option, idx) => (
183
+ <React.Fragment key={option.key}>
184
+ <MenuOptionButton
185
+ option={option}
186
+ classNames={classNames}
187
+ {...restProps}
188
+ isLastItem={idx === optionsFiltered.length - 1}
189
+ />
190
+ </React.Fragment>
191
+ ))
192
+ )}
135
193
  </>
136
194
  );
137
195
  }
@@ -248,9 +306,14 @@ export const Menu: React$AbstractComponent<MenuProps, HTMLDivElement> =
248
306
  width,
249
307
  isFluid = true,
250
308
  allowSearch,
309
+ virtualization = {
310
+ enable: false,
311
+ menuHeight: null,
312
+ itemHeight: null,
313
+ },
251
314
  } = props;
252
315
  const [searchText, setSearchText] = React.useState('');
253
-
316
+ const {menuHeight} = virtualization;
254
317
  return (
255
318
  <div
256
319
  className={classify(
@@ -262,7 +325,10 @@ export const Menu: React$AbstractComponent<MenuProps, HTMLDivElement> =
262
325
  },
263
326
  classNames?.wrapper,
264
327
  )}
265
- style={{width}}
328
+ style={{
329
+ width,
330
+ maxHeight: menuHeight ? menuHeight + 'px' : '',
331
+ }}
266
332
  ref={ref}
267
333
  >
268
334
  {allowSearch && (
@@ -30,7 +30,8 @@ const MenuOptionButton = props => {
30
30
  isLastItem,
31
31
  onTabOut,
32
32
  resolveLabel,
33
- resolveSecondaryLabel
33
+ resolveSecondaryLabel,
34
+ style
34
35
  } = props;
35
36
  const {
36
37
  key,
@@ -79,6 +80,7 @@ const MenuOptionButton = props => {
79
80
  [_MenuModule.default.withIconLeft]: !!iconLeft,
80
81
  [_MenuModule.default.withIconRight]: !!iconRight
81
82
  }, classNames?.option, optionClassNames?.wrapper),
83
+ style: style,
82
84
  disabled: menuDisabled || disabled,
83
85
  onClick: e => onSelect && onSelect(option, e),
84
86
  autoFocus: selectedOption?.key === key
@@ -17,6 +17,7 @@ export type MenuOptionProps = {
17
17
  ...BaseMenuProps,
18
18
  option: MenuOption,
19
19
  isLastItem?: boolean,
20
+ style?: mixed,
20
21
  };
21
22
 
22
23
  export const MenuOptionButton = (props: MenuOptionProps): React.Node => {
@@ -35,6 +36,7 @@ export const MenuOptionButton = (props: MenuOptionProps): React.Node => {
35
36
  onTabOut,
36
37
  resolveLabel,
37
38
  resolveSecondaryLabel,
39
+ style,
38
40
  } = props;
39
41
  const {
40
42
  key,
@@ -97,6 +99,7 @@ export const MenuOptionButton = (props: MenuOptionProps): React.Node => {
97
99
  classNames?.option,
98
100
  optionClassNames?.wrapper,
99
101
  )}
102
+ style={style}
100
103
  disabled={menuDisabled || disabled}
101
104
  onClick={(e) => onSelect && onSelect(option, e)}
102
105
  autoFocus={selectedOption?.key === key}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spaced-out/ui-design-system",
3
- "version": "0.1.93",
3
+ "version": "0.1.94-beta.0",
4
4
  "main": "index.js",
5
5
  "description": "Sense UI components library",
6
6
  "author": {
@@ -50,7 +50,8 @@
50
50
  "highcharts-react-official": "^3.2.1",
51
51
  "lodash": "^4.17.21",
52
52
  "moment-timezone": "^0.5.45",
53
- "react-dropzone": "^14.2.3"
53
+ "react-dropzone": "^14.2.3",
54
+ "react-window": "^1.8.10"
54
55
  },
55
56
  "devDependencies": {
56
57
  "@babel/cli": "^7.18.10",