@itwin/itwinui-react 3.3.3 → 3.4.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.
- package/CHANGELOG.md +20 -0
- package/cjs/core/Carousel/CarouselSlider.js +1 -1
- package/cjs/core/ComboBox/ComboBox.js +1 -1
- package/cjs/core/DatePicker/DatePicker.d.ts +8 -0
- package/cjs/core/DatePicker/DatePicker.js +9 -4
- package/cjs/core/Dialog/DialogMain.js +5 -4
- package/cjs/core/FileUpload/FileUploadTemplate.d.ts +2 -1
- package/cjs/core/FileUpload/FileUploadTemplate.js +2 -1
- package/cjs/core/LinkAction/LinkAction.d.ts +3 -2
- package/cjs/core/LinkAction/LinkAction.js +33 -1
- package/cjs/core/Modal/Modal.d.ts +12 -0
- package/cjs/core/Modal/Modal.js +4 -4
- package/cjs/core/Popover/Popover.js +1 -1
- package/cjs/core/ProgressIndicators/ProgressLinear.d.ts +15 -7
- package/cjs/core/ProgressIndicators/ProgressLinear.js +14 -6
- package/cjs/core/ProgressIndicators/ProgressRadial.d.ts +3 -2
- package/cjs/core/ProgressIndicators/ProgressRadial.js +3 -1
- package/cjs/core/Table/Table.js +23 -10
- package/cjs/core/Tabs/Tabs.js +17 -16
- package/cjs/core/Tag/Tag.d.ts +29 -7
- package/cjs/core/Tag/Tag.js +12 -5
- package/cjs/core/ThemeProvider/ThemeProvider.js +2 -2
- package/cjs/core/utils/components/VirtualScroll.js +7 -7
- package/cjs/core/utils/hooks/useIsomorphicLayoutEffect.d.ts +4 -1
- package/cjs/core/utils/hooks/useIsomorphicLayoutEffect.js +5 -2
- package/cjs/core/utils/hooks/useMediaQuery.js +1 -1
- package/cjs/core/utils/hooks/useOverflow.js +3 -3
- package/esm/core/Carousel/CarouselSlider.js +2 -2
- package/esm/core/ComboBox/ComboBox.js +2 -2
- package/esm/core/DatePicker/DatePicker.d.ts +8 -0
- package/esm/core/DatePicker/DatePicker.js +9 -4
- package/esm/core/Dialog/DialogMain.js +6 -5
- package/esm/core/FileUpload/FileUploadTemplate.d.ts +2 -1
- package/esm/core/FileUpload/FileUploadTemplate.js +2 -1
- package/esm/core/LinkAction/LinkAction.d.ts +3 -2
- package/esm/core/LinkAction/LinkAction.js +7 -1
- package/esm/core/Modal/Modal.d.ts +12 -0
- package/esm/core/Modal/Modal.js +4 -4
- package/esm/core/Popover/Popover.js +2 -2
- package/esm/core/ProgressIndicators/ProgressLinear.d.ts +15 -7
- package/esm/core/ProgressIndicators/ProgressLinear.js +14 -6
- package/esm/core/ProgressIndicators/ProgressRadial.d.ts +3 -2
- package/esm/core/ProgressIndicators/ProgressRadial.js +3 -1
- package/esm/core/Table/Table.js +24 -11
- package/esm/core/Tabs/Tabs.js +18 -17
- package/esm/core/Tag/Tag.d.ts +29 -7
- package/esm/core/Tag/Tag.js +13 -6
- package/esm/core/ThemeProvider/ThemeProvider.js +3 -3
- package/esm/core/utils/components/VirtualScroll.js +8 -8
- package/esm/core/utils/hooks/useIsomorphicLayoutEffect.d.ts +4 -1
- package/esm/core/utils/hooks/useIsomorphicLayoutEffect.js +4 -1
- package/esm/core/utils/hooks/useMediaQuery.js +2 -2
- package/esm/core/utils/hooks/useOverflow.js +4 -4
- package/package.json +2 -2
- package/styles.css +9 -9
|
@@ -116,7 +116,7 @@ const useParentThemeAndContext = (rootElement) => {
|
|
|
116
116
|
const [parentThemeState, setParentTheme] = React.useState(parentContext?.theme);
|
|
117
117
|
const [parentHighContrastState, setParentHighContrastState] = React.useState(parentContext?.themeOptions?.highContrast);
|
|
118
118
|
const parentThemeRef = (0, index_js_1.useLatestRef)(parentContext?.theme);
|
|
119
|
-
(0, index_js_1.
|
|
119
|
+
(0, index_js_1.useLayoutEffect)(() => {
|
|
120
120
|
// bail if we already have theme from context
|
|
121
121
|
if (parentThemeRef.current) {
|
|
122
122
|
return;
|
|
@@ -155,7 +155,7 @@ const useParentThemeAndContext = (rootElement) => {
|
|
|
155
155
|
* dynamically import it (if possible) and fallback to loading it from a CDN.
|
|
156
156
|
*/
|
|
157
157
|
const FallbackStyles = ({ root }) => {
|
|
158
|
-
(0, index_js_1.
|
|
158
|
+
(0, index_js_1.useLayoutEffect)(() => {
|
|
159
159
|
// bail if styles are already loaded
|
|
160
160
|
if (getComputedStyle(root).getPropertyValue('--_iui-v3-loaded') === 'yes') {
|
|
161
161
|
return;
|
|
@@ -172,17 +172,17 @@ const useVirtualization = (props) => {
|
|
|
172
172
|
const [resizeRef, resizeObserver] = (0, index_js_1.useResizeObserver)(onResize);
|
|
173
173
|
// Find scrollable parent
|
|
174
174
|
// Needed only on init
|
|
175
|
-
(0, index_js_1.
|
|
175
|
+
(0, index_js_1.useLayoutEffect)(() => {
|
|
176
176
|
const scrollableParent = getScrollableParent(parentRef.current, parentRef.current?.ownerDocument);
|
|
177
177
|
scrollContainer.current = scrollableParent;
|
|
178
178
|
resizeRef(scrollableParent);
|
|
179
179
|
}, [resizeRef]);
|
|
180
180
|
// Stop watching resize, when virtual scroll is unmounted
|
|
181
|
-
(0, index_js_1.
|
|
181
|
+
(0, index_js_1.useLayoutEffect)(() => {
|
|
182
182
|
return () => resizeObserver?.disconnect();
|
|
183
183
|
}, [resizeObserver]);
|
|
184
184
|
// Get child height when children available
|
|
185
|
-
(0, index_js_1.
|
|
185
|
+
(0, index_js_1.useLayoutEffect)(() => updateChildHeight(), [updateChildHeight]);
|
|
186
186
|
const updateVirtualScroll = React.useCallback(() => {
|
|
187
187
|
const scrollableContainer = getScrollableContainer();
|
|
188
188
|
if (!scrollableContainer) {
|
|
@@ -215,7 +215,7 @@ const useVirtualization = (props) => {
|
|
|
215
215
|
: scrollContainer.current.removeEventListener('scroll', onScrollRef.current);
|
|
216
216
|
}, []);
|
|
217
217
|
// Add event listener to the scrollable container.
|
|
218
|
-
(0, index_js_1.
|
|
218
|
+
(0, index_js_1.useLayoutEffect)(() => {
|
|
219
219
|
removeScrollListener();
|
|
220
220
|
onScrollRef.current = onScroll;
|
|
221
221
|
if (!scrollContainer.current ||
|
|
@@ -227,7 +227,7 @@ const useVirtualization = (props) => {
|
|
|
227
227
|
}
|
|
228
228
|
return removeScrollListener;
|
|
229
229
|
}, [onScroll, removeScrollListener]);
|
|
230
|
-
(0, index_js_1.
|
|
230
|
+
(0, index_js_1.useLayoutEffect)(() => {
|
|
231
231
|
if (!isMounted) {
|
|
232
232
|
return;
|
|
233
233
|
}
|
|
@@ -282,8 +282,8 @@ const useVirtualization = (props) => {
|
|
|
282
282
|
});
|
|
283
283
|
}
|
|
284
284
|
}
|
|
285
|
-
}, [scrollToIndex, isMounted]);
|
|
286
|
-
(0, index_js_1.
|
|
285
|
+
}, [scrollToIndex, isMounted, itemsLength]);
|
|
286
|
+
(0, index_js_1.useLayoutEffect)(() => {
|
|
287
287
|
if (!scrollContainerHeight) {
|
|
288
288
|
return;
|
|
289
289
|
}
|
|
@@ -2,6 +2,9 @@ import * as React from 'react';
|
|
|
2
2
|
/**
|
|
3
3
|
* SSR-safe version of `useLayoutEffect` that replaces it with `useEffect` on the server.
|
|
4
4
|
*
|
|
5
|
+
* Exported as `useLayoutEffect` so that the react hooks linter correctly identifies the necessary dependencies.
|
|
6
|
+
*
|
|
5
7
|
* @see https://fb.me/react-uselayouteffect-ssr
|
|
6
8
|
*/
|
|
7
|
-
|
|
9
|
+
declare const useIsomorphicLayoutEffect: typeof React.useEffect;
|
|
10
|
+
export { useIsomorphicLayoutEffect as useLayoutEffect };
|
|
@@ -23,7 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.
|
|
26
|
+
exports.useLayoutEffect = void 0;
|
|
27
27
|
/*---------------------------------------------------------------------------------------------
|
|
28
28
|
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
29
29
|
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
@@ -32,6 +32,9 @@ const React = __importStar(require("react"));
|
|
|
32
32
|
/**
|
|
33
33
|
* SSR-safe version of `useLayoutEffect` that replaces it with `useEffect` on the server.
|
|
34
34
|
*
|
|
35
|
+
* Exported as `useLayoutEffect` so that the react hooks linter correctly identifies the necessary dependencies.
|
|
36
|
+
*
|
|
35
37
|
* @see https://fb.me/react-uselayouteffect-ssr
|
|
36
38
|
*/
|
|
37
|
-
|
|
39
|
+
const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;
|
|
40
|
+
exports.useLayoutEffect = useIsomorphicLayoutEffect;
|
|
@@ -33,7 +33,7 @@ const index_js_1 = require("../functions/index.js");
|
|
|
33
33
|
const useIsomorphicLayoutEffect_js_1 = require("./useIsomorphicLayoutEffect.js");
|
|
34
34
|
const useMediaQuery = (queryString) => {
|
|
35
35
|
const [matches, setMatches] = React.useState();
|
|
36
|
-
(0, useIsomorphicLayoutEffect_js_1.
|
|
36
|
+
(0, useIsomorphicLayoutEffect_js_1.useLayoutEffect)(() => {
|
|
37
37
|
const mediaQueryList = (0, index_js_1.getWindow)()?.matchMedia?.(queryString);
|
|
38
38
|
const handleChange = ({ matches }) => setMatches(matches);
|
|
39
39
|
if (mediaQueryList != undefined) {
|
|
@@ -64,7 +64,7 @@ const useOverflow = (items, disabled = false, orientation = 'horizontal') => {
|
|
|
64
64
|
const updateContainerSize = React.useCallback(({ width, height }) => setContainerSize(orientation === 'horizontal' ? width : height), [orientation]);
|
|
65
65
|
const [resizeRef, observer] = (0, useResizeObserver_js_1.useResizeObserver)(updateContainerSize);
|
|
66
66
|
const resizeObserverRef = React.useRef(observer);
|
|
67
|
-
(0, useIsomorphicLayoutEffect_js_1.
|
|
67
|
+
(0, useIsomorphicLayoutEffect_js_1.useLayoutEffect)(() => {
|
|
68
68
|
if (disabled) {
|
|
69
69
|
setVisibleCount(items.length);
|
|
70
70
|
}
|
|
@@ -74,7 +74,7 @@ const useOverflow = (items, disabled = false, orientation = 'horizontal') => {
|
|
|
74
74
|
}
|
|
75
75
|
}, [containerSize, disabled, items]);
|
|
76
76
|
const mergedRefs = (0, useMergedRefs_js_1.useMergedRefs)(containerRef, resizeRef);
|
|
77
|
-
(0, useIsomorphicLayoutEffect_js_1.
|
|
77
|
+
(0, useIsomorphicLayoutEffect_js_1.useLayoutEffect)(() => {
|
|
78
78
|
if (!containerRef.current || disabled) {
|
|
79
79
|
resizeObserverRef.current?.disconnect();
|
|
80
80
|
return;
|
|
@@ -103,7 +103,7 @@ const useOverflow = (items, disabled = false, orientation = 'horizontal') => {
|
|
|
103
103
|
}
|
|
104
104
|
needsFullRerender.current = false;
|
|
105
105
|
}, [containerSize, visibleCount, disabled, items.length, orientation]);
|
|
106
|
-
(0, useIsomorphicLayoutEffect_js_1.
|
|
106
|
+
(0, useIsomorphicLayoutEffect_js_1.useLayoutEffect)(() => {
|
|
107
107
|
previousContainerSize.current = containerSize;
|
|
108
108
|
}, [containerSize]);
|
|
109
109
|
return [mergedRefs, visibleCount];
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import * as React from 'react';
|
|
6
6
|
import cx from 'classnames';
|
|
7
7
|
import { CarouselContext } from './CarouselContext.js';
|
|
8
|
-
import { getWindow, useMergedRefs,
|
|
8
|
+
import { getWindow, useMergedRefs, useLayoutEffect, Box, } from '../utils/index.js';
|
|
9
9
|
/**
|
|
10
10
|
* `CarouselSlider` is the scrollable list that should consist of `CarouselSlide` components.
|
|
11
11
|
*/
|
|
@@ -23,7 +23,7 @@ export const CarouselSlider = React.forwardRef((props, ref) => {
|
|
|
23
23
|
index,
|
|
24
24
|
})
|
|
25
25
|
: child) ?? [], [children, idPrefix]);
|
|
26
|
-
|
|
26
|
+
useLayoutEffect(() => {
|
|
27
27
|
setSlideCount(items.length);
|
|
28
28
|
}, [items.length, setSlideCount]);
|
|
29
29
|
const sliderRef = React.useRef(null);
|
|
@@ -6,7 +6,7 @@ import * as React from 'react';
|
|
|
6
6
|
import { MenuExtraContent } from '../Menu/MenuExtraContent.js';
|
|
7
7
|
import { SelectTag } from '../Select/SelectTag.js';
|
|
8
8
|
import { Text } from '../Typography/Text.js';
|
|
9
|
-
import { mergeRefs, useLatestRef,
|
|
9
|
+
import { mergeRefs, useLatestRef, useLayoutEffect, AutoclearingHiddenLiveRegion, useId, } from '../utils/index.js';
|
|
10
10
|
import { usePopover } from '../Popover/Popover.js';
|
|
11
11
|
import { ComboBoxActionContext, comboBoxReducer, ComboBoxRefsContext, ComboBoxStateContext, } from './helpers.js';
|
|
12
12
|
import { ComboBoxEndIcon } from './ComboBoxEndIcon.js';
|
|
@@ -94,7 +94,7 @@ export const ComboBox = React.forwardRef((props, forwardedRef) => {
|
|
|
94
94
|
dispatch({ type: 'close' });
|
|
95
95
|
onHideRef.current?.();
|
|
96
96
|
}, [onHideRef]);
|
|
97
|
-
|
|
97
|
+
useLayoutEffect(() => {
|
|
98
98
|
// When the dropdown opens
|
|
99
99
|
if (isOpen) {
|
|
100
100
|
inputRef.current?.focus(); // Focus the input
|
|
@@ -96,6 +96,14 @@ type DatePickerProps = {
|
|
|
96
96
|
* @default true
|
|
97
97
|
*/
|
|
98
98
|
applyBackground?: boolean;
|
|
99
|
+
/**
|
|
100
|
+
* Whether dates outside the current month should be displayed (in a muted text style).
|
|
101
|
+
*
|
|
102
|
+
* It is recommended to set this to false. Currently it defaults to true for backward compatibility.
|
|
103
|
+
*
|
|
104
|
+
* @default true
|
|
105
|
+
*/
|
|
106
|
+
showDatesOutsideMonth?: boolean;
|
|
99
107
|
} & DateRangePickerProps & Omit<TimePickerProps, 'date' | 'onChange' | 'setFocusHour'>;
|
|
100
108
|
/**
|
|
101
109
|
* Date picker component
|
|
@@ -110,7 +110,7 @@ export const generateLocalizedStrings = (locale) => {
|
|
|
110
110
|
* <DatePicker date={new Date()} onChange={(e) => console.log('New date value: ' + e)} />
|
|
111
111
|
*/
|
|
112
112
|
export const DatePicker = React.forwardRef((props, forwardedRef) => {
|
|
113
|
-
const { date, onChange, localizedNames, className, setFocus = false, showTime = false, use12Hours = false, precision, hourStep, minuteStep, secondStep, useCombinedRenderer, combinedRenderer, hourRenderer, minuteRenderer, secondRenderer, meridiemRenderer, showYearSelection = false, enableRangeSelect = false, startDate, endDate, monthYearProps, calendarProps, monthProps, weekDayProps, dayProps, weekProps, isDateDisabled, applyBackground = true, ...rest } = props;
|
|
113
|
+
const { date, onChange, localizedNames, className, setFocus = false, showTime = false, use12Hours = false, precision, hourStep, minuteStep, secondStep, useCombinedRenderer, combinedRenderer, hourRenderer, minuteRenderer, secondRenderer, meridiemRenderer, showYearSelection = false, enableRangeSelect = false, startDate, endDate, monthYearProps, calendarProps, monthProps, weekDayProps, dayProps, weekProps, isDateDisabled, applyBackground = true, showDatesOutsideMonth = true, ...rest } = props;
|
|
114
114
|
const monthNames = localizedNames?.months ?? defaultMonths;
|
|
115
115
|
const shortDays = localizedNames?.shortDays ?? defaultShortDays;
|
|
116
116
|
const longDays = localizedNames?.days ?? defaultLongDays;
|
|
@@ -152,8 +152,9 @@ export const DatePicker = React.forwardRef((props, forwardedRef) => {
|
|
|
152
152
|
}, [date, setMonthAndYear, startDate, endDate, enableRangeSelect]);
|
|
153
153
|
const days = React.useMemo(() => {
|
|
154
154
|
let offsetToFirst = new Date(displayedYear, displayedMonthIndex, 1).getDay();
|
|
155
|
-
//
|
|
156
|
-
|
|
155
|
+
// If it's sunday, show one week before, but only if dates outside month are shown.
|
|
156
|
+
// (We do not want empty space at the top if dates outside month are not shown.)
|
|
157
|
+
if (0 === offsetToFirst && showDatesOutsideMonth) {
|
|
157
158
|
offsetToFirst = 7;
|
|
158
159
|
}
|
|
159
160
|
const daysInMonth = [];
|
|
@@ -163,7 +164,7 @@ export const DatePicker = React.forwardRef((props, forwardedRef) => {
|
|
|
163
164
|
daysInMonth.push(new Date(displayedYear, displayedMonthIndex, adjustedDay));
|
|
164
165
|
}
|
|
165
166
|
return daysInMonth;
|
|
166
|
-
}, [displayedMonthIndex, displayedYear]);
|
|
167
|
+
}, [displayedMonthIndex, displayedYear, showDatesOutsideMonth]);
|
|
167
168
|
const weeks = React.useMemo(() => {
|
|
168
169
|
const weeksInMonth = [];
|
|
169
170
|
const weekCount = Math.ceil(days.length / 7);
|
|
@@ -353,6 +354,10 @@ export const DatePicker = React.forwardRef((props, forwardedRef) => {
|
|
|
353
354
|
return (React.createElement(Box, { as: 'div', key: `week-${displayedMonthIndex}-${weekIndex}`, ...weekProps, className: cx('iui-calendar-week', weekProps?.className) }, weekDays.map((weekDay, dayIndex) => {
|
|
354
355
|
const dateValue = weekDay.getDate();
|
|
355
356
|
const isDisabled = isDateDisabled?.(weekDay);
|
|
357
|
+
const isOutsideMonth = weekDay.getMonth() !== displayedMonthIndex;
|
|
358
|
+
if (isOutsideMonth && !showDatesOutsideMonth) {
|
|
359
|
+
return (React.createElement(Box, { key: `day-${displayedMonthIndex}-${dayIndex}`, className: cx(getDayClass(weekDay), dayProps?.className), "aria-hidden": true }));
|
|
360
|
+
}
|
|
356
361
|
return (React.createElement(Box, { as: 'div', key: `day-${displayedMonthIndex}-${dayIndex}`, onClick: () => !isDisabled && onDayClick(weekDay), role: 'option', tabIndex: isSameDay(weekDay, focusedDay) ? 0 : -1, "aria-disabled": isDisabled ? 'true' : undefined, ref: (element) => isSameDay(weekDay, focusedDay) &&
|
|
357
362
|
needFocus.current &&
|
|
358
363
|
element?.focus(), ...dayProps, className: cx(getDayClass(weekDay), dayProps?.className) }, dateValue));
|
|
@@ -4,11 +4,12 @@
|
|
|
4
4
|
*--------------------------------------------------------------------------------------------*/
|
|
5
5
|
import * as React from 'react';
|
|
6
6
|
import cx from 'classnames';
|
|
7
|
-
import { FocusTrap, getTranslateValuesFromElement, Resizer, useMergedRefs,
|
|
7
|
+
import { FocusTrap, getTranslateValuesFromElement, Resizer, useMergedRefs, useLayoutEffect, Box, } from '../utils/index.js';
|
|
8
8
|
import { useDialogContext } from './DialogContext.js';
|
|
9
9
|
import { CSSTransition } from 'react-transition-group';
|
|
10
10
|
import { DialogDragContext } from './DialogDragContext.js';
|
|
11
11
|
import useDragAndDrop from '../utils/hooks/useDragAndDrop.js';
|
|
12
|
+
import styles from '../../styles.js';
|
|
12
13
|
/**
|
|
13
14
|
* Dialog component which can wrap any content.
|
|
14
15
|
* @example
|
|
@@ -80,7 +81,7 @@ export const DialogMain = React.forwardRef((props, ref) => {
|
|
|
80
81
|
}
|
|
81
82
|
}, [isDraggable, onPointerDown]);
|
|
82
83
|
// Prevents dialog from moving when window is being resized
|
|
83
|
-
|
|
84
|
+
useLayoutEffect(() => {
|
|
84
85
|
if (!isDraggable || !isOpen) {
|
|
85
86
|
return;
|
|
86
87
|
}
|
|
@@ -104,7 +105,6 @@ export const DialogMain = React.forwardRef((props, ref) => {
|
|
|
104
105
|
const content = (React.createElement(Box, { className: cx('iui-dialog', {
|
|
105
106
|
'iui-dialog-default': styleType === 'default',
|
|
106
107
|
'iui-dialog-full-page': styleType === 'fullPage',
|
|
107
|
-
'iui-dialog-visible': isOpen,
|
|
108
108
|
'iui-dialog-draggable': isDraggable,
|
|
109
109
|
}, className), role: 'dialog', ref: useMergedRefs(dialogRef, ref), onKeyDown: handleKeyDown, tabIndex: -1, "data-iui-placement": placement, style: {
|
|
110
110
|
transform,
|
|
@@ -119,8 +119,9 @@ export const DialogMain = React.forwardRef((props, ref) => {
|
|
|
119
119
|
}, onResizeEnd: setResizeStyle })),
|
|
120
120
|
children));
|
|
121
121
|
return (React.createElement(CSSTransition, { in: isOpen, classNames: {
|
|
122
|
-
enter: 'iui-dialog-animation-enter',
|
|
123
|
-
enterActive: 'iui-dialog-animation-enter-active',
|
|
122
|
+
enter: styles['iui-dialog-animation-enter'],
|
|
123
|
+
enterActive: styles['iui-dialog-animation-enter-active'],
|
|
124
|
+
enterDone: styles['iui-dialog-visible'],
|
|
124
125
|
}, timeout: { exit: 600 },
|
|
125
126
|
// Focuses dialog when opened
|
|
126
127
|
onEntered: () => {
|
|
@@ -32,7 +32,8 @@ type FileUploadTemplateProps = {
|
|
|
32
32
|
children?: React.ReactNode;
|
|
33
33
|
};
|
|
34
34
|
/**
|
|
35
|
-
* @deprecated Use `FileUploadCard` instead.
|
|
35
|
+
* @deprecated Use [`FileUploadCard`](https://itwinui.bentley.com/docs/fileupload#fileuploadcard) instead.
|
|
36
|
+
*
|
|
36
37
|
* Default template to be used with the `FileUpload` wrapper component.
|
|
37
38
|
* Contains a hidden input with styled labels (customizable).
|
|
38
39
|
* @example
|
|
@@ -7,7 +7,8 @@ import cx from 'classnames';
|
|
|
7
7
|
import { SvgUpload, Box } from '../utils/index.js';
|
|
8
8
|
import { Anchor } from '../Typography/Anchor.js';
|
|
9
9
|
/**
|
|
10
|
-
* @deprecated Use `FileUploadCard` instead.
|
|
10
|
+
* @deprecated Use [`FileUploadCard`](https://itwinui.bentley.com/docs/fileupload#fileuploadcard) instead.
|
|
11
|
+
*
|
|
11
12
|
* Default template to be used with the `FileUpload` wrapper component.
|
|
12
13
|
* Contains a hidden input with styled labels (customizable).
|
|
13
14
|
* @example
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { PolymorphicForwardRefComponent } from '../utils/props.js';
|
|
1
2
|
/**
|
|
2
3
|
* Polymorphic link action component.
|
|
3
4
|
* It is rendered as `a` by default.
|
|
@@ -8,7 +9,7 @@
|
|
|
8
9
|
* </Surface>
|
|
9
10
|
* </LinkBox>
|
|
10
11
|
*/
|
|
11
|
-
export declare const LinkAction:
|
|
12
|
+
export declare const LinkAction: PolymorphicForwardRefComponent<"a", {}>;
|
|
12
13
|
/**
|
|
13
14
|
* Polymorphic link box component.
|
|
14
15
|
* Used to wrap around your component to use LinkAction.
|
|
@@ -20,4 +21,4 @@ export declare const LinkAction: import("../utils/props.js").PolymorphicForwardR
|
|
|
20
21
|
* </Surface>
|
|
21
22
|
* </LinkBox>
|
|
22
23
|
*/
|
|
23
|
-
export declare const LinkBox:
|
|
24
|
+
export declare const LinkBox: PolymorphicForwardRefComponent<"div", {}>;
|
|
@@ -2,7 +2,10 @@
|
|
|
2
2
|
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
3
3
|
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
4
4
|
*--------------------------------------------------------------------------------------------*/
|
|
5
|
+
import * as React from 'react';
|
|
6
|
+
import cx from 'classnames';
|
|
5
7
|
import { polymorphic } from '../utils/functions/polymorphic.js';
|
|
8
|
+
import { Box } from '../utils/components/index.js';
|
|
6
9
|
/**
|
|
7
10
|
* Polymorphic link action component.
|
|
8
11
|
* It is rendered as `a` by default.
|
|
@@ -13,7 +16,10 @@ import { polymorphic } from '../utils/functions/polymorphic.js';
|
|
|
13
16
|
* </Surface>
|
|
14
17
|
* </LinkBox>
|
|
15
18
|
*/
|
|
16
|
-
export const LinkAction =
|
|
19
|
+
export const LinkAction = React.forwardRef((props, forwardedRef) => {
|
|
20
|
+
const { as: asProp = (!!props.href ? 'a' : 'button') } = props;
|
|
21
|
+
return (React.createElement(Box, { ...props, as: asProp, className: cx('iui-link-action', props.className), ref: forwardedRef }));
|
|
22
|
+
});
|
|
17
23
|
LinkAction.displayName = 'LinkAction';
|
|
18
24
|
/**
|
|
19
25
|
* Polymorphic link box component.
|
|
@@ -42,6 +42,18 @@ type ModalProps = {
|
|
|
42
42
|
* Content of the modal.
|
|
43
43
|
*/
|
|
44
44
|
children: React.ReactNode;
|
|
45
|
+
/**
|
|
46
|
+
* Props for customizing the title bar element.
|
|
47
|
+
*/
|
|
48
|
+
titleBarProps?: React.ComponentPropsWithRef<'div'>;
|
|
49
|
+
/**
|
|
50
|
+
* Props for customizing the dialog-wrapper element.
|
|
51
|
+
*/
|
|
52
|
+
wrapperProps?: React.ComponentPropsWithoutRef<'div'>;
|
|
53
|
+
/**
|
|
54
|
+
* Props for customizing the backdrop element.
|
|
55
|
+
*/
|
|
56
|
+
backdropProps?: React.ComponentPropsWithRef<'div'>;
|
|
45
57
|
} & Pick<DialogMainProps, 'isOpen' | 'styleType'>;
|
|
46
58
|
/**
|
|
47
59
|
* Modal component which can wrap any content.
|
package/esm/core/Modal/Modal.js
CHANGED
|
@@ -26,11 +26,11 @@ import { Dialog } from '../Dialog/Dialog.js';
|
|
|
26
26
|
* </Modal>
|
|
27
27
|
*/
|
|
28
28
|
export const Modal = React.forwardRef((props, forwardedRef) => {
|
|
29
|
-
const { isOpen = false, isDismissible = true, closeOnEsc = true, closeOnExternalClick = true, onClose, title, children, portal = true, ...rest } = props;
|
|
30
|
-
return (React.createElement(Dialog, { isOpen: isOpen, closeOnEsc: closeOnEsc, closeOnExternalClick: closeOnExternalClick, isDismissible: isDismissible, onClose: onClose, preventDocumentScroll: true, trapFocus: true, setFocus: true, ref: forwardedRef, portal: portal },
|
|
31
|
-
React.createElement(Dialog.Backdrop,
|
|
29
|
+
const { isOpen = false, isDismissible = true, closeOnEsc = true, closeOnExternalClick = true, onClose, title, children, portal = true, wrapperProps, backdropProps, titleBarProps, ...rest } = props;
|
|
30
|
+
return (React.createElement(Dialog, { isOpen: isOpen, closeOnEsc: closeOnEsc, closeOnExternalClick: closeOnExternalClick, isDismissible: isDismissible, onClose: onClose, preventDocumentScroll: true, trapFocus: true, setFocus: true, ref: forwardedRef, portal: portal, ...wrapperProps },
|
|
31
|
+
React.createElement(Dialog.Backdrop, { ...backdropProps }),
|
|
32
32
|
React.createElement(Dialog.Main, { "aria-modal": true, ...rest },
|
|
33
|
-
React.createElement(Dialog.TitleBar, { titleText: title }),
|
|
33
|
+
React.createElement(Dialog.TitleBar, { titleText: title, ...titleBarProps }),
|
|
34
34
|
children)));
|
|
35
35
|
});
|
|
36
36
|
export default Modal;
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
import * as React from 'react';
|
|
6
6
|
import cx from 'classnames';
|
|
7
7
|
import { useFloating, useClick, useDismiss, useInteractions, size, autoUpdate, offset, flip, shift, autoPlacement, inline, hide, FloatingFocusManager, useHover, useFocus, safePolygon, useRole, FloatingPortal, } from '@floating-ui/react';
|
|
8
|
-
import { Box, cloneElementWithRef, useControlledState, useId,
|
|
8
|
+
import { Box, cloneElementWithRef, useControlledState, useId, useLayoutEffect, useMergedRefs, } from '../utils/index.js';
|
|
9
9
|
import { Portal } from '../utils/components/Portal.js';
|
|
10
10
|
import { ThemeProvider } from '../ThemeProvider/ThemeProvider.js';
|
|
11
11
|
// ----------------------------------------------------------------------------
|
|
@@ -101,7 +101,7 @@ export const Popover = React.forwardRef((props, forwardedRef) => {
|
|
|
101
101
|
const popoverRef = useMergedRefs(popover.refs.setFloating, forwardedRef, setPopoverElement);
|
|
102
102
|
const triggerId = `${useId()}-trigger`;
|
|
103
103
|
const hasAriaLabel = !!props['aria-labelledby'] || !!props['aria-label'];
|
|
104
|
-
|
|
104
|
+
useLayoutEffect(() => {
|
|
105
105
|
if (!positionReference) {
|
|
106
106
|
return;
|
|
107
107
|
}
|
|
@@ -23,7 +23,7 @@ type ProgressLinearProps = {
|
|
|
23
23
|
/**
|
|
24
24
|
* Status of progress.
|
|
25
25
|
*/
|
|
26
|
-
status?: 'positive' | 'negative';
|
|
26
|
+
status?: 'positive' | 'negative' | 'warning';
|
|
27
27
|
/**
|
|
28
28
|
* Pass props to ProgressLinear label group.
|
|
29
29
|
*/
|
|
@@ -32,16 +32,24 @@ type ProgressLinearProps = {
|
|
|
32
32
|
/**
|
|
33
33
|
* Shows progress on a linear bar
|
|
34
34
|
* @example
|
|
35
|
-
* Determinate
|
|
35
|
+
* // Determinate
|
|
36
36
|
* <ProgressLinear value={25}/>
|
|
37
|
-
* Indeterminate
|
|
37
|
+
* // Indeterminate
|
|
38
38
|
* <ProgressLinear indeterminate={true}/>
|
|
39
|
-
* Labeled - Center
|
|
39
|
+
* // Labeled - Center
|
|
40
40
|
* <ProgressLinear value={50} labels={['Centered Label']} />
|
|
41
|
-
* Labeled - Left & Right
|
|
41
|
+
* // Labeled - Left & Right
|
|
42
42
|
* <ProgressLinear value={50} labels={['Loading...', '50%']} />
|
|
43
|
-
*
|
|
44
|
-
* <ProgressLinear
|
|
43
|
+
* // Status
|
|
44
|
+
* <ProgressLinear
|
|
45
|
+
* status='positive'
|
|
46
|
+
* labels={[
|
|
47
|
+
* 'Upload done!',
|
|
48
|
+
* <Icon key='icon'>
|
|
49
|
+
* <SvgStatusSuccess />{' '}
|
|
50
|
+
* </Icon>
|
|
51
|
+
* ]}
|
|
52
|
+
* />
|
|
45
53
|
* <ProgressLinear status='negative' />
|
|
46
54
|
*/
|
|
47
55
|
export declare const ProgressLinear: PolymorphicForwardRefComponent<"div", ProgressLinearProps>;
|
|
@@ -8,16 +8,24 @@ import { Box, getBoundedValue } from '../utils/index.js';
|
|
|
8
8
|
/**
|
|
9
9
|
* Shows progress on a linear bar
|
|
10
10
|
* @example
|
|
11
|
-
* Determinate
|
|
11
|
+
* // Determinate
|
|
12
12
|
* <ProgressLinear value={25}/>
|
|
13
|
-
* Indeterminate
|
|
13
|
+
* // Indeterminate
|
|
14
14
|
* <ProgressLinear indeterminate={true}/>
|
|
15
|
-
* Labeled - Center
|
|
15
|
+
* // Labeled - Center
|
|
16
16
|
* <ProgressLinear value={50} labels={['Centered Label']} />
|
|
17
|
-
* Labeled - Left & Right
|
|
17
|
+
* // Labeled - Left & Right
|
|
18
18
|
* <ProgressLinear value={50} labels={['Loading...', '50%']} />
|
|
19
|
-
*
|
|
20
|
-
* <ProgressLinear
|
|
19
|
+
* // Status
|
|
20
|
+
* <ProgressLinear
|
|
21
|
+
* status='positive'
|
|
22
|
+
* labels={[
|
|
23
|
+
* 'Upload done!',
|
|
24
|
+
* <Icon key='icon'>
|
|
25
|
+
* <SvgStatusSuccess />{' '}
|
|
26
|
+
* </Icon>
|
|
27
|
+
* ]}
|
|
28
|
+
* />
|
|
21
29
|
* <ProgressLinear status='negative' />
|
|
22
30
|
*/
|
|
23
31
|
export const ProgressLinear = React.forwardRef((props, forwardedRef) => {
|
|
@@ -14,7 +14,7 @@ type ProgressRadialProps = {
|
|
|
14
14
|
/**
|
|
15
15
|
* Status of Progress. Positive status always has 100% value.
|
|
16
16
|
*/
|
|
17
|
-
status?: 'positive' | 'negative';
|
|
17
|
+
status?: 'positive' | 'negative' | 'warning';
|
|
18
18
|
/**
|
|
19
19
|
* Size of the progress indicator. Defaults to medium size.
|
|
20
20
|
* @default ''
|
|
@@ -32,9 +32,10 @@ type ProgressRadialProps = {
|
|
|
32
32
|
* <ProgressRadial value={50} />
|
|
33
33
|
* Indeterminate
|
|
34
34
|
* <ProgressRadial indeterminate />
|
|
35
|
-
* Positive / Negative
|
|
35
|
+
* // Positive / Negative / Warning
|
|
36
36
|
* <ProgressRadial status='positive' />
|
|
37
37
|
* <ProgressRadial status='negative' />
|
|
38
|
+
* <ProgressRadial status='warning' />
|
|
38
39
|
* Centered Content
|
|
39
40
|
* <ProgressRadial value={63}>63</ProgressRadial>
|
|
40
41
|
* Small
|
|
@@ -12,9 +12,10 @@ import { SvgCheckmarkSmall, SvgImportantSmall, Box, getBoundedValue, } from '../
|
|
|
12
12
|
* <ProgressRadial value={50} />
|
|
13
13
|
* Indeterminate
|
|
14
14
|
* <ProgressRadial indeterminate />
|
|
15
|
-
* Positive / Negative
|
|
15
|
+
* // Positive / Negative / Warning
|
|
16
16
|
* <ProgressRadial status='positive' />
|
|
17
17
|
* <ProgressRadial status='negative' />
|
|
18
|
+
* <ProgressRadial status='warning' />
|
|
18
19
|
* Centered Content
|
|
19
20
|
* <ProgressRadial value={63}>63</ProgressRadial>
|
|
20
21
|
* Small
|
|
@@ -25,6 +26,7 @@ export const ProgressRadial = React.forwardRef((props, forwardedRef) => {
|
|
|
25
26
|
const statusMap = {
|
|
26
27
|
negative: React.createElement(SvgImportantSmall, { "aria-hidden": true }),
|
|
27
28
|
positive: React.createElement(SvgCheckmarkSmall, { "aria-hidden": true }),
|
|
29
|
+
warning: React.createElement(SvgImportantSmall, { "aria-hidden": true }),
|
|
28
30
|
};
|
|
29
31
|
return (React.createElement(Box, { className: cx('iui-progress-indicator-radial', className), "data-iui-size": size, "data-iui-status": status, "data-iui-indeterminate": indeterminate ? 'true' : undefined, ref: forwardedRef, style: {
|
|
30
32
|
...(value !== undefined && {
|
package/esm/core/Table/Table.js
CHANGED
|
@@ -7,7 +7,7 @@ import * as ReactDOM from 'react-dom';
|
|
|
7
7
|
import cx from 'classnames';
|
|
8
8
|
import { actions as TableActions, useFlexLayout, useFilters, useRowSelect, useSortBy, useTable, useExpanded, usePagination, useColumnOrder, useGlobalFilter, } from 'react-table';
|
|
9
9
|
import { ProgressRadial } from '../ProgressIndicators/ProgressRadial.js';
|
|
10
|
-
import { useGlobals, useResizeObserver, SvgSortDown, SvgSortUp,
|
|
10
|
+
import { useGlobals, useResizeObserver, SvgSortDown, SvgSortUp, useLayoutEffect, Box, createWarningLogger, } from '../utils/index.js';
|
|
11
11
|
import { getCellStyle, getStickyStyle, getSubRowStyle } from './utils.js';
|
|
12
12
|
import { TableRowMemoized } from './TableRowMemoized.js';
|
|
13
13
|
import { FilterToggle } from './filters/index.js';
|
|
@@ -287,10 +287,19 @@ export const Table = (props) => {
|
|
|
287
287
|
instance.selectedFlatRows,
|
|
288
288
|
selectionMode,
|
|
289
289
|
]);
|
|
290
|
+
const headerRef = React.useRef(null);
|
|
291
|
+
const bodyRef = React.useRef(null);
|
|
290
292
|
const { scrollToIndex, tableRowRef } = useScrollToRow({ ...props, page });
|
|
291
293
|
const columnRefs = React.useRef({});
|
|
292
294
|
const previousTableWidth = React.useRef(0);
|
|
293
295
|
const onTableResize = React.useCallback(({ width }) => {
|
|
296
|
+
// Handle header properties, regardless of whether the table is resizable
|
|
297
|
+
setHeaderScrollWidth(headerRef.current?.scrollWidth ?? 0);
|
|
298
|
+
setHeaderClientWidth(headerRef.current?.clientWidth ?? 0);
|
|
299
|
+
// Handle table properties, but only when table is resizable
|
|
300
|
+
if (!isResizable) {
|
|
301
|
+
return;
|
|
302
|
+
}
|
|
294
303
|
instance.tableWidth = width;
|
|
295
304
|
if (width === previousTableWidth.current) {
|
|
296
305
|
return;
|
|
@@ -308,10 +317,18 @@ export const Table = (props) => {
|
|
|
308
317
|
return;
|
|
309
318
|
}
|
|
310
319
|
dispatch({ type: tableResizeStartAction });
|
|
311
|
-
}, [
|
|
320
|
+
}, [
|
|
321
|
+
dispatch,
|
|
322
|
+
state.columnResizing.columnWidths,
|
|
323
|
+
flatHeaders,
|
|
324
|
+
instance,
|
|
325
|
+
isResizable,
|
|
326
|
+
]);
|
|
312
327
|
const [resizeRef] = useResizeObserver(onTableResize);
|
|
328
|
+
const [headerScrollWidth, setHeaderScrollWidth] = React.useState(0);
|
|
329
|
+
const [headerClientWidth, setHeaderClientWidth] = React.useState(0);
|
|
313
330
|
// Flexbox handles columns resize so we take new column widths before browser repaints.
|
|
314
|
-
|
|
331
|
+
useLayoutEffect(() => {
|
|
315
332
|
if (state.isTableResizing) {
|
|
316
333
|
const newColumnWidths = {};
|
|
317
334
|
flatHeaders.forEach((column) => {
|
|
@@ -323,8 +340,6 @@ export const Table = (props) => {
|
|
|
323
340
|
dispatch({ type: tableResizeEndAction, columnWidths: newColumnWidths });
|
|
324
341
|
}
|
|
325
342
|
});
|
|
326
|
-
const headerRef = React.useRef(null);
|
|
327
|
-
const bodyRef = React.useRef(null);
|
|
328
343
|
const getPreparedRow = React.useCallback((index) => {
|
|
329
344
|
const row = page[index];
|
|
330
345
|
prepareRow(row);
|
|
@@ -374,9 +389,7 @@ export const Table = (props) => {
|
|
|
374
389
|
return (React.createElement(React.Fragment, null,
|
|
375
390
|
React.createElement(Box, { ref: (element) => {
|
|
376
391
|
ownerDocument.current = element?.ownerDocument;
|
|
377
|
-
|
|
378
|
-
resizeRef(element);
|
|
379
|
-
}
|
|
392
|
+
resizeRef(element);
|
|
380
393
|
}, id: id, ...getTableProps({
|
|
381
394
|
className: cx('iui-table', className),
|
|
382
395
|
style: {
|
|
@@ -468,12 +481,12 @@ export const Table = (props) => {
|
|
|
468
481
|
}, tabIndex: -1, "aria-multiselectable": (isSelectable && selectionMode === 'multi') || undefined },
|
|
469
482
|
React.createElement(ShadowTemplate, null,
|
|
470
483
|
React.createElement("slot", null),
|
|
471
|
-
React.createElement("div", { "aria-hidden": true, style: {
|
|
484
|
+
rows.length === 0 && headerScrollWidth > headerClientWidth && (React.createElement("div", { "aria-hidden": true, style: {
|
|
472
485
|
// This ensures that the table-body is always the same width as the table-header,
|
|
473
486
|
// even if the table has no rows. See https://github.com/iTwin/iTwinUI/pull/1725
|
|
474
|
-
width:
|
|
487
|
+
width: headerScrollWidth,
|
|
475
488
|
height: 0.1,
|
|
476
|
-
} })),
|
|
489
|
+
} }))),
|
|
477
490
|
data.length !== 0 && (React.createElement(React.Fragment, null, enableVirtualization ? (React.createElement(VirtualScroll, { itemsLength: page.length, itemRenderer: virtualizedItemRenderer, scrollToIndex: scrollToIndex })) : (page.map((_, index) => getPreparedRow(index))))),
|
|
478
491
|
isLoading && data.length === 0 && (React.createElement(Box, { as: 'div', ...emptyTableContentProps, className: cx('iui-table-empty', emptyTableContentProps?.className) },
|
|
479
492
|
React.createElement(ProgressRadial, { indeterminate: true }))),
|