@itwin/itwinui-react 3.0.0-dev.13 → 3.0.0-dev.15

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 (47) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/cjs/core/Carousel/Carousel.d.ts +12 -5
  3. package/cjs/core/Carousel/Carousel.js +9 -39
  4. package/cjs/core/Carousel/CarouselContext.d.ts +0 -4
  5. package/cjs/core/Carousel/CarouselDot.js +1 -1
  6. package/cjs/core/Carousel/CarouselDotsList.js +26 -2
  7. package/cjs/core/Carousel/CarouselNavigation.d.ts +1 -1
  8. package/cjs/core/Carousel/CarouselNavigation.js +4 -17
  9. package/cjs/core/Carousel/CarouselSlide.d.ts +1 -1
  10. package/cjs/core/Carousel/CarouselSlide.js +12 -2
  11. package/cjs/core/Carousel/CarouselSlider.d.ts +1 -1
  12. package/cjs/core/Carousel/CarouselSlider.js +2 -2
  13. package/cjs/core/Slider/Slider.d.ts +2 -6
  14. package/cjs/core/Slider/Slider.js +8 -22
  15. package/cjs/core/Slider/Thumb.d.ts +1 -2
  16. package/cjs/core/Slider/Thumb.js +1 -5
  17. package/cjs/core/Tabs/Tabs.js +12 -18
  18. package/cjs/core/ThemeProvider/ThemeProvider.d.ts +3 -2
  19. package/cjs/core/ThemeProvider/ThemeProvider.js +14 -7
  20. package/cjs/core/Tile/Tile.js +11 -10
  21. package/cjs/core/utils/components/WithCSSTransition.js +7 -1
  22. package/cjs/core/utils/hooks/useOverflow.js +3 -1
  23. package/cjs/styles.js +8 -10
  24. package/esm/core/Carousel/Carousel.d.ts +12 -5
  25. package/esm/core/Carousel/Carousel.js +9 -39
  26. package/esm/core/Carousel/CarouselContext.d.ts +0 -4
  27. package/esm/core/Carousel/CarouselDot.js +1 -1
  28. package/esm/core/Carousel/CarouselDotsList.js +26 -2
  29. package/esm/core/Carousel/CarouselNavigation.d.ts +1 -1
  30. package/esm/core/Carousel/CarouselNavigation.js +5 -22
  31. package/esm/core/Carousel/CarouselSlide.d.ts +1 -1
  32. package/esm/core/Carousel/CarouselSlide.js +15 -3
  33. package/esm/core/Carousel/CarouselSlider.d.ts +1 -1
  34. package/esm/core/Carousel/CarouselSlider.js +2 -2
  35. package/esm/core/Slider/Slider.d.ts +2 -6
  36. package/esm/core/Slider/Slider.js +8 -19
  37. package/esm/core/Slider/Thumb.d.ts +1 -2
  38. package/esm/core/Slider/Thumb.js +1 -5
  39. package/esm/core/Tabs/Tabs.js +13 -17
  40. package/esm/core/ThemeProvider/ThemeProvider.d.ts +3 -2
  41. package/esm/core/ThemeProvider/ThemeProvider.js +14 -7
  42. package/esm/core/Tile/Tile.js +11 -10
  43. package/esm/core/utils/components/WithCSSTransition.js +7 -1
  44. package/esm/core/utils/hooks/useOverflow.js +3 -1
  45. package/esm/styles.js +8 -10
  46. package/package.json +2 -2
  47. package/styles.css +31 -45
@@ -16,12 +16,9 @@ import {
16
16
  mergeEventHandlers,
17
17
  useControlledState,
18
18
  useId,
19
- getWindow,
19
+ useLatestRef,
20
20
  } from '../utils/index.js';
21
21
  import { Icon } from '../Icon/Icon.js';
22
- // Checking user motion preference for scroll into view animation
23
- const isMotionOk = () =>
24
- getWindow()?.matchMedia?.('(prefers-reduced-motion: no-preference)')?.matches;
25
22
  const TabsWrapper = React.forwardRef((props, ref) => {
26
23
  const {
27
24
  className,
@@ -123,21 +120,19 @@ const Tab = React.forwardRef((props, forwardedRef) => {
123
120
  const { tabsWidth } = useSafeContext(TabListContext);
124
121
  const tabRef = React.useRef();
125
122
  const isActive = activeValue === value;
123
+ const isActiveRef = useLatestRef(isActive);
124
+ // Scroll to active tab only on initial render
126
125
  useIsomorphicLayoutEffect(() => {
127
- if (isActive) {
128
- if (orientation === 'horizontal') {
129
- tabRef.current?.scrollIntoView({
130
- inline: 'center',
131
- behavior: isMotionOk() ? 'smooth' : 'auto',
132
- });
133
- } else {
134
- tabRef.current?.scrollIntoView({
135
- block: 'center',
136
- behavior: isMotionOk() ? 'smooth' : 'auto',
137
- });
138
- }
126
+ if (isActiveRef.current) {
127
+ tabRef.current?.parentElement?.scrollTo({
128
+ [orientation === 'horizontal' ? 'left' : 'top']:
129
+ tabRef.current?.[
130
+ orientation === 'horizontal' ? 'offsetLeft' : 'offsetTop'
131
+ ] - 4,
132
+ behavior: 'instant', // not using 'smooth' to reduce layout shift on page load
133
+ });
139
134
  }
140
- }, [isActive]);
135
+ }, []);
141
136
  const updateStripe = () => {
142
137
  const currentTabRect = tabRef.current?.getBoundingClientRect();
143
138
  setStripeProperties({
@@ -231,6 +226,7 @@ const Tab = React.forwardRef((props, forwardedRef) => {
231
226
  onClick: mergeEventHandlers(props.onClick, () => setActiveValue(value)),
232
227
  onKeyDown: mergeEventHandlers(props.onKeyDown, onKeyDown),
233
228
  onFocus: mergeEventHandlers(props.onFocus, () => {
229
+ tabRef.current?.scrollIntoView({ block: 'nearest', inline: 'nearest' });
234
230
  if (focusActivationMode === 'auto' && !props.disabled) {
235
231
  setActiveValue(value);
236
232
  }
@@ -17,9 +17,10 @@ type RootProps = {
17
17
  * This can cause a flash of incorrect theme on first render.
18
18
  *
19
19
  * The 'inherit' option is intended to be used by packages, to enable incremental adoption
20
- * of iTwinUI v2 in app that might be using v1 in other places.
20
+ * of iTwinUI while respecting the theme set by the consuming app. It will fall back to 'light'
21
+ * if no parent theme is found. Additionally, it will attempt to inherit the `portalContainer` if possible.
21
22
  *
22
- * @default 'light'
23
+ * @default 'inherit'
23
24
  */
24
25
  theme?: ThemeType | 'inherit';
25
26
  themeOptions?: Pick<ThemeOptions, 'highContrast'> & {
@@ -50,12 +50,19 @@ export const ThemeProvider = React.forwardRef((props, forwardedRef) => {
50
50
  portalContainer: portalContainerProp,
51
51
  ...rest
52
52
  } = props;
53
+ const [parentTheme, rootRef, parentContext] = useParentTheme();
54
+ const theme = themeProp === 'inherit' ? parentTheme || 'light' : themeProp;
55
+ /**
56
+ * We will portal our portal container into `portalContainer` prop (if specified),
57
+ * or inherit `portalContainer` from context (if also inheriting theme).
58
+ */
59
+ const portaledPortalContainer =
60
+ portalContainerProp ||
61
+ (themeProp === 'inherit' ? parentContext?.portalContainer : undefined);
53
62
  const [portalContainer, setPortalContainer] = useControlledState(
54
63
  null,
55
- portalContainerProp,
64
+ portaledPortalContainer,
56
65
  );
57
- const [parentTheme, rootRef] = useParentTheme();
58
- const theme = themeProp === 'inherit' ? parentTheme || 'light' : themeProp;
59
66
  const shouldApplyBackground = themeOptions?.applyBackground ?? !parentTheme;
60
67
  const contextValue = React.useMemo(
61
68
  () => ({ theme, themeOptions, portalContainer }),
@@ -79,14 +86,14 @@ export const ThemeProvider = React.forwardRef((props, forwardedRef) => {
79
86
  ToastProvider,
80
87
  null,
81
88
  children,
82
- portalContainerProp
89
+ portaledPortalContainer
83
90
  ? ReactDOM.createPortal(
84
91
  React.createElement(Toaster, null),
85
- portalContainerProp,
92
+ portaledPortalContainer,
86
93
  )
87
94
  : React.createElement(
88
95
  'div',
89
- { ref: setPortalContainer },
96
+ { ref: setPortalContainer, style: { display: 'contents' } },
90
97
  React.createElement(Toaster, null),
91
98
  ),
92
99
  ),
@@ -144,5 +151,5 @@ const useParentTheme = () => {
144
151
  ?.getAttribute('data-iui-theme'),
145
152
  );
146
153
  }, []);
147
- return [parentContext?.theme ?? parentThemeState, rootRef];
154
+ return [parentContext?.theme ?? parentThemeState, rootRef, parentContext];
148
155
  };
@@ -308,16 +308,17 @@ const TileComponent = React.forwardRef((props, forwardedRef) => {
308
308
  : name,
309
309
  ),
310
310
  ),
311
- React.createElement(
312
- TileThumbnailArea,
313
- null,
314
- typeof thumbnail !== 'string'
315
- ? React.createElement(TileThumbnailPicture, null, thumbnail)
316
- : React.createElement(TileThumbnailPicture, { url: thumbnail }),
317
- badge && React.createElement(TileBadgeContainer, null, badge),
318
- leftIcon && React.createElement(TileTypeIndicator, null, leftIcon),
319
- rightIcon && React.createElement(TileQuickAction, null, rightIcon),
320
- ),
311
+ thumbnail &&
312
+ React.createElement(
313
+ TileThumbnailArea,
314
+ null,
315
+ typeof thumbnail !== 'string'
316
+ ? React.createElement(TileThumbnailPicture, null, thumbnail)
317
+ : React.createElement(TileThumbnailPicture, { url: thumbnail }),
318
+ badge && React.createElement(TileBadgeContainer, null, badge),
319
+ leftIcon && React.createElement(TileTypeIndicator, null, leftIcon),
320
+ rightIcon && React.createElement(TileQuickAction, null, rightIcon),
321
+ ),
321
322
  React.createElement(
322
323
  TileContentArea,
323
324
  null,
@@ -4,6 +4,7 @@
4
4
  *--------------------------------------------------------------------------------------------*/
5
5
  import * as React from 'react';
6
6
  import { CSSTransition } from 'react-transition-group';
7
+ import styles from '../../../styles.js';
7
8
  export const WithCSSTransition = (props) => {
8
9
  const { in: visible, dimension = 'height', children, ...rest } = props;
9
10
  const expandedSize = React.useRef(0);
@@ -32,7 +33,12 @@ export const WithCSSTransition = (props) => {
32
33
  node.style[`min${dimensionCamelCase}`] = 'initial';
33
34
  node.style[dimension] = '0px';
34
35
  },
35
- classNames: 'iui',
36
+ classNames: {
37
+ enter: styles['iui-enter'],
38
+ enterActive: styles['iui-enter-active'],
39
+ exit: styles['iui-exit'],
40
+ exitActive: styles['iui-exit-active'],
41
+ },
36
42
  ...rest,
37
43
  },
38
44
  React.isValidElement(children)
@@ -68,7 +68,9 @@ export const useOverflow = (
68
68
  if (availableSize < requiredSize) {
69
69
  const avgItemSize = requiredSize / visibleCount;
70
70
  const visibleItems = Math.floor(availableSize / avgItemSize);
71
- setVisibleCount(visibleItems);
71
+ /* When first item is larger than the container - visibleItems count is 0,
72
+ We can assume that at least some part of the first item is visible and return 1. */
73
+ setVisibleCount(visibleItems > 0 ? visibleItems : 1);
72
74
  } else if (needsFullRerender.current) {
73
75
  const childrenSize = Array.from(containerRef.current.children).reduce(
74
76
  (sum, child) => sum + child[`offset${dimension}`],
package/esm/styles.js CHANGED
@@ -71,9 +71,7 @@ const styles = {
71
71
  'iui-color-selection-wrapper': '_iui3-color-selection-wrapper',
72
72
  'iui-color-field': '_iui3-color-field',
73
73
  'iui-hue-slider': '_iui3-hue-slider',
74
- 'iui-slider-container': '_iui3-slider-container',
75
- 'iui-slider-rail': '_iui3-slider-rail',
76
- 'iui-slider-thumb': '_iui3-slider-thumb',
74
+ 'iui-slider': '_iui3-slider',
77
75
  'iui-opacity-slider': '_iui3-opacity-slider',
78
76
  'iui-color-dot': '_iui3-color-dot',
79
77
  'iui-date-picker': '_iui3-date-picker',
@@ -214,10 +212,10 @@ const styles = {
214
212
  'iui-overlay-exiting': '_iui3-overlay-exiting',
215
213
  closeAnimation,
216
214
  'iui-progress-indicator-radial': '_iui3-progress-indicator-radial',
217
- 'iui-uktpgli': '_iui3-uktpgli',
215
+ 'iui-uodwwa8': '_iui3-uodwwa8',
218
216
  'iui-progress-indicator-linear-label':
219
217
  '_iui3-progress-indicator-linear-label',
220
- 'iui-uktpgmg': '_iui3-uktpgmg',
218
+ 'iui-uodwwal': '_iui3-uodwwal',
221
219
  'iui-radio': '_iui3-radio',
222
220
  'iui-radio-tile': '_iui3-radio-tile',
223
221
  'iui-radio-tile-icon': '_iui3-radio-tile-icon',
@@ -229,6 +227,7 @@ const styles = {
229
227
  'iui-expandable-searchbox': '_iui3-expandable-searchbox',
230
228
  'iui-searchbox-open-button': '_iui3-searchbox-open-button',
231
229
  'iui-search-icon': '_iui3-search-icon',
230
+ 'iui-search-input': '_iui3-search-input',
232
231
  'iui-placeholder': '_iui3-placeholder',
233
232
  'iui-select-tag': '_iui3-select-tag',
234
233
  'iui-select-tag-label': '_iui3-select-tag-label',
@@ -256,15 +255,14 @@ const styles = {
256
255
  '_iui3-side-navigation-submenu-header-actions',
257
256
  'iui-side-navigation-wrapper': '_iui3-side-navigation-wrapper',
258
257
  'iui-skip-to-content-link': '_iui3-skip-to-content-link',
259
- 'iui-slider-component-container': '_iui3-slider-component-container',
260
- 'iui-slider-track': '_iui3-slider-track',
258
+ 'iui-slider-container': '_iui3-slider-container',
261
259
  'iui-slider-min': '_iui3-slider-min',
262
260
  'iui-slider-max': '_iui3-slider-max',
261
+ 'iui-slider-ticks': '_iui3-slider-ticks',
263
262
  'iui-slider-tick': '_iui3-slider-tick',
263
+ 'iui-slider-track': '_iui3-slider-track',
264
+ 'iui-slider-thumb': '_iui3-slider-thumb',
264
265
  'iui-grabbing': '_iui3-grabbing',
265
- 'iui-slider-ticks': '_iui3-slider-ticks',
266
- 'iui-slider-horizontal': '_iui3-slider-horizontal',
267
- 'iui-slider-vertical': '_iui3-slider-vertical',
268
266
  'iui-stepper': '_iui3-stepper',
269
267
  'iui-stepper-step': '_iui3-stepper-step',
270
268
  'iui-current': '_iui3-current',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itwin/itwinui-react",
3
- "version": "3.0.0-dev.13",
3
+ "version": "3.0.0-dev.15",
4
4
  "author": "Bentley Systems",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -83,7 +83,7 @@
83
83
  "tslib": "^2.6.0"
84
84
  },
85
85
  "devDependencies": {
86
- "@itwin/itwinui-css": "^2.0.0-dev.12",
86
+ "@itwin/itwinui-css": "^2.0.0-dev.13",
87
87
  "@itwin/itwinui-illustrations-react": "^2.1.0",
88
88
  "@itwin/itwinui-variables": "3.0.0-dev.1",
89
89
  "@swc/cli": "^0.1.62",