@itwin/itwinui-react 1.38.1 → 1.40.1

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 (98) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/cjs/core/Carousel/Carousel.js +21 -12
  3. package/cjs/core/Carousel/CarouselContext.d.ts +4 -2
  4. package/cjs/core/Carousel/CarouselDotsList.js +1 -0
  5. package/cjs/core/Carousel/CarouselNavigation.js +8 -10
  6. package/cjs/core/Carousel/CarouselSlide.js +3 -7
  7. package/cjs/core/Carousel/CarouselSlider.js +23 -28
  8. package/cjs/core/ColorPicker/ColorPickerContext.d.ts +2 -2
  9. package/cjs/core/ComboBox/ComboBox.d.ts +10 -1
  10. package/cjs/core/ComboBox/ComboBox.js +39 -20
  11. package/cjs/core/ComboBox/ComboBoxDropdown.d.ts +5 -6
  12. package/cjs/core/ComboBox/ComboBoxInput.js +28 -9
  13. package/cjs/core/ComboBox/ComboBoxMenu.js +10 -2
  14. package/cjs/core/ComboBox/helpers.d.ts +1 -1
  15. package/cjs/core/ComboBox/helpers.js +1 -1
  16. package/cjs/core/DatePicker/DatePicker.d.ts +1 -1
  17. package/cjs/core/Menu/MenuItemSkeleton.d.ts +32 -0
  18. package/cjs/core/Menu/MenuItemSkeleton.js +53 -0
  19. package/cjs/core/Menu/index.d.ts +2 -0
  20. package/cjs/core/Menu/index.js +3 -1
  21. package/cjs/core/Table/Table.js +68 -25
  22. package/cjs/core/Table/TableCell.js +10 -3
  23. package/cjs/core/Table/TablePaginator.js +1 -1
  24. package/cjs/core/Table/TableRowMemoized.js +5 -1
  25. package/cjs/core/Table/actionHandlers/resizeHandler.d.ts +8 -0
  26. package/cjs/core/Table/actionHandlers/selectHandler.d.ts +4 -0
  27. package/cjs/core/Table/columns/selectionColumn.js +4 -2
  28. package/cjs/core/Table/filters/tableFilters.d.ts +3 -3
  29. package/cjs/core/Table/hooks/index.d.ts +1 -0
  30. package/cjs/core/Table/hooks/index.js +3 -1
  31. package/cjs/core/Table/hooks/useExpanderCell.js +11 -1
  32. package/cjs/core/Table/hooks/useStickyColumns.d.ts +2 -0
  33. package/cjs/core/Table/hooks/useStickyColumns.js +84 -0
  34. package/cjs/core/Table/utils.d.ts +1 -0
  35. package/cjs/core/Table/utils.js +36 -1
  36. package/cjs/core/Toast/Toaster.js +97 -18
  37. package/cjs/core/index.d.ts +2 -2
  38. package/cjs/core/index.js +4 -3
  39. package/cjs/core/utils/components/Popover.d.ts +1 -18
  40. package/cjs/core/utils/components/VirtualScroll.js +2 -2
  41. package/cjs/core/utils/components/VisuallyHidden.d.ts +9 -0
  42. package/cjs/core/utils/components/VisuallyHidden.js +44 -0
  43. package/cjs/core/utils/components/WithCSSTransition.d.ts +1 -2
  44. package/cjs/core/utils/components/icons.d.ts +4 -4
  45. package/cjs/core/utils/components/index.d.ts +1 -0
  46. package/cjs/core/utils/components/index.js +1 -0
  47. package/cjs/core/utils/hooks/useOverflow.js +4 -2
  48. package/cjs/core/utils/hooks/useTheme.d.ts +1 -1
  49. package/cjs/types/react-table-config.d.ts +9 -0
  50. package/esm/core/Carousel/Carousel.js +21 -12
  51. package/esm/core/Carousel/CarouselContext.d.ts +4 -2
  52. package/esm/core/Carousel/CarouselDotsList.js +1 -0
  53. package/esm/core/Carousel/CarouselNavigation.js +8 -10
  54. package/esm/core/Carousel/CarouselSlide.js +3 -7
  55. package/esm/core/Carousel/CarouselSlider.js +24 -29
  56. package/esm/core/ColorPicker/ColorPickerContext.d.ts +2 -2
  57. package/esm/core/ComboBox/ComboBox.d.ts +10 -1
  58. package/esm/core/ComboBox/ComboBox.js +39 -20
  59. package/esm/core/ComboBox/ComboBoxDropdown.d.ts +5 -6
  60. package/esm/core/ComboBox/ComboBoxInput.js +28 -9
  61. package/esm/core/ComboBox/ComboBoxMenu.js +10 -2
  62. package/esm/core/ComboBox/helpers.d.ts +1 -1
  63. package/esm/core/ComboBox/helpers.js +1 -1
  64. package/esm/core/DatePicker/DatePicker.d.ts +1 -1
  65. package/esm/core/Menu/MenuItemSkeleton.d.ts +32 -0
  66. package/esm/core/Menu/MenuItemSkeleton.js +46 -0
  67. package/esm/core/Menu/index.d.ts +2 -0
  68. package/esm/core/Menu/index.js +1 -0
  69. package/esm/core/Table/Table.js +70 -27
  70. package/esm/core/Table/TableCell.js +11 -4
  71. package/esm/core/Table/TablePaginator.js +1 -1
  72. package/esm/core/Table/TableRowMemoized.js +5 -1
  73. package/esm/core/Table/actionHandlers/resizeHandler.d.ts +8 -0
  74. package/esm/core/Table/actionHandlers/selectHandler.d.ts +4 -0
  75. package/esm/core/Table/columns/selectionColumn.js +4 -2
  76. package/esm/core/Table/filters/tableFilters.d.ts +3 -3
  77. package/esm/core/Table/hooks/index.d.ts +1 -0
  78. package/esm/core/Table/hooks/index.js +1 -0
  79. package/esm/core/Table/hooks/useExpanderCell.js +8 -1
  80. package/esm/core/Table/hooks/useStickyColumns.d.ts +2 -0
  81. package/esm/core/Table/hooks/useStickyColumns.js +80 -0
  82. package/esm/core/Table/utils.d.ts +1 -0
  83. package/esm/core/Table/utils.js +34 -0
  84. package/esm/core/Toast/Toaster.js +75 -19
  85. package/esm/core/index.d.ts +2 -2
  86. package/esm/core/index.js +1 -1
  87. package/esm/core/utils/components/Popover.d.ts +1 -18
  88. package/esm/core/utils/components/VirtualScroll.js +2 -2
  89. package/esm/core/utils/components/VisuallyHidden.d.ts +9 -0
  90. package/esm/core/utils/components/VisuallyHidden.js +38 -0
  91. package/esm/core/utils/components/WithCSSTransition.d.ts +1 -2
  92. package/esm/core/utils/components/icons.d.ts +4 -4
  93. package/esm/core/utils/components/index.d.ts +1 -0
  94. package/esm/core/utils/components/index.js +1 -0
  95. package/esm/core/utils/hooks/useOverflow.js +4 -2
  96. package/esm/core/utils/hooks/useTheme.d.ts +1 -1
  97. package/esm/types/react-table-config.d.ts +9 -0
  98. package/package.json +24 -39
@@ -35,9 +35,10 @@ export declare type ComboBoxProps<T> = {
35
35
  dropdownMenuProps?: PopoverProps;
36
36
  /**
37
37
  * Message shown when no options are available.
38
+ * If `JSX.Element` is provided, it will be rendered as is and won't be wrapped with `MenuExtraContent`.
38
39
  * @default 'No options found'
39
40
  */
40
- emptyStateMessage?: string;
41
+ emptyStateMessage?: React.ReactNode;
41
42
  /**
42
43
  * A custom item renderer can be specified to control the rendering.
43
44
  *
@@ -58,6 +59,14 @@ export declare type ComboBoxProps<T> = {
58
59
  * @beta
59
60
  */
60
61
  enableVirtualization?: boolean;
62
+ /**
63
+ * Callback fired when dropdown menu is opened.
64
+ */
65
+ onShow?: () => void;
66
+ /**
67
+ * Callback fired when dropdown menu is closed.
68
+ */
69
+ onHide?: () => void;
61
70
  } & Pick<InputContainerProps, 'status'> & Omit<CommonProps, 'title'>;
62
71
  /**
63
72
  * ComboBox component that allows typing a value to filter the options in dropdown list.
@@ -56,8 +56,8 @@ var getOptionId = function (option, idPrefix) {
56
56
  * />
57
57
  */
58
58
  export var ComboBox = function (props) {
59
- var _a;
60
- var options = props.options, valueProp = props.value, onChange = props.onChange, filterFunction = props.filterFunction, inputProps = props.inputProps, dropdownMenuProps = props.dropdownMenuProps, _b = props.emptyStateMessage, emptyStateMessage = _b === void 0 ? 'No options found' : _b, itemRenderer = props.itemRenderer, _c = props.enableVirtualization, enableVirtualization = _c === void 0 ? false : _c, rest = __rest(props, ["options", "value", "onChange", "filterFunction", "inputProps", "dropdownMenuProps", "emptyStateMessage", "itemRenderer", "enableVirtualization"]);
59
+ var _a, _b;
60
+ var options = props.options, valueProp = props.value, onChange = props.onChange, filterFunction = props.filterFunction, inputProps = props.inputProps, dropdownMenuProps = props.dropdownMenuProps, _c = props.emptyStateMessage, emptyStateMessage = _c === void 0 ? 'No options found' : _c, itemRenderer = props.itemRenderer, _d = props.enableVirtualization, enableVirtualization = _d === void 0 ? false : _d, onShow = props.onShow, onHide = props.onHide, rest = __rest(props, ["options", "value", "onChange", "filterFunction", "inputProps", "dropdownMenuProps", "emptyStateMessage", "itemRenderer", "enableVirtualization", "onShow", "onHide"]);
61
61
  // Generate a stateful random id if not specified
62
62
  var id = React.useState(function () {
63
63
  var _a, _b;
@@ -89,17 +89,18 @@ export var ComboBox = function (props) {
89
89
  });
90
90
  }
91
91
  // Reducer where all the component-wide state is stored
92
- var _d = React.useReducer(comboBoxReducer, {
92
+ var _e = React.useReducer(comboBoxReducer, {
93
93
  isOpen: false,
94
94
  selectedIndex: -1,
95
95
  focusedIndex: -1,
96
- }), _e = _d[0], isOpen = _e.isOpen, selectedIndex = _e.selectedIndex, focusedIndex = _e.focusedIndex, dispatch = _d[1];
97
- React.useEffect(function () {
96
+ }), _f = _e[0], isOpen = _f.isOpen, selectedIndex = _f.selectedIndex, focusedIndex = _f.focusedIndex, dispatch = _e[1];
97
+ React.useLayoutEffect(function () {
98
98
  var _a, _b;
99
99
  // When the dropdown opens
100
100
  if (isOpen) {
101
101
  (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.focus(); // Focus the input
102
102
  setFilteredOptions(options); // Reset the filtered list
103
+ dispatch(['focus']);
103
104
  }
104
105
  // When the dropdown closes
105
106
  else {
@@ -112,19 +113,30 @@ export var ComboBox = function (props) {
112
113
  }
113
114
  }, [isOpen, options, selectedIndex]);
114
115
  // Set min-width of menu to be same as input
115
- var _f = React.useState(0), minWidth = _f[0], setMinWidth = _f[1];
116
+ var _g = React.useState(0), minWidth = _g[0], setMinWidth = _g[1];
116
117
  React.useEffect(function () {
117
118
  if (inputRef.current) {
118
119
  setMinWidth(inputRef.current.offsetWidth);
119
120
  }
120
121
  }, [isOpen]);
121
- // Initialize filtered options to the latest value options
122
- var _g = React.useState(options), filteredOptions = _g[0], setFilteredOptions = _g[1];
122
+ // Update filtered options to the latest value options according to input value
123
+ var _h = React.useState(options), filteredOptions = _h[0], setFilteredOptions = _h[1];
123
124
  React.useEffect(function () {
124
- setFilteredOptions(options);
125
+ var _a;
126
+ if (inputValue) {
127
+ setFilteredOptions((_a = filterFunction === null || filterFunction === void 0 ? void 0 : filterFunction(options, inputValue)) !== null && _a !== void 0 ? _a : options.filter(function (option) {
128
+ return option.label.toLowerCase().includes(inputValue.toLowerCase());
129
+ }));
130
+ }
131
+ else {
132
+ setFilteredOptions(options);
133
+ }
134
+ dispatch(['focus']);
135
+ // Only need to call on options update
136
+ // eslint-disable-next-line react-hooks/exhaustive-deps
125
137
  }, [options]);
126
138
  // Filter options based on input value
127
- var _h = React.useState((_a = inputProps === null || inputProps === void 0 ? void 0 : inputProps.value) !== null && _a !== void 0 ? _a : ''), inputValue = _h[0], setInputValue = _h[1];
139
+ var _j = React.useState((_b = (_a = inputProps === null || inputProps === void 0 ? void 0 : inputProps.value) === null || _a === void 0 ? void 0 : _a.toString()) !== null && _b !== void 0 ? _b : ''), inputValue = _j[0], setInputValue = _j[1];
128
140
  var handleOnInput = React.useCallback(function (event) {
129
141
  var _a, _b;
130
142
  var value = event.currentTarget.value;
@@ -133,12 +145,11 @@ export var ComboBox = function (props) {
133
145
  setFilteredOptions((_a = filterFunction === null || filterFunction === void 0 ? void 0 : filterFunction(options, value)) !== null && _a !== void 0 ? _a : options.filter(function (option) {
134
146
  return option.label.toLowerCase().includes(value.toLowerCase());
135
147
  }));
148
+ if (focusedIndex != -1) {
149
+ dispatch(['focus', -1]);
150
+ }
136
151
  (_b = inputProps === null || inputProps === void 0 ? void 0 : inputProps.onChange) === null || _b === void 0 ? void 0 : _b.call(inputProps, event);
137
- }, [filterFunction, inputProps, options]);
138
- // Reset focused item when filteredOptions change
139
- React.useEffect(function () {
140
- dispatch(['focus']);
141
- }, [filteredOptions]);
152
+ }, [filterFunction, focusedIndex, inputProps, options]);
142
153
  // When the value prop changes, update the selectedIndex
143
154
  React.useEffect(function () {
144
155
  dispatch([
@@ -157,7 +168,7 @@ export var ComboBox = function (props) {
157
168
  (_b = onChangeProp.current) === null || _b === void 0 ? void 0 : _b.call(onChangeProp, value);
158
169
  }
159
170
  }, [options, selectedIndex, valueProp]);
160
- var getMenuItem = React.useCallback(function (option) {
171
+ var getMenuItem = React.useCallback(function (option, filteredIndex) {
161
172
  var optionId = getOptionId(option, id);
162
173
  var __originalIndex = optionsExtraInfoRef.current[optionId].__originalIndex;
163
174
  var customItem = itemRenderer
@@ -172,6 +183,7 @@ export var ComboBox = function (props) {
172
183
  onClick: function (e) {
173
184
  var _a, _b;
174
185
  dispatch(['select', __originalIndex]);
186
+ dispatch(['close']);
175
187
  (_b = (_a = customItem.props).onClick) === null || _b === void 0 ? void 0 : _b.call(_a, e);
176
188
  },
177
189
  // ComboBox.MenuItem handles scrollIntoView, data-iui-index and iui-focused through context
@@ -180,13 +192,19 @@ export var ComboBox = function (props) {
180
192
  'iui-focused': focusedIndex === __originalIndex,
181
193
  }),
182
194
  'data-iui-index': __originalIndex,
195
+ 'data-iui-filtered-index': filteredIndex,
183
196
  ref: mergeRefs(customItem.props.ref, function (el) {
184
197
  if (!enableVirtualization && focusedIndex === __originalIndex) {
185
198
  el === null || el === void 0 ? void 0 : el.scrollIntoView({ block: 'nearest' });
186
199
  }
187
200
  }),
188
- })) : (React.createElement(ComboBoxMenuItem, __assign({ key: optionId, id: optionId }, option, { isSelected: selectedIndex === __originalIndex, onClick: function () { return dispatch(['select', __originalIndex]); }, index: __originalIndex }), option.label));
201
+ })) : (React.createElement(ComboBoxMenuItem, __assign({ key: optionId, id: optionId }, option, { isSelected: selectedIndex === __originalIndex, onClick: function () {
202
+ dispatch(['select', __originalIndex]);
203
+ dispatch(['close']);
204
+ }, index: __originalIndex, "data-iui-filtered-index": filteredIndex }), option.label));
189
205
  }, [enableVirtualization, focusedIndex, id, itemRenderer, selectedIndex]);
206
+ var emptyContent = React.useMemo(function () { return (React.createElement(React.Fragment, null, React.isValidElement(emptyStateMessage) ? (emptyStateMessage) : (React.createElement(MenuExtraContent, null,
207
+ React.createElement(Text, { isMuted: true }, emptyStateMessage))))); }, [emptyStateMessage]);
190
208
  return (React.createElement(ComboBoxRefsContext.Provider, { value: { inputRef: inputRef, menuRef: menuRef, toggleButtonRef: toggleButtonRef, optionsExtraInfoRef: optionsExtraInfoRef } },
191
209
  React.createElement(ComboBoxActionContext.Provider, { value: dispatch },
192
210
  React.createElement(ComboBoxStateContext.Provider, { value: {
@@ -201,8 +219,9 @@ export var ComboBox = function (props) {
201
219
  React.createElement(ComboBoxInputContainer, __assign({ disabled: inputProps === null || inputProps === void 0 ? void 0 : inputProps.disabled }, rest),
202
220
  React.createElement(ComboBoxInput, __assign({ value: inputValue }, inputProps, { onChange: handleOnInput })),
203
221
  React.createElement(ComboBoxEndIcon, { disabled: inputProps === null || inputProps === void 0 ? void 0 : inputProps.disabled, isOpen: isOpen })),
204
- React.createElement(ComboBoxDropdown, __assign({}, dropdownMenuProps),
205
- React.createElement(ComboBoxMenu, null, filteredOptions.length > 0 && !enableVirtualization ? (filteredOptions.map(getMenuItem)) : (React.createElement(MenuExtraContent, null,
206
- React.createElement(Text, { isMuted: true }, emptyStateMessage)))))))));
222
+ React.createElement(ComboBoxDropdown, __assign({}, dropdownMenuProps, { onShow: onShow, onHide: onHide }),
223
+ React.createElement(ComboBoxMenu, null, filteredOptions.length > 0 && !enableVirtualization
224
+ ? filteredOptions.map(getMenuItem)
225
+ : emptyContent))))));
207
226
  };
208
227
  export default ComboBox;
@@ -1,8 +1,7 @@
1
1
  import React from 'react';
2
- export declare const ComboBoxDropdown: React.ForwardRefExoticComponent<Pick<{
3
- visible?: boolean | undefined;
4
- trigger?: string | undefined;
5
- placement?: import("@popperjs/core").Placement | undefined;
6
- } & Omit<import("@tippyjs/react").TippyProps, "placement" | "trigger" | "visible"> & {
2
+ import { PopoverProps } from '../utils';
3
+ declare type ComboBoxDropdownProps = PopoverProps & {
7
4
  children: JSX.Element;
8
- }, "disabled" | "children" | "placement" | "trigger" | "visible" | "content" | "render" | "animateFill" | "appendTo" | "aria" | "delay" | "duration" | "followCursor" | "getReferenceClientRect" | "hideOnClick" | "ignoreAttributes" | "inlinePositioning" | "interactive" | "interactiveBorder" | "interactiveDebounce" | "moveTransition" | "offset" | "plugins" | "popperOptions" | "showOnCreate" | "sticky" | "touch" | "triggerTarget" | "onAfterUpdate" | "onBeforeUpdate" | "onCreate" | "onDestroy" | "onHidden" | "onHide" | "onMount" | "onShow" | "onShown" | "onTrigger" | "onUntrigger" | "onClickOutside" | "allowHTML" | "animation" | "arrow" | "inertia" | "maxWidth" | "role" | "theme" | "zIndex" | "className" | "singleton" | "reference"> & React.RefAttributes<Element>>;
5
+ };
6
+ export declare const ComboBoxDropdown: React.ForwardRefExoticComponent<Pick<ComboBoxDropdownProps, "disabled" | "children" | "placement" | "trigger" | "visible" | "content" | "render" | "animateFill" | "appendTo" | "aria" | "delay" | "duration" | "followCursor" | "getReferenceClientRect" | "hideOnClick" | "ignoreAttributes" | "inlinePositioning" | "interactive" | "interactiveBorder" | "interactiveDebounce" | "moveTransition" | "offset" | "plugins" | "popperOptions" | "showOnCreate" | "sticky" | "touch" | "triggerTarget" | "onAfterUpdate" | "onBeforeUpdate" | "onCreate" | "onDestroy" | "onHidden" | "onHide" | "onMount" | "onShow" | "onShown" | "onTrigger" | "onUntrigger" | "onClickOutside" | "allowHTML" | "animation" | "arrow" | "inertia" | "maxWidth" | "role" | "theme" | "zIndex" | "className" | "singleton" | "reference"> & React.RefAttributes<Element>>;
7
+ export {};
@@ -30,7 +30,7 @@ import { useSafeContext, useMergedRefs } from '../utils';
30
30
  import { ComboBoxStateContext, ComboBoxActionContext, ComboBoxRefsContext, } from './helpers';
31
31
  export var ComboBoxInput = React.forwardRef(function (props, forwardedRef) {
32
32
  var onKeyDownProp = props.onKeyDown, onFocusProp = props.onFocus, rest = __rest(props, ["onKeyDown", "onFocus"]);
33
- var _a = useSafeContext(ComboBoxStateContext), isOpen = _a.isOpen, id = _a.id, focusedIndex = _a.focusedIndex;
33
+ var _a = useSafeContext(ComboBoxStateContext), isOpen = _a.isOpen, id = _a.id, focusedIndex = _a.focusedIndex, enableVirtualization = _a.enableVirtualization;
34
34
  var dispatch = useSafeContext(ComboBoxActionContext);
35
35
  var _b = useSafeContext(ComboBoxRefsContext), inputRef = _b.inputRef, menuRef = _b.menuRef, optionsExtraInfoRef = _b.optionsExtraInfoRef;
36
36
  var refs = useMergedRefs(inputRef, forwardedRef);
@@ -43,7 +43,7 @@ export var ComboBoxInput = React.forwardRef(function (props, forwardedRef) {
43
43
  return ((_c = (_b = (_a = menuRef.current) === null || _a === void 0 ? void 0 : _a.querySelector("[data-iui-index=\"".concat(index, "\"]"))) === null || _b === void 0 ? void 0 : _b.id) !== null && _c !== void 0 ? _c : '');
44
44
  };
45
45
  var handleKeyDown = React.useCallback(function (event) {
46
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
46
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
47
47
  onKeyDownProp === null || onKeyDownProp === void 0 ? void 0 : onKeyDownProp(event);
48
48
  var length = (_a = Object.keys(optionsExtraInfoRef.current).length) !== null && _a !== void 0 ? _a : 0;
49
49
  switch (event.key) {
@@ -56,15 +56,21 @@ export var ComboBoxInput = React.forwardRef(function (props, forwardedRef) {
56
56
  return;
57
57
  }
58
58
  if (focusedIndexRef.current === -1) {
59
+ var currentElement = (_b = menuRef.current) === null || _b === void 0 ? void 0 : _b.querySelector('[data-iui-index]');
59
60
  return dispatch([
60
61
  'focus',
61
- (_c = (_b = Object.values(optionsExtraInfoRef.current)) === null || _b === void 0 ? void 0 : _b[0].__originalIndex) !== null && _c !== void 0 ? _c : -1,
62
+ Number((_c = currentElement === null || currentElement === void 0 ? void 0 : currentElement.getAttribute('data-iui-index')) !== null && _c !== void 0 ? _c : 0),
62
63
  ]);
63
64
  }
65
+ // If virtualization is enabled, dont let round scrolling
66
+ if (enableVirtualization &&
67
+ !((_e = (_d = menuRef.current) === null || _d === void 0 ? void 0 : _d.querySelector("[data-iui-index=\"".concat(focusedIndexRef.current, "\"]"))) === null || _e === void 0 ? void 0 : _e.nextElementSibling)) {
68
+ return;
69
+ }
64
70
  var nextIndex = focusedIndexRef.current;
65
71
  do {
66
- var currentElement = (_d = menuRef.current) === null || _d === void 0 ? void 0 : _d.querySelector("[data-iui-index=\"".concat(nextIndex, "\"]"));
67
- var nextElement = (_e = currentElement === null || currentElement === void 0 ? void 0 : currentElement.nextElementSibling) !== null && _e !== void 0 ? _e : (_f = menuRef.current) === null || _f === void 0 ? void 0 : _f.querySelector('[data-iui-index]');
72
+ var currentElement = (_f = menuRef.current) === null || _f === void 0 ? void 0 : _f.querySelector("[data-iui-index=\"".concat(nextIndex, "\"]"));
73
+ var nextElement = (_g = currentElement === null || currentElement === void 0 ? void 0 : currentElement.nextElementSibling) !== null && _g !== void 0 ? _g : (_h = menuRef.current) === null || _h === void 0 ? void 0 : _h.querySelector('[data-iui-index]');
68
74
  nextIndex = Number(nextElement === null || nextElement === void 0 ? void 0 : nextElement.getAttribute('data-iui-index'));
69
75
  if ((nextElement === null || nextElement === void 0 ? void 0 : nextElement.ariaDisabled) !== 'true') {
70
76
  return dispatch(['focus', nextIndex]);
@@ -80,16 +86,21 @@ export var ComboBoxInput = React.forwardRef(function (props, forwardedRef) {
80
86
  if (length === 0) {
81
87
  return;
82
88
  }
89
+ // If virtualization is enabled, dont let round scrolling
90
+ if (enableVirtualization &&
91
+ !((_k = (_j = menuRef.current) === null || _j === void 0 ? void 0 : _j.querySelector("[data-iui-index=\"".concat(focusedIndexRef.current, "\"]"))) === null || _k === void 0 ? void 0 : _k.previousElementSibling)) {
92
+ return;
93
+ }
83
94
  if (focusedIndexRef.current === -1) {
84
95
  return dispatch([
85
96
  'focus',
86
- (_h = (_g = Object.values(optionsExtraInfoRef.current)) === null || _g === void 0 ? void 0 : _g[length - 1].__originalIndex) !== null && _h !== void 0 ? _h : -1,
97
+ (_m = (_l = Object.values(optionsExtraInfoRef.current)) === null || _l === void 0 ? void 0 : _l[length - 1].__originalIndex) !== null && _m !== void 0 ? _m : -1,
87
98
  ]);
88
99
  }
89
100
  var prevIndex = focusedIndexRef.current;
90
101
  do {
91
- var currentElement = (_j = menuRef.current) === null || _j === void 0 ? void 0 : _j.querySelector("[data-iui-index=\"".concat(prevIndex, "\"]"));
92
- var prevElement = (_k = currentElement === null || currentElement === void 0 ? void 0 : currentElement.previousElementSibling) !== null && _k !== void 0 ? _k : (_l = menuRef.current) === null || _l === void 0 ? void 0 : _l.querySelector('[data-iui-index]:last-of-type');
102
+ var currentElement = (_o = menuRef.current) === null || _o === void 0 ? void 0 : _o.querySelector("[data-iui-index=\"".concat(prevIndex, "\"]"));
103
+ var prevElement = (_p = currentElement === null || currentElement === void 0 ? void 0 : currentElement.previousElementSibling) !== null && _p !== void 0 ? _p : (_q = menuRef.current) === null || _q === void 0 ? void 0 : _q.querySelector('[data-iui-index]:last-of-type');
93
104
  prevIndex = Number(prevElement === null || prevElement === void 0 ? void 0 : prevElement.getAttribute('data-iui-index'));
94
105
  if ((prevElement === null || prevElement === void 0 ? void 0 : prevElement.ariaDisabled) !== 'true') {
95
106
  return dispatch(['focus', prevIndex]);
@@ -101,6 +112,7 @@ export var ComboBoxInput = React.forwardRef(function (props, forwardedRef) {
101
112
  event.preventDefault();
102
113
  if (isOpen) {
103
114
  dispatch(['select', focusedIndexRef.current]);
115
+ dispatch(['close']);
104
116
  }
105
117
  else {
106
118
  dispatch(['open']);
@@ -116,7 +128,14 @@ export var ComboBoxInput = React.forwardRef(function (props, forwardedRef) {
116
128
  dispatch(['close']);
117
129
  break;
118
130
  }
119
- }, [dispatch, isOpen, menuRef, onKeyDownProp, optionsExtraInfoRef]);
131
+ }, [
132
+ dispatch,
133
+ enableVirtualization,
134
+ isOpen,
135
+ menuRef,
136
+ onKeyDownProp,
137
+ optionsExtraInfoRef,
138
+ ]);
120
139
  var handleFocus = React.useCallback(function (event) {
121
140
  dispatch(['open']);
122
141
  onFocusProp === null || onFocusProp === void 0 ? void 0 : onFocusProp(event);
@@ -37,16 +37,24 @@ var VirtualizedComboBoxMenu = React.forwardRef(function (_a, forwardedRef) {
37
37
  var menuRef = useSafeContext(ComboBoxRefsContext).menuRef;
38
38
  var virtualItemRenderer = React.useCallback(function (index) {
39
39
  return filteredOptions.length > 0
40
- ? getMenuItem(filteredOptions[index])
40
+ ? getMenuItem(filteredOptions[index], index)
41
41
  : children;
42
42
  }, // Here is expected empty state content
43
43
  [filteredOptions, getMenuItem, children]);
44
+ var focusedVisibleIndex = React.useMemo(function () {
45
+ var _a, _b;
46
+ var currentElement = (_a = menuRef.current) === null || _a === void 0 ? void 0 : _a.querySelector("[data-iui-index=\"".concat(focusedIndex, "\"]"));
47
+ if (!currentElement) {
48
+ return focusedIndex;
49
+ }
50
+ return Number((_b = currentElement.getAttribute('data-iui-filtered-index')) !== null && _b !== void 0 ? _b : focusedIndex);
51
+ }, [focusedIndex, menuRef]);
44
52
  var _f = useVirtualization({
45
53
  // 'Fool' VirtualScroll by passing length 1
46
54
  // whenever there is no elements, to show empty state message
47
55
  itemsLength: filteredOptions.length || 1,
48
56
  itemRenderer: virtualItemRenderer,
49
- scrollToIndex: focusedIndex,
57
+ scrollToIndex: focusedVisibleIndex,
50
58
  }), outerProps = _f.outerProps, innerProps = _f.innerProps, visibleChildren = _f.visibleChildren;
51
59
  var overflowY = ((_d = (_c = (_b = getWindow()) === null || _b === void 0 ? void 0 : _b.CSS) === null || _c === void 0 ? void 0 : _c.supports) === null || _d === void 0 ? void 0 : _d.call(_c, 'overflow-x: overlay'))
52
60
  ? { overflowY: 'overlay' }
@@ -24,7 +24,7 @@ declare type ComboBoxStateContextProps<T = unknown> = {
24
24
  minWidth: number;
25
25
  enableVirtualization: boolean;
26
26
  filteredOptions: SelectOption<T>[];
27
- getMenuItem: (option: SelectOption<T>) => JSX.Element;
27
+ getMenuItem: (option: SelectOption<T>, filteredIndex?: number) => JSX.Element;
28
28
  focusedIndex?: number;
29
29
  };
30
30
  export declare const ComboBoxStateContext: React.Context<ComboBoxStateContextProps<unknown> | undefined>;
@@ -25,7 +25,7 @@ export var comboBoxReducer = function (state, _a) {
25
25
  return __assign(__assign({}, state), { isOpen: false });
26
26
  }
27
27
  case 'select': {
28
- return __assign(__assign({}, state), { isOpen: false, selectedIndex: value !== null && value !== void 0 ? value : state.selectedIndex, focusedIndex: value !== null && value !== void 0 ? value : state.focusedIndex });
28
+ return __assign(__assign({}, state), { selectedIndex: value !== null && value !== void 0 ? value : state.selectedIndex, focusedIndex: value !== null && value !== void 0 ? value : state.focusedIndex });
29
29
  }
30
30
  case 'focus': {
31
31
  return __assign(__assign({}, state), { focusedIndex: (_b = value !== null && value !== void 0 ? value : state.selectedIndex) !== null && _b !== void 0 ? _b : -1 });
@@ -5,7 +5,7 @@ import { TimePickerProps } from '../TimePicker';
5
5
  * Generate localized months and days strings using `Intl.DateTimeFormat` for passed locale to use in DatePicker component.
6
6
  * If locale is not passed, browser locale will be used.
7
7
  */
8
- export declare const generateLocalizedStrings: (locale?: string | undefined) => {
8
+ export declare const generateLocalizedStrings: (locale?: string) => {
9
9
  months: string[];
10
10
  shortDays: string[];
11
11
  days: string[];
@@ -0,0 +1,32 @@
1
+ /// <reference types="react" />
2
+ import { CommonProps } from '../utils';
3
+ import '@itwin/itwinui-css/css/menu.css';
4
+ export declare type MenuItemSkeletonProps = {
5
+ /**
6
+ * Flag whether to show skeleton for sub-label.
7
+ */
8
+ hasSublabel?: boolean;
9
+ /**
10
+ * Flag whether to show skeleton for icon.
11
+ */
12
+ hasIcon?: boolean;
13
+ /**
14
+ * Skeleton content width.
15
+ */
16
+ contentWidth?: string;
17
+ /**
18
+ * Translated strings used for accessibility.
19
+ */
20
+ translatedStrings?: {
21
+ /**
22
+ * Label for loading state. Defaults to "Loading…".
23
+ * It is only visible for the screen readers.
24
+ */
25
+ loading: string;
26
+ };
27
+ } & CommonProps;
28
+ /**
29
+ * Menu item that uses skeletons to indicate loading state.
30
+ */
31
+ export declare const MenuItemSkeleton: (props: MenuItemSkeletonProps) => JSX.Element;
32
+ export default MenuItemSkeleton;
@@ -0,0 +1,46 @@
1
+ var __assign = (this && this.__assign) || function () {
2
+ __assign = Object.assign || function(t) {
3
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
4
+ s = arguments[i];
5
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
6
+ t[p] = s[p];
7
+ }
8
+ return t;
9
+ };
10
+ return __assign.apply(this, arguments);
11
+ };
12
+ var __rest = (this && this.__rest) || function (s, e) {
13
+ var t = {};
14
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
15
+ t[p] = s[p];
16
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
17
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
18
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
19
+ t[p[i]] = s[p[i]];
20
+ }
21
+ return t;
22
+ };
23
+ /*---------------------------------------------------------------------------------------------
24
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
25
+ * See LICENSE.md in the project root for license terms and full copyright notice.
26
+ *--------------------------------------------------------------------------------------------*/
27
+ import React from 'react';
28
+ import cx from 'classnames';
29
+ import { useTheme, VisuallyHidden } from '../utils';
30
+ import '@itwin/itwinui-css/css/menu.css';
31
+ /**
32
+ * Menu item that uses skeletons to indicate loading state.
33
+ */
34
+ export var MenuItemSkeleton = function (props) {
35
+ var hasSublabel = props.hasSublabel, hasIcon = props.hasIcon, contentWidth = props.contentWidth, _a = props.translatedStrings, translatedStrings = _a === void 0 ? { loading: 'Loading…' } : _a, className = props.className, style = props.style, rest = __rest(props, ["hasSublabel", "hasIcon", "contentWidth", "translatedStrings", "className", "style"]);
36
+ useTheme();
37
+ return (React.createElement("li", __assign({ className: cx('iui-menu-item', 'iui-menu-item-skeleton', { 'iui-large': hasSublabel }, className), style: __assign({
38
+ '--iui-menu-item-content-skeleton-max-width': contentWidth,
39
+ }, style) }, rest),
40
+ hasIcon && React.createElement("div", { className: 'iui-icon iui-skeleton', "aria-hidden": true }),
41
+ React.createElement("span", { className: 'iui-content' },
42
+ React.createElement("div", { className: 'iui-menu-label iui-skeleton', "aria-hidden": true }),
43
+ hasSublabel && (React.createElement("div", { className: 'iui-menu-description iui-skeleton', "aria-hidden": true })),
44
+ React.createElement(VisuallyHidden, null, translatedStrings.loading))));
45
+ };
46
+ export default MenuItemSkeleton;
@@ -6,3 +6,5 @@ export { MenuDivider } from './MenuDivider';
6
6
  export type { MenuDividerProps } from './MenuDivider';
7
7
  export { MenuExtraContent } from './MenuExtraContent';
8
8
  export type { MenuExtraContentProps } from './MenuExtraContent';
9
+ export { MenuItemSkeleton } from './MenuItemSkeleton';
10
+ export type { MenuItemSkeletonProps } from './MenuItemSkeleton';
@@ -6,3 +6,4 @@ export { Menu } from './Menu';
6
6
  export { MenuItem } from './MenuItem';
7
7
  export { MenuDivider } from './MenuDivider';
8
8
  export { MenuExtraContent } from './MenuExtraContent';
9
+ export { MenuItemSkeleton } from './MenuItemSkeleton';
@@ -32,11 +32,11 @@ import { useTheme, useResizeObserver } from '../utils';
32
32
  import '@itwin/itwinui-css/css/table.css';
33
33
  import SvgSortDown from '@itwin/itwinui-icons-react/cjs/icons/SortDown';
34
34
  import SvgSortUp from '@itwin/itwinui-icons-react/cjs/icons/SortUp';
35
- import { getCellStyle } from './utils';
35
+ import { getCellStyle, getStickyStyle } from './utils';
36
36
  import { TableRowMemoized } from './TableRowMemoized';
37
37
  import { FilterToggle } from './filters';
38
38
  import { customFilterFunctions } from './filters/customFilterFunctions';
39
- import { useExpanderCell, useSelectionCell, useSubRowFiltering, useSubRowSelection, useResizeColumns, useColumnDragAndDrop, } from './hooks';
39
+ import { useExpanderCell, useSelectionCell, useSubRowFiltering, useSubRowSelection, useResizeColumns, useColumnDragAndDrop, useStickyColumns, } from './hooks';
40
40
  import { onExpandHandler, onFilterHandler, onSelectHandler, onSingleSelectHandler, onTableResizeEnd, onTableResizeStart, } from './actionHandlers';
41
41
  import VirtualScroll from '../utils/components/VirtualScroll';
42
42
  import { SELECTION_CELL_ID } from './columns';
@@ -171,8 +171,8 @@ export var Table = function (props) {
171
171
  return getSubRows ? getSubRows(item, index) : item.subRows;
172
172
  });
173
173
  }, [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));
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;
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;
176
176
  var ariaDataAttributes = Object.entries(rest).reduce(function (result, _a) {
177
177
  var key = _a[0], value = _a[1];
178
178
  if (key.startsWith('data-') || key.startsWith('aria-')) {
@@ -181,6 +181,12 @@ export var Table = function (props) {
181
181
  return result;
182
182
  }, {});
183
183
  var areFiltersSet = allColumns.some(function (column) { return column.filterValue != null && column.filterValue !== ''; });
184
+ var showFilterButton = function (column) {
185
+ return (data.length !== 0 || areFiltersSet) && column.canFilter;
186
+ };
187
+ var showSortButton = function (column) {
188
+ return data.length !== 0 && column.canSort;
189
+ };
184
190
  var onRowClickHandler = React.useCallback(function (event, row) {
185
191
  var isDisabled = isRowDisabled === null || isRowDisabled === void 0 ? void 0 : isRowDisabled(row.original);
186
192
  if (!isDisabled) {
@@ -281,6 +287,30 @@ export var Table = function (props) {
281
287
  subComponent,
282
288
  ]);
283
289
  var virtualizedItemRenderer = React.useCallback(function (index) { return getPreparedRow(index); }, [getPreparedRow]);
290
+ var updateStickyState = function () {
291
+ if (!bodyRef.current || flatHeaders.every(function (header) { return !header.sticky; })) {
292
+ return;
293
+ }
294
+ if (bodyRef.current.scrollLeft !== 0) {
295
+ dispatch({ type: TableActions.setScrolledRight, value: true });
296
+ }
297
+ else {
298
+ dispatch({ type: TableActions.setScrolledRight, value: false });
299
+ }
300
+ // If scrolled a bit to the left looking from the right side
301
+ if (bodyRef.current.scrollLeft !==
302
+ bodyRef.current.scrollWidth - bodyRef.current.clientWidth) {
303
+ dispatch({ type: TableActions.setScrolledLeft, value: true });
304
+ }
305
+ else {
306
+ dispatch({ type: TableActions.setScrolledLeft, value: false });
307
+ }
308
+ };
309
+ React.useEffect(function () {
310
+ updateStickyState();
311
+ // Call only on init
312
+ // eslint-disable-next-line react-hooks/exhaustive-deps
313
+ }, []);
284
314
  return (React.createElement(React.Fragment, null,
285
315
  React.createElement("div", __assign({ ref: function (element) {
286
316
  setOwnerDocument(element === null || element === void 0 ? void 0 : element.ownerDocument);
@@ -289,30 +319,42 @@ export var Table = function (props) {
289
319
  }
290
320
  }, id: id }, getTableProps({
291
321
  className: cx('iui-table', (_a = {}, _a["iui-".concat(density)] = density !== 'default', _a), className),
292
- style: style,
322
+ style: __assign({ minWidth: 0 }, style),
293
323
  }), ariaDataAttributes),
294
- React.createElement("div", { className: 'iui-table-header', ref: headerRef }, headerGroups.slice(1).map(function (headerGroup) {
295
- var headerGroupProps = headerGroup.getHeaderGroupProps({
296
- className: 'iui-row',
297
- });
298
- return (React.createElement("div", __assign({}, headerGroupProps, { key: headerGroupProps.key }), headerGroup.headers.map(function (column, index) {
299
- var columnProps = column.getHeaderProps(__assign(__assign({}, column.getSortByToggleProps()), { className: cx('iui-cell', { 'iui-actionable': column.canSort }, { 'iui-sorted': column.isSorted }, column.columnClassName), style: __assign(__assign({}, getCellStyle(column, !!state.isTableResizing)), { flexWrap: 'unset' }) }));
300
- return (React.createElement("div", __assign({}, columnProps, column.getDragAndDropProps(), { key: columnProps.key, title: undefined, ref: function (el) {
301
- if (el && isResizable) {
302
- columnRefs.current[column.id] = el;
303
- column.resizeWidth = el.getBoundingClientRect().width;
304
- }
305
- } }),
306
- column.render('Header'),
307
- (data.length !== 0 || areFiltersSet) && (React.createElement(FilterToggle, { column: column, ownerDocument: ownerDocument })),
308
- data.length !== 0 && column.canSort && (React.createElement("div", { className: 'iui-cell-end-icon' }, column.isSorted && column.isSortedDesc ? (React.createElement(SvgSortDown, { className: 'iui-icon iui-sort', "aria-hidden": true })) : (React.createElement(SvgSortUp, { className: 'iui-icon iui-sort', "aria-hidden": true })))),
309
- isResizable &&
310
- column.isResizerVisible &&
311
- index !== headerGroup.headers.length - 1 && (React.createElement("div", __assign({}, column.getResizerProps(), { className: 'iui-resizer' }),
312
- React.createElement("div", { className: 'iui-resizer-bar' }))),
313
- enableColumnReordering && !column.disableReordering && (React.createElement("div", { className: 'iui-reorder-bar' }))));
314
- })));
315
- })),
324
+ React.createElement("div", { className: 'iui-table-header-wrapper', ref: headerRef },
325
+ React.createElement("div", { className: 'iui-table-header' }, headerGroups.slice(1).map(function (headerGroup) {
326
+ var headerGroupProps = headerGroup.getHeaderGroupProps({
327
+ className: 'iui-row',
328
+ });
329
+ return (React.createElement("div", __assign({}, headerGroupProps, { key: headerGroupProps.key }), headerGroup.headers.map(function (column, index) {
330
+ var columnProps = column.getHeaderProps(__assign(__assign({}, column.getSortByToggleProps()), { className: cx('iui-cell', {
331
+ 'iui-actionable': column.canSort,
332
+ 'iui-sorted': column.isSorted,
333
+ 'iui-cell-sticky': !!column.sticky,
334
+ }, column.columnClassName), style: __assign(__assign(__assign({}, getCellStyle(column, !!state.isTableResizing)), getStickyStyle(column, visibleColumns)), { flexWrap: 'unset' }) }));
335
+ return (React.createElement("div", __assign({}, columnProps, column.getDragAndDropProps(), { key: columnProps.key, title: undefined, ref: function (el) {
336
+ if (el) {
337
+ columnRefs.current[column.id] = el;
338
+ column.resizeWidth = el.getBoundingClientRect().width;
339
+ }
340
+ } }),
341
+ column.render('Header'),
342
+ (showFilterButton(column) ||
343
+ showSortButton(column)) && (React.createElement("div", { className: 'iui-table-header-actions-container' },
344
+ showFilterButton(column) && (React.createElement(FilterToggle, { column: column, ownerDocument: ownerDocument })),
345
+ showSortButton(column) && (React.createElement("div", { className: 'iui-cell-end-icon' }, column.isSorted && column.isSortedDesc ? (React.createElement(SvgSortDown, { className: 'iui-icon iui-sort', "aria-hidden": true })) : (React.createElement(SvgSortUp, { className: 'iui-icon iui-sort', "aria-hidden": true })))))),
346
+ isResizable &&
347
+ column.isResizerVisible &&
348
+ index !== headerGroup.headers.length - 1 && (React.createElement("div", __assign({}, column.getResizerProps(), { className: 'iui-resizer' }),
349
+ React.createElement("div", { className: 'iui-resizer-bar' }))),
350
+ enableColumnReordering &&
351
+ !column.disableReordering && (React.createElement("div", { className: 'iui-reorder-bar' })),
352
+ column.sticky === 'left' &&
353
+ state.sticky.isScrolledToRight && (React.createElement("div", { className: 'iui-cell-shadow-right' })),
354
+ column.sticky === 'right' &&
355
+ state.sticky.isScrolledToLeft && (React.createElement("div", { className: 'iui-cell-shadow-left' }))));
356
+ })));
357
+ }))),
316
358
  React.createElement("div", __assign({}, getTableBodyProps({
317
359
  className: cx('iui-table-body', {
318
360
  'iui-zebra-striping': styleType === 'zebra-rows',
@@ -321,6 +363,7 @@ export var Table = function (props) {
321
363
  }), { ref: bodyRef, onScroll: function () {
322
364
  if (headerRef.current && bodyRef.current) {
323
365
  headerRef.current.scrollLeft = bodyRef.current.scrollLeft;
366
+ updateStickyState();
324
367
  }
325
368
  }, tabIndex: -1 }),
326
369
  data.length !== 0 && (React.createElement(React.Fragment, null, enableVirtualization ? (React.createElement(VirtualScroll, { itemsLength: page.length, itemRenderer: virtualizedItemRenderer })) : (page.map(function (_, index) { return getPreparedRow(index); })))),
@@ -15,7 +15,7 @@ var __assign = (this && this.__assign) || function () {
15
15
  *--------------------------------------------------------------------------------------------*/
16
16
  import React from 'react';
17
17
  import cx from 'classnames';
18
- import { getCellStyle } from './utils';
18
+ import { getCellStyle, getStickyStyle } from './utils';
19
19
  import { SubRowExpander } from './SubRowExpander';
20
20
  import { SELECTION_CELL_ID } from './columns';
21
21
  import { DefaultCell } from './cells';
@@ -34,8 +34,10 @@ export var TableCell = function (props) {
34
34
  };
35
35
  };
36
36
  var cellElementProps = cell.getCellProps({
37
- className: cx('iui-cell', cell.column.cellClassName),
38
- style: __assign(__assign({}, getCellStyle(cell.column, !!tableInstance.state.isTableResizing)), getSubRowStyle()),
37
+ className: cx('iui-cell', cell.column.cellClassName, {
38
+ 'iui-cell-sticky': !!cell.column.sticky,
39
+ }),
40
+ style: __assign(__assign(__assign({}, getCellStyle(cell.column, !!tableInstance.state.isTableResizing)), getSubRowStyle()), getStickyStyle(cell.column, tableInstance.visibleColumns)),
39
41
  });
40
42
  var cellProps = __assign(__assign({}, tableInstance), { cell: cell, row: cell.row, value: cell.value, column: cell.column });
41
43
  var cellContent = (React.createElement(React.Fragment, null,
@@ -44,7 +46,12 @@ export var TableCell = function (props) {
44
46
  var cellRendererProps = {
45
47
  cellElementProps: cellElementProps,
46
48
  cellProps: cellProps,
47
- children: cellContent,
49
+ children: (React.createElement(React.Fragment, null,
50
+ cellContent,
51
+ cell.column.sticky === 'left' &&
52
+ tableInstance.state.sticky.isScrolledToRight && (React.createElement("div", { className: 'iui-cell-shadow-right' })),
53
+ cell.column.sticky === 'right' &&
54
+ tableInstance.state.sticky.isScrolledToLeft && (React.createElement("div", { className: 'iui-cell-shadow-left' })))),
48
55
  };
49
56
  return (React.createElement(React.Fragment, null, cell.column.cellRenderer ? (cell.column.cellRenderer(__assign(__assign({}, cellRendererProps), { isDisabled: function () { return isDisabled; } }))) : (React.createElement(DefaultCell, __assign({}, cellRendererProps, { isDisabled: function () { return isDisabled; } })))));
50
57
  };