@itwin/itwinui-react 2.0.0 → 2.0.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 (56) hide show
  1. package/CHANGELOG.md +22 -4
  2. package/cjs/core/Avatar/Avatar.d.ts +1 -1
  3. package/cjs/core/AvatarGroup/AvatarGroup.d.ts +1 -1
  4. package/cjs/core/AvatarGroup/AvatarGroup.js +1 -1
  5. package/cjs/core/Carousel/CarouselSlider.js +2 -2
  6. package/cjs/core/ColorPicker/ColorBuilder.js +2 -7
  7. package/cjs/core/ColorPicker/ColorPalette.js +1 -1
  8. package/cjs/core/ColorPicker/ColorPicker.js +1 -3
  9. package/cjs/core/ComboBox/ComboBox.js +1 -1
  10. package/cjs/core/ComboBox/ComboBoxMenu.js +1 -1
  11. package/cjs/core/Dialog/DialogMain.js +1 -1
  12. package/cjs/core/Modal/ModalButtonBar.d.ts +1 -1
  13. package/cjs/core/Modal/ModalButtonBar.js +10 -1
  14. package/cjs/core/Modal/ModalContent.d.ts +1 -1
  15. package/cjs/core/Modal/ModalContent.js +10 -1
  16. package/cjs/core/Table/Table.js +1 -1
  17. package/cjs/core/Table/TablePaginator.d.ts +6 -0
  18. package/cjs/core/Table/TablePaginator.js +2 -1
  19. package/cjs/core/Table/hooks/useColumnDragAndDrop.js +3 -1
  20. package/cjs/core/Tabs/Tabs.js +3 -3
  21. package/cjs/core/utils/color/ColorValue.js +4 -2
  22. package/cjs/core/utils/components/Resizer.js +3 -2
  23. package/cjs/core/utils/components/VirtualScroll.js +7 -8
  24. package/cjs/core/utils/functions/styles.d.ts +1 -1
  25. package/cjs/core/utils/functions/styles.js +1 -1
  26. package/cjs/core/utils/hooks/useDragAndDrop.js +1 -1
  27. package/cjs/core/utils/hooks/useOverflow.js +4 -3
  28. package/cjs/core/utils/hooks/useTheme.js +2 -2
  29. package/esm/core/Avatar/Avatar.d.ts +1 -1
  30. package/esm/core/AvatarGroup/AvatarGroup.d.ts +1 -1
  31. package/esm/core/AvatarGroup/AvatarGroup.js +1 -1
  32. package/esm/core/Carousel/CarouselSlider.js +3 -3
  33. package/esm/core/ColorPicker/ColorBuilder.js +2 -7
  34. package/esm/core/ColorPicker/ColorPalette.js +1 -1
  35. package/esm/core/ColorPicker/ColorPicker.js +1 -3
  36. package/esm/core/ComboBox/ComboBox.js +2 -2
  37. package/esm/core/ComboBox/ComboBoxMenu.js +1 -1
  38. package/esm/core/Dialog/DialogMain.js +2 -2
  39. package/esm/core/Modal/ModalButtonBar.d.ts +1 -1
  40. package/esm/core/Modal/ModalButtonBar.js +6 -1
  41. package/esm/core/Modal/ModalContent.d.ts +1 -1
  42. package/esm/core/Modal/ModalContent.js +6 -1
  43. package/esm/core/Table/Table.js +2 -2
  44. package/esm/core/Table/TablePaginator.d.ts +6 -0
  45. package/esm/core/Table/TablePaginator.js +2 -1
  46. package/esm/core/Table/hooks/useColumnDragAndDrop.js +3 -1
  47. package/esm/core/Tabs/Tabs.js +4 -4
  48. package/esm/core/utils/color/ColorValue.js +4 -2
  49. package/esm/core/utils/components/Resizer.js +3 -2
  50. package/esm/core/utils/components/VirtualScroll.js +7 -8
  51. package/esm/core/utils/functions/styles.d.ts +1 -1
  52. package/esm/core/utils/functions/styles.js +1 -1
  53. package/esm/core/utils/hooks/useDragAndDrop.js +1 -1
  54. package/esm/core/utils/hooks/useOverflow.js +4 -3
  55. package/esm/core/utils/hooks/useTheme.js +2 -2
  56. package/package.json +4 -5
package/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ### [2.0.1](https://www.github.com/iTwin/iTwinUI-react/compare/v2.0.0...v2.0.1) (2022-12-05)
4
+
5
+ ### Fixes
6
+
7
+ * **useTheme:** Exit early if theme is already set on body ([#963](https://www.github.com/iTwin/iTwinUI-react/issues/963)) ([29033d4](https://www.github.com/iTwin/iTwinUI-react/commit/29033d488bc6cefb3ea064305898ade85475e2ff))
8
+ * **ModalButtonBar, ModalContent:** Wrap `DialogButtonBar` and `DialogContent` instead of directly assigning ([#961](https://www.github.com/iTwin/iTwinUI-react/issues/961)) ([0881e92](https://www.github.com/iTwin/iTwinUI-react/commit/0881e92f037b7ce717f05742014ac2d6dd8c580d))
9
+ * **Table:** Added localization for selected rows count ([#945](https://www.github.com/iTwin/iTwinUI-react/issues/945)) ([71f2326](https://www.github.com/iTwin/iTwinUI-react/commit/71f232605237e0095ebe0bff4cf01d241c143c49))
10
+ * Replaced all instances of `useLayoutEffect` with `useIsomorphicLayoutEffect` to fix SSR warnings ([#964](https://www.github.com/iTwin/iTwinUI-react/issues/964)) ([15b0389](https://www.github.com/iTwin/iTwinUI-react/commit/15b038934e55d3f61631113d91f2952127426c1d))
11
+ * Fixed css warnings about `start` vs `flex-start` through base itwinui-css update ([#962](https://www.github.com/iTwin/iTwinUI-react/issues/962))
12
+
3
13
  ## [2.0.0](https://www.github.com/iTwin/iTwinUI-react/compare/v1.48.1...v2.0.0) (2022-11-15)
4
14
 
5
15
  Welcome to the v2 release of iTwinUI-react. 🎉
@@ -10,11 +20,19 @@ These release notes offer a brief summary of the main changes. Check out the [iT
10
20
 
11
21
  ### ⚠ BREAKING CHANGES
12
22
 
13
- There is only one new breaking change in this release.
23
+ iTwinUI no longer supports Internet Explorer. The build output now targets `es2018` rather than `es5`, and CSS variables and grid are used without fallbacks.
24
+
25
+ As for breaking API changes, there is only one:
14
26
 
15
27
  * **Table:** `columns` prop must now be an array. First level `Header` is no longer required ([#935](https://www.github.com/iTwin/iTwinUI-react/issues/935)) ([83d5cfe](https://www.github.com/iTwin/iTwinUI-react/commit/83d5cfe93980b628c79ec3951d05663a054699fc))
28
+ ```diff
29
+ - const columns = { Header: 'Table', columns: [{ accessor: 'name', Header: 'Name' }, … ] };
30
+ + const columns = [{ accessor: 'name', Header: 'Name' }, … ];
31
+
32
+ <Table columns={columns} data={data} />
33
+ ```
16
34
 
17
- Other than that, we have removed props and components that were already deprecated in v1.
35
+ Other than that, props and components that were already deprecated in v1 have been removed:
18
36
 
19
37
  * **Tabs:** Remove deprecated `HorizontalTab` and `HorizontalTabProps` ([#852](https://www.github.com/iTwin/iTwinUI-react/issues/852)) ([31ddeae](https://www.github.com/iTwin/iTwinUI-react/commit/31ddeaed3dc5919f69edb1bd9580d766fabc35c2))
20
38
  * **Checkbox, Radio:** Remove deprecated `checkmarkClassName` and `checkmarkStyle` ([#855](https://www.github.com/iTwin/iTwinUI-react/issues/855)) ([5c339be](https://www.github.com/iTwin/iTwinUI-react/commit/5c339beddd117bdf5a834b96dff65d4fd67d5255))
@@ -22,7 +40,7 @@ Other than that, we have removed props and components that were already deprecat
22
40
 
23
41
  ### Deprecations
24
42
 
25
- We have taken this opportunity to deprecate a few more things while not removing them just yet, to minimize the number of breaking changes.
43
+ We have also taken this opportunity to deprecate a few more things while not removing them just yet, to minimize the number of breaking changes.
26
44
 
27
45
  * **Avatar, AvatarGroup:** Deprecate `UserIcon`/`UserIconGroup`, replace with `Avatar`/`AvatarGroup` ([#902](https://www.github.com/iTwin/iTwinUI-react/issues/902)) ([4001bd1](https://www.github.com/iTwin/iTwinUI-react/commit/4001bd12aa9021fdcbb3e49c271eec10ec853a83))
28
46
  - Also deprecated `userIcon` prop in `Header`.
@@ -40,7 +58,7 @@ We have taken this opportunity to deprecate a few more things while not removing
40
58
  * **Table:** Row selection count for paginator ([#837](https://www.github.com/iTwin/iTwinUI-react/issues/837)) ([e43148a](https://www.github.com/iTwin/iTwinUI-react/commit/e43148af9fc6250cf2470d258831a3ef8d33e582))
41
59
  * **Tile:** Add status and loading state ([#872](https://www.github.com/iTwin/iTwinUI-react/issues/872)) ([2fcb41f](https://www.github.com/iTwin/iTwinUI-react/commit/2fcb41f5c41a8a32d32a3312edecf8e2b646033e))
42
60
 
43
- If you're interested in more details about every signle change, check out a full diff in [`v1.48.1..v2.0.0`](https://www.github.com/iTwin/iTwinUI/compare/v1.48.1...v2.0.0).
61
+ If you're interested in more details about every signle change, check out a full diff in [`v1.48.1..v2.0.0`](https://www.github.com/iTwin/iTwinUI-react/compare/v1.48.1...v2.0.0).
44
62
 
45
63
  ## 1.X
46
64
 
@@ -11,7 +11,7 @@ export declare type StatusTitles = {
11
11
  };
12
12
  export declare type AvatarProps = {
13
13
  /**
14
- * Size of a avatar.
14
+ * Size of an avatar.
15
15
  * @default 'small'
16
16
  */
17
17
  size?: 'small' | 'medium' | 'large' | 'x-large';
@@ -44,7 +44,7 @@ export declare type UserIconGroupProps = AvatarGroupProps;
44
44
  * You can add custom Count Avatar behavior by using `countAvatarProps`.
45
45
  *
46
46
  * @example
47
- * <AvatarGroup avatarSize='medium'>
47
+ * <AvatarGroup iconSize='medium'>
48
48
  * <Avatar
49
49
  * abbreviation="TR"
50
50
  * backgroundColor={getUserColor("Terry Rivers")}
@@ -21,7 +21,7 @@ require("@itwin/itwinui-css/css/avatar.css");
21
21
  * You can add custom Count Avatar behavior by using `countAvatarProps`.
22
22
  *
23
23
  * @example
24
- * <AvatarGroup avatarSize='medium'>
24
+ * <AvatarGroup iconSize='medium'>
25
25
  * <Avatar
26
26
  * abbreviation="TR"
27
27
  * backgroundColor={getUserColor("Terry Rivers")}
@@ -21,7 +21,7 @@ exports.CarouselSlider = react_1.default.forwardRef((props, ref) => {
21
21
  if (!context) {
22
22
  throw new Error('CarouselSlider must be used within Carousel');
23
23
  }
24
- const { setSlideCount, idPrefix, scrollToSlide, isManuallyUpdating, } = context;
24
+ const { setSlideCount, idPrefix, scrollToSlide, isManuallyUpdating } = context;
25
25
  const items = react_1.default.useMemo(() => {
26
26
  var _a;
27
27
  return (_a = react_1.default.Children.map(children, (child, index) => react_1.default.isValidElement(child)
@@ -31,7 +31,7 @@ exports.CarouselSlider = react_1.default.forwardRef((props, ref) => {
31
31
  })
32
32
  : child)) !== null && _a !== void 0 ? _a : [];
33
33
  }, [children, idPrefix]);
34
- react_1.default.useLayoutEffect(() => {
34
+ (0, utils_1.useIsomorphicLayoutEffect)(() => {
35
35
  setSlideCount(items.length);
36
36
  }, [items.length, setSlideCount]);
37
37
  const sliderRef = react_1.default.useRef(null);
@@ -37,14 +37,9 @@ exports.ColorBuilder = react_1.default.forwardRef((props, ref) => {
37
37
  // Set values for slider
38
38
  const hueSliderColor = react_1.default.useMemo(() => utils_1.ColorValue.create({ h: hsvColor.h, s: 100, v: 100 }), [hsvColor.h]);
39
39
  const sliderValue = react_1.default.useMemo(() => hsvColor.h, [hsvColor]);
40
- const alphaValue = react_1.default.useMemo(() => { var _a; return (showAlpha ? (_a = hsvColor.a) !== null && _a !== void 0 ? _a : 1 : 1); }, [
41
- hsvColor.a,
42
- showAlpha,
43
- ]);
40
+ const alphaValue = react_1.default.useMemo(() => { var _a; return (showAlpha ? (_a = hsvColor.a) !== null && _a !== void 0 ? _a : 1 : 1); }, [hsvColor.a, showAlpha]);
44
41
  // Set values for color square and color dot
45
- const dotColorString = react_1.default.useMemo(() => activeColor.toHexString(), [
46
- activeColor,
47
- ]);
42
+ const dotColorString = react_1.default.useMemo(() => activeColor.toHexString(), [activeColor]);
48
43
  const [colorDotActive, setColorDotActive] = react_1.default.useState(false);
49
44
  const hueColorString = hueSliderColor.toHexString();
50
45
  const squareTop = 100 - hsvColor.v;
@@ -29,7 +29,7 @@ require("@itwin/itwinui-css/css/color-picker.css");
29
29
  exports.ColorPalette = react_1.default.forwardRef((props, ref) => {
30
30
  const { colors, label, className, children, ...rest } = props;
31
31
  (0, utils_1.useTheme)();
32
- const { activeColor, setActiveColor, onChangeComplete, } = (0, ColorPickerContext_1.useColorPickerContext)();
32
+ const { activeColor, setActiveColor, onChangeComplete } = (0, ColorPickerContext_1.useColorPickerContext)();
33
33
  const [focusedIndex, setFocusedIndex] = react_1.default.useState();
34
34
  // callback ref to set tabindex=0 on first child if none of the swatches are tabbable
35
35
  const setDefaultTabIndex = (el) => {
@@ -44,9 +44,7 @@ const ColorPicker = (props) => {
44
44
  tabbableElements[0].focus();
45
45
  }
46
46
  }, [setFocus]);
47
- const inColor = react_1.default.useMemo(() => (0, exports.getColorValue)(selectedColor), [
48
- selectedColor,
49
- ]);
47
+ const inColor = react_1.default.useMemo(() => (0, exports.getColorValue)(selectedColor), [selectedColor]);
50
48
  const activeColorTbgr = react_1.default.useRef(inColor.toTbgr());
51
49
  const [activeColor, setActiveColor] = react_1.default.useState(inColor); // Color of colorDot or active ColorSwatch
52
50
  react_1.default.useEffect(() => {
@@ -79,7 +79,7 @@ const ComboBox = (props) => {
79
79
  : -1,
80
80
  focusedIndex: -1,
81
81
  });
82
- react_1.default.useLayoutEffect(() => {
82
+ (0, utils_1.useIsomorphicLayoutEffect)(() => {
83
83
  var _a, _b;
84
84
  // When the dropdown opens
85
85
  if (isOpen) {
@@ -16,7 +16,7 @@ const utils_1 = require("../utils");
16
16
  const helpers_1 = require("./helpers");
17
17
  const VirtualizedComboBoxMenu = react_1.default.forwardRef(({ children, className, style, ...rest }, forwardedRef) => {
18
18
  var _a, _b, _c;
19
- const { minWidth, id, filteredOptions, getMenuItem, focusedIndex, } = (0, utils_1.useSafeContext)(helpers_1.ComboBoxStateContext);
19
+ const { minWidth, id, filteredOptions, getMenuItem, focusedIndex } = (0, utils_1.useSafeContext)(helpers_1.ComboBoxStateContext);
20
20
  const { menuRef } = (0, utils_1.useSafeContext)(helpers_1.ComboBoxRefsContext);
21
21
  const virtualItemRenderer = react_1.default.useCallback((index) => filteredOptions.length > 0
22
22
  ? getMenuItem(filteredOptions[index], index)
@@ -108,7 +108,7 @@ exports.DialogMain = react_1.default.forwardRef((props, ref) => {
108
108
  }
109
109
  }, [isDraggable, onPointerDown]);
110
110
  // Prevents dialog from moving when window is being resized
111
- react_1.default.useLayoutEffect(() => {
111
+ (0, utils_1.useIsomorphicLayoutEffect)(() => {
112
112
  var _a;
113
113
  if (!isDraggable || !isOpen) {
114
114
  return;
@@ -9,5 +9,5 @@ export declare type ModalButtonBarProps = {
9
9
  /**
10
10
  * Container for Buttons in modal.
11
11
  */
12
- export declare const ModalButtonBar: React.ForwardRefExoticComponent<Pick<import("../Dialog/DialogButtonBar").DialogButtonBarProps, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & React.RefAttributes<HTMLDivElement>>;
12
+ export declare const ModalButtonBar: (props: ModalButtonBarProps) => JSX.Element;
13
13
  export default ModalButtonBar;
@@ -1,9 +1,18 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.ModalButtonBar = void 0;
7
+ /*---------------------------------------------------------------------------------------------
8
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
9
+ * See LICENSE.md in the project root for license terms and full copyright notice.
10
+ *--------------------------------------------------------------------------------------------*/
11
+ const react_1 = __importDefault(require("react"));
4
12
  const DialogButtonBar_1 = require("../Dialog/DialogButtonBar");
5
13
  /**
6
14
  * Container for Buttons in modal.
7
15
  */
8
- exports.ModalButtonBar = DialogButtonBar_1.DialogButtonBar;
16
+ const ModalButtonBar = (props) => (react_1.default.createElement(DialogButtonBar_1.DialogButtonBar, { ...props }));
17
+ exports.ModalButtonBar = ModalButtonBar;
9
18
  exports.default = exports.ModalButtonBar;
@@ -9,5 +9,5 @@ export declare type ModalContentProps = {
9
9
  /**
10
10
  * Container for content in `Modal`.
11
11
  */
12
- export declare const ModalContent: React.ForwardRefExoticComponent<Pick<import("../Dialog/DialogContent").DialogContentProps, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & React.RefAttributes<HTMLDivElement>>;
12
+ export declare const ModalContent: (props: ModalContentProps) => JSX.Element;
13
13
  export default ModalContent;
@@ -1,9 +1,18 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.ModalContent = void 0;
7
+ /*---------------------------------------------------------------------------------------------
8
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
9
+ * See LICENSE.md in the project root for license terms and full copyright notice.
10
+ *--------------------------------------------------------------------------------------------*/
11
+ const react_1 = __importDefault(require("react"));
4
12
  const DialogContent_1 = require("../Dialog/DialogContent");
5
13
  /**
6
14
  * Container for content in `Modal`.
7
15
  */
8
- exports.ModalContent = DialogContent_1.DialogContent;
16
+ const ModalContent = (props) => (react_1.default.createElement(DialogContent_1.DialogContent, { ...props }));
17
+ exports.ModalContent = ModalContent;
9
18
  exports.default = exports.ModalContent;
@@ -291,7 +291,7 @@ const Table = (props) => {
291
291
  }, [dispatch, state.columnResizing.columnWidths, flatHeaders, instance]);
292
292
  const [resizeRef] = (0, utils_1.useResizeObserver)(onTableResize);
293
293
  // Flexbox handles columns resize so we take new column widths before browser repaints.
294
- react_1.default.useLayoutEffect(() => {
294
+ (0, utils_1.useIsomorphicLayoutEffect)(() => {
295
295
  if (state.isTableResizing) {
296
296
  const newColumnWidths = {};
297
297
  flatHeaders.forEach((column) => {
@@ -56,6 +56,12 @@ export declare type TablePaginatorProps = {
56
56
  * @default 'Rows per page'
57
57
  */
58
58
  rowsPerPageLabel?: string | null;
59
+ /**
60
+ * Function that returns a label shown in the bottom left to notify how many rows are selected.
61
+ * Only used if multi-selection mode is enabled.
62
+ * @default (totalSelectedRowsCount: number) => `${totalSelectedRowsCount} ${totalSelectedRowsCount === 1 ? 'row' : 'rows'} selected`;
63
+ */
64
+ rowsSelectedLabel?: (totalSelectedRowsCount: number) => string;
59
65
  };
60
66
  } & TablePaginatorRendererProps & Omit<CommonProps, 'title'>;
61
67
  /**
@@ -24,6 +24,7 @@ const defaultLocalization = {
24
24
  nextPage: 'Next page',
25
25
  goToPageLabel: (page) => `Go to page ${page}`,
26
26
  rowsPerPageLabel: 'Rows per page',
27
+ rowsSelectedLabel: (totalSelectedRowsCount) => `${totalSelectedRowsCount} ${totalSelectedRowsCount === 1 ? 'row' : 'rows'} selected`,
27
28
  };
28
29
  /**
29
30
  * Table paginator component. Recommended to pass to the `Table` as `paginatorRenderer` prop.
@@ -126,7 +127,7 @@ const TablePaginator = (props) => {
126
127
  return null;
127
128
  }
128
129
  return (react_1.default.createElement("div", { className: (0, classnames_1.default)('iui-table-paginator', className), ref: paginatorResizeRef, ...rest },
129
- react_1.default.createElement("div", { className: 'iui-left' }, totalSelectedRowsCount > 0 && (react_1.default.createElement("span", null, `${totalSelectedRowsCount} ${totalSelectedRowsCount === 1 ? 'row' : 'rows'} selected`))),
130
+ react_1.default.createElement("div", { className: 'iui-left' }, totalSelectedRowsCount > 0 && (react_1.default.createElement("span", null, localization.rowsSelectedLabel(totalSelectedRowsCount)))),
130
131
  showPagesList && (react_1.default.createElement("div", { className: 'iui-center', ref: overflowRef },
131
132
  react_1.default.createElement(Buttons_1.IconButton, { styleType: 'borderless', disabled: currentPage === 0, onClick: () => onPageChange(currentPage - 1), size: buttonSize, "aria-label": localization.previousPage },
132
133
  react_1.default.createElement(utils_1.SvgChevronLeft, null)),
@@ -43,7 +43,9 @@ const defaultGetDragAndDropProps = (isEnabled) => (props, { instance, header, })
43
43
  event.preventDefault();
44
44
  const headerIndex = instance.flatHeaders.indexOf(header);
45
45
  if (instance.state.columnReorderStartIndex !== headerIndex) {
46
- setOnDragColumnStyle(event, instance.state.columnReorderStartIndex > headerIndex ? 'left' : 'right');
46
+ setOnDragColumnStyle(event, instance.state.columnReorderStartIndex > headerIndex
47
+ ? 'left'
48
+ : 'right');
47
49
  }
48
50
  };
49
51
  const onDragLeave = (event) => {
@@ -49,14 +49,14 @@ const Tabs = (props) => {
49
49
  const [currentActiveIndex, setCurrentActiveIndex] = react_1.default.useState(() => activeIndex != null
50
50
  ? (0, utils_1.getBoundedValue)(activeIndex, 0, labels.length - 1)
51
51
  : 0);
52
- react_1.default.useLayoutEffect(() => {
52
+ (0, utils_1.useIsomorphicLayoutEffect)(() => {
53
53
  if (activeIndex != null && currentActiveIndex !== activeIndex) {
54
54
  setCurrentActiveIndex((0, utils_1.getBoundedValue)(activeIndex, 0, labels.length - 1));
55
55
  }
56
56
  }, [activeIndex, currentActiveIndex, labels.length]);
57
57
  // CSS custom properties to place the active stripe
58
58
  const [stripeProperties, setStripeProperties] = react_1.default.useState({});
59
- react_1.default.useLayoutEffect(() => {
59
+ (0, utils_1.useIsomorphicLayoutEffect)(() => {
60
60
  if (type !== 'default' && tablistRef.current != undefined) {
61
61
  const activeTab = tablistRef.current.children[currentActiveIndex];
62
62
  const activeTabRect = activeTab.getBoundingClientRect();
@@ -80,7 +80,7 @@ const Tabs = (props) => {
80
80
  }
81
81
  }, [focusedIndex]);
82
82
  const [hasSublabel, setHasSublabel] = react_1.default.useState(false); // used for setting size
83
- react_1.default.useLayoutEffect(() => {
83
+ (0, utils_1.useIsomorphicLayoutEffect)(() => {
84
84
  var _a;
85
85
  setHasSublabel(type !== 'pill' && // pill tabs should never have sublabels
86
86
  !!((_a = tablistRef.current) === null || _a === void 0 ? void 0 : _a.querySelector('.iui-tab-description')));
@@ -219,7 +219,8 @@ class ColorValue {
219
219
  switch (name) {
220
220
  case 'rgb':
221
221
  case 'rgba':
222
- color = /^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(components);
222
+ color =
223
+ /^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(components);
223
224
  if (color) {
224
225
  // rgb(255,0,0) rgba(255,0,0,0.5)
225
226
  return [
@@ -232,7 +233,8 @@ class ColorValue {
232
233
  break;
233
234
  case 'hsl':
234
235
  case 'hsla':
235
- color = /^(\d*\.?\d+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(components);
236
+ color =
237
+ /^(\d*\.?\d+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(components);
236
238
  if (color) {
237
239
  // hsl(120,50%,50%) hsla(120,50%,50%,0.5)
238
240
  const h = parseFloat(color[1]);
@@ -32,7 +32,7 @@ const Resizer = (props) => {
32
32
  const initialPointerX = event.clientX;
33
33
  const initialPointerY = event.clientY;
34
34
  const [initialTranslateX, initialTranslateY] = (0, functions_1.getTranslateValues)(elementRef.current);
35
- const { width: initialWidth, height: initialHeight, } = elementRef.current.getBoundingClientRect();
35
+ const { width: initialWidth, height: initialHeight } = elementRef.current.getBoundingClientRect();
36
36
  let width = `${initialWidth}px`;
37
37
  let height = `${initialHeight}px`;
38
38
  let translateX = initialTranslateX;
@@ -132,7 +132,8 @@ const Resizer = (props) => {
132
132
  elementRef.current.ownerDocument.addEventListener('pointerup', () => {
133
133
  document.removeEventListener('pointermove', onResizePointerMove);
134
134
  if (elementRef.current) {
135
- elementRef.current.ownerDocument.body.style.userSelect = originalUserSelect;
135
+ elementRef.current.ownerDocument.body.style.userSelect =
136
+ originalUserSelect;
136
137
  isResizing.current = false;
137
138
  onResizeEnd === null || onResizeEnd === void 0 ? void 0 : onResizeEnd({
138
139
  width,
@@ -10,7 +10,6 @@ exports.useVirtualization = exports.VirtualScroll = void 0;
10
10
  *--------------------------------------------------------------------------------------------*/
11
11
  const react_1 = __importDefault(require("react"));
12
12
  const hooks_1 = require("../hooks");
13
- const useResizeObserver_1 = require("../hooks/useResizeObserver");
14
13
  const getScrollableParent = (element, ownerDocument = document) => {
15
14
  if (!element || element === ownerDocument.body) {
16
15
  return ownerDocument.body;
@@ -149,21 +148,21 @@ const useVirtualization = (props) => {
149
148
  setScrollContainerHeight(height);
150
149
  updateChildHeight();
151
150
  }, [updateChildHeight]);
152
- const [resizeRef, resizeObserver] = (0, useResizeObserver_1.useResizeObserver)(onResize);
151
+ const [resizeRef, resizeObserver] = (0, hooks_1.useResizeObserver)(onResize);
153
152
  // Find scrollable parent
154
153
  // Needed only on init
155
- react_1.default.useLayoutEffect(() => {
154
+ (0, hooks_1.useIsomorphicLayoutEffect)(() => {
156
155
  var _a;
157
156
  const scrollableParent = getScrollableParent(parentRef.current, (_a = parentRef.current) === null || _a === void 0 ? void 0 : _a.ownerDocument);
158
157
  scrollContainer.current = scrollableParent;
159
158
  resizeRef(scrollableParent);
160
159
  }, [resizeRef]);
161
160
  // Stop watching resize, when virtual scroll is unmounted
162
- react_1.default.useLayoutEffect(() => {
161
+ (0, hooks_1.useIsomorphicLayoutEffect)(() => {
163
162
  return () => resizeObserver === null || resizeObserver === void 0 ? void 0 : resizeObserver.disconnect();
164
163
  }, [resizeObserver]);
165
164
  // Get child height when children available
166
- react_1.default.useLayoutEffect(() => updateChildHeight(), [updateChildHeight]);
165
+ (0, hooks_1.useIsomorphicLayoutEffect)(() => updateChildHeight(), [updateChildHeight]);
167
166
  const updateVirtualScroll = react_1.default.useCallback(() => {
168
167
  const scrollableContainer = getScrollableContainer();
169
168
  if (!scrollableContainer) {
@@ -197,7 +196,7 @@ const useVirtualization = (props) => {
197
196
  : scrollContainer.current.removeEventListener('scroll', onScrollRef.current);
198
197
  }, []);
199
198
  // Add event listener to the scrollable container.
200
- react_1.default.useLayoutEffect(() => {
199
+ (0, hooks_1.useIsomorphicLayoutEffect)(() => {
201
200
  var _a, _b;
202
201
  removeScrollListener();
203
202
  onScrollRef.current = onScroll;
@@ -210,7 +209,7 @@ const useVirtualization = (props) => {
210
209
  }
211
210
  return removeScrollListener;
212
211
  }, [onScroll, removeScrollListener]);
213
- react_1.default.useLayoutEffect(() => {
212
+ (0, hooks_1.useIsomorphicLayoutEffect)(() => {
214
213
  if (!isMounted) {
215
214
  return;
216
215
  }
@@ -262,7 +261,7 @@ const useVirtualization = (props) => {
262
261
  }
263
262
  }
264
263
  }, [scrollToIndex, isMounted]);
265
- react_1.default.useLayoutEffect(() => {
264
+ (0, hooks_1.useIsomorphicLayoutEffect)(() => {
266
265
  if (!scrollContainerHeight) {
267
266
  return;
268
267
  }
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Returns translate values as an array of a given element.
3
3
  * @param element HTML element you want to get translate value of
4
- * @returns Translate values in pixels in a array `[translateX, translateY]`
4
+ * @returns Translate values in pixels in an array `[translateX, translateY]`
5
5
  */
6
6
  export declare const getTranslateValues: (element: HTMLElement | null | undefined) => number[];
@@ -8,7 +8,7 @@ exports.getTranslateValues = void 0;
8
8
  /**
9
9
  * Returns translate values as an array of a given element.
10
10
  * @param element HTML element you want to get translate value of
11
- * @returns Translate values in pixels in a array `[translateX, translateY]`
11
+ * @returns Translate values in pixels in an array `[translateX, translateY]`
12
12
  */
13
13
  const getTranslateValues = (element) => {
14
14
  if (!element) {
@@ -41,7 +41,7 @@ const useDragAndDrop = (elementRef, containerRef, enabled = true) => {
41
41
  if (!elementRef.current || !enabled) {
42
42
  return;
43
43
  }
44
- const { top, right, bottom, left, } = (_a = elementRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
44
+ const { top, right, bottom, left } = (_a = elementRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
45
45
  let [newTranslateX, newTranslateY] = (0, functions_1.getTranslateValues)(elementRef.current);
46
46
  containerRectRef.current = getContainerRect(containerRef);
47
47
  if (bottom > containerRectRef.current.bottom) {
@@ -11,6 +11,7 @@ exports.useOverflow = void 0;
11
11
  const react_1 = __importDefault(require("react"));
12
12
  const useMergedRefs_1 = require("./useMergedRefs");
13
13
  const useResizeObserver_1 = require("./useResizeObserver");
14
+ const useIsomorphicLayoutEffect_1 = require("./useIsomorphicLayoutEffect");
14
15
  const STARTING_MAX_ITEMS_COUNT = 20;
15
16
  /**
16
17
  * Hook that observes the size of an element and returns the number of items
@@ -43,7 +44,7 @@ const useOverflow = (items, disabled = false, orientation = 'horizontal') => {
43
44
  const updateContainerSize = react_1.default.useCallback(({ width, height }) => setContainerSize(orientation === 'horizontal' ? width : height), [orientation]);
44
45
  const [resizeRef, observer] = (0, useResizeObserver_1.useResizeObserver)(updateContainerSize);
45
46
  const resizeObserverRef = react_1.default.useRef(observer);
46
- react_1.default.useLayoutEffect(() => {
47
+ (0, useIsomorphicLayoutEffect_1.useIsomorphicLayoutEffect)(() => {
47
48
  if (disabled) {
48
49
  setVisibleCount(items.length);
49
50
  }
@@ -53,7 +54,7 @@ const useOverflow = (items, disabled = false, orientation = 'horizontal') => {
53
54
  }
54
55
  }, [containerSize, disabled, items]);
55
56
  const mergedRefs = (0, useMergedRefs_1.useMergedRefs)(containerRef, resizeRef);
56
- react_1.default.useLayoutEffect(() => {
57
+ (0, useIsomorphicLayoutEffect_1.useIsomorphicLayoutEffect)(() => {
57
58
  var _a;
58
59
  if (!containerRef.current || disabled) {
59
60
  (_a = resizeObserverRef.current) === null || _a === void 0 ? void 0 : _a.disconnect();
@@ -81,7 +82,7 @@ const useOverflow = (items, disabled = false, orientation = 'horizontal') => {
81
82
  }
82
83
  needsFullRerender.current = false;
83
84
  }, [containerSize, visibleCount, disabled, items.length, orientation]);
84
- react_1.default.useLayoutEffect(() => {
85
+ (0, useIsomorphicLayoutEffect_1.useIsomorphicLayoutEffect)(() => {
85
86
  previousContainerSize.current = containerSize;
86
87
  }, [containerSize]);
87
88
  return [mergedRefs, visibleCount];
@@ -28,8 +28,8 @@ const useTheme = (theme, themeOptions) => {
28
28
  const themeContext = react_1.default.useContext(ThemeProvider_1.ThemeContext);
29
29
  const ownerDocument = (_a = themeOptions === null || themeOptions === void 0 ? void 0 : themeOptions.ownerDocument) !== null && _a !== void 0 ? _a : (0, functions_1.getDocument)();
30
30
  (0, useIsomorphicLayoutEffect_1.useIsomorphicLayoutEffect)(() => {
31
- // exit early if theme was already set by provider
32
- if (themeContext || !ownerDocument) {
31
+ // exit early if theme was already set by provider or is present on <body>
32
+ if (themeContext || !ownerDocument || ownerDocument.body.dataset.iuiTheme) {
33
33
  return;
34
34
  }
35
35
  ownerDocument.body.classList.toggle('iui-root', true);
@@ -11,7 +11,7 @@ export declare type StatusTitles = {
11
11
  };
12
12
  export declare type AvatarProps = {
13
13
  /**
14
- * Size of a avatar.
14
+ * Size of an avatar.
15
15
  * @default 'small'
16
16
  */
17
17
  size?: 'small' | 'medium' | 'large' | 'x-large';
@@ -44,7 +44,7 @@ export declare type UserIconGroupProps = AvatarGroupProps;
44
44
  * You can add custom Count Avatar behavior by using `countAvatarProps`.
45
45
  *
46
46
  * @example
47
- * <AvatarGroup avatarSize='medium'>
47
+ * <AvatarGroup iconSize='medium'>
48
48
  * <Avatar
49
49
  * abbreviation="TR"
50
50
  * backgroundColor={getUserColor("Terry Rivers")}
@@ -15,7 +15,7 @@ import '@itwin/itwinui-css/css/avatar.css';
15
15
  * You can add custom Count Avatar behavior by using `countAvatarProps`.
16
16
  *
17
17
  * @example
18
- * <AvatarGroup avatarSize='medium'>
18
+ * <AvatarGroup iconSize='medium'>
19
19
  * <Avatar
20
20
  * abbreviation="TR"
21
21
  * backgroundColor={getUserColor("Terry Rivers")}
@@ -5,7 +5,7 @@
5
5
  import React from 'react';
6
6
  import cx from 'classnames';
7
7
  import { CarouselContext } from './CarouselContext';
8
- import { getWindow, useMergedRefs } from '../utils';
8
+ import { getWindow, useMergedRefs, useIsomorphicLayoutEffect } from '../utils';
9
9
  /**
10
10
  * `CarouselSlider` is the scrollable list that should consist of `CarouselSlide` components.
11
11
  */
@@ -15,7 +15,7 @@ export const CarouselSlider = React.forwardRef((props, ref) => {
15
15
  if (!context) {
16
16
  throw new Error('CarouselSlider must be used within Carousel');
17
17
  }
18
- const { setSlideCount, idPrefix, scrollToSlide, isManuallyUpdating, } = context;
18
+ const { setSlideCount, idPrefix, scrollToSlide, isManuallyUpdating } = context;
19
19
  const items = React.useMemo(() => {
20
20
  var _a;
21
21
  return (_a = React.Children.map(children, (child, index) => React.isValidElement(child)
@@ -25,7 +25,7 @@ export const CarouselSlider = React.forwardRef((props, ref) => {
25
25
  })
26
26
  : child)) !== null && _a !== void 0 ? _a : [];
27
27
  }, [children, idPrefix]);
28
- React.useLayoutEffect(() => {
28
+ useIsomorphicLayoutEffect(() => {
29
29
  setSlideCount(items.length);
30
30
  }, [items.length, setSlideCount]);
31
31
  const sliderRef = React.useRef(null);
@@ -31,14 +31,9 @@ export const ColorBuilder = React.forwardRef((props, ref) => {
31
31
  // Set values for slider
32
32
  const hueSliderColor = React.useMemo(() => ColorValue.create({ h: hsvColor.h, s: 100, v: 100 }), [hsvColor.h]);
33
33
  const sliderValue = React.useMemo(() => hsvColor.h, [hsvColor]);
34
- const alphaValue = React.useMemo(() => { var _a; return (showAlpha ? (_a = hsvColor.a) !== null && _a !== void 0 ? _a : 1 : 1); }, [
35
- hsvColor.a,
36
- showAlpha,
37
- ]);
34
+ const alphaValue = React.useMemo(() => { var _a; return (showAlpha ? (_a = hsvColor.a) !== null && _a !== void 0 ? _a : 1 : 1); }, [hsvColor.a, showAlpha]);
38
35
  // Set values for color square and color dot
39
- const dotColorString = React.useMemo(() => activeColor.toHexString(), [
40
- activeColor,
41
- ]);
36
+ const dotColorString = React.useMemo(() => activeColor.toHexString(), [activeColor]);
42
37
  const [colorDotActive, setColorDotActive] = React.useState(false);
43
38
  const hueColorString = hueSliderColor.toHexString();
44
39
  const squareTop = 100 - hsvColor.v;
@@ -23,7 +23,7 @@ import '@itwin/itwinui-css/css/color-picker.css';
23
23
  export const ColorPalette = React.forwardRef((props, ref) => {
24
24
  const { colors, label, className, children, ...rest } = props;
25
25
  useTheme();
26
- const { activeColor, setActiveColor, onChangeComplete, } = useColorPickerContext();
26
+ const { activeColor, setActiveColor, onChangeComplete } = useColorPickerContext();
27
27
  const [focusedIndex, setFocusedIndex] = React.useState();
28
28
  // callback ref to set tabindex=0 on first child if none of the swatches are tabbable
29
29
  const setDefaultTabIndex = (el) => {
@@ -37,9 +37,7 @@ export const ColorPicker = (props) => {
37
37
  tabbableElements[0].focus();
38
38
  }
39
39
  }, [setFocus]);
40
- const inColor = React.useMemo(() => getColorValue(selectedColor), [
41
- selectedColor,
42
- ]);
40
+ const inColor = React.useMemo(() => getColorValue(selectedColor), [selectedColor]);
43
41
  const activeColorTbgr = React.useRef(inColor.toTbgr());
44
42
  const [activeColor, setActiveColor] = React.useState(inColor); // Color of colorDot or active ColorSwatch
45
43
  React.useEffect(() => {
@@ -6,7 +6,7 @@ import React from 'react';
6
6
  import cx from 'classnames';
7
7
  import { MenuExtraContent } from '../Menu';
8
8
  import { Text } from '../Typography';
9
- import { useTheme, getRandomValue, mergeRefs, useLatestRef, } from '../utils';
9
+ import { useTheme, getRandomValue, mergeRefs, useLatestRef, useIsomorphicLayoutEffect, } from '../utils';
10
10
  import 'tippy.js/animations/shift-away.css';
11
11
  import { ComboBoxActionContext, comboBoxReducer, ComboBoxRefsContext, ComboBoxStateContext, } from './helpers';
12
12
  import { ComboBoxDropdown } from './ComboBoxDropdown';
@@ -73,7 +73,7 @@ export const ComboBox = (props) => {
73
73
  : -1,
74
74
  focusedIndex: -1,
75
75
  });
76
- React.useLayoutEffect(() => {
76
+ useIsomorphicLayoutEffect(() => {
77
77
  var _a, _b;
78
78
  // When the dropdown opens
79
79
  if (isOpen) {
@@ -10,7 +10,7 @@ import { useSafeContext, useMergedRefs, useVirtualization, mergeRefs, getWindow,
10
10
  import { ComboBoxStateContext, ComboBoxRefsContext } from './helpers';
11
11
  const VirtualizedComboBoxMenu = React.forwardRef(({ children, className, style, ...rest }, forwardedRef) => {
12
12
  var _a, _b, _c;
13
- const { minWidth, id, filteredOptions, getMenuItem, focusedIndex, } = useSafeContext(ComboBoxStateContext);
13
+ const { minWidth, id, filteredOptions, getMenuItem, focusedIndex } = useSafeContext(ComboBoxStateContext);
14
14
  const { menuRef } = useSafeContext(ComboBoxRefsContext);
15
15
  const virtualItemRenderer = React.useCallback((index) => filteredOptions.length > 0
16
16
  ? getMenuItem(filteredOptions[index], index)
@@ -4,7 +4,7 @@
4
4
  *--------------------------------------------------------------------------------------------*/
5
5
  import React from 'react';
6
6
  import cx from 'classnames';
7
- import { FocusTrap, getTranslateValues, useLatestRef, Resizer, useMergedRefs, useTheme, } from '../utils';
7
+ import { FocusTrap, getTranslateValues, useLatestRef, Resizer, useMergedRefs, useTheme, useIsomorphicLayoutEffect, } from '../utils';
8
8
  import '@itwin/itwinui-css/css/dialog.css';
9
9
  import { useDialogContext } from './DialogContext';
10
10
  import { CSSTransition } from 'react-transition-group';
@@ -102,7 +102,7 @@ export const DialogMain = React.forwardRef((props, ref) => {
102
102
  }
103
103
  }, [isDraggable, onPointerDown]);
104
104
  // Prevents dialog from moving when window is being resized
105
- React.useLayoutEffect(() => {
105
+ useIsomorphicLayoutEffect(() => {
106
106
  var _a;
107
107
  if (!isDraggable || !isOpen) {
108
108
  return;
@@ -9,5 +9,5 @@ export declare type ModalButtonBarProps = {
9
9
  /**
10
10
  * Container for Buttons in modal.
11
11
  */
12
- export declare const ModalButtonBar: React.ForwardRefExoticComponent<Pick<import("../Dialog/DialogButtonBar").DialogButtonBarProps, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & React.RefAttributes<HTMLDivElement>>;
12
+ export declare const ModalButtonBar: (props: ModalButtonBarProps) => JSX.Element;
13
13
  export default ModalButtonBar;
@@ -1,6 +1,11 @@
1
+ /*---------------------------------------------------------------------------------------------
2
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
3
+ * See LICENSE.md in the project root for license terms and full copyright notice.
4
+ *--------------------------------------------------------------------------------------------*/
5
+ import React from 'react';
1
6
  import { DialogButtonBar } from '../Dialog/DialogButtonBar';
2
7
  /**
3
8
  * Container for Buttons in modal.
4
9
  */
5
- export const ModalButtonBar = DialogButtonBar;
10
+ export const ModalButtonBar = (props) => (React.createElement(DialogButtonBar, { ...props }));
6
11
  export default ModalButtonBar;
@@ -9,5 +9,5 @@ export declare type ModalContentProps = {
9
9
  /**
10
10
  * Container for content in `Modal`.
11
11
  */
12
- export declare const ModalContent: React.ForwardRefExoticComponent<Pick<import("../Dialog/DialogContent").DialogContentProps, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & React.RefAttributes<HTMLDivElement>>;
12
+ export declare const ModalContent: (props: ModalContentProps) => JSX.Element;
13
13
  export default ModalContent;
@@ -1,6 +1,11 @@
1
+ /*---------------------------------------------------------------------------------------------
2
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
3
+ * See LICENSE.md in the project root for license terms and full copyright notice.
4
+ *--------------------------------------------------------------------------------------------*/
5
+ import React from 'react';
1
6
  import { DialogContent } from '../Dialog/DialogContent';
2
7
  /**
3
8
  * Container for content in `Modal`.
4
9
  */
5
- export const ModalContent = DialogContent;
10
+ export const ModalContent = (props) => (React.createElement(DialogContent, { ...props }));
6
11
  export default ModalContent;
@@ -6,7 +6,7 @@ import React from 'react';
6
6
  import cx from 'classnames';
7
7
  import { actions as TableActions, useFlexLayout, useFilters, useRowSelect, useSortBy, useTable, useExpanded, usePagination, useColumnOrder, useGlobalFilter, } from 'react-table';
8
8
  import { ProgressRadial } from '../ProgressIndicators';
9
- import { useTheme, useResizeObserver, SvgSortDown, SvgSortUp, } from '../utils';
9
+ import { useTheme, useResizeObserver, SvgSortDown, SvgSortUp, useIsomorphicLayoutEffect, } from '../utils';
10
10
  import '@itwin/itwinui-css/css/table.css';
11
11
  import { getCellStyle, getStickyStyle } from './utils';
12
12
  import { TableRowMemoized } from './TableRowMemoized';
@@ -285,7 +285,7 @@ export const Table = (props) => {
285
285
  }, [dispatch, state.columnResizing.columnWidths, flatHeaders, instance]);
286
286
  const [resizeRef] = useResizeObserver(onTableResize);
287
287
  // Flexbox handles columns resize so we take new column widths before browser repaints.
288
- React.useLayoutEffect(() => {
288
+ useIsomorphicLayoutEffect(() => {
289
289
  if (state.isTableResizing) {
290
290
  const newColumnWidths = {};
291
291
  flatHeaders.forEach((column) => {
@@ -56,6 +56,12 @@ export declare type TablePaginatorProps = {
56
56
  * @default 'Rows per page'
57
57
  */
58
58
  rowsPerPageLabel?: string | null;
59
+ /**
60
+ * Function that returns a label shown in the bottom left to notify how many rows are selected.
61
+ * Only used if multi-selection mode is enabled.
62
+ * @default (totalSelectedRowsCount: number) => `${totalSelectedRowsCount} ${totalSelectedRowsCount === 1 ? 'row' : 'rows'} selected`;
63
+ */
64
+ rowsSelectedLabel?: (totalSelectedRowsCount: number) => string;
59
65
  };
60
66
  } & TablePaginatorRendererProps & Omit<CommonProps, 'title'>;
61
67
  /**
@@ -18,6 +18,7 @@ const defaultLocalization = {
18
18
  nextPage: 'Next page',
19
19
  goToPageLabel: (page) => `Go to page ${page}`,
20
20
  rowsPerPageLabel: 'Rows per page',
21
+ rowsSelectedLabel: (totalSelectedRowsCount) => `${totalSelectedRowsCount} ${totalSelectedRowsCount === 1 ? 'row' : 'rows'} selected`,
21
22
  };
22
23
  /**
23
24
  * Table paginator component. Recommended to pass to the `Table` as `paginatorRenderer` prop.
@@ -120,7 +121,7 @@ export const TablePaginator = (props) => {
120
121
  return null;
121
122
  }
122
123
  return (React.createElement("div", { className: cx('iui-table-paginator', className), ref: paginatorResizeRef, ...rest },
123
- React.createElement("div", { className: 'iui-left' }, totalSelectedRowsCount > 0 && (React.createElement("span", null, `${totalSelectedRowsCount} ${totalSelectedRowsCount === 1 ? 'row' : 'rows'} selected`))),
124
+ React.createElement("div", { className: 'iui-left' }, totalSelectedRowsCount > 0 && (React.createElement("span", null, localization.rowsSelectedLabel(totalSelectedRowsCount)))),
124
125
  showPagesList && (React.createElement("div", { className: 'iui-center', ref: overflowRef },
125
126
  React.createElement(IconButton, { styleType: 'borderless', disabled: currentPage === 0, onClick: () => onPageChange(currentPage - 1), size: buttonSize, "aria-label": localization.previousPage },
126
127
  React.createElement(SvgChevronLeft, null)),
@@ -39,7 +39,9 @@ const defaultGetDragAndDropProps = (isEnabled) => (props, { instance, header, })
39
39
  event.preventDefault();
40
40
  const headerIndex = instance.flatHeaders.indexOf(header);
41
41
  if (instance.state.columnReorderStartIndex !== headerIndex) {
42
- setOnDragColumnStyle(event, instance.state.columnReorderStartIndex > headerIndex ? 'left' : 'right');
42
+ setOnDragColumnStyle(event, instance.state.columnReorderStartIndex > headerIndex
43
+ ? 'left'
44
+ : 'right');
43
45
  }
44
46
  };
45
47
  const onDragLeave = (event) => {
@@ -4,7 +4,7 @@
4
4
  *--------------------------------------------------------------------------------------------*/
5
5
  import cx from 'classnames';
6
6
  import React from 'react';
7
- import { useTheme, useMergedRefs, getBoundedValue, useContainerWidth, } from '../utils';
7
+ import { useTheme, useMergedRefs, getBoundedValue, useContainerWidth, useIsomorphicLayoutEffect, } from '../utils';
8
8
  import '@itwin/itwinui-css/css/tabs.css';
9
9
  import { Tab } from './Tab';
10
10
  /**
@@ -43,14 +43,14 @@ export const Tabs = (props) => {
43
43
  const [currentActiveIndex, setCurrentActiveIndex] = React.useState(() => activeIndex != null
44
44
  ? getBoundedValue(activeIndex, 0, labels.length - 1)
45
45
  : 0);
46
- React.useLayoutEffect(() => {
46
+ useIsomorphicLayoutEffect(() => {
47
47
  if (activeIndex != null && currentActiveIndex !== activeIndex) {
48
48
  setCurrentActiveIndex(getBoundedValue(activeIndex, 0, labels.length - 1));
49
49
  }
50
50
  }, [activeIndex, currentActiveIndex, labels.length]);
51
51
  // CSS custom properties to place the active stripe
52
52
  const [stripeProperties, setStripeProperties] = React.useState({});
53
- React.useLayoutEffect(() => {
53
+ useIsomorphicLayoutEffect(() => {
54
54
  if (type !== 'default' && tablistRef.current != undefined) {
55
55
  const activeTab = tablistRef.current.children[currentActiveIndex];
56
56
  const activeTabRect = activeTab.getBoundingClientRect();
@@ -74,7 +74,7 @@ export const Tabs = (props) => {
74
74
  }
75
75
  }, [focusedIndex]);
76
76
  const [hasSublabel, setHasSublabel] = React.useState(false); // used for setting size
77
- React.useLayoutEffect(() => {
77
+ useIsomorphicLayoutEffect(() => {
78
78
  var _a;
79
79
  setHasSublabel(type !== 'pill' && // pill tabs should never have sublabels
80
80
  !!((_a = tablistRef.current) === null || _a === void 0 ? void 0 : _a.querySelector('.iui-tab-description')));
@@ -213,7 +213,8 @@ export class ColorValue {
213
213
  switch (name) {
214
214
  case 'rgb':
215
215
  case 'rgba':
216
- color = /^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(components);
216
+ color =
217
+ /^(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(components);
217
218
  if (color) {
218
219
  // rgb(255,0,0) rgba(255,0,0,0.5)
219
220
  return [
@@ -226,7 +227,8 @@ export class ColorValue {
226
227
  break;
227
228
  case 'hsl':
228
229
  case 'hsla':
229
- color = /^(\d*\.?\d+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(components);
230
+ color =
231
+ /^(\d*\.?\d+)\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(components);
230
232
  if (color) {
231
233
  // hsl(120,50%,50%) hsla(120,50%,50%,0.5)
232
234
  const h = parseFloat(color[1]);
@@ -26,7 +26,7 @@ export const Resizer = (props) => {
26
26
  const initialPointerX = event.clientX;
27
27
  const initialPointerY = event.clientY;
28
28
  const [initialTranslateX, initialTranslateY] = getTranslateValues(elementRef.current);
29
- const { width: initialWidth, height: initialHeight, } = elementRef.current.getBoundingClientRect();
29
+ const { width: initialWidth, height: initialHeight } = elementRef.current.getBoundingClientRect();
30
30
  let width = `${initialWidth}px`;
31
31
  let height = `${initialHeight}px`;
32
32
  let translateX = initialTranslateX;
@@ -126,7 +126,8 @@ export const Resizer = (props) => {
126
126
  elementRef.current.ownerDocument.addEventListener('pointerup', () => {
127
127
  document.removeEventListener('pointermove', onResizePointerMove);
128
128
  if (elementRef.current) {
129
- elementRef.current.ownerDocument.body.style.userSelect = originalUserSelect;
129
+ elementRef.current.ownerDocument.body.style.userSelect =
130
+ originalUserSelect;
130
131
  isResizing.current = false;
131
132
  onResizeEnd === null || onResizeEnd === void 0 ? void 0 : onResizeEnd({
132
133
  width,
@@ -3,8 +3,7 @@
3
3
  * See LICENSE.md in the project root for license terms and full copyright notice.
4
4
  *--------------------------------------------------------------------------------------------*/
5
5
  import React from 'react';
6
- import { mergeRefs } from '../hooks';
7
- import { useResizeObserver } from '../hooks/useResizeObserver';
6
+ import { mergeRefs, useResizeObserver, useIsomorphicLayoutEffect, } from '../hooks';
8
7
  const getScrollableParent = (element, ownerDocument = document) => {
9
8
  if (!element || element === ownerDocument.body) {
10
9
  return ownerDocument.body;
@@ -146,18 +145,18 @@ export const useVirtualization = (props) => {
146
145
  const [resizeRef, resizeObserver] = useResizeObserver(onResize);
147
146
  // Find scrollable parent
148
147
  // Needed only on init
149
- React.useLayoutEffect(() => {
148
+ useIsomorphicLayoutEffect(() => {
150
149
  var _a;
151
150
  const scrollableParent = getScrollableParent(parentRef.current, (_a = parentRef.current) === null || _a === void 0 ? void 0 : _a.ownerDocument);
152
151
  scrollContainer.current = scrollableParent;
153
152
  resizeRef(scrollableParent);
154
153
  }, [resizeRef]);
155
154
  // Stop watching resize, when virtual scroll is unmounted
156
- React.useLayoutEffect(() => {
155
+ useIsomorphicLayoutEffect(() => {
157
156
  return () => resizeObserver === null || resizeObserver === void 0 ? void 0 : resizeObserver.disconnect();
158
157
  }, [resizeObserver]);
159
158
  // Get child height when children available
160
- React.useLayoutEffect(() => updateChildHeight(), [updateChildHeight]);
159
+ useIsomorphicLayoutEffect(() => updateChildHeight(), [updateChildHeight]);
161
160
  const updateVirtualScroll = React.useCallback(() => {
162
161
  const scrollableContainer = getScrollableContainer();
163
162
  if (!scrollableContainer) {
@@ -191,7 +190,7 @@ export const useVirtualization = (props) => {
191
190
  : scrollContainer.current.removeEventListener('scroll', onScrollRef.current);
192
191
  }, []);
193
192
  // Add event listener to the scrollable container.
194
- React.useLayoutEffect(() => {
193
+ useIsomorphicLayoutEffect(() => {
195
194
  var _a, _b;
196
195
  removeScrollListener();
197
196
  onScrollRef.current = onScroll;
@@ -204,7 +203,7 @@ export const useVirtualization = (props) => {
204
203
  }
205
204
  return removeScrollListener;
206
205
  }, [onScroll, removeScrollListener]);
207
- React.useLayoutEffect(() => {
206
+ useIsomorphicLayoutEffect(() => {
208
207
  if (!isMounted) {
209
208
  return;
210
209
  }
@@ -256,7 +255,7 @@ export const useVirtualization = (props) => {
256
255
  }
257
256
  }
258
257
  }, [scrollToIndex, isMounted]);
259
- React.useLayoutEffect(() => {
258
+ useIsomorphicLayoutEffect(() => {
260
259
  if (!scrollContainerHeight) {
261
260
  return;
262
261
  }
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Returns translate values as an array of a given element.
3
3
  * @param element HTML element you want to get translate value of
4
- * @returns Translate values in pixels in a array `[translateX, translateY]`
4
+ * @returns Translate values in pixels in an array `[translateX, translateY]`
5
5
  */
6
6
  export declare const getTranslateValues: (element: HTMLElement | null | undefined) => number[];
@@ -5,7 +5,7 @@
5
5
  /**
6
6
  * Returns translate values as an array of a given element.
7
7
  * @param element HTML element you want to get translate value of
8
- * @returns Translate values in pixels in a array `[translateX, translateY]`
8
+ * @returns Translate values in pixels in an array `[translateX, translateY]`
9
9
  */
10
10
  export const getTranslateValues = (element) => {
11
11
  if (!element) {
@@ -35,7 +35,7 @@ export const useDragAndDrop = (elementRef, containerRef, enabled = true) => {
35
35
  if (!elementRef.current || !enabled) {
36
36
  return;
37
37
  }
38
- const { top, right, bottom, left, } = (_a = elementRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
38
+ const { top, right, bottom, left } = (_a = elementRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
39
39
  let [newTranslateX, newTranslateY] = getTranslateValues(elementRef.current);
40
40
  containerRectRef.current = getContainerRect(containerRef);
41
41
  if (bottom > containerRectRef.current.bottom) {
@@ -5,6 +5,7 @@
5
5
  import React from 'react';
6
6
  import { useMergedRefs } from './useMergedRefs';
7
7
  import { useResizeObserver } from './useResizeObserver';
8
+ import { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect';
8
9
  const STARTING_MAX_ITEMS_COUNT = 20;
9
10
  /**
10
11
  * Hook that observes the size of an element and returns the number of items
@@ -37,7 +38,7 @@ export const useOverflow = (items, disabled = false, orientation = 'horizontal')
37
38
  const updateContainerSize = React.useCallback(({ width, height }) => setContainerSize(orientation === 'horizontal' ? width : height), [orientation]);
38
39
  const [resizeRef, observer] = useResizeObserver(updateContainerSize);
39
40
  const resizeObserverRef = React.useRef(observer);
40
- React.useLayoutEffect(() => {
41
+ useIsomorphicLayoutEffect(() => {
41
42
  if (disabled) {
42
43
  setVisibleCount(items.length);
43
44
  }
@@ -47,7 +48,7 @@ export const useOverflow = (items, disabled = false, orientation = 'horizontal')
47
48
  }
48
49
  }, [containerSize, disabled, items]);
49
50
  const mergedRefs = useMergedRefs(containerRef, resizeRef);
50
- React.useLayoutEffect(() => {
51
+ useIsomorphicLayoutEffect(() => {
51
52
  var _a;
52
53
  if (!containerRef.current || disabled) {
53
54
  (_a = resizeObserverRef.current) === null || _a === void 0 ? void 0 : _a.disconnect();
@@ -75,7 +76,7 @@ export const useOverflow = (items, disabled = false, orientation = 'horizontal')
75
76
  }
76
77
  needsFullRerender.current = false;
77
78
  }, [containerSize, visibleCount, disabled, items.length, orientation]);
78
- React.useLayoutEffect(() => {
79
+ useIsomorphicLayoutEffect(() => {
79
80
  previousContainerSize.current = containerSize;
80
81
  }, [containerSize]);
81
82
  return [mergedRefs, visibleCount];
@@ -22,8 +22,8 @@ export const useTheme = (theme, themeOptions) => {
22
22
  const themeContext = React.useContext(ThemeContext);
23
23
  const ownerDocument = (_a = themeOptions === null || themeOptions === void 0 ? void 0 : themeOptions.ownerDocument) !== null && _a !== void 0 ? _a : getDocument();
24
24
  useIsomorphicLayoutEffect(() => {
25
- // exit early if theme was already set by provider
26
- if (themeContext || !ownerDocument) {
25
+ // exit early if theme was already set by provider or is present on <body>
26
+ if (themeContext || !ownerDocument || ownerDocument.body.dataset.iuiTheme) {
27
27
  return;
28
28
  }
29
29
  ownerDocument.body.classList.toggle('iui-root', true);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itwin/itwinui-react",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
4
4
  "author": "Bentley Systems",
5
5
  "license": "MIT",
6
6
  "main": "cjs/index.js",
@@ -46,8 +46,8 @@
46
46
  "ux"
47
47
  ],
48
48
  "scripts": {
49
- "build": "yarn clean:build && yarn copy-files && tsc -p tsconfig.cjs.json && tsc -p tsconfig.esm.json",
50
- "build:watch": "yarn clean:build && yarn copy-files && concurrently \"tsc -p tsconfig.cjs.json --watch\" \"tsc -p tsconfig.esm.json --watch\"",
49
+ "build": "yarn clean:build && tsc -p tsconfig.cjs.json && tsc -p tsconfig.esm.json",
50
+ "build:watch": "yarn clean:build && concurrently \"tsc -p tsconfig.cjs.json --watch\" \"tsc -p tsconfig.esm.json --watch\"",
51
51
  "clean:build": "yarn clean:coverage && rimraf esm && rimraf cjs",
52
52
  "clean:coverage": "rimraf coverage",
53
53
  "clean": "rimraf .turbo && yarn clean:coverage && yarn clean:build && rimraf node_modules",
@@ -56,12 +56,11 @@
56
56
  "format": "prettier --config .prettierrc **/*.{tsx,ts,js} --ignore-path .gitignore --write",
57
57
  "lint": "eslint \"**/*.{js,ts,tsx}\" --max-warnings=0",
58
58
  "lint:fix": "yarn lint --fix && node ../configs/copyrightLinter.js --fix \"*/**/*.{js,ts,tsx}\"",
59
- "copy-files": "cpy \"../../{README,LICENSE}.md\" .",
60
59
  "dev": "yarn build:watch",
61
60
  "createComponent": "node ../../scripts/createComponent.js"
62
61
  },
63
62
  "dependencies": {
64
- "@itwin/itwinui-css": "^1.0.0",
63
+ "@itwin/itwinui-css": "^1.1.0",
65
64
  "@itwin/itwinui-illustrations-react": "^2.0.0",
66
65
  "@itwin/itwinui-variables": "^1.0.0",
67
66
  "@tippyjs/react": "^4.2.6",