@itwin/itwinui-react 1.45.0 → 1.46.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/cjs/core/Breadcrumbs/Breadcrumbs.d.ts +116 -0
  3. package/cjs/core/Breadcrumbs/Breadcrumbs.js +2 -3
  4. package/cjs/core/ButtonGroup/ButtonGroup.js +1 -1
  5. package/cjs/core/ColorPicker/ColorSwatch.d.ts +1 -1
  6. package/cjs/core/DatePicker/DatePicker.d.ts +24 -4
  7. package/cjs/core/DatePicker/DatePicker.js +116 -19
  8. package/cjs/core/Dialog/Dialog.d.ts +5 -5
  9. package/cjs/core/Dialog/Dialog.js +38 -6
  10. package/cjs/core/Dialog/DialogBackdrop.d.ts +2 -2
  11. package/cjs/core/Dialog/DialogBackdrop.js +2 -2
  12. package/cjs/core/Dialog/DialogContext.d.ts +31 -0
  13. package/cjs/core/Dialog/DialogDragContext.d.ts +8 -0
  14. package/cjs/core/Dialog/DialogDragContext.js +28 -0
  15. package/cjs/core/Dialog/DialogMain.d.ts +2 -2
  16. package/cjs/core/Dialog/DialogMain.js +46 -6
  17. package/cjs/core/Dialog/DialogTitleBar.d.ts +2 -2
  18. package/cjs/core/Dialog/DialogTitleBar.js +12 -2
  19. package/cjs/core/Modal/Modal.js +1 -1
  20. package/cjs/core/Table/Table.d.ts +6 -0
  21. package/cjs/core/Table/Table.js +51 -6
  22. package/cjs/core/Table/actionHandlers/index.d.ts +1 -1
  23. package/cjs/core/Table/actionHandlers/index.js +2 -1
  24. package/cjs/core/Table/actionHandlers/resizeHandler.d.ts +2 -0
  25. package/cjs/core/Table/actionHandlers/selectHandler.d.ts +5 -0
  26. package/cjs/core/Table/actionHandlers/selectHandler.js +35 -2
  27. package/cjs/core/index.d.ts +3 -1
  28. package/cjs/core/index.js +6 -3
  29. package/cjs/core/utils/components/Resizer.d.ts +31 -0
  30. package/cjs/core/utils/components/Resizer.js +206 -0
  31. package/cjs/core/utils/components/VirtualScroll.js +26 -24
  32. package/cjs/core/utils/components/index.d.ts +1 -0
  33. package/cjs/core/utils/components/index.js +1 -0
  34. package/cjs/core/utils/functions/index.d.ts +1 -0
  35. package/cjs/core/utils/functions/index.js +1 -0
  36. package/cjs/core/utils/functions/styles.d.ts +6 -0
  37. package/cjs/core/utils/functions/styles.js +21 -0
  38. package/cjs/core/utils/hooks/useContainerWidth.d.ts +1 -1
  39. package/cjs/core/utils/hooks/useDragAndDrop.d.ts +14 -0
  40. package/cjs/core/utils/hooks/useDragAndDrop.js +110 -0
  41. package/cjs/core/utils/hooks/useEventListener.d.ts +1 -1
  42. package/cjs/core/utils/hooks/useOverflow.d.ts +1 -1
  43. package/cjs/core/utils/hooks/useResizeObserver.d.ts +1 -1
  44. package/cjs/types/react-table-config.d.ts +2 -1
  45. package/esm/core/Breadcrumbs/Breadcrumbs.d.ts +116 -0
  46. package/esm/core/Breadcrumbs/Breadcrumbs.js +2 -3
  47. package/esm/core/ButtonGroup/ButtonGroup.js +1 -1
  48. package/esm/core/ColorPicker/ColorSwatch.d.ts +1 -1
  49. package/esm/core/DatePicker/DatePicker.d.ts +24 -4
  50. package/esm/core/DatePicker/DatePicker.js +116 -19
  51. package/esm/core/Dialog/Dialog.d.ts +5 -5
  52. package/esm/core/Dialog/Dialog.js +37 -5
  53. package/esm/core/Dialog/DialogBackdrop.d.ts +2 -2
  54. package/esm/core/Dialog/DialogBackdrop.js +2 -2
  55. package/esm/core/Dialog/DialogContext.d.ts +31 -0
  56. package/esm/core/Dialog/DialogDragContext.d.ts +8 -0
  57. package/esm/core/Dialog/DialogDragContext.js +21 -0
  58. package/esm/core/Dialog/DialogMain.d.ts +2 -2
  59. package/esm/core/Dialog/DialogMain.js +47 -7
  60. package/esm/core/Dialog/DialogTitleBar.d.ts +2 -2
  61. package/esm/core/Dialog/DialogTitleBar.js +12 -2
  62. package/esm/core/Modal/Modal.js +1 -1
  63. package/esm/core/Table/Table.d.ts +6 -0
  64. package/esm/core/Table/Table.js +53 -8
  65. package/esm/core/Table/actionHandlers/index.d.ts +1 -1
  66. package/esm/core/Table/actionHandlers/index.js +1 -1
  67. package/esm/core/Table/actionHandlers/resizeHandler.d.ts +2 -0
  68. package/esm/core/Table/actionHandlers/selectHandler.d.ts +5 -0
  69. package/esm/core/Table/actionHandlers/selectHandler.js +33 -1
  70. package/esm/core/index.d.ts +3 -1
  71. package/esm/core/index.js +2 -1
  72. package/esm/core/utils/components/Resizer.d.ts +31 -0
  73. package/esm/core/utils/components/Resizer.js +199 -0
  74. package/esm/core/utils/components/VirtualScroll.js +26 -24
  75. package/esm/core/utils/components/index.d.ts +1 -0
  76. package/esm/core/utils/components/index.js +1 -0
  77. package/esm/core/utils/functions/index.d.ts +1 -0
  78. package/esm/core/utils/functions/index.js +1 -0
  79. package/esm/core/utils/functions/styles.d.ts +6 -0
  80. package/esm/core/utils/functions/styles.js +17 -0
  81. package/esm/core/utils/hooks/useContainerWidth.d.ts +1 -1
  82. package/esm/core/utils/hooks/useDragAndDrop.d.ts +14 -0
  83. package/esm/core/utils/hooks/useDragAndDrop.js +103 -0
  84. package/esm/core/utils/hooks/useEventListener.d.ts +1 -1
  85. package/esm/core/utils/hooks/useOverflow.d.ts +1 -1
  86. package/esm/core/utils/hooks/useResizeObserver.d.ts +1 -1
  87. package/esm/types/react-table-config.d.ts +2 -1
  88. package/package.json +1 -1
@@ -26,10 +26,12 @@ var __rest = (this && this.__rest) || function (s, e) {
26
26
  *--------------------------------------------------------------------------------------------*/
27
27
  import React from 'react';
28
28
  import cx from 'classnames';
29
- import { FocusTrap, useMergedRefs, useTheme } from '../utils';
29
+ import { FocusTrap, getTranslateValues, useLatestRef, Resizer, useMergedRefs, useTheme, } from '../utils';
30
30
  import '@itwin/itwinui-css/css/dialog.css';
31
31
  import { useDialogContext } from './DialogContext';
32
32
  import { CSSTransition } from 'react-transition-group';
33
+ import { DialogDragContext } from './DialogDragContext';
34
+ import useDragAndDrop from '../utils/hooks/useDragAndDrop';
33
35
  /**
34
36
  * Dialog component which can wrap any content.
35
37
  * @example
@@ -52,14 +54,19 @@ import { CSSTransition } from 'react-transition-group';
52
54
  */
53
55
  export var DialogMain = React.forwardRef(function (props, ref) {
54
56
  var dialogContext = useDialogContext();
55
- var className = props.className, children = props.children, _a = props.styleType, styleType = _a === void 0 ? 'default' : _a, _b = props.isOpen, isOpen = _b === void 0 ? dialogContext.isOpen : _b, _c = props.isDismissible, isDismissible = _c === void 0 ? dialogContext.isDismissible : _c, _d = props.onClose, onClose = _d === void 0 ? dialogContext.onClose : _d, _e = props.closeOnEsc, closeOnEsc = _e === void 0 ? dialogContext.closeOnEsc : _e, _f = props.trapFocus, trapFocus = _f === void 0 ? dialogContext.trapFocus : _f, _g = props.preventDocumentScroll, preventDocumentScroll = _g === void 0 ? dialogContext.preventDocumentScroll : _g, onKeyDown = props.onKeyDown, rest = __rest(props, ["className", "children", "styleType", "isOpen", "isDismissible", "onClose", "closeOnEsc", "trapFocus", "preventDocumentScroll", "onKeyDown"]);
57
+ var className = props.className, children = props.children, _a = props.styleType, styleType = _a === void 0 ? 'default' : _a, _b = props.isOpen, isOpen = _b === void 0 ? dialogContext.isOpen : _b, _c = props.isDismissible, isDismissible = _c === void 0 ? dialogContext.isDismissible : _c, _d = props.onClose, onClose = _d === void 0 ? dialogContext.onClose : _d, _e = props.closeOnEsc, closeOnEsc = _e === void 0 ? dialogContext.closeOnEsc : _e, _f = props.trapFocus, trapFocus = _f === void 0 ? dialogContext.trapFocus : _f, _g = props.setFocus, setFocus = _g === void 0 ? dialogContext.setFocus : _g, _h = props.preventDocumentScroll, preventDocumentScroll = _h === void 0 ? dialogContext.preventDocumentScroll : _h, onKeyDown = props.onKeyDown, _j = props.isDraggable, isDraggable = _j === void 0 ? dialogContext.isDraggable : _j, _k = props.isResizable, isResizable = _k === void 0 ? dialogContext.isResizable : _k, propStyle = props.style, rest = __rest(props, ["className", "children", "styleType", "isOpen", "isDismissible", "onClose", "closeOnEsc", "trapFocus", "setFocus", "preventDocumentScroll", "onKeyDown", "isDraggable", "isResizable", "style"]);
56
58
  useTheme();
59
+ var _l = React.useState(), style = _l[0], setStyle = _l[1];
57
60
  var dialogRef = React.useRef(null);
58
61
  var refs = useMergedRefs(dialogRef, ref);
59
62
  // Focuses dialog when opened and brings back focus to the previously focused element when closed.
60
63
  var previousFocusedElement = React.useRef();
64
+ var setFocusRef = useLatestRef(setFocus);
61
65
  React.useEffect(function () {
62
66
  var _a, _b, _c;
67
+ if (!setFocusRef.current) {
68
+ return;
69
+ }
63
70
  if (isOpen) {
64
71
  previousFocusedElement.current = (_a = dialogRef.current) === null || _a === void 0 ? void 0 : _a.ownerDocument.activeElement;
65
72
  (_b = dialogRef.current) === null || _b === void 0 ? void 0 : _b.focus();
@@ -73,17 +80,25 @@ export var DialogMain = React.forwardRef(function (props, ref) {
73
80
  (ref === null || ref === void 0 ? void 0 : ref.contains(document.activeElement)) &&
74
81
  ((_a = previousFocusedElement.current) === null || _a === void 0 ? void 0 : _a.focus());
75
82
  };
83
+ }, [isOpen, setFocusRef]);
84
+ var originalBodyOverflow = React.useRef('');
85
+ React.useEffect(function () {
86
+ if (isOpen) {
87
+ originalBodyOverflow.current = document.body.style.overflow;
88
+ }
76
89
  }, [isOpen]);
77
90
  // Prevents document from scrolling when the dialog is open.
78
- var originalBodyOverflow = React.useRef('');
79
91
  React.useEffect(function () {
80
92
  var _a;
81
93
  var ownerDocument = (_a = dialogRef.current) === null || _a === void 0 ? void 0 : _a.ownerDocument;
82
- if (!ownerDocument || !preventDocumentScroll) {
94
+ // If there is no `ownerDocument` or `preventDocumentScroll` is false or
95
+ // document body originally has `overflow: hidden` (possibly from other/parent dialog), then do nothing.
96
+ if (!ownerDocument ||
97
+ !preventDocumentScroll ||
98
+ originalBodyOverflow.current === 'hidden') {
83
99
  return;
84
100
  }
85
101
  if (isOpen) {
86
- originalBodyOverflow.current = ownerDocument.body.style.overflow;
87
102
  ownerDocument.body.style.overflow = 'hidden';
88
103
  }
89
104
  else {
@@ -101,13 +116,38 @@ export var DialogMain = React.forwardRef(function (props, ref) {
101
116
  }
102
117
  onKeyDown === null || onKeyDown === void 0 ? void 0 : onKeyDown(event);
103
118
  };
119
+ var _m = useDragAndDrop(dialogRef, dialogContext.dialogRootRef, isDraggable), onPointerDown = _m.onPointerDown, transform = _m.transform;
120
+ var handlePointerDown = React.useCallback(function (event) {
121
+ if (isDraggable) {
122
+ onPointerDown(event);
123
+ }
124
+ }, [isDraggable, onPointerDown]);
125
+ // Prevents dialog from moving when window is being resized
126
+ React.useLayoutEffect(function () {
127
+ var _a;
128
+ if (!isDraggable || !isOpen) {
129
+ return;
130
+ }
131
+ var rect = (_a = dialogRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
132
+ var _b = getTranslateValues(dialogRef.current), translateX = _b[0], translateY = _b[1];
133
+ setStyle(function (oldStyle) {
134
+ var _a, _b;
135
+ return (__assign(__assign({}, oldStyle), { width: rect === null || rect === void 0 ? void 0 : rect.width, height: rect === null || rect === void 0 ? void 0 : rect.height, left: (_a = dialogRef.current) === null || _a === void 0 ? void 0 : _a.offsetLeft, top: (_b = dialogRef.current) === null || _b === void 0 ? void 0 : _b.offsetTop, transform: "translate(".concat(translateX, "px,").concat(translateY, "px)") }));
136
+ });
137
+ }, [isDraggable, isOpen]);
138
+ var setResizeStyle = React.useCallback(function (newStyle) {
139
+ setStyle(function (oldStyle) { return (__assign(__assign({}, oldStyle), newStyle)); });
140
+ }, []);
104
141
  var content = (React.createElement("div", __assign({ className: cx('iui-dialog', {
105
142
  'iui-dialog-default': styleType === 'default',
106
143
  'iui-dialog-full-page': styleType === 'fullPage',
107
144
  'iui-dialog-visible': isOpen,
108
- }, className), role: 'dialog', ref: refs, onKeyDown: handleKeyDown, tabIndex: -1 }, rest), children));
145
+ 'iui-dialog-draggable': isDraggable,
146
+ }, className), role: 'dialog', ref: refs, onKeyDown: handleKeyDown, tabIndex: -1, style: __assign(__assign({ transform: transform, overflow: 'unset' }, style), propStyle) }, rest),
147
+ isResizable && (React.createElement(Resizer, { elementRef: dialogRef, containerRef: dialogContext.dialogRootRef, onResizeEnd: setResizeStyle })),
148
+ children));
109
149
  return (React.createElement(CSSTransition, { in: isOpen, classNames: 'iui-dialog-animation', timeout: { exit: 600 }, unmountOnExit: true, nodeRef: dialogRef },
110
- React.createElement(React.Fragment, null,
150
+ React.createElement(DialogDragContext.Provider, { value: { onPointerDown: handlePointerDown } },
111
151
  trapFocus && React.createElement(FocusTrap, null, content),
112
152
  !trapFocus && content)));
113
153
  });
@@ -10,7 +10,7 @@ export declare type DialogTitleBarProps = {
10
10
  * Dialog title.
11
11
  */
12
12
  titleText?: React.ReactNode;
13
- } & Pick<DialogContextProps, 'isDismissible' | 'onClose'> & React.ComponentPropsWithRef<'div'>;
13
+ } & Pick<DialogContextProps, 'isDismissible' | 'onClose' | 'isDraggable'> & React.ComponentPropsWithRef<'div'>;
14
14
  /**
15
15
  * Dialog title bar. Recommended to be used as a child of `Dialog`.
16
16
  * @example
@@ -28,7 +28,7 @@ export declare type DialogTitleBarProps = {
28
28
  * </IconButton>
29
29
  * </Dialog.TitleBar>
30
30
  */
31
- export declare const DialogTitleBar: React.ForwardRefExoticComponent<Pick<DialogTitleBarProps, "onClose" | "key" | keyof React.HTMLAttributes<HTMLDivElement> | "isDismissible" | "titleText"> & React.RefAttributes<HTMLDivElement>> & {
31
+ export declare const DialogTitleBar: React.ForwardRefExoticComponent<Pick<DialogTitleBarProps, "onClose" | "key" | keyof React.HTMLAttributes<HTMLDivElement> | "isDismissible" | "isDraggable" | "titleText"> & React.RefAttributes<HTMLDivElement>> & {
32
32
  Title: React.ForwardRefExoticComponent<Pick<import("./DialogTitleBarTitle").DialogTitleBarTitleProps, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & React.RefAttributes<HTMLDivElement>>;
33
33
  };
34
34
  export default DialogTitleBar;
@@ -32,6 +32,7 @@ import { IconButton } from '../Buttons';
32
32
  import '@itwin/itwinui-css/css/dialog.css';
33
33
  import { useDialogContext } from './DialogContext';
34
34
  import { DialogTitleBarTitle } from './DialogTitleBarTitle';
35
+ import { useDialogDragContext } from './DialogDragContext';
35
36
  /**
36
37
  * Dialog title bar. Recommended to be used as a child of `Dialog`.
37
38
  * @example
@@ -51,9 +52,18 @@ import { DialogTitleBarTitle } from './DialogTitleBarTitle';
51
52
  */
52
53
  export var DialogTitleBar = Object.assign(React.forwardRef(function (props, ref) {
53
54
  var dialogContext = useDialogContext();
54
- var children = props.children, titleText = props.titleText, _a = props.isDismissible, isDismissible = _a === void 0 ? dialogContext.isDismissible : _a, _b = props.onClose, onClose = _b === void 0 ? dialogContext.onClose : _b, className = props.className, rest = __rest(props, ["children", "titleText", "isDismissible", "onClose", "className"]);
55
+ var children = props.children, titleText = props.titleText, _a = props.isDismissible, isDismissible = _a === void 0 ? dialogContext.isDismissible : _a, _b = props.onClose, onClose = _b === void 0 ? dialogContext.onClose : _b, _c = props.isDraggable, isDraggable = _c === void 0 ? dialogContext.isDraggable : _c, className = props.className, onPointerDownProp = props.onPointerDown, rest = __rest(props, ["children", "titleText", "isDismissible", "onClose", "isDraggable", "className", "onPointerDown"]);
56
+ var onPointerDown = useDialogDragContext().onPointerDown;
57
+ var handlePointerDown = React.useCallback(function (event) {
58
+ onPointerDownProp === null || onPointerDownProp === void 0 ? void 0 : onPointerDownProp(event);
59
+ if (!event.defaultPrevented) {
60
+ onPointerDown === null || onPointerDown === void 0 ? void 0 : onPointerDown(event);
61
+ }
62
+ }, [onPointerDown, onPointerDownProp]);
55
63
  useTheme();
56
- return (React.createElement("div", __assign({ className: cx('iui-dialog-title-bar', className), ref: ref }, rest), children ? (children) : (React.createElement(React.Fragment, null,
64
+ return (React.createElement("div", __assign({ className: cx('iui-dialog-title-bar', className, {
65
+ 'iui-dialog-title-bar-filled': isDraggable,
66
+ }), ref: ref, onPointerDown: handlePointerDown }, rest), children ? (children) : (React.createElement(React.Fragment, null,
57
67
  React.createElement(DialogTitleBarTitle, null, titleText),
58
68
  isDismissible && (React.createElement(IconButton, { size: 'small', styleType: 'borderless', onClick: onClose, "aria-label": 'Close' },
59
69
  React.createElement(SvgClose, null)))))));
@@ -54,7 +54,7 @@ export var Modal = function (props) {
54
54
  var _a = props.isOpen, isOpen = _a === void 0 ? false : _a, _b = props.isDismissible, isDismissible = _b === void 0 ? true : _b, _c = props.closeOnEsc, closeOnEsc = _c === void 0 ? true : _c, _d = props.closeOnExternalClick, closeOnExternalClick = _d === void 0 ? true : _d, onClose = props.onClose, title = props.title, children = props.children, _e = props.modalRootId, modalRootId = _e === void 0 ? 'iui-react-portal-container' : _e, _f = props.ownerDocument, ownerDocument = _f === void 0 ? getDocument() : _f, rest = __rest(props, ["isOpen", "isDismissible", "closeOnEsc", "closeOnExternalClick", "onClose", "title", "children", "modalRootId", "ownerDocument"]);
55
55
  useTheme();
56
56
  var container = getContainer(modalRootId, ownerDocument);
57
- return !!container ? (ReactDOM.createPortal(React.createElement(Dialog, { isOpen: isOpen, closeOnEsc: closeOnEsc, closeOnExternalClick: closeOnExternalClick, isDismissible: isDismissible, onClose: onClose, preventDocumentScroll: true, trapFocus: true },
57
+ return !!container ? (ReactDOM.createPortal(React.createElement(Dialog, { isOpen: isOpen, closeOnEsc: closeOnEsc, closeOnExternalClick: closeOnExternalClick, isDismissible: isDismissible, onClose: onClose, preventDocumentScroll: true, trapFocus: true, setFocus: true },
58
58
  React.createElement(Dialog.Backdrop, null),
59
59
  React.createElement(Dialog.Main, __assign({ "aria-modal": true }, rest),
60
60
  React.createElement(Dialog.TitleBar, { titleText: title }),
@@ -116,6 +116,12 @@ export declare type TableProps<T extends Record<string, unknown> = Record<string
116
116
  * Must be memoized.
117
117
  */
118
118
  onFilter?: (filters: TableFilterValue<T>[], state: TableState<T>) => void;
119
+ /**
120
+ * Value used for global filtering.
121
+ * Use with `globalFilter` and/or `manualGlobalFilter` to handle filtering yourself e.g. filter in server-side.
122
+ * Must be memoized.
123
+ */
124
+ globalFilterValue?: unknown;
119
125
  /**
120
126
  * Content shown when there is no data after filtering.
121
127
  */
@@ -26,7 +26,7 @@ var __rest = (this && this.__rest) || function (s, e) {
26
26
  *--------------------------------------------------------------------------------------------*/
27
27
  import React from 'react';
28
28
  import cx from 'classnames';
29
- import { actions as TableActions, useFlexLayout, useFilters, useRowSelect, useSortBy, useTable, useExpanded, usePagination, useColumnOrder, } from 'react-table';
29
+ import { actions as TableActions, useFlexLayout, useFilters, useRowSelect, useSortBy, useTable, useExpanded, usePagination, useColumnOrder, useGlobalFilter, } from 'react-table';
30
30
  import { ProgressRadial } from '../ProgressIndicators';
31
31
  import { useTheme, useResizeObserver, mergeRefs } from '../utils';
32
32
  import '@itwin/itwinui-css/css/table.css';
@@ -37,10 +37,11 @@ import { TableRowMemoized } from './TableRowMemoized';
37
37
  import { FilterToggle } from './filters';
38
38
  import { customFilterFunctions } from './filters/customFilterFunctions';
39
39
  import { useExpanderCell, useSelectionCell, useSubRowFiltering, useSubRowSelection, useResizeColumns, useColumnDragAndDrop, useScrollToRow, useStickyColumns, } from './hooks';
40
- import { onExpandHandler, onFilterHandler, onSelectHandler, onSingleSelectHandler, onTableResizeEnd, onTableResizeStart, } from './actionHandlers';
40
+ import { onExpandHandler, onFilterHandler, onSelectHandler, onShiftSelectHandler, onSingleSelectHandler, onTableResizeEnd, onTableResizeStart, } from './actionHandlers';
41
41
  import VirtualScroll from '../utils/components/VirtualScroll';
42
42
  import { SELECTION_CELL_ID } from './columns';
43
43
  var singleRowSelectedAction = 'singleRowSelected';
44
+ var shiftRowSelectedAction = 'shiftRowSelected';
44
45
  export var tableResizeStartAction = 'tableResizeStart';
45
46
  var tableResizeEndAction = 'tableResizeEnd';
46
47
  var flattenColumns = function (columns) {
@@ -97,7 +98,7 @@ var flattenColumns = function (columns) {
97
98
  */
98
99
  export var Table = function (props) {
99
100
  var _a;
100
- var data = props.data, columns = props.columns, _b = props.isLoading, isLoading = _b === void 0 ? false : _b, emptyTableContent = props.emptyTableContent, className = props.className, style = props.style, id = props.id, _c = props.isSelectable, isSelectable = _c === void 0 ? false : _c, onSelect = props.onSelect, onRowClick = props.onRowClick, _d = props.selectionMode, selectionMode = _d === void 0 ? 'multi' : _d, _e = props.isSortable, isSortable = _e === void 0 ? false : _e, onSort = props.onSort, stateReducer = props.stateReducer, onBottomReached = props.onBottomReached, onRowInViewport = props.onRowInViewport, _f = props.intersectionMargin, intersectionMargin = _f === void 0 ? 300 : _f, subComponent = props.subComponent, onExpand = props.onExpand, onFilter = props.onFilter, emptyFilteredTableContent = props.emptyFilteredTableContent, filterFunctions = props.filterTypes, expanderCell = props.expanderCell, isRowDisabled = props.isRowDisabled, rowProps = props.rowProps, _g = props.density, density = _g === void 0 ? 'default' : _g, _h = props.selectSubRows, selectSubRows = _h === void 0 ? true : _h, getSubRows = props.getSubRows, _j = props.selectRowOnClick, selectRowOnClick = _j === void 0 ? true : _j, paginatorRenderer = props.paginatorRenderer, _k = props.pageSize, pageSize = _k === void 0 ? 25 : _k, _l = props.isResizable, isResizable = _l === void 0 ? false : _l, _m = props.styleType, styleType = _m === void 0 ? 'default' : _m, _o = props.enableVirtualization, enableVirtualization = _o === void 0 ? false : _o, _p = props.enableColumnReordering, enableColumnReordering = _p === void 0 ? false : _p, rest = __rest(props, ["data", "columns", "isLoading", "emptyTableContent", "className", "style", "id", "isSelectable", "onSelect", "onRowClick", "selectionMode", "isSortable", "onSort", "stateReducer", "onBottomReached", "onRowInViewport", "intersectionMargin", "subComponent", "onExpand", "onFilter", "emptyFilteredTableContent", "filterTypes", "expanderCell", "isRowDisabled", "rowProps", "density", "selectSubRows", "getSubRows", "selectRowOnClick", "paginatorRenderer", "pageSize", "isResizable", "styleType", "enableVirtualization", "enableColumnReordering"]);
101
+ var data = props.data, columns = props.columns, _b = props.isLoading, isLoading = _b === void 0 ? false : _b, emptyTableContent = props.emptyTableContent, className = props.className, style = props.style, id = props.id, _c = props.isSelectable, isSelectable = _c === void 0 ? false : _c, onSelect = props.onSelect, onRowClick = props.onRowClick, _d = props.selectionMode, selectionMode = _d === void 0 ? 'multi' : _d, _e = props.isSortable, isSortable = _e === void 0 ? false : _e, onSort = props.onSort, stateReducer = props.stateReducer, onBottomReached = props.onBottomReached, onRowInViewport = props.onRowInViewport, _f = props.intersectionMargin, intersectionMargin = _f === void 0 ? 300 : _f, subComponent = props.subComponent, onExpand = props.onExpand, onFilter = props.onFilter, globalFilterValue = props.globalFilterValue, emptyFilteredTableContent = props.emptyFilteredTableContent, filterFunctions = props.filterTypes, expanderCell = props.expanderCell, isRowDisabled = props.isRowDisabled, rowProps = props.rowProps, _g = props.density, density = _g === void 0 ? 'default' : _g, _h = props.selectSubRows, selectSubRows = _h === void 0 ? true : _h, getSubRows = props.getSubRows, _j = props.selectRowOnClick, selectRowOnClick = _j === void 0 ? true : _j, paginatorRenderer = props.paginatorRenderer, _k = props.pageSize, pageSize = _k === void 0 ? 25 : _k, _l = props.isResizable, isResizable = _l === void 0 ? false : _l, _m = props.styleType, styleType = _m === void 0 ? 'default' : _m, _o = props.enableVirtualization, enableVirtualization = _o === void 0 ? false : _o, _p = props.enableColumnReordering, enableColumnReordering = _p === void 0 ? false : _p, rest = __rest(props, ["data", "columns", "isLoading", "emptyTableContent", "className", "style", "id", "isSelectable", "onSelect", "onRowClick", "selectionMode", "isSortable", "onSort", "stateReducer", "onBottomReached", "onRowInViewport", "intersectionMargin", "subComponent", "onExpand", "onFilter", "globalFilterValue", "emptyFilteredTableContent", "filterTypes", "expanderCell", "isRowDisabled", "rowProps", "density", "selectSubRows", "getSubRows", "selectRowOnClick", "paginatorRenderer", "pageSize", "isResizable", "styleType", "enableVirtualization", "enableColumnReordering"]);
101
102
  useTheme();
102
103
  var _q = React.useState(), ownerDocument = _q[0], setOwnerDocument = _q[1];
103
104
  var defaultColumn = React.useMemo(function () { return ({
@@ -116,6 +117,34 @@ export var Table = function (props) {
116
117
  var flatColumns = flattenColumns(columns);
117
118
  return flatColumns.some(function (column) { return column.id === SELECTION_CELL_ID; });
118
119
  }, [columns]);
120
+ var disableUserSelect = React.useCallback(function (e) {
121
+ if (e.key === 'Shift') {
122
+ ownerDocument &&
123
+ (ownerDocument.documentElement.style.userSelect = 'none');
124
+ }
125
+ }, [ownerDocument]);
126
+ var enableUserSelect = React.useCallback(function (e) {
127
+ if (e.key === 'Shift') {
128
+ ownerDocument && (ownerDocument.documentElement.style.userSelect = '');
129
+ }
130
+ }, [ownerDocument]);
131
+ React.useEffect(function () {
132
+ if (!isSelectable || selectionMode !== 'multi') {
133
+ return;
134
+ }
135
+ ownerDocument === null || ownerDocument === void 0 ? void 0 : ownerDocument.addEventListener('keydown', disableUserSelect);
136
+ ownerDocument === null || ownerDocument === void 0 ? void 0 : ownerDocument.addEventListener('keyup', enableUserSelect);
137
+ return function () {
138
+ ownerDocument === null || ownerDocument === void 0 ? void 0 : ownerDocument.removeEventListener('keydown', disableUserSelect);
139
+ ownerDocument === null || ownerDocument === void 0 ? void 0 : ownerDocument.removeEventListener('keyup', enableUserSelect);
140
+ };
141
+ }, [
142
+ isSelectable,
143
+ selectionMode,
144
+ ownerDocument,
145
+ disableUserSelect,
146
+ enableUserSelect,
147
+ ]);
119
148
  var tableStateReducer = React.useCallback(function (newState, action, previousState, instance) {
120
149
  switch (action.type) {
121
150
  case TableActions.toggleSortBy:
@@ -134,6 +163,12 @@ export var Table = function (props) {
134
163
  hasManualSelectionColumn ? undefined : isRowDisabled);
135
164
  break;
136
165
  }
166
+ case shiftRowSelectedAction: {
167
+ newState = onShiftSelectHandler(newState, action, instance, onSelect,
168
+ // If it has manual selection column, then we can't check whether row is disabled
169
+ hasManualSelectionColumn ? undefined : isRowDisabled);
170
+ break;
171
+ }
137
172
  case TableActions.toggleRowSelected:
138
173
  case TableActions.toggleAllRowsSelected:
139
174
  case TableActions.toggleAllPageRowsSelected: {
@@ -171,8 +206,8 @@ export var Table = function (props) {
171
206
  return getSubRows ? getSubRows(item, index) : item.subRows;
172
207
  });
173
208
  }, [data, getSubRows]);
174
- var instance = useTable(__assign(__assign({ manualPagination: !paginatorRenderer, paginateExpandedRows: false }, props), { columns: columns, defaultColumn: defaultColumn, disableSortBy: !isSortable, stateReducer: tableStateReducer, filterTypes: filterTypes, selectSubRows: selectSubRows, data: data, getSubRows: getSubRows, initialState: __assign({ pageSize: pageSize }, props.initialState) }), useFlexLayout, useResizeColumns(ownerDocument), useFilters, useSubRowFiltering(hasAnySubRows), useSortBy, useExpanded, usePagination, useRowSelect, useSubRowSelection, useExpanderCell(subComponent, expanderCell, isRowDisabled), useSelectionCell(isSelectable, selectionMode, isRowDisabled), useColumnOrder, useColumnDragAndDrop(enableColumnReordering), useStickyColumns);
175
- var getTableProps = instance.getTableProps, rows = instance.rows, headerGroups = instance.headerGroups, getTableBodyProps = instance.getTableBodyProps, prepareRow = instance.prepareRow, state = instance.state, allColumns = instance.allColumns, filteredFlatRows = instance.filteredFlatRows, dispatch = instance.dispatch, page = instance.page, gotoPage = instance.gotoPage, setPageSize = instance.setPageSize, flatHeaders = instance.flatHeaders, visibleColumns = instance.visibleColumns;
209
+ var instance = useTable(__assign(__assign({ manualPagination: !paginatorRenderer, paginateExpandedRows: false }, props), { columns: columns, defaultColumn: defaultColumn, disableSortBy: !isSortable, stateReducer: tableStateReducer, filterTypes: filterTypes, selectSubRows: selectSubRows, data: data, getSubRows: getSubRows, initialState: __assign({ pageSize: pageSize }, props.initialState) }), useFlexLayout, useResizeColumns(ownerDocument), useFilters, useSubRowFiltering(hasAnySubRows), useGlobalFilter, useSortBy, useExpanded, usePagination, useRowSelect, useSubRowSelection, useExpanderCell(subComponent, expanderCell, isRowDisabled), useSelectionCell(isSelectable, selectionMode, isRowDisabled), useColumnOrder, useColumnDragAndDrop(enableColumnReordering), useStickyColumns);
210
+ var getTableProps = instance.getTableProps, rows = instance.rows, headerGroups = instance.headerGroups, getTableBodyProps = instance.getTableBodyProps, prepareRow = instance.prepareRow, state = instance.state, allColumns = instance.allColumns, dispatch = instance.dispatch, page = instance.page, gotoPage = instance.gotoPage, setPageSize = instance.setPageSize, flatHeaders = instance.flatHeaders, visibleColumns = instance.visibleColumns, setGlobalFilter = instance.setGlobalFilter;
176
211
  var ariaDataAttributes = Object.entries(rest).reduce(function (result, _a) {
177
212
  var key = _a[0], value = _a[1];
178
213
  if (key.startsWith('data-') || key.startsWith('aria-')) {
@@ -180,7 +215,7 @@ export var Table = function (props) {
180
215
  }
181
216
  return result;
182
217
  }, {});
183
- var areFiltersSet = allColumns.some(function (column) { return column.filterValue != null && column.filterValue !== ''; });
218
+ var areFiltersSet = allColumns.some(function (column) { return column.filterValue != null && column.filterValue !== ''; }) || !!globalFilterValue;
184
219
  var showFilterButton = function (column) {
185
220
  return (data.length !== 0 || areFiltersSet) && column.canFilter;
186
221
  };
@@ -196,7 +231,14 @@ export var Table = function (props) {
196
231
  !isDisabled &&
197
232
  selectRowOnClick &&
198
233
  !event.isDefaultPrevented()) {
199
- if (!row.isSelected && (selectionMode === 'single' || !event.ctrlKey)) {
234
+ if (selectionMode === 'multi' && event.shiftKey) {
235
+ dispatch({
236
+ type: shiftRowSelectedAction,
237
+ id: row.id,
238
+ });
239
+ }
240
+ else if (!row.isSelected &&
241
+ (selectionMode === 'single' || !event.ctrlKey)) {
200
242
  dispatch({
201
243
  type: singleRowSelectedAction,
202
244
  id: row.id,
@@ -214,6 +256,9 @@ export var Table = function (props) {
214
256
  dispatch,
215
257
  onRowClick,
216
258
  ]);
259
+ React.useEffect(function () {
260
+ setGlobalFilter(globalFilterValue);
261
+ }, [globalFilterValue, setGlobalFilter]);
217
262
  React.useEffect(function () {
218
263
  setPageSize(pageSize);
219
264
  }, [pageSize, setPageSize]);
@@ -387,7 +432,7 @@ export var Table = function (props) {
387
432
  !isLoading && data.length === 0 && !areFiltersSet && (React.createElement("div", { className: 'iui-table-empty' },
388
433
  React.createElement("div", null, emptyTableContent))),
389
434
  !isLoading &&
390
- (data.length === 0 || filteredFlatRows.length === 0) &&
435
+ (data.length === 0 || rows.length === 0) &&
391
436
  areFiltersSet && (React.createElement("div", { className: 'iui-table-empty' },
392
437
  React.createElement("div", null, emptyFilteredTableContent)))), paginatorRenderer === null || paginatorRenderer === void 0 ? void 0 :
393
438
  paginatorRenderer(paginatorRendererProps))));
@@ -1,4 +1,4 @@
1
1
  export { onExpandHandler } from './expandHandler';
2
2
  export { onFilterHandler } from './filterHandler';
3
- export { onSelectHandler, onSingleSelectHandler } from './selectHandler';
3
+ export { onSelectHandler, onSingleSelectHandler, onShiftSelectHandler, } from './selectHandler';
4
4
  export { onTableResizeStart, onTableResizeEnd } from './resizeHandler';
@@ -4,5 +4,5 @@
4
4
  *--------------------------------------------------------------------------------------------*/
5
5
  export { onExpandHandler } from './expandHandler';
6
6
  export { onFilterHandler } from './filterHandler';
7
- export { onSelectHandler, onSingleSelectHandler } from './selectHandler';
7
+ export { onSelectHandler, onSingleSelectHandler, onShiftSelectHandler, } from './selectHandler';
8
8
  export { onTableResizeStart, onTableResizeEnd } from './resizeHandler';
@@ -16,6 +16,7 @@ export declare const onTableResizeStart: <T extends Record<string, unknown>>(sta
16
16
  isScrolledToRight?: boolean | undefined;
17
17
  isScrolledToLeft?: boolean | undefined;
18
18
  };
19
+ lastSelectedRowId?: string | undefined;
19
20
  columnOrder: import("react-table").IdType<T>[];
20
21
  expanded: Record<import("react-table").IdType<T>, boolean>;
21
22
  filters: import("react-table").Filters<T>;
@@ -46,6 +47,7 @@ export declare const onTableResizeEnd: <T extends Record<string, unknown>>(state
46
47
  isScrolledToRight?: boolean | undefined;
47
48
  isScrolledToLeft?: boolean | undefined;
48
49
  };
50
+ lastSelectedRowId?: string | undefined;
49
51
  columnOrder: import("react-table").IdType<T>[];
50
52
  expanded: Record<import("react-table").IdType<T>, boolean>;
51
53
  filters: import("react-table").Filters<T>;
@@ -7,6 +7,7 @@ export declare const onSelectHandler: <T extends Record<string, unknown>>(newSta
7
7
  * Handles selection when clicked on a row.
8
8
  */
9
9
  export declare const onSingleSelectHandler: <T extends Record<string, unknown>>(state: TableState<T>, action: ActionType, instance?: TableInstance<T> | undefined, onSelect?: ((selectedData: T[] | undefined, tableState?: TableState<T> | undefined) => void) | undefined, isRowDisabled?: ((rowData: T) => boolean) | undefined) => {
10
+ lastSelectedRowId: any;
10
11
  selectedRowIds: Record<string, boolean>;
11
12
  hiddenColumns?: import("react-table").IdType<T>[] | undefined;
12
13
  columnResizing: {
@@ -36,3 +37,7 @@ export declare const onSingleSelectHandler: <T extends Record<string, unknown>>(
36
37
  }>;
37
38
  sortBy: import("react-table").SortingRule<T>[];
38
39
  };
40
+ /**
41
+ * Handles selection when clicked on a row while shift key is pressed.
42
+ */
43
+ export declare const onShiftSelectHandler: <T extends Record<string, unknown>>(state: TableState<T>, action: ActionType, instance?: TableInstance<T> | undefined, onSelect?: ((selectedData: T[] | undefined, tableState?: TableState<T> | undefined) => void) | undefined, isRowDisabled?: ((rowData: T) => boolean) | undefined) => TableState<T>;
@@ -57,11 +57,43 @@ export var onSingleSelectHandler = function (state, action, instance, onSelect,
57
57
  };
58
58
  handleRow_1(instance.rowsById[action.id]);
59
59
  }
60
- var newState = __assign(__assign({}, state), { selectedRowIds: selectedRowIds });
60
+ var newState = __assign(__assign({}, state), { lastSelectedRowId: action.id, selectedRowIds: selectedRowIds });
61
61
  // Passing to `onSelectHandler` to handle filtered sub-rows
62
62
  onSelectHandler(newState, instance, onSelect, isRowDisabled);
63
63
  return newState;
64
64
  };
65
+ /**
66
+ * Handles selection when clicked on a row while shift key is pressed.
67
+ */
68
+ export var onShiftSelectHandler = function (state, action, instance, onSelect, isRowDisabled) {
69
+ if (instance == null) {
70
+ return state;
71
+ }
72
+ var startIndex = Math.max(0, instance.flatRows.findIndex(function (row) { return row.id === state.lastSelectedRowId; }));
73
+ var endIndex = Math.max(0, instance.flatRows.findIndex(function (row) { return row.id === action.id; }));
74
+ if (startIndex > endIndex) {
75
+ var temp = startIndex;
76
+ startIndex = endIndex;
77
+ endIndex = temp;
78
+ }
79
+ var selectedRowIds = {};
80
+ // 1. Select all rows between start and end
81
+ instance.flatRows
82
+ .slice(startIndex, endIndex + 1)
83
+ .forEach(function (r) { return (selectedRowIds[r.id] = true); });
84
+ // 2. Select all children of the last row (endIndex)
85
+ // Since lastRow's children come after endIndex + 1 (not selected in step 1)
86
+ var handleRow = function (row) {
87
+ selectedRowIds[row.id] = true;
88
+ row.subRows.forEach(function (r) { return handleRow(r); });
89
+ };
90
+ handleRow(instance.flatRows[endIndex]);
91
+ var newState = __assign(__assign({}, state), { selectedRowIds: selectedRowIds });
92
+ // 3.1 Deselect all selected disabled rows and their children
93
+ // 3.2 Convert all partially selected rows marked with tick mark to horizontal line
94
+ onSelectHandler(newState, instance, onSelect, isRowDisabled);
95
+ return newState;
96
+ };
65
97
  var getSelectedData = function (selectedRowIds, instance) {
66
98
  var selectedData = [];
67
99
  var setSelectedData = function (row) {
@@ -20,6 +20,8 @@ export { ComboBox } from './ComboBox';
20
20
  export type { ComboBoxProps } from './ComboBox';
21
21
  export { DatePicker, generateLocalizedStrings } from './DatePicker';
22
22
  export type { DatePickerProps } from './DatePicker';
23
+ export { Dialog } from './Dialog';
24
+ export type { DialogProps, DialogButtonBarProps, DialogContentProps, DialogMainProps, DialogTitleBarProps, } from './Dialog';
23
25
  export { DropdownMenu } from './DropdownMenu';
24
26
  export type { DropdownMenuProps } from './DropdownMenu';
25
27
  export { ErrorPage } from './ErrorPage';
@@ -72,7 +74,7 @@ export { StatusMessage } from './StatusMessage';
72
74
  export type { StatusMessageProps } from './StatusMessage';
73
75
  export { Surface } from './Surface';
74
76
  export type { SurfaceProps } from './Surface';
75
- export { Table, tableFilters, FilterButtonBar, DefaultCell, EditableCell, TablePaginator, ActionColumn, ExpanderColumn, SelectionColumn, } from './Table';
77
+ export { Table, tableFilters, BaseFilter, FilterButtonBar, DefaultCell, EditableCell, TablePaginator, ActionColumn, ExpanderColumn, SelectionColumn, } from './Table';
76
78
  export type { TableProps, TableFilterProps, TableFilterValue, DateRangeFilterOptions, FilterButtonBarProps, DefaultCellProps, EditableCellProps, TablePaginatorProps, TablePaginatorRendererProps, } from './Table';
77
79
  export { Tag, TagContainer } from './Tag';
78
80
  export type { TagProps, TagContainerProps } from './Tag';
package/esm/core/index.js CHANGED
@@ -13,6 +13,7 @@ export { Checkbox } from './Checkbox';
13
13
  export { ColorPicker, ColorSwatch, ColorBuilder, ColorInputPanel, ColorPalette, } from './ColorPicker';
14
14
  export { ComboBox } from './ComboBox';
15
15
  export { DatePicker, generateLocalizedStrings } from './DatePicker';
16
+ export { Dialog } from './Dialog';
16
17
  export { DropdownMenu } from './DropdownMenu';
17
18
  export { ErrorPage } from './ErrorPage';
18
19
  export { ExpandableBlock } from './ExpandableBlock';
@@ -39,7 +40,7 @@ export { SkipToContentLink } from './SkipToContentLink';
39
40
  export { Slider } from './Slider';
40
41
  export { StatusMessage } from './StatusMessage';
41
42
  export { Surface } from './Surface';
42
- export { Table, tableFilters, FilterButtonBar, DefaultCell, EditableCell, TablePaginator, ActionColumn, ExpanderColumn, SelectionColumn, } from './Table';
43
+ export { Table, tableFilters, BaseFilter, FilterButtonBar, DefaultCell, EditableCell, TablePaginator, ActionColumn, ExpanderColumn, SelectionColumn, } from './Table';
43
44
  export { Tag, TagContainer } from './Tag';
44
45
  export { Textarea } from './Textarea';
45
46
  export { Tile } from './Tile';
@@ -0,0 +1,31 @@
1
+ import React from 'react';
2
+ export declare type ResizerProps = {
3
+ /**
4
+ * Ref of the element that is being resized.
5
+ */
6
+ elementRef: React.RefObject<HTMLElement>;
7
+ /**
8
+ * Ref of the container element in order to avoid resizing past container boundaries.
9
+ * If not passed, viewport will be used.
10
+ */
11
+ containerRef?: React.RefObject<HTMLElement>;
12
+ /**
13
+ * Callback that is being called on resize end.
14
+ * Useful to preserve state if element is being closed.
15
+ */
16
+ onResizeEnd?: (style: React.CSSProperties) => void;
17
+ };
18
+ /**
19
+ * Component that allows to resize parent element.
20
+ * Parent must have `position: relative`.
21
+ * @private
22
+ * @example
23
+ * const ref = React.useRef<HTMLDivElement>(null);
24
+ * return (
25
+ * <div ref={ref} style={{ position: 'relative' }}>
26
+ * <Resizer elementRef={ref} />
27
+ * </div>
28
+ * );
29
+ */
30
+ export declare const Resizer: (props: ResizerProps) => JSX.Element;
31
+ export default Resizer;