@itwin/itwinui-react 2.6.1 → 2.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/CHANGELOG.md +73 -2
  2. package/cjs/core/Badge/Badge.d.ts +1 -1
  3. package/cjs/core/Badge/Badge.js +14 -15
  4. package/cjs/core/Carousel/Carousel.js +3 -2
  5. package/cjs/core/DatePicker/DatePicker.d.ts +5 -0
  6. package/cjs/core/DatePicker/DatePicker.js +26 -7
  7. package/cjs/core/Dialog/DialogMain.js +18 -23
  8. package/cjs/core/Slider/Thumb.js +2 -4
  9. package/cjs/core/Surface/Surface.d.ts +24 -2
  10. package/cjs/core/Surface/Surface.js +38 -2
  11. package/cjs/core/Surface/index.d.ts +1 -1
  12. package/cjs/core/Tabs/Tabs.js +3 -1
  13. package/cjs/core/Tile/Tile.d.ts +24 -2
  14. package/cjs/core/Tile/Tile.js +83 -50
  15. package/cjs/core/ToggleSwitch/ToggleSwitch.d.ts +11 -31
  16. package/cjs/core/ToggleSwitch/ToggleSwitch.js +8 -1
  17. package/cjs/core/index.d.ts +3 -3
  18. package/cjs/core/index.js +5 -1
  19. package/cjs/core/utils/components/Divider.d.ts +14 -0
  20. package/cjs/core/utils/components/Divider.js +23 -0
  21. package/cjs/core/utils/components/LinkAction.d.ts +30 -0
  22. package/cjs/core/utils/components/LinkAction.js +44 -0
  23. package/cjs/core/utils/components/Resizer.js +9 -9
  24. package/cjs/core/utils/components/VisuallyHidden.d.ts +20 -6
  25. package/cjs/core/utils/components/VisuallyHidden.js +10 -3
  26. package/cjs/core/utils/components/index.d.ts +2 -0
  27. package/cjs/core/utils/components/index.js +2 -0
  28. package/cjs/core/utils/functions/index.d.ts +1 -0
  29. package/cjs/core/utils/functions/index.js +1 -0
  30. package/cjs/core/utils/functions/supports.d.ts +4 -0
  31. package/cjs/core/utils/functions/supports.js +13 -0
  32. package/cjs/core/utils/hooks/index.d.ts +1 -0
  33. package/cjs/core/utils/hooks/index.js +1 -0
  34. package/cjs/core/utils/hooks/useDragAndDrop.js +4 -3
  35. package/cjs/core/utils/hooks/useIsClient.d.ts +1 -0
  36. package/cjs/core/utils/hooks/useIsClient.js +19 -0
  37. package/cjs/core/utils/hooks/useTheme.js +44 -0
  38. package/esm/core/Badge/Badge.d.ts +1 -1
  39. package/esm/core/Badge/Badge.js +14 -15
  40. package/esm/core/Carousel/Carousel.js +3 -2
  41. package/esm/core/DatePicker/DatePicker.d.ts +5 -0
  42. package/esm/core/DatePicker/DatePicker.js +26 -7
  43. package/esm/core/Dialog/DialogMain.js +19 -24
  44. package/esm/core/Slider/Thumb.js +2 -4
  45. package/esm/core/Surface/Surface.d.ts +24 -2
  46. package/esm/core/Surface/Surface.js +39 -3
  47. package/esm/core/Surface/index.d.ts +1 -1
  48. package/esm/core/Tabs/Tabs.js +4 -2
  49. package/esm/core/Tile/Tile.d.ts +24 -2
  50. package/esm/core/Tile/Tile.js +82 -49
  51. package/esm/core/ToggleSwitch/ToggleSwitch.d.ts +11 -31
  52. package/esm/core/ToggleSwitch/ToggleSwitch.js +8 -1
  53. package/esm/core/index.d.ts +3 -3
  54. package/esm/core/index.js +1 -1
  55. package/esm/core/utils/components/Divider.d.ts +14 -0
  56. package/esm/core/utils/components/Divider.js +17 -0
  57. package/esm/core/utils/components/LinkAction.d.ts +30 -0
  58. package/esm/core/utils/components/LinkAction.js +38 -0
  59. package/esm/core/utils/components/Resizer.js +9 -9
  60. package/esm/core/utils/components/VisuallyHidden.d.ts +20 -6
  61. package/esm/core/utils/components/VisuallyHidden.js +10 -3
  62. package/esm/core/utils/components/index.d.ts +2 -0
  63. package/esm/core/utils/components/index.js +2 -0
  64. package/esm/core/utils/functions/index.d.ts +1 -0
  65. package/esm/core/utils/functions/index.js +1 -0
  66. package/esm/core/utils/functions/supports.d.ts +4 -0
  67. package/esm/core/utils/functions/supports.js +9 -0
  68. package/esm/core/utils/hooks/index.d.ts +1 -0
  69. package/esm/core/utils/hooks/index.js +1 -0
  70. package/esm/core/utils/hooks/useDragAndDrop.js +4 -3
  71. package/esm/core/utils/hooks/useIsClient.d.ts +1 -0
  72. package/esm/core/utils/hooks/useIsClient.js +12 -0
  73. package/esm/core/utils/hooks/useTheme.js +21 -0
  74. package/package.json +2 -2
@@ -1,10 +1,34 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
2
25
  Object.defineProperty(exports, "__esModule", { value: true });
3
26
  exports.useTheme = void 0;
4
27
  /*---------------------------------------------------------------------------------------------
5
28
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
6
29
  * See LICENSE.md in the project root for license terms and full copyright notice.
7
30
  *--------------------------------------------------------------------------------------------*/
31
+ const React = __importStar(require("react"));
8
32
  const functions_1 = require("../functions");
9
33
  const useIsomorphicLayoutEffect_1 = require("./useIsomorphicLayoutEffect");
10
34
  const useIsThemeAlreadySet_1 = require("./useIsThemeAlreadySet");
@@ -23,6 +47,7 @@ const useTheme = (theme, themeOptions) => {
23
47
  var _a;
24
48
  const ownerDocument = (_a = themeOptions === null || themeOptions === void 0 ? void 0 : themeOptions.ownerDocument) !== null && _a !== void 0 ? _a : (0, functions_1.getDocument)();
25
49
  const isThemeAlreadySet = (0, useIsThemeAlreadySet_1.useIsThemeAlreadySet)(ownerDocument);
50
+ useCorrectRootFontSize();
26
51
  (0, useIsomorphicLayoutEffect_1.useIsomorphicLayoutEffect)(() => {
27
52
  if (!ownerDocument || isThemeAlreadySet.current) {
28
53
  return;
@@ -81,3 +106,22 @@ const handleTheme = (theme, ownerDocument, highContrast) => {
81
106
  (_b = prefersHCQuery === null || prefersHCQuery === void 0 ? void 0 : prefersHCQuery.removeEventListener) === null || _b === void 0 ? void 0 : _b.call(prefersHCQuery, 'change', changeHandler);
82
107
  };
83
108
  };
109
+ let didLogWarning = false;
110
+ let isDev = false;
111
+ // wrapping in try-catch because process might be undefined
112
+ try {
113
+ isDev = process.env.NODE_ENV !== 'production';
114
+ }
115
+ catch (_a) { }
116
+ /** Shows console error if the page changes the root font size */
117
+ const useCorrectRootFontSize = () => {
118
+ React.useEffect(() => {
119
+ if (isDev && !didLogWarning) {
120
+ const rootFontSize = parseInt(getComputedStyle(document.documentElement).fontSize);
121
+ if (rootFontSize < 16) {
122
+ console.error('Root font size must not be overridden. \nSee https://github.com/iTwin/iTwinUI/wiki/iTwinUI-react-v2-migration-guide#relative-font-size');
123
+ didLogWarning = true;
124
+ }
125
+ }
126
+ }, []);
127
+ };
@@ -10,7 +10,7 @@ export declare type BadgeProps = {
10
10
  *
11
11
  * If not specified, a default neutral background will be used.
12
12
  */
13
- backgroundColor?: 'primary' | 'positive' | 'negative' | 'warning' | keyof typeof SoftBackgrounds | AnyString;
13
+ backgroundColor?: 'primary' | 'informational' | 'positive' | 'negative' | 'warning' | keyof typeof SoftBackgrounds | AnyString;
14
14
  /**
15
15
  * Badge label.
16
16
  * Always gets converted to uppercase, and truncated if too long.
@@ -13,18 +13,14 @@ const getBadgeColorValue = (color) => {
13
13
  if (!color) {
14
14
  return '';
15
15
  }
16
- switch (color) {
17
- case 'primary':
18
- return '#A5D7F5';
19
- case 'positive':
20
- return '#C3E1AF';
21
- case 'negative':
22
- return '#EFA9A9';
23
- case 'warning':
24
- return '#F9D7AB';
25
- default:
26
- return isSoftBackground(color) ? SoftBackgrounds[color] : color;
27
- }
16
+ return isSoftBackground(color) ? SoftBackgrounds[color] : color;
17
+ };
18
+ /**
19
+ * Helper function that returns one of the preset badge status values.
20
+ */
21
+ const getStatusValue = (color) => {
22
+ const statuses = ['positive', 'negative', 'warning', 'informational'];
23
+ return color && statuses.includes(color) ? color : undefined;
28
24
  };
29
25
  /**
30
26
  * A colorful visual indicator for categorizing items.
@@ -36,12 +32,15 @@ const getBadgeColorValue = (color) => {
36
32
  export const Badge = (props) => {
37
33
  const { backgroundColor, style, className, children, ...rest } = props;
38
34
  useTheme();
39
- const _style = backgroundColor
35
+ // choosing 'primary' status should result in data-iui-status equaling 'informational'
36
+ const reducedBackgroundColor = backgroundColor === 'primary' ? 'informational' : backgroundColor;
37
+ const statusValue = getStatusValue(reducedBackgroundColor);
38
+ const _style = reducedBackgroundColor && !statusValue
40
39
  ? {
41
- '--iui-badge-background-color': getBadgeColorValue(backgroundColor),
40
+ '--iui-badge-background-color': getBadgeColorValue(reducedBackgroundColor),
42
41
  ...style,
43
42
  }
44
43
  : { ...style };
45
- return (React.createElement("span", { className: cx('iui-badge', className), style: _style, ...rest }, children));
44
+ return (React.createElement("span", { className: cx('iui-badge', className), style: _style, "data-iui-status": statusValue, ...rest }, children));
46
45
  };
47
46
  export default Badge;
@@ -60,8 +60,9 @@ export const Carousel = Object.assign(React.forwardRef((props, ref) => {
60
60
  if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) {
61
61
  return;
62
62
  }
63
- if (event.key === 'ArrowLeft' || event.key === 'ArrowRight') {
64
- setKeysPressed((old) => ({ ...old, [event.key]: true }));
63
+ const key = event.key;
64
+ if (key === 'ArrowLeft' || key === 'ArrowRight') {
65
+ setKeysPressed((old) => ({ ...old, [key]: true }));
65
66
  }
66
67
  };
67
68
  const handleKeyUp = (event) => {
@@ -61,6 +61,11 @@ export declare type DatePickerProps = {
61
61
  * @default false
62
62
  */
63
63
  showYearSelection?: boolean;
64
+ /**
65
+ * Will disable dates for which this function returns true.
66
+ * Disabled dates cannot be selected.
67
+ */
68
+ isDateDisabled?: (date: Date) => boolean;
64
69
  } & DateRangePickerProps & Omit<TimePickerProps, 'date' | 'onChange' | 'setFocusHour'>;
65
70
  /**
66
71
  * Date picker component
@@ -123,7 +123,7 @@ export const generateLocalizedStrings = (locale) => {
123
123
  */
124
124
  export const DatePicker = (props) => {
125
125
  var _a, _b, _c, _d, _e, _f, _g, _h;
126
- const { date, onChange, localizedNames, className, style, setFocus = false, showTime = false, use12Hours = false, precision, hourStep, minuteStep, secondStep, useCombinedRenderer, combinedRenderer, hourRenderer, minuteRenderer, secondRenderer, meridiemRenderer, showYearSelection = false, enableRangeSelect = false, startDate, endDate, ...rest } = props;
126
+ const { date, onChange, localizedNames, className, style, setFocus = false, showTime = false, use12Hours = false, precision, hourStep, minuteStep, secondStep, useCombinedRenderer, combinedRenderer, hourRenderer, minuteRenderer, secondRenderer, meridiemRenderer, showYearSelection = false, enableRangeSelect = false, startDate, endDate, isDateDisabled, ...rest } = props;
127
127
  useTheme();
128
128
  const monthNames = (_a = localizedNames === null || localizedNames === void 0 ? void 0 : localizedNames.months) !== null && _a !== void 0 ? _a : defaultMonths;
129
129
  const shortDays = (_b = localizedNames === null || localizedNames === void 0 ? void 0 : localizedNames.shortDays) !== null && _b !== void 0 ? _b : defaultShortDays;
@@ -260,6 +260,10 @@ export const DatePicker = (props) => {
260
260
  }
261
261
  }
262
262
  };
263
+ const isPreviousMonthDisabled = isDateDisabled === null || isDateDisabled === void 0 ? void 0 : isDateDisabled(new Date(displayedYear, displayedMonthIndex, 0));
264
+ const isNextMonthDisabled = isDateDisabled === null || isDateDisabled === void 0 ? void 0 : isDateDisabled(new Date(displayedYear, displayedMonthIndex + 1, 1));
265
+ const isPreviousYearDisabled = isDateDisabled === null || isDateDisabled === void 0 ? void 0 : isDateDisabled(new Date(displayedYear - 1, 11, 31));
266
+ const isNextYearDisabled = isDateDisabled === null || isDateDisabled === void 0 ? void 0 : isDateDisabled(new Date(displayedYear + 1, 0, 1));
263
267
  const handleCalendarKeyDown = (event) => {
264
268
  if (!focusedDay) {
265
269
  return;
@@ -269,6 +273,9 @@ export const DatePicker = (props) => {
269
273
  case 'ArrowDown':
270
274
  adjustedFocusedDay.setDate(focusedDay.getDate() + 7);
271
275
  if (adjustedFocusedDay.getMonth() !== displayedMonthIndex) {
276
+ if (isNextMonthDisabled) {
277
+ return;
278
+ }
272
279
  handleMoveToNextMonth();
273
280
  }
274
281
  setFocusedDay(adjustedFocusedDay);
@@ -278,6 +285,9 @@ export const DatePicker = (props) => {
278
285
  case 'ArrowUp':
279
286
  adjustedFocusedDay.setDate(focusedDay.getDate() - 7);
280
287
  if (adjustedFocusedDay.getMonth() !== displayedMonthIndex) {
288
+ if (isPreviousMonthDisabled) {
289
+ return;
290
+ }
281
291
  handleMoveToPreviousMonth();
282
292
  }
283
293
  setFocusedDay(adjustedFocusedDay);
@@ -287,6 +297,9 @@ export const DatePicker = (props) => {
287
297
  case 'ArrowLeft':
288
298
  adjustedFocusedDay.setDate(focusedDay.getDate() - 1);
289
299
  if (adjustedFocusedDay.getMonth() !== displayedMonthIndex) {
300
+ if (isPreviousMonthDisabled) {
301
+ return;
302
+ }
290
303
  handleMoveToPreviousMonth();
291
304
  }
292
305
  setFocusedDay(adjustedFocusedDay);
@@ -296,6 +309,9 @@ export const DatePicker = (props) => {
296
309
  case 'ArrowRight':
297
310
  adjustedFocusedDay.setDate(focusedDay.getDate() + 1);
298
311
  if (adjustedFocusedDay.getMonth() !== displayedMonthIndex) {
312
+ if (isNextMonthDisabled) {
313
+ return;
314
+ }
299
315
  handleMoveToNextMonth();
300
316
  }
301
317
  setFocusedDay(adjustedFocusedDay);
@@ -305,7 +321,9 @@ export const DatePicker = (props) => {
305
321
  case 'Enter':
306
322
  case ' ':
307
323
  case 'Spacebar':
308
- onDayClick(focusedDay);
324
+ if (!(isDateDisabled === null || isDateDisabled === void 0 ? void 0 : isDateDisabled(focusedDay))) {
325
+ onDayClick(focusedDay);
326
+ }
309
327
  event.preventDefault();
310
328
  break;
311
329
  }
@@ -340,23 +358,24 @@ export const DatePicker = (props) => {
340
358
  return (React.createElement("div", { className: cx('iui-date-picker', className), style: style, ...rest },
341
359
  React.createElement("div", null,
342
360
  React.createElement("div", { className: 'iui-calendar-month-year' },
343
- showYearSelection && (React.createElement(IconButton, { styleType: 'borderless', onClick: handleMoveToPreviousYear, "aria-label": 'Previous year', size: 'small' },
361
+ showYearSelection && (React.createElement(IconButton, { styleType: 'borderless', onClick: handleMoveToPreviousYear, "aria-label": 'Previous year', size: 'small', disabled: isPreviousYearDisabled },
344
362
  React.createElement(SvgChevronLeftDouble, null))),
345
- React.createElement(IconButton, { styleType: 'borderless', onClick: handleMoveToPreviousMonth, "aria-label": 'Previous month', size: 'small' },
363
+ React.createElement(IconButton, { styleType: 'borderless', onClick: handleMoveToPreviousMonth, "aria-label": 'Previous month', size: 'small', disabled: isPreviousMonthDisabled },
346
364
  React.createElement(SvgChevronLeft, null)),
347
365
  React.createElement("span", { "aria-live": 'polite' },
348
366
  React.createElement("span", { className: 'iui-calendar-month', title: monthNames[displayedMonthIndex] }, monthNames[displayedMonthIndex]),
349
367
  "\u00A0",
350
368
  displayedYear),
351
- React.createElement(IconButton, { styleType: 'borderless', onClick: handleMoveToNextMonth, "aria-label": 'Next month', size: 'small' },
369
+ React.createElement(IconButton, { styleType: 'borderless', onClick: handleMoveToNextMonth, "aria-label": 'Next month', size: 'small', disabled: isNextMonthDisabled },
352
370
  React.createElement(SvgChevronRight, null)),
353
- showYearSelection && (React.createElement(IconButton, { styleType: 'borderless', onClick: handleMoveToNextYear, "aria-label": 'Next year', size: 'small' },
371
+ showYearSelection && (React.createElement(IconButton, { styleType: 'borderless', onClick: handleMoveToNextYear, "aria-label": 'Next year', size: 'small', disabled: isNextYearDisabled },
354
372
  React.createElement(SvgChevronRightDouble, null)))),
355
373
  React.createElement("div", { className: 'iui-calendar-weekdays' }, shortDays.map((day, index) => (React.createElement("div", { key: day, title: longDays[index] }, day)))),
356
374
  React.createElement("div", { onKeyDown: handleCalendarKeyDown, role: 'listbox' }, weeks.map((weekDays, weekIndex) => {
357
375
  return (React.createElement("div", { key: `week-${displayedMonthIndex}-${weekIndex}`, className: 'iui-calendar-week' }, weekDays.map((weekDay, dayIndex) => {
358
376
  const dateValue = weekDay.getDate();
359
- return (React.createElement("div", { key: `day-${displayedMonthIndex}-${dayIndex}`, className: getDayClass(weekDay), onClick: () => onDayClick(weekDay), role: 'option', tabIndex: isSameDay(weekDay, focusedDay) ? 0 : -1, ref: (element) => isSameDay(weekDay, focusedDay) &&
377
+ const isDisabled = isDateDisabled === null || isDateDisabled === void 0 ? void 0 : isDateDisabled(weekDay);
378
+ return (React.createElement("div", { key: `day-${displayedMonthIndex}-${dayIndex}`, className: getDayClass(weekDay), onClick: () => !isDisabled && onDayClick(weekDay), role: 'option', tabIndex: isSameDay(weekDay, focusedDay) ? 0 : -1, "aria-disabled": isDisabled ? 'true' : undefined, ref: (element) => isSameDay(weekDay, focusedDay) &&
360
379
  needFocus.current &&
361
380
  (element === null || element === void 0 ? void 0 : element.focus()) }, dateValue));
362
381
  })));
@@ -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, useIsomorphicLayoutEffect, } from '../utils';
7
+ import { FocusTrap, getTranslateValues, 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';
@@ -38,28 +38,7 @@ export const DialogMain = React.forwardRef((props, ref) => {
38
38
  const dialogRef = React.useRef(null);
39
39
  const refs = useMergedRefs(dialogRef, ref);
40
40
  const hasBeenResized = React.useRef(false);
41
- // Focuses dialog when opened and brings back focus to the previously focused element when closed.
42
41
  const previousFocusedElement = React.useRef();
43
- const setFocusRef = useLatestRef(setFocus);
44
- React.useEffect(() => {
45
- var _a, _b, _c;
46
- if (!setFocusRef.current) {
47
- return;
48
- }
49
- if (isOpen) {
50
- previousFocusedElement.current = (_a = dialogRef.current) === null || _a === void 0 ? void 0 : _a.ownerDocument.activeElement;
51
- (_b = dialogRef.current) === null || _b === void 0 ? void 0 : _b.focus();
52
- }
53
- else {
54
- (_c = previousFocusedElement.current) === null || _c === void 0 ? void 0 : _c.focus();
55
- }
56
- const ref = dialogRef.current;
57
- return () => {
58
- var _a;
59
- (ref === null || ref === void 0 ? void 0 : ref.contains(document.activeElement)) &&
60
- ((_a = previousFocusedElement.current) === null || _a === void 0 ? void 0 : _a.focus());
61
- };
62
- }, [isOpen, setFocusRef]);
63
42
  const originalBodyOverflow = React.useRef('');
64
43
  React.useEffect(() => {
65
44
  if (isOpen) {
@@ -130,7 +109,6 @@ export const DialogMain = React.forwardRef((props, ref) => {
130
109
  const content = (React.createElement("div", { className: cx('iui-dialog', {
131
110
  'iui-dialog-default': styleType === 'default',
132
111
  'iui-dialog-full-page': styleType === 'fullPage',
133
- 'iui-dialog-visible': isOpen,
134
112
  'iui-dialog-draggable': isDraggable,
135
113
  }, className), role: 'dialog', ref: refs, onKeyDown: handleKeyDown, tabIndex: -1, style: {
136
114
  transform,
@@ -145,7 +123,24 @@ export const DialogMain = React.forwardRef((props, ref) => {
145
123
  }
146
124
  }, onResizeEnd: setResizeStyle })),
147
125
  children));
148
- return (React.createElement(CSSTransition, { in: isOpen, classNames: 'iui-dialog-animation', timeout: { exit: 600 }, unmountOnExit: true, nodeRef: dialogRef },
126
+ return (React.createElement(CSSTransition, { in: isOpen, classNames: {
127
+ enter: 'iui-dialog-animation-enter',
128
+ enterActive: 'iui-dialog-animation-enter-active',
129
+ enterDone: 'iui-dialog-visible',
130
+ }, timeout: { exit: 600 },
131
+ // Focuses dialog when opened
132
+ onEntered: () => {
133
+ var _a, _b;
134
+ previousFocusedElement.current = (_a = dialogRef.current) === null || _a === void 0 ? void 0 : _a.ownerDocument.activeElement;
135
+ setFocus && ((_b = dialogRef.current) === null || _b === void 0 ? void 0 : _b.focus({ preventScroll: true }));
136
+ },
137
+ // Brings back focus to the previously focused element when closed
138
+ onExit: () => {
139
+ var _a, _b, _c;
140
+ if ((_a = dialogRef.current) === null || _a === void 0 ? void 0 : _a.contains((_b = dialogRef.current) === null || _b === void 0 ? void 0 : _b.ownerDocument.activeElement)) {
141
+ (_c = previousFocusedElement.current) === null || _c === void 0 ? void 0 : _c.focus();
142
+ }
143
+ }, unmountOnExit: true, nodeRef: dialogRef },
149
144
  React.createElement(DialogDragContext.Provider, { value: { onPointerDown: handlePointerDown } },
150
145
  trapFocus && React.createElement(FocusTrap, null, content),
151
146
  !trapFocus && content)));
@@ -40,8 +40,6 @@ export const Thumb = (props) => {
40
40
  const handlePointerDownOnThumb = React.useCallback(() => {
41
41
  !disabled && onThumbActivated(index);
42
42
  }, [disabled, index, onThumbActivated]);
43
- const [hasFocus, setHasFocus] = React.useState(false);
44
- const [isHovered, setIsHovered] = React.useState(false);
45
43
  const adjustedValue = React.useMemo(() => {
46
44
  if (value < sliderMin) {
47
45
  return sliderMin;
@@ -58,11 +56,11 @@ export const Thumb = (props) => {
58
56
  return (100.0 * (adjustedValue - sliderMin)) / (sliderMax - sliderMin);
59
57
  }, [adjustedValue, sliderMax, sliderMin]);
60
58
  const { style, className, ...rest } = thumbProps || {};
61
- return (React.createElement(Tooltip, { visible: isActive || hasFocus || isHovered, placement: 'top', ...tooltipProps },
59
+ return (React.createElement(Tooltip, { placement: 'top', trigger: (tooltipProps === null || tooltipProps === void 0 ? void 0 : tooltipProps.visible) == null ? 'mouseenter click focus' : undefined, ...tooltipProps },
62
60
  React.createElement("div", { ...rest, "data-index": index, ref: thumbRef, style: {
63
61
  ...style,
64
62
  ...(orientation === 'horizontal'
65
63
  ? { left: `${lowPercent}%` }
66
64
  : { bottom: `${lowPercent}%` }),
67
- }, className: cx('iui-slider-thumb', { 'iui-active': isActive }, className), role: 'slider', tabIndex: disabled ? undefined : 0, "aria-valuemin": minVal, "aria-valuenow": value, "aria-valuemax": maxVal, "aria-disabled": disabled, onPointerDown: handlePointerDownOnThumb, onKeyDown: (event) => handleOnKeyboardEvent(event, false), onKeyUp: (event) => handleOnKeyboardEvent(event, true), onFocus: () => setHasFocus(true), onBlur: () => setHasFocus(false), onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false) })));
65
+ }, className: cx('iui-slider-thumb', { 'iui-active': isActive }, className), role: 'slider', tabIndex: disabled ? undefined : 0, "aria-valuemin": minVal, "aria-valuenow": value, "aria-valuemax": maxVal, "aria-disabled": disabled, onPointerDown: handlePointerDownOnThumb, onKeyDown: (event) => handleOnKeyboardEvent(event, false), onKeyUp: (event) => handleOnKeyboardEvent(event, true) })));
68
66
  };
@@ -1,6 +1,15 @@
1
1
  import React from 'react';
2
- import { CommonProps } from '../utils';
2
+ import { CommonProps, PolymorphicComponentProps, PolymorphicForwardRefComponent } from '../utils';
3
3
  import '@itwin/itwinui-css/css/surface.css';
4
+ declare type SurfaceHeaderOwnProps = {};
5
+ export declare type SurfaceHeaderProps<T extends React.ElementType = 'div'> = PolymorphicComponentProps<T, SurfaceHeaderOwnProps>;
6
+ declare type SurfaceBodyOwnProps = {
7
+ /**
8
+ * Gives padding to the surface body
9
+ */
10
+ isPadded?: boolean;
11
+ };
12
+ export declare type SurfaceBodyProps<T extends React.ElementType = 'div'> = PolymorphicComponentProps<T, SurfaceBodyOwnProps>;
4
13
  export declare type SurfaceProps = {
5
14
  /**
6
15
  * Sets the elevation of the surface
@@ -16,6 +25,10 @@ export declare type SurfaceProps = {
16
25
  * @example
17
26
  * <Surface>Surface Content</Surface>
18
27
  * <Surface elevation={2}>Surface Content</Surface>
28
+ * <Surface>
29
+ * <Surface.Header>Surface Header Content</Surface.Header>
30
+ * <Surface.Body isPadded={true}>Surface Body Content</Surface.Body>
31
+ * </Surface>
19
32
  */
20
33
  export declare const Surface: React.ForwardRefExoticComponent<{
21
34
  /**
@@ -26,5 +39,14 @@ export declare const Surface: React.ForwardRefExoticComponent<{
26
39
  * Content in the surface.
27
40
  */
28
41
  children: React.ReactNode;
29
- } & Omit<CommonProps, "title"> & React.RefAttributes<HTMLDivElement>>;
42
+ } & Omit<CommonProps, "title"> & React.RefAttributes<HTMLDivElement>> & {
43
+ /**
44
+ * Surface header subcomponent
45
+ */
46
+ Header: PolymorphicForwardRefComponent<"div", SurfaceHeaderOwnProps>;
47
+ /**
48
+ * Surface body subcomponent. Additional padding can be added to the body through the 'isPadded' prop
49
+ */
50
+ Body: PolymorphicForwardRefComponent<"div", SurfaceBodyOwnProps>;
51
+ };
30
52
  export default Surface;
@@ -4,7 +4,7 @@
4
4
  *--------------------------------------------------------------------------------------------*/
5
5
  import React from 'react';
6
6
  import cx from 'classnames';
7
- import { useTheme } from '../utils';
7
+ import { useSafeContext, useTheme, supportsHas, } from '../utils';
8
8
  import '@itwin/itwinui-css/css/surface.css';
9
9
  /**
10
10
  * Helper function that returns one of the preset surface elevation values.
@@ -27,19 +27,55 @@ const getSurfaceElevationValue = (elevation) => {
27
27
  return '';
28
28
  }
29
29
  };
30
+ const SurfaceHeader = React.forwardRef((props, ref) => {
31
+ const { as: Element = 'div', children, className, ...rest } = props;
32
+ const { setHasLayout } = useSafeContext(SurfaceContext);
33
+ React.useEffect(() => {
34
+ if (!supportsHas()) {
35
+ setHasLayout(true);
36
+ }
37
+ }, [setHasLayout]);
38
+ return (React.createElement(Element, { className: cx('iui-surface-header', className), ref: ref, ...rest }, children));
39
+ });
40
+ const SurfaceBody = React.forwardRef((props, ref) => {
41
+ const { as: Element = 'div', children, className, isPadded, ...rest } = props;
42
+ const { setHasLayout } = useSafeContext(SurfaceContext);
43
+ React.useEffect(() => {
44
+ if (!supportsHas()) {
45
+ setHasLayout(true);
46
+ }
47
+ }, [setHasLayout]);
48
+ return (React.createElement(Element, { className: cx('iui-surface-body', className), ref: ref, "data-iui-padded": isPadded ? 'true' : undefined, ...rest }, children));
49
+ });
30
50
  /**
31
51
  * The Surface container allows content to appear elevated through the use of a drop shadow
32
52
  * @example
33
53
  * <Surface>Surface Content</Surface>
34
54
  * <Surface elevation={2}>Surface Content</Surface>
55
+ * <Surface>
56
+ * <Surface.Header>Surface Header Content</Surface.Header>
57
+ * <Surface.Body isPadded={true}>Surface Body Content</Surface.Body>
58
+ * </Surface>
35
59
  */
36
- export const Surface = React.forwardRef((props, ref) => {
60
+ export const Surface = Object.assign(React.forwardRef((props, ref) => {
37
61
  const { elevation, className, style, children, ...rest } = props;
38
62
  useTheme();
63
+ const [hasLayout, setHasLayout] = React.useState(false);
39
64
  const _style = {
40
65
  '--iui-surface-elevation': getSurfaceElevationValue(elevation),
41
66
  ...style,
42
67
  };
43
- return (React.createElement("div", { className: cx('iui-surface', className), style: _style, ref: ref, ...rest }, children));
68
+ return (React.createElement("div", { className: cx('iui-surface', className), style: _style, ref: ref, "data-iui-layout": hasLayout ? 'true' : undefined, ...rest },
69
+ React.createElement(SurfaceContext.Provider, { value: { setHasLayout } }, children)));
70
+ }), {
71
+ /**
72
+ * Surface header subcomponent
73
+ */
74
+ Header: SurfaceHeader,
75
+ /**
76
+ * Surface body subcomponent. Additional padding can be added to the body through the 'isPadded' prop
77
+ */
78
+ Body: SurfaceBody,
44
79
  });
80
+ const SurfaceContext = React.createContext(undefined);
45
81
  export default Surface;
@@ -1,4 +1,4 @@
1
1
  export { Surface } from './Surface';
2
- export type { SurfaceProps } from './Surface';
2
+ export type { SurfaceProps, SurfaceHeaderProps, SurfaceBodyProps, } from './Surface';
3
3
  declare const _default: "./Surface";
4
4
  export default _default;
@@ -4,7 +4,7 @@
4
4
  *--------------------------------------------------------------------------------------------*/
5
5
  import cx from 'classnames';
6
6
  import React from 'react';
7
- import { useTheme, useMergedRefs, getBoundedValue, useContainerWidth, useIsomorphicLayoutEffect, } from '../utils';
7
+ import { useTheme, useMergedRefs, getBoundedValue, useContainerWidth, useIsomorphicLayoutEffect, useIsClient, } from '../utils';
8
8
  import '@itwin/itwinui-css/css/tabs.css';
9
9
  import { Tab } from './Tab';
10
10
  /**
@@ -44,6 +44,7 @@ export const Tabs = (props) => {
44
44
  }
45
45
  const { labels, activeIndex, onTabSelected, focusActivationMode = 'auto', type = 'default', color = 'blue', orientation = 'horizontal', tabsClassName, contentClassName, wrapperClassName, children, ...rest } = props;
46
46
  useTheme();
47
+ const isClient = useIsClient();
47
48
  const tablistRef = React.useRef(null);
48
49
  const [tablistSizeRef, tabsWidth] = useContainerWidth(type !== 'default');
49
50
  const refs = useMergedRefs(tablistRef, tablistSizeRef);
@@ -155,7 +156,8 @@ export const Tabs = (props) => {
155
156
  return (React.createElement("div", { className: cx('iui-tabs-wrapper', `iui-${orientation}`, wrapperClassName), style: stripeProperties },
156
157
  React.createElement("ul", { className: cx('iui-tabs', `iui-${type}`, {
157
158
  'iui-green': color === 'green',
158
- 'iui-animated': type !== 'default',
159
+ 'iui-animated': type !== 'default' && isClient,
160
+ 'iui-not-animated': type !== 'default' && !isClient,
159
161
  'iui-large': hasSublabel,
160
162
  }, tabsClassName), role: 'tablist', ref: refs, onKeyDown: onKeyDown, ...rest }, labels.map((label, index) => {
161
163
  const onClick = () => {
@@ -1,5 +1,16 @@
1
1
  import React from 'react';
2
+ import { PolymorphicComponentProps } from '../utils';
2
3
  import '@itwin/itwinui-css/css/tile.css';
4
+ declare type TileActionOwnProps = {};
5
+ /**
6
+ * Polymorphic Tile action component. Recommended to be used in a "name" of `Tile`.
7
+ * Renders `a` element by default.
8
+ * @example
9
+ * <Tile
10
+ * name={<Tile.Action href='/new-page'>Tile name<Tile.Action/>}
11
+ * />
12
+ */
13
+ export declare const TileAction: (props: PolymorphicComponentProps<'a', TileActionOwnProps>) => JSX.Element;
3
14
  export declare type TileProps = {
4
15
  /**
5
16
  * Name or title of the tile.
@@ -102,7 +113,8 @@ export declare type TileProps = {
102
113
  * @default false
103
114
  */
104
115
  isDisabled?: boolean;
105
- } & React.ComponentPropsWithoutRef<'div'>;
116
+ onClick?: React.MouseEventHandler<HTMLElement>;
117
+ } & Omit<React.ComponentPropsWithoutRef<'div'>, 'onClick'>;
106
118
  /**
107
119
  * Tile component that displays content and actions in a card-like format.
108
120
  * @example
@@ -120,5 +132,15 @@ export declare type TileProps = {
120
132
  * isNew={false}
121
133
  * />
122
134
  */
123
- export declare const Tile: (props: TileProps) => JSX.Element;
135
+ export declare const Tile: ((props: TileProps) => JSX.Element) & {
136
+ /**
137
+ * Polymorphic Tile action component. Recommended to be used in a "name" of `Tile`.
138
+ * Renders `a` element by default.
139
+ * @example
140
+ * <Tile
141
+ * name={<Tile.Action href='/new-page'>Tile name<Tile.Action/>}
142
+ * />
143
+ */
144
+ Action: (props: PolymorphicComponentProps<'a', TileActionOwnProps>) => JSX.Element;
145
+ };
124
146
  export default Tile;