@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
package/CHANGELOG.md CHANGED
@@ -1,10 +1,81 @@
1
1
  # Changelog
2
2
 
3
- ## 2.6.1
3
+ ## 2.8.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 861fcab3: The `Surface` component can now be broken down using the `Surface.Header` and `Surface.Body` subcomponents. Users can add padding to the body using `isPadded`.
8
+
9
+ ```jsx
10
+ <Surface>
11
+ <Surface.Header>Surface Header Content</Surface.Header>
12
+ <Surface.Body isPadded={true}>Surface Body Content</Surface.Body>
13
+ </Surface>
14
+ ```
15
+
16
+ - 861fcab3: A new `Divider` component has been created which can be used horizontally or vertically
17
+
18
+ ```jsx
19
+ <Divider orientation={'vertical'} />
20
+ ```
21
+
22
+ - 8c89441f: Added `VisuallyHidden`, a utility component for providing text to assistive technologies while hiding it visually.
23
+
24
+ ```jsx
25
+ <div aria-hidden='true'>★★★☆☆</div>
26
+ <VisuallyHidden>3 stars out of 5</VisuallyHidden>
27
+ ```
4
28
 
5
29
  ### Patch Changes
6
30
 
7
- - c5cfa4c: Fixed an issue with incremental migration where adding a close button to v2 Toaster was breaking v1 styles for the whole page.
31
+ - 3ad2dd90: Fixed an issue in draggable/resizable dialogs opened in popup windows, where pointermove event listeners were not being removed correctly.
32
+ - 521610a0: iTwinUI will now show a warning in development if it detects that the page overrides the root font size. For more details, see the [migration guide](https://github.com/iTwin/iTwinUI/wiki/iTwinUI-react-v2-migration-guide#relative-font-size).
33
+ - 6caccc8d: Fixes jumpy animation when opening full page dialog
34
+ - Updated dependencies
35
+ - @itwin/itwinui-css@1.9.0
36
+
37
+ ## 2.7.0
38
+
39
+ ### Minor Changes
40
+
41
+ - bea577e2: Updated the visuals for status colors in Badge.
42
+ - c581e9ed: Added `LinkBox` and `LinkAction`components to improve components with action accessibility.
43
+
44
+ Usage:
45
+
46
+ ```js
47
+ <LinkBox>
48
+ <LinkAction href='/new-page'>Link to click</LinkAction>
49
+ </LinkBox>
50
+ ```
51
+
52
+ - c581e9ed: Added `Tile.Action` to take advantage of these new a11y components in Tile.
53
+
54
+ Usage:
55
+
56
+ ```js
57
+ <Tile
58
+ name={
59
+ <Tile.Action as='button' onClick={() => {/* Do things */}>
60
+ Tile name that is also a button
61
+ </Tile.Action>
62
+ }
63
+ />
64
+ ```
65
+
66
+ - 61f44293: Added new `isDateDisabled` prop to DatePicker. Accepts a function which takes a date and returns a boolean to indicate whether that date is not selectable.
67
+
68
+ ### Patch Changes
69
+
70
+ - 198d6a95: Remove the ability to set icon prop for ToggleSwitch when size is set to small
71
+ - c5cfa4c6: Fixed an issue with incremental migration where adding a close button to v2 Toaster was breaking v1 styles for the whole page.
72
+ - a1f235d0: Fixed Carousel showing warnings in React 16 when using arrow keys.
73
+ - c9dee6f5: Fixed an issue where Slider's tooltip was still visible after unmounting the component.
74
+ - 775933e3: The DOM order of Tile content has changed so that the name comes before the thumbnail region. This improves accessibility without affecting visuals.
75
+ - 028d4cd7: Updated actionable tile to have a more prominent hover effect.
76
+ - 341449ca: Fixes an issue where stripe width for borderless and pill tabs was rendering an incorrect length upon first visiting the page.
77
+ - Updated dependencies
78
+ - @itwin/itwinui-css@1.8.0
8
79
 
9
80
  ## 2.6.0
10
81
 
@@ -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.
@@ -19,18 +19,14 @@ const getBadgeColorValue = (color) => {
19
19
  if (!color) {
20
20
  return '';
21
21
  }
22
- switch (color) {
23
- case 'primary':
24
- return '#A5D7F5';
25
- case 'positive':
26
- return '#C3E1AF';
27
- case 'negative':
28
- return '#EFA9A9';
29
- case 'warning':
30
- return '#F9D7AB';
31
- default:
32
- return (0, utils_1.isSoftBackground)(color) ? utils_1.SoftBackgrounds[color] : color;
33
- }
22
+ return (0, utils_1.isSoftBackground)(color) ? utils_1.SoftBackgrounds[color] : color;
23
+ };
24
+ /**
25
+ * Helper function that returns one of the preset badge status values.
26
+ */
27
+ const getStatusValue = (color) => {
28
+ const statuses = ['positive', 'negative', 'warning', 'informational'];
29
+ return color && statuses.includes(color) ? color : undefined;
34
30
  };
35
31
  /**
36
32
  * A colorful visual indicator for categorizing items.
@@ -42,13 +38,16 @@ const getBadgeColorValue = (color) => {
42
38
  const Badge = (props) => {
43
39
  const { backgroundColor, style, className, children, ...rest } = props;
44
40
  (0, utils_1.useTheme)();
45
- const _style = backgroundColor
41
+ // choosing 'primary' status should result in data-iui-status equaling 'informational'
42
+ const reducedBackgroundColor = backgroundColor === 'primary' ? 'informational' : backgroundColor;
43
+ const statusValue = getStatusValue(reducedBackgroundColor);
44
+ const _style = reducedBackgroundColor && !statusValue
46
45
  ? {
47
- '--iui-badge-background-color': getBadgeColorValue(backgroundColor),
46
+ '--iui-badge-background-color': getBadgeColorValue(reducedBackgroundColor),
48
47
  ...style,
49
48
  }
50
49
  : { ...style };
51
- return (react_1.default.createElement("span", { className: (0, classnames_1.default)('iui-badge', className), style: _style, ...rest }, children));
50
+ return (react_1.default.createElement("span", { className: (0, classnames_1.default)('iui-badge', className), style: _style, "data-iui-status": statusValue, ...rest }, children));
52
51
  };
53
52
  exports.Badge = Badge;
54
53
  exports.default = exports.Badge;
@@ -66,8 +66,9 @@ exports.Carousel = Object.assign(react_1.default.forwardRef((props, ref) => {
66
66
  if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) {
67
67
  return;
68
68
  }
69
- if (event.key === 'ArrowLeft' || event.key === 'ArrowRight') {
70
- setKeysPressed((old) => ({ ...old, [event.key]: true }));
69
+ const key = event.key;
70
+ if (key === 'ArrowLeft' || key === 'ArrowRight') {
71
+ setKeysPressed((old) => ({ ...old, [key]: true }));
71
72
  }
72
73
  };
73
74
  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
@@ -130,7 +130,7 @@ exports.generateLocalizedStrings = generateLocalizedStrings;
130
130
  */
131
131
  const DatePicker = (props) => {
132
132
  var _a, _b, _c, _d, _e, _f, _g, _h;
133
- 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;
133
+ 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;
134
134
  (0, utils_1.useTheme)();
135
135
  const monthNames = (_a = localizedNames === null || localizedNames === void 0 ? void 0 : localizedNames.months) !== null && _a !== void 0 ? _a : defaultMonths;
136
136
  const shortDays = (_b = localizedNames === null || localizedNames === void 0 ? void 0 : localizedNames.shortDays) !== null && _b !== void 0 ? _b : defaultShortDays;
@@ -267,6 +267,10 @@ const DatePicker = (props) => {
267
267
  }
268
268
  }
269
269
  };
270
+ const isPreviousMonthDisabled = isDateDisabled === null || isDateDisabled === void 0 ? void 0 : isDateDisabled(new Date(displayedYear, displayedMonthIndex, 0));
271
+ const isNextMonthDisabled = isDateDisabled === null || isDateDisabled === void 0 ? void 0 : isDateDisabled(new Date(displayedYear, displayedMonthIndex + 1, 1));
272
+ const isPreviousYearDisabled = isDateDisabled === null || isDateDisabled === void 0 ? void 0 : isDateDisabled(new Date(displayedYear - 1, 11, 31));
273
+ const isNextYearDisabled = isDateDisabled === null || isDateDisabled === void 0 ? void 0 : isDateDisabled(new Date(displayedYear + 1, 0, 1));
270
274
  const handleCalendarKeyDown = (event) => {
271
275
  if (!focusedDay) {
272
276
  return;
@@ -276,6 +280,9 @@ const DatePicker = (props) => {
276
280
  case 'ArrowDown':
277
281
  adjustedFocusedDay.setDate(focusedDay.getDate() + 7);
278
282
  if (adjustedFocusedDay.getMonth() !== displayedMonthIndex) {
283
+ if (isNextMonthDisabled) {
284
+ return;
285
+ }
279
286
  handleMoveToNextMonth();
280
287
  }
281
288
  setFocusedDay(adjustedFocusedDay);
@@ -285,6 +292,9 @@ const DatePicker = (props) => {
285
292
  case 'ArrowUp':
286
293
  adjustedFocusedDay.setDate(focusedDay.getDate() - 7);
287
294
  if (adjustedFocusedDay.getMonth() !== displayedMonthIndex) {
295
+ if (isPreviousMonthDisabled) {
296
+ return;
297
+ }
288
298
  handleMoveToPreviousMonth();
289
299
  }
290
300
  setFocusedDay(adjustedFocusedDay);
@@ -294,6 +304,9 @@ const DatePicker = (props) => {
294
304
  case 'ArrowLeft':
295
305
  adjustedFocusedDay.setDate(focusedDay.getDate() - 1);
296
306
  if (adjustedFocusedDay.getMonth() !== displayedMonthIndex) {
307
+ if (isPreviousMonthDisabled) {
308
+ return;
309
+ }
297
310
  handleMoveToPreviousMonth();
298
311
  }
299
312
  setFocusedDay(adjustedFocusedDay);
@@ -303,6 +316,9 @@ const DatePicker = (props) => {
303
316
  case 'ArrowRight':
304
317
  adjustedFocusedDay.setDate(focusedDay.getDate() + 1);
305
318
  if (adjustedFocusedDay.getMonth() !== displayedMonthIndex) {
319
+ if (isNextMonthDisabled) {
320
+ return;
321
+ }
306
322
  handleMoveToNextMonth();
307
323
  }
308
324
  setFocusedDay(adjustedFocusedDay);
@@ -312,7 +328,9 @@ const DatePicker = (props) => {
312
328
  case 'Enter':
313
329
  case ' ':
314
330
  case 'Spacebar':
315
- onDayClick(focusedDay);
331
+ if (!(isDateDisabled === null || isDateDisabled === void 0 ? void 0 : isDateDisabled(focusedDay))) {
332
+ onDayClick(focusedDay);
333
+ }
316
334
  event.preventDefault();
317
335
  break;
318
336
  }
@@ -347,23 +365,24 @@ const DatePicker = (props) => {
347
365
  return (react_1.default.createElement("div", { className: (0, classnames_1.default)('iui-date-picker', className), style: style, ...rest },
348
366
  react_1.default.createElement("div", null,
349
367
  react_1.default.createElement("div", { className: 'iui-calendar-month-year' },
350
- showYearSelection && (react_1.default.createElement(IconButton_1.IconButton, { styleType: 'borderless', onClick: handleMoveToPreviousYear, "aria-label": 'Previous year', size: 'small' },
368
+ showYearSelection && (react_1.default.createElement(IconButton_1.IconButton, { styleType: 'borderless', onClick: handleMoveToPreviousYear, "aria-label": 'Previous year', size: 'small', disabled: isPreviousYearDisabled },
351
369
  react_1.default.createElement(utils_1.SvgChevronLeftDouble, null))),
352
- react_1.default.createElement(IconButton_1.IconButton, { styleType: 'borderless', onClick: handleMoveToPreviousMonth, "aria-label": 'Previous month', size: 'small' },
370
+ react_1.default.createElement(IconButton_1.IconButton, { styleType: 'borderless', onClick: handleMoveToPreviousMonth, "aria-label": 'Previous month', size: 'small', disabled: isPreviousMonthDisabled },
353
371
  react_1.default.createElement(utils_1.SvgChevronLeft, null)),
354
372
  react_1.default.createElement("span", { "aria-live": 'polite' },
355
373
  react_1.default.createElement("span", { className: 'iui-calendar-month', title: monthNames[displayedMonthIndex] }, monthNames[displayedMonthIndex]),
356
374
  "\u00A0",
357
375
  displayedYear),
358
- react_1.default.createElement(IconButton_1.IconButton, { styleType: 'borderless', onClick: handleMoveToNextMonth, "aria-label": 'Next month', size: 'small' },
376
+ react_1.default.createElement(IconButton_1.IconButton, { styleType: 'borderless', onClick: handleMoveToNextMonth, "aria-label": 'Next month', size: 'small', disabled: isNextMonthDisabled },
359
377
  react_1.default.createElement(utils_1.SvgChevronRight, null)),
360
- showYearSelection && (react_1.default.createElement(IconButton_1.IconButton, { styleType: 'borderless', onClick: handleMoveToNextYear, "aria-label": 'Next year', size: 'small' },
378
+ showYearSelection && (react_1.default.createElement(IconButton_1.IconButton, { styleType: 'borderless', onClick: handleMoveToNextYear, "aria-label": 'Next year', size: 'small', disabled: isNextYearDisabled },
361
379
  react_1.default.createElement(utils_1.SvgChevronRightDouble, null)))),
362
380
  react_1.default.createElement("div", { className: 'iui-calendar-weekdays' }, shortDays.map((day, index) => (react_1.default.createElement("div", { key: day, title: longDays[index] }, day)))),
363
381
  react_1.default.createElement("div", { onKeyDown: handleCalendarKeyDown, role: 'listbox' }, weeks.map((weekDays, weekIndex) => {
364
382
  return (react_1.default.createElement("div", { key: `week-${displayedMonthIndex}-${weekIndex}`, className: 'iui-calendar-week' }, weekDays.map((weekDay, dayIndex) => {
365
383
  const dateValue = weekDay.getDate();
366
- return (react_1.default.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) &&
384
+ const isDisabled = isDateDisabled === null || isDateDisabled === void 0 ? void 0 : isDateDisabled(weekDay);
385
+ return (react_1.default.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) &&
367
386
  needFocus.current &&
368
387
  (element === null || element === void 0 ? void 0 : element.focus()) }, dateValue));
369
388
  })));
@@ -44,28 +44,7 @@ exports.DialogMain = react_1.default.forwardRef((props, ref) => {
44
44
  const dialogRef = react_1.default.useRef(null);
45
45
  const refs = (0, utils_1.useMergedRefs)(dialogRef, ref);
46
46
  const hasBeenResized = react_1.default.useRef(false);
47
- // Focuses dialog when opened and brings back focus to the previously focused element when closed.
48
47
  const previousFocusedElement = react_1.default.useRef();
49
- const setFocusRef = (0, utils_1.useLatestRef)(setFocus);
50
- react_1.default.useEffect(() => {
51
- var _a, _b, _c;
52
- if (!setFocusRef.current) {
53
- return;
54
- }
55
- if (isOpen) {
56
- previousFocusedElement.current = (_a = dialogRef.current) === null || _a === void 0 ? void 0 : _a.ownerDocument.activeElement;
57
- (_b = dialogRef.current) === null || _b === void 0 ? void 0 : _b.focus();
58
- }
59
- else {
60
- (_c = previousFocusedElement.current) === null || _c === void 0 ? void 0 : _c.focus();
61
- }
62
- const ref = dialogRef.current;
63
- return () => {
64
- var _a;
65
- (ref === null || ref === void 0 ? void 0 : ref.contains(document.activeElement)) &&
66
- ((_a = previousFocusedElement.current) === null || _a === void 0 ? void 0 : _a.focus());
67
- };
68
- }, [isOpen, setFocusRef]);
69
48
  const originalBodyOverflow = react_1.default.useRef('');
70
49
  react_1.default.useEffect(() => {
71
50
  if (isOpen) {
@@ -136,7 +115,6 @@ exports.DialogMain = react_1.default.forwardRef((props, ref) => {
136
115
  const content = (react_1.default.createElement("div", { className: (0, classnames_1.default)('iui-dialog', {
137
116
  'iui-dialog-default': styleType === 'default',
138
117
  'iui-dialog-full-page': styleType === 'fullPage',
139
- 'iui-dialog-visible': isOpen,
140
118
  'iui-dialog-draggable': isDraggable,
141
119
  }, className), role: 'dialog', ref: refs, onKeyDown: handleKeyDown, tabIndex: -1, style: {
142
120
  transform,
@@ -151,7 +129,24 @@ exports.DialogMain = react_1.default.forwardRef((props, ref) => {
151
129
  }
152
130
  }, onResizeEnd: setResizeStyle })),
153
131
  children));
154
- return (react_1.default.createElement(react_transition_group_1.CSSTransition, { in: isOpen, classNames: 'iui-dialog-animation', timeout: { exit: 600 }, unmountOnExit: true, nodeRef: dialogRef },
132
+ return (react_1.default.createElement(react_transition_group_1.CSSTransition, { in: isOpen, classNames: {
133
+ enter: 'iui-dialog-animation-enter',
134
+ enterActive: 'iui-dialog-animation-enter-active',
135
+ enterDone: 'iui-dialog-visible',
136
+ }, timeout: { exit: 600 },
137
+ // Focuses dialog when opened
138
+ onEntered: () => {
139
+ var _a, _b;
140
+ previousFocusedElement.current = (_a = dialogRef.current) === null || _a === void 0 ? void 0 : _a.ownerDocument.activeElement;
141
+ setFocus && ((_b = dialogRef.current) === null || _b === void 0 ? void 0 : _b.focus({ preventScroll: true }));
142
+ },
143
+ // Brings back focus to the previously focused element when closed
144
+ onExit: () => {
145
+ var _a, _b, _c;
146
+ if ((_a = dialogRef.current) === null || _a === void 0 ? void 0 : _a.contains((_b = dialogRef.current) === null || _b === void 0 ? void 0 : _b.ownerDocument.activeElement)) {
147
+ (_c = previousFocusedElement.current) === null || _c === void 0 ? void 0 : _c.focus();
148
+ }
149
+ }, unmountOnExit: true, nodeRef: dialogRef },
155
150
  react_1.default.createElement(DialogDragContext_1.DialogDragContext.Provider, { value: { onPointerDown: handlePointerDown } },
156
151
  trapFocus && react_1.default.createElement(utils_1.FocusTrap, null, content),
157
152
  !trapFocus && content)));
@@ -46,8 +46,6 @@ const Thumb = (props) => {
46
46
  const handlePointerDownOnThumb = react_1.default.useCallback(() => {
47
47
  !disabled && onThumbActivated(index);
48
48
  }, [disabled, index, onThumbActivated]);
49
- const [hasFocus, setHasFocus] = react_1.default.useState(false);
50
- const [isHovered, setIsHovered] = react_1.default.useState(false);
51
49
  const adjustedValue = react_1.default.useMemo(() => {
52
50
  if (value < sliderMin) {
53
51
  return sliderMin;
@@ -64,12 +62,12 @@ const Thumb = (props) => {
64
62
  return (100.0 * (adjustedValue - sliderMin)) / (sliderMax - sliderMin);
65
63
  }, [adjustedValue, sliderMax, sliderMin]);
66
64
  const { style, className, ...rest } = thumbProps || {};
67
- return (react_1.default.createElement(Tooltip_1.Tooltip, { visible: isActive || hasFocus || isHovered, placement: 'top', ...tooltipProps },
65
+ return (react_1.default.createElement(Tooltip_1.Tooltip, { placement: 'top', trigger: (tooltipProps === null || tooltipProps === void 0 ? void 0 : tooltipProps.visible) == null ? 'mouseenter click focus' : undefined, ...tooltipProps },
68
66
  react_1.default.createElement("div", { ...rest, "data-index": index, ref: thumbRef, style: {
69
67
  ...style,
70
68
  ...(orientation === 'horizontal'
71
69
  ? { left: `${lowPercent}%` }
72
70
  : { bottom: `${lowPercent}%` }),
73
- }, className: (0, classnames_1.default)('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) })));
71
+ }, className: (0, classnames_1.default)('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) })));
74
72
  };
75
73
  exports.Thumb = Thumb;
@@ -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;
@@ -33,19 +33,55 @@ const getSurfaceElevationValue = (elevation) => {
33
33
  return '';
34
34
  }
35
35
  };
36
+ const SurfaceHeader = react_1.default.forwardRef((props, ref) => {
37
+ const { as: Element = 'div', children, className, ...rest } = props;
38
+ const { setHasLayout } = (0, utils_1.useSafeContext)(SurfaceContext);
39
+ react_1.default.useEffect(() => {
40
+ if (!(0, utils_1.supportsHas)()) {
41
+ setHasLayout(true);
42
+ }
43
+ }, [setHasLayout]);
44
+ return (react_1.default.createElement(Element, { className: (0, classnames_1.default)('iui-surface-header', className), ref: ref, ...rest }, children));
45
+ });
46
+ const SurfaceBody = react_1.default.forwardRef((props, ref) => {
47
+ const { as: Element = 'div', children, className, isPadded, ...rest } = props;
48
+ const { setHasLayout } = (0, utils_1.useSafeContext)(SurfaceContext);
49
+ react_1.default.useEffect(() => {
50
+ if (!(0, utils_1.supportsHas)()) {
51
+ setHasLayout(true);
52
+ }
53
+ }, [setHasLayout]);
54
+ return (react_1.default.createElement(Element, { className: (0, classnames_1.default)('iui-surface-body', className), ref: ref, "data-iui-padded": isPadded ? 'true' : undefined, ...rest }, children));
55
+ });
36
56
  /**
37
57
  * The Surface container allows content to appear elevated through the use of a drop shadow
38
58
  * @example
39
59
  * <Surface>Surface Content</Surface>
40
60
  * <Surface elevation={2}>Surface Content</Surface>
61
+ * <Surface>
62
+ * <Surface.Header>Surface Header Content</Surface.Header>
63
+ * <Surface.Body isPadded={true}>Surface Body Content</Surface.Body>
64
+ * </Surface>
41
65
  */
42
- exports.Surface = react_1.default.forwardRef((props, ref) => {
66
+ exports.Surface = Object.assign(react_1.default.forwardRef((props, ref) => {
43
67
  const { elevation, className, style, children, ...rest } = props;
44
68
  (0, utils_1.useTheme)();
69
+ const [hasLayout, setHasLayout] = react_1.default.useState(false);
45
70
  const _style = {
46
71
  '--iui-surface-elevation': getSurfaceElevationValue(elevation),
47
72
  ...style,
48
73
  };
49
- return (react_1.default.createElement("div", { className: (0, classnames_1.default)('iui-surface', className), style: _style, ref: ref, ...rest }, children));
74
+ return (react_1.default.createElement("div", { className: (0, classnames_1.default)('iui-surface', className), style: _style, ref: ref, "data-iui-layout": hasLayout ? 'true' : undefined, ...rest },
75
+ react_1.default.createElement(SurfaceContext.Provider, { value: { setHasLayout } }, children)));
76
+ }), {
77
+ /**
78
+ * Surface header subcomponent
79
+ */
80
+ Header: SurfaceHeader,
81
+ /**
82
+ * Surface body subcomponent. Additional padding can be added to the body through the 'isPadded' prop
83
+ */
84
+ Body: SurfaceBody,
50
85
  });
86
+ const SurfaceContext = react_1.default.createContext(undefined);
51
87
  exports.default = exports.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;
@@ -50,6 +50,7 @@ const Tabs = (props) => {
50
50
  }
51
51
  const { labels, activeIndex, onTabSelected, focusActivationMode = 'auto', type = 'default', color = 'blue', orientation = 'horizontal', tabsClassName, contentClassName, wrapperClassName, children, ...rest } = props;
52
52
  (0, utils_1.useTheme)();
53
+ const isClient = (0, utils_1.useIsClient)();
53
54
  const tablistRef = react_1.default.useRef(null);
54
55
  const [tablistSizeRef, tabsWidth] = (0, utils_1.useContainerWidth)(type !== 'default');
55
56
  const refs = (0, utils_1.useMergedRefs)(tablistRef, tablistSizeRef);
@@ -161,7 +162,8 @@ const Tabs = (props) => {
161
162
  return (react_1.default.createElement("div", { className: (0, classnames_1.default)('iui-tabs-wrapper', `iui-${orientation}`, wrapperClassName), style: stripeProperties },
162
163
  react_1.default.createElement("ul", { className: (0, classnames_1.default)('iui-tabs', `iui-${type}`, {
163
164
  'iui-green': color === 'green',
164
- 'iui-animated': type !== 'default',
165
+ 'iui-animated': type !== 'default' && isClient,
166
+ 'iui-not-animated': type !== 'default' && !isClient,
165
167
  'iui-large': hasSublabel,
166
168
  }, tabsClassName), role: 'tablist', ref: refs, onKeyDown: onKeyDown, ...rest }, labels.map((label, index) => {
167
169
  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;