@monolith-forensics/monolith-ui 2.1.1-dev.3 → 2.1.1-dev.5

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.
@@ -10,7 +10,7 @@ const getNumericCssLength = (value) => {
10
10
  const pixelMatch = value.trim().match(/^(\d+(?:\.\d+)?)px$/);
11
11
  return pixelMatch ? Number(pixelMatch[1]) : undefined;
12
12
  };
13
- export const DropDownMenu = ({ data, children, defaultValue, value, variant, arrow, size, searchable, grouped, onAddNew, loading, loadingMore, onScroll, onScrollToTop, onScrollToBottom, onSearch, manualSearch, multiselect, enableSelectAll, enableSelectedOptionStyling, renderOption, dynamicOptionHeight, onItemSelect, onChange, buttonProps, TooltipContent, dropDownProps, disabled, }) => {
13
+ export const DropDownMenu = ({ data, children, defaultValue, value, variant, arrow, size, searchable, grouped, onAddNew, loading, loadingMore, onScroll, onScrollToTop, onScrollToBottom, onSearch, searchDebounceMs, manualSearch, multiselect, enableSelectAll, enableSelectedOptionStyling, renderOption, dynamicOptionHeight, onItemSelect, onChange, buttonProps, TooltipContent, dropDownProps, disabled, }) => {
14
14
  var _a, _b, _c, _d, _e;
15
15
  const isObjectArray = [
16
16
  ...(data || []),
@@ -48,5 +48,5 @@ export const DropDownMenu = ({ data, children, defaultValue, value, variant, arr
48
48
  const handleScrollToBottom = (e) => {
49
49
  onScrollToBottom === null || onScrollToBottom === void 0 ? void 0 : onScrollToBottom(e);
50
50
  };
51
- return (_jsx(Menu, { label: children, disabled: disabled, arrow: arrow, buttonSize: size, variant: variant, multiselect: multiselect, buttonProps: buttonProps, onMenuClose: handleMenuClose, dropDownProps: dropDownProps, children: _jsx(StyledInnerItemContainer, { children: _jsx(MenuItemList, { menuItems: data, searchable: searchable, grouped: grouped, onAddNew: onAddNew, onSearch: onSearch, manualSearch: manualSearch, dynamicOptionHeight: dynamicOptionHeight, maxDropdownHeight: maxDropdownHeight, selected: selected, TooltipContent: TooltipContent, multiselect: multiselect, enableSelectAll: enableSelectAll, enableSelectedOptionStyling: enableSelectedOptionStyling, size: size, loading: loading, loadingMore: loadingMore, handleAddItem: handleAddItem, handleRemoveItem: handleRemoveItem, handleSetSelected: handleSetSelected, onItemSelect: onItemSelect, renderOption: renderOption, onScroll: onScroll, onScrollToTop: onScrollToTop, onScrollToBottom: handleScrollToBottom }) }) }));
51
+ return (_jsx(Menu, { label: children, disabled: disabled, arrow: arrow, buttonSize: size, variant: variant, multiselect: multiselect, buttonProps: buttonProps, onMenuClose: handleMenuClose, dropDownProps: dropDownProps, children: _jsx(StyledInnerItemContainer, { children: _jsx(MenuItemList, { menuItems: data, searchable: searchable, grouped: grouped, onAddNew: onAddNew, onSearch: onSearch, searchDebounceMs: searchDebounceMs, manualSearch: manualSearch, dynamicOptionHeight: dynamicOptionHeight, maxDropdownHeight: maxDropdownHeight, selected: selected, TooltipContent: TooltipContent, multiselect: multiselect, enableSelectAll: enableSelectAll, enableSelectedOptionStyling: enableSelectedOptionStyling, size: size, loading: loading, loadingMore: loadingMore, handleAddItem: handleAddItem, handleRemoveItem: handleRemoveItem, handleSetSelected: handleSetSelected, onItemSelect: onItemSelect, renderOption: renderOption, onScroll: onScroll, onScrollToTop: onScrollToTop, onScrollToBottom: handleScrollToBottom }) }) }));
52
52
  };
@@ -6,6 +6,7 @@ export declare const MenuItemList: React.FC<{
6
6
  searchable?: boolean;
7
7
  searchValue?: string;
8
8
  onSearch?: (value: string) => void;
9
+ searchDebounceMs?: number;
9
10
  manualSearch?: boolean;
10
11
  dynamicOptionHeight?: boolean;
11
12
  selected?: DropDownItem[];
@@ -128,22 +128,20 @@ const MeasuredRow = ({ children, index, setItemSize, style }) => {
128
128
  }, [children, index, setItemSize]);
129
129
  return (_jsx("div", { style: Object.assign(Object.assign({}, style), { overflow: "visible" }), children: _jsx("div", { ref: rowRef, children: children }) }));
130
130
  };
131
- export const MenuItemList = ({ menuItems, searchable, onSearch, manualSearch, dynamicOptionHeight, selected, TooltipContent, multiselect, enableSelectAll, enableSelectedOptionStyling, grouped, onAddNew, size, handleAddItem, handleRemoveItem, handleSetSelected, onItemSelect, renderOption, onScroll, onScrollToTop, onScrollToBottom, maxDropdownHeight = DEFAULT_DROPDOWN_MAX_HEIGHT, loading, loadingMore, }) => {
131
+ export const MenuItemList = ({ menuItems, searchable, onSearch, searchDebounceMs = 150, manualSearch, dynamicOptionHeight, selected, TooltipContent, multiselect, enableSelectAll, enableSelectedOptionStyling, grouped, onAddNew, size, handleAddItem, handleRemoveItem, handleSetSelected, onItemSelect, renderOption, onScroll, onScrollToTop, onScrollToBottom, maxDropdownHeight = DEFAULT_DROPDOWN_MAX_HEIGHT, loading, loadingMore, }) => {
132
132
  const [searchValue, setSearchValue] = useState("");
133
- const targetElm = useRef(null);
134
133
  const listElm = useRef(null);
135
134
  const fixedListRef = useRef(null);
136
135
  const variableListRef = useRef(null);
137
136
  const hasHandledInitialSelectedScroll = useRef(false);
138
137
  const itemSizeMap = useRef({});
139
- const [viewPortDimensions, setViewPortDimensions] = useState({
140
- width: 0,
141
- height: 0,
142
- });
143
138
  const [, setMeasurementRevision] = useState(0);
144
- const handleSearch = useDebouncedCallback((e) => {
145
- setSearchValue(e.target.value);
146
- }, 150);
139
+ const handleSearch = useDebouncedCallback((value) => {
140
+ setSearchValue(value);
141
+ }, searchDebounceMs);
142
+ const handleExternalSearch = useDebouncedCallback((value) => {
143
+ onSearch === null || onSearch === void 0 ? void 0 : onSearch(value);
144
+ }, searchDebounceMs);
147
145
  const handleItemClick = (item, isSelected) => {
148
146
  var _a;
149
147
  if (multiselect) {
@@ -271,32 +269,8 @@ export const MenuItemList = ({ menuItems, searchable, onSearch, manualSearch, dy
271
269
  DROPDOWN_CONTENT_VERTICAL_PADDING -
272
270
  searchHeight -
273
271
  selectAllHeight);
274
- const availableHeight = viewPortDimensions.height || maxListHeight;
275
- const height = Math.min(estimatedHeight, availableHeight, maxListHeight);
272
+ const height = Math.min(estimatedHeight, maxListHeight);
276
273
  const width = "100%";
277
- useLayoutEffect(() => {
278
- const target = targetElm.current;
279
- if (!target)
280
- return;
281
- const updateDimensions = () => {
282
- const nextDimensions = target.getBoundingClientRect();
283
- setViewPortDimensions((currentDimensions) => {
284
- const width = Math.ceil(nextDimensions.width);
285
- const height = Math.floor(nextDimensions.height);
286
- if (currentDimensions.width === width &&
287
- currentDimensions.height === height) {
288
- return currentDimensions;
289
- }
290
- return { width, height };
291
- });
292
- };
293
- updateDimensions();
294
- if (typeof ResizeObserver === "undefined")
295
- return;
296
- const observer = new ResizeObserver(updateDimensions);
297
- observer.observe(target);
298
- return () => observer.disconnect();
299
- }, [displayItemsKey, isLoading]);
300
274
  const setItemSize = useCallback((index, measuredSize) => {
301
275
  var _a;
302
276
  if (itemSizeMap.current[index] === measuredSize)
@@ -369,10 +343,11 @@ export const MenuItemList = ({ menuItems, searchable, onSearch, manualSearch, dy
369
343
  (typeof item === "string" || typeof item === "number" ? item : null) }, index));
370
344
  };
371
345
  return (_jsxs(MenuItemListRoot, { children: [searchable && (_jsx(SearchInput, { variant: "outlined", size: size, placeholder: "Search", defaultValue: searchValue, onChange: (e) => {
346
+ const nextValue = e.target.value;
372
347
  if (!manualSearch) {
373
- handleSearch(e);
348
+ handleSearch(nextValue);
374
349
  }
375
- onSearch === null || onSearch === void 0 ? void 0 : onSearch(e.target.value);
350
+ handleExternalSearch(nextValue);
376
351
  } })), multiselect && enableSelectAll && selectableItems.length > 0 && (_jsx(MenuItem, { className: "MenuItem", size: size, multiselect: true, leftSection: _jsx(CheckBox, { value: allSelectableItemsSelected, partialCheck: someSelectableItemsSelected, size: size, onChange: handleToggleSelectAll }), onClick: (e) => {
377
352
  e.preventDefault();
378
353
  e.stopPropagation();
@@ -385,7 +360,7 @@ export const MenuItemList = ({ menuItems, searchable, onSearch, manualSearch, dy
385
360
  alignItems: "center",
386
361
  height: "100%",
387
362
  padding: "10px 0",
388
- }, children: [_jsx("div", { style: { fontSize: `${sizeTokens.supportingFontSize}px` }, children: "Loading..." }), _jsx(Loader, {})] })), !isLoading && (_jsx(ListViewPort, { ref: targetElm, children: dynamicListEnabled ? (_jsx(VariableSizeList, { ref: variableListRef, itemData: displayItems, overscanCount: overscanCount, height: height, width: width, itemCount: itemCount, itemSize: getDynamicItemSize, outerElementType: ListScroller, outerRef: listElm, children: ({ data, index, style }) => {
363
+ }, children: [_jsx("div", { style: { fontSize: `${sizeTokens.supportingFontSize}px` }, children: "Loading..." }), _jsx(Loader, {})] })), !isLoading && (_jsx(ListViewPort, { children: dynamicListEnabled ? (_jsx(VariableSizeList, { ref: variableListRef, itemData: displayItems, overscanCount: overscanCount, height: height, width: width, itemCount: itemCount, itemSize: getDynamicItemSize, outerElementType: ListScroller, outerRef: listElm, children: ({ data, index, style }) => {
389
364
  const item = data === null || data === void 0 ? void 0 : data[index];
390
365
  if (!item)
391
366
  return null;
@@ -43,6 +43,7 @@ export type DropDownMenuProps = {
43
43
  onScrollToBottom?: (e: Event) => void;
44
44
  onSearch?: (value: string) => void;
45
45
  searchable?: boolean;
46
+ searchDebounceMs?: number;
46
47
  manualSearch?: boolean;
47
48
  grouped?: boolean;
48
49
  dynamicOptionHeight?: boolean;
@@ -55,6 +55,7 @@ export interface FilterDefinition {
55
55
  isoString?: boolean;
56
56
  placeholder?: string;
57
57
  selectOptions?: DropDownItem[];
58
+ manualSearch?: boolean;
58
59
  superDatePickerProps?: Omit<SuperDatePickerProps, "defaultValue" | "format" | "onChange" | "size" | "value" | "variant" | "width">;
59
60
  dropDownOptions?: {
60
61
  style?: React.CSSProperties;
@@ -1,7 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
3
3
  import { useTheme } from "styled-components";
4
- import { useDebouncedCallback } from "use-debounce";
5
4
  import { DropDownMenu } from "../../DropDownMenu";
6
5
  import { QUERY_FILTER_SELECT_VALUE_LABEL } from "../QueryFilter.constants";
7
6
  const DEFAULT_FILTER_OPTIONS_STALE_TIME = 5 * 60 * 1000;
@@ -156,12 +155,9 @@ const useFilterOptionsQuery = (query) => {
156
155
  };
157
156
  };
158
157
  export const MultiSelectEditor = ({ rule, filterDef, onChange }) => {
159
- var _a, _b;
158
+ var _a, _b, _c;
160
159
  const theme = useTheme();
161
160
  const optionsQuery = useFilterOptionsQuery(filterDef === null || filterDef === void 0 ? void 0 : filterDef.query);
162
- const handleAsyncSearch = useDebouncedCallback((value) => {
163
- optionsQuery.setSearch(value);
164
- }, 150);
165
161
  const handleChange = (selected, diff) => {
166
162
  onChange === null || onChange === void 0 ? void 0 : onChange(selected, diff);
167
163
  };
@@ -175,6 +171,7 @@ export const MultiSelectEditor = ({ rule, filterDef, onChange }) => {
175
171
  if (Array.isArray(rule.value) && rule.value.length > 1) {
176
172
  display = `${rule.value.length} ${(filterDef === null || filterDef === void 0 ? void 0 : filterDef.pluralLabel) || "Values"}`;
177
173
  }
174
+ const manualSearch = (_b = filterDef === null || filterDef === void 0 ? void 0 : filterDef.manualSearch) !== null && _b !== void 0 ? _b : !!(filterDef === null || filterDef === void 0 ? void 0 : filterDef.query);
178
175
  return (_jsx(DropDownMenu, { data: dropDownOptions, variant: "outlined", multiselect: true, searchable: true, size: "xs", buttonProps: {
179
176
  title: QUERY_FILTER_SELECT_VALUE_LABEL,
180
177
  variant: "contained",
@@ -194,8 +191,8 @@ export const MultiSelectEditor = ({ rule, filterDef, onChange }) => {
194
191
  : theme.palette.text.secondary,
195
192
  },
196
193
  }, dropDownProps: {
197
- style: Object.assign({ width: 200, maxWidth: 400 }, (_b = filterDef === null || filterDef === void 0 ? void 0 : filterDef.dropDownOptions) === null || _b === void 0 ? void 0 : _b.style),
198
- }, loading: optionsQuery.isLoading && dropDownOptions.length === 0, loadingMore: optionsQuery.isFetchingNextPage, value: selected, onChange: handleChange, manualSearch: !!(filterDef === null || filterDef === void 0 ? void 0 : filterDef.query), onSearch: (filterDef === null || filterDef === void 0 ? void 0 : filterDef.query)
199
- ? (value) => handleAsyncSearch(value)
194
+ style: Object.assign({ width: 200, maxWidth: 400 }, (_c = filterDef === null || filterDef === void 0 ? void 0 : filterDef.dropDownOptions) === null || _c === void 0 ? void 0 : _c.style),
195
+ }, loading: optionsQuery.isLoading && dropDownOptions.length === 0, loadingMore: optionsQuery.isFetchingNextPage, value: selected, onChange: handleChange, manualSearch: manualSearch, onSearch: (filterDef === null || filterDef === void 0 ? void 0 : filterDef.query) && manualSearch
196
+ ? (value) => optionsQuery.setSearch(value)
200
197
  : undefined, onScrollToBottom: (filterDef === null || filterDef === void 0 ? void 0 : filterDef.query) ? optionsQuery.loadNextPage : undefined, children: display }));
201
198
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monolith-forensics/monolith-ui",
3
- "version": "2.1.1-dev.3",
3
+ "version": "2.1.1-dev.5",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./dist/index.d.ts",
6
6
  "author": "Matt Danner (Monolith Forensics LLC)",