@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
@@ -4,11 +4,29 @@
4
4
  *--------------------------------------------------------------------------------------------*/
5
5
  import React from 'react';
6
6
  import cx from 'classnames';
7
- import { StatusIconMap, useTheme, SvgMore, SvgNew, SvgCheckmark, } from '../utils';
7
+ import { StatusIconMap, useTheme, SvgMore, SvgNew, SvgCheckmark, LinkAction, useSafeContext, supportsHas, } from '../utils';
8
8
  import '@itwin/itwinui-css/css/tile.css';
9
9
  import { DropdownMenu } from '../DropdownMenu';
10
10
  import { IconButton } from '../Buttons';
11
11
  import { ProgressRadial } from '../ProgressIndicators';
12
+ const TileContext = React.createContext(undefined);
13
+ /**
14
+ * Polymorphic Tile action component. Recommended to be used in a "name" of `Tile`.
15
+ * Renders `a` element by default.
16
+ * @example
17
+ * <Tile
18
+ * name={<Tile.Action href='/new-page'>Tile name<Tile.Action/>}
19
+ * />
20
+ */
21
+ export const TileAction = (props) => {
22
+ const tileContext = useSafeContext(TileContext);
23
+ React.useEffect(() => {
24
+ if (!supportsHas()) {
25
+ tileContext.setActionable(true);
26
+ }
27
+ }, [tileContext]);
28
+ return React.createElement(LinkAction, { ...props });
29
+ };
12
30
  /**
13
31
  * Tile component that displays content and actions in a card-like format.
14
32
  * @example
@@ -26,58 +44,73 @@ import { ProgressRadial } from '../ProgressIndicators';
26
44
  * isNew={false}
27
45
  * />
28
46
  */
29
- export const Tile = (props) => {
30
- const { className, name, description, metadata, thumbnail, buttons, leftIcon, rightIcon, badge, isNew, isSelected, moreOptions, variant = 'default', children, isActionable, status, isLoading = false, isDisabled = false, ...rest } = props;
47
+ export const Tile = Object.assign((props) => {
48
+ const { className, name, description, metadata, thumbnail, buttons, leftIcon, rightIcon, badge, isNew, isSelected, moreOptions, variant = 'default', children, isActionable: isActionableProp, status, isLoading = false, isDisabled = false, onClick, ...rest } = props;
31
49
  useTheme();
32
50
  const [isMenuVisible, setIsMenuVisible] = React.useState(false);
33
51
  const showMenu = React.useCallback(() => setIsMenuVisible(true), []);
34
52
  const hideMenu = React.useCallback(() => setIsMenuVisible(false), []);
35
- return (React.createElement("div", { className: cx('iui-tile', {
36
- 'iui-folder': variant === 'folder',
37
- 'iui-new': isNew,
38
- 'iui-selected': isSelected,
39
- 'iui-actionable': isActionable,
40
- [`iui-${status}`]: !!status,
41
- 'iui-loading': isLoading,
42
- }, className), "aria-disabled": isDisabled, tabIndex: isActionable && !isDisabled ? 0 : undefined, ...rest },
43
- thumbnail && (React.createElement("div", { className: 'iui-tile-thumbnail' },
44
- typeof thumbnail === 'string' ? (React.createElement("div", { className: 'iui-tile-thumbnail-picture', style: { backgroundImage: `url(${thumbnail})` } })) : thumbnail && thumbnail.type === 'img' ? (React.cloneElement(thumbnail, {
45
- className: 'iui-tile-thumbnail-picture',
46
- })) : React.isValidElement(thumbnail) ? (React.cloneElement(thumbnail, {
47
- className: cx('iui-thumbnail-icon', thumbnail.props.className),
48
- })) : (thumbnail),
49
- leftIcon &&
50
- React.cloneElement(leftIcon, {
51
- className: 'iui-tile-thumbnail-type-indicator',
52
- 'data-iui-size': 'small',
53
- }),
54
- rightIcon &&
55
- React.cloneElement(rightIcon, {
56
- className: 'iui-tile-thumbnail-quick-action',
57
- 'data-iui-size': 'small',
58
- }),
59
- badge && (React.createElement("div", { className: 'iui-tile-thumbnail-badge-container' }, badge)))),
60
- React.createElement("div", { className: 'iui-tile-content' },
61
- React.createElement("div", { className: 'iui-tile-name' },
62
- React.createElement(TitleIcon, { isLoading: isLoading, isSelected: isSelected, isNew: isNew, status: status }),
63
- React.createElement("span", { className: 'iui-tile-name-label' }, name)),
64
- description != undefined && (React.createElement("div", { className: 'iui-tile-description' }, description)),
65
- metadata != undefined && (React.createElement("div", { className: 'iui-tile-metadata' }, metadata)),
66
- moreOptions && (React.createElement(DropdownMenu, { onShow: showMenu, onHide: hideMenu, menuItems: (close) => moreOptions.map((option) => React.cloneElement(option, {
67
- onClick: (value) => {
68
- var _a, _b;
69
- close();
70
- (_b = (_a = option.props).onClick) === null || _b === void 0 ? void 0 : _b.call(_a, value);
71
- },
72
- })) },
73
- React.createElement("div", { className: cx('iui-tile-more-options', {
74
- 'iui-visible': isMenuVisible,
75
- }) },
76
- React.createElement(IconButton, { styleType: 'borderless', size: 'small', "aria-label": 'More options' },
77
- React.createElement(SvgMore, null))))),
78
- children),
79
- buttons && React.createElement("div", { className: 'iui-tile-buttons' }, buttons)));
80
- };
53
+ const [localActionable, setLocalActionable] = React.useState(isActionableProp);
54
+ const isActionable = isActionableProp !== null && isActionableProp !== void 0 ? isActionableProp : localActionable;
55
+ const tileName = (React.createElement("div", { className: 'iui-tile-name' },
56
+ React.createElement(TitleIcon, { isLoading: isLoading, isSelected: isSelected, isNew: isNew, status: status }),
57
+ React.createElement("span", { className: 'iui-tile-name-label' }, isActionable && onClick ? (React.createElement(LinkAction, { as: 'button', onClick: !isDisabled ? onClick : undefined, "aria-disabled": isDisabled }, name)) : (name))));
58
+ return (React.createElement(TileContext.Provider, { value: { setActionable: setLocalActionable } },
59
+ React.createElement("div", { className: cx('iui-tile', {
60
+ 'iui-folder': variant === 'folder',
61
+ 'iui-new': isNew,
62
+ 'iui-selected': isSelected,
63
+ 'iui-actionable': isActionable,
64
+ [`iui-${status}`]: !!status,
65
+ 'iui-loading': isLoading,
66
+ }, className), "aria-disabled": isDisabled, ...rest },
67
+ variant !== 'folder' ? tileName : null,
68
+ thumbnail && (React.createElement("div", { className: 'iui-tile-thumbnail' },
69
+ typeof thumbnail === 'string' ? (React.createElement("div", { className: 'iui-tile-thumbnail-picture', style: { backgroundImage: `url(${thumbnail})` } })) : thumbnail && thumbnail.type === 'img' ? (React.cloneElement(thumbnail, {
70
+ className: 'iui-tile-thumbnail-picture',
71
+ })) : React.isValidElement(thumbnail) ? (React.cloneElement(thumbnail, {
72
+ className: cx('iui-thumbnail-icon', thumbnail.props.className),
73
+ })) : (thumbnail),
74
+ leftIcon &&
75
+ React.cloneElement(leftIcon, {
76
+ className: 'iui-tile-thumbnail-type-indicator',
77
+ 'data-iui-size': 'small',
78
+ }),
79
+ rightIcon &&
80
+ React.cloneElement(rightIcon, {
81
+ className: 'iui-tile-thumbnail-quick-action',
82
+ 'data-iui-size': 'small',
83
+ }),
84
+ badge && (React.createElement("div", { className: 'iui-tile-thumbnail-badge-container' }, badge)))),
85
+ React.createElement("div", { className: 'iui-tile-content' },
86
+ variant === 'folder' ? tileName : null,
87
+ description != undefined && (React.createElement("div", { className: 'iui-tile-description' }, description)),
88
+ metadata != undefined && (React.createElement("div", { className: 'iui-tile-metadata' }, metadata)),
89
+ moreOptions && (React.createElement(DropdownMenu, { onShow: showMenu, onHide: hideMenu, menuItems: (close) => moreOptions.map((option) => React.cloneElement(option, {
90
+ onClick: (value) => {
91
+ var _a, _b;
92
+ close();
93
+ (_b = (_a = option.props).onClick) === null || _b === void 0 ? void 0 : _b.call(_a, value);
94
+ },
95
+ })) },
96
+ React.createElement("div", { className: cx('iui-tile-more-options', {
97
+ 'iui-visible': isMenuVisible,
98
+ }) },
99
+ React.createElement(IconButton, { styleType: 'borderless', size: 'small', "aria-label": 'More options' },
100
+ React.createElement(SvgMore, null))))),
101
+ children),
102
+ buttons && React.createElement("div", { className: 'iui-tile-buttons' }, buttons))));
103
+ }, {
104
+ /**
105
+ * Polymorphic Tile action component. Recommended to be used in a "name" of `Tile`.
106
+ * Renders `a` element by default.
107
+ * @example
108
+ * <Tile
109
+ * name={<Tile.Action href='/new-page'>Tile name<Tile.Action/>}
110
+ * />
111
+ */
112
+ Action: TileAction,
113
+ });
81
114
  const TitleIcon = ({ isLoading = false, isSelected = false, isNew = false, status, }) => {
82
115
  const StatusIcon = !!status && StatusIconMap[status];
83
116
  if (isLoading) {
@@ -15,16 +15,20 @@ export declare type ToggleSwitchProps = {
15
15
  * @default false
16
16
  */
17
17
  setFocus?: boolean;
18
- /**
19
- * Icon inside the toggle switch. Shown only when toggle is checked.
20
- */
21
- icon?: JSX.Element;
18
+ } & ({
22
19
  /**
23
20
  * Size of the toggle switch.
24
21
  * @default 'default'
25
22
  */
26
- size?: 'default' | 'small';
27
- } & Omit<React.InputHTMLAttributes<HTMLInputElement>, 'type' | 'size'>;
23
+ size?: 'default';
24
+ /**
25
+ * Icon inside the toggle switch. Shown only when toggle is checked and size is not small.
26
+ */
27
+ icon?: JSX.Element;
28
+ } | {
29
+ size: 'small';
30
+ icon?: never;
31
+ }) & Omit<React.InputHTMLAttributes<HTMLInputElement>, 'type' | 'size'>;
28
32
  /**
29
33
  * A switch for turning on and off.
30
34
  * @example
@@ -43,29 +47,5 @@ export declare type ToggleSwitchProps = {
43
47
  * <caption>Toggle with icon</caption>
44
48
  * <ToggleSwitch label='With icon toggle' icon={<svg viewBox='0 0 16 16'><path d='M1 1v14h14V1H1zm13 1.7v10.6L8.7 8 14 2.7zM8 7.3L2.7 2h10.6L8 7.3zm-.7.7L2 13.3V2.7L7.3 8zm.7.7l5.3 5.3H2.7L8 8.7z' /></svg>} />
45
49
  */
46
- export declare const ToggleSwitch: React.ForwardRefExoticComponent<{
47
- /**
48
- * Label for the toggle switch.
49
- */
50
- label?: React.ReactNode;
51
- /**
52
- * Position of the label.
53
- * @default 'right'
54
- */
55
- labelPosition?: "right" | "left" | undefined;
56
- /**
57
- * Set focus on toggle.
58
- * @default false
59
- */
60
- setFocus?: boolean | undefined;
61
- /**
62
- * Icon inside the toggle switch. Shown only when toggle is checked.
63
- */
64
- icon?: JSX.Element | undefined;
65
- /**
66
- * Size of the toggle switch.
67
- * @default 'default'
68
- */
69
- size?: "small" | "default" | undefined;
70
- } & Omit<React.InputHTMLAttributes<HTMLInputElement>, "type" | "size"> & React.RefAttributes<HTMLInputElement>>;
50
+ export declare const ToggleSwitch: React.ForwardRefExoticComponent<ToggleSwitchProps & React.RefAttributes<HTMLInputElement>>;
71
51
  export default ToggleSwitch;
@@ -25,7 +25,13 @@ import '@itwin/itwinui-css/css/toggle-switch.css';
25
25
  * <ToggleSwitch label='With icon toggle' icon={<svg viewBox='0 0 16 16'><path d='M1 1v14h14V1H1zm13 1.7v10.6L8.7 8 14 2.7zM8 7.3L2.7 2h10.6L8 7.3zm-.7.7L2 13.3V2.7L7.3 8zm.7.7l5.3 5.3H2.7L8 8.7z' /></svg>} />
26
26
  */
27
27
  export const ToggleSwitch = React.forwardRef((props, ref) => {
28
- const { disabled = false, labelPosition = 'right', icon, label, setFocus = false, className, style, size = 'default', ...rest } = props;
28
+ let icon;
29
+ if (props.size !== 'small') {
30
+ icon = props.icon;
31
+ props = { ...props };
32
+ delete props.icon;
33
+ }
34
+ const { disabled = false, labelPosition = 'right', label, setFocus = false, className, style, size = 'default', ...rest } = props;
29
35
  useTheme();
30
36
  const inputElementRef = React.useRef(null);
31
37
  const refs = useMergedRefs(inputElementRef, ref);
@@ -42,6 +48,7 @@ export const ToggleSwitch = React.forwardRef((props, ref) => {
42
48
  }, className), "data-iui-size": size, style: style },
43
49
  React.createElement("input", { className: 'iui-toggle-switch', type: 'checkbox', role: 'switch', disabled: disabled, ref: refs, ...rest }),
44
50
  icon &&
51
+ size !== 'small' &&
45
52
  React.cloneElement(icon, {
46
53
  className: cx('iui-toggle-switch-icon', icon.props.className),
47
54
  'aria-hidden': true,
@@ -79,7 +79,7 @@ export type { SliderProps } from './Slider';
79
79
  export { StatusMessage } from './StatusMessage';
80
80
  export type { StatusMessageProps } from './StatusMessage';
81
81
  export { Surface } from './Surface';
82
- export type { SurfaceProps } from './Surface';
82
+ export type { SurfaceProps, SurfaceHeaderProps, SurfaceBodyProps, } from './Surface';
83
83
  export { Table, tableFilters, BaseFilter, FilterButtonBar, DefaultCell, EditableCell, TablePaginator, ActionColumn, ExpanderColumn, SelectionColumn, } from './Table';
84
84
  export type { TableProps, TableFilterProps, TableFilterValue, DateRangeFilterOptions, FilterButtonBarProps, DefaultCellProps, EditableCellProps, TablePaginatorProps, TablePaginatorRendererProps, } from './Table';
85
85
  export { Tag, TagContainer } from './Tag';
@@ -104,5 +104,5 @@ export { Anchor, Body, Headline, Leading, Small, Subheading, Title, Blockquote,
104
104
  export type { AnchorProps, BodyProps, HeadlineProps, LeadingProps, SmallProps, SubheadingProps, TitleProps, BlockquoteProps, CodeProps, KbdProps, TextProps, } from './Typography';
105
105
  export { Wizard, Stepper, WorkflowDiagram } from './Stepper';
106
106
  export type { WizardProps, StepProperties, WizardType, WizardLocalization, StepperProps, StepperLocalization, WorkflowDiagramProps, } from './Stepper';
107
- export { getUserColor, useTheme, ColorValue, MiddleTextTruncation, Icon, Flex, } from './utils';
108
- export type { ThemeType, MiddleTextTruncationProps, IconProps, FlexProps, FlexItemProps, FlexSpacerProps, } from './utils';
107
+ export { getUserColor, useTheme, ColorValue, MiddleTextTruncation, LinkBox, LinkAction, Icon, Flex, VisuallyHidden, Divider, } from './utils';
108
+ export type { ThemeType, MiddleTextTruncationProps, IconProps, FlexProps, FlexItemProps, FlexSpacerProps, DividerProps, LinkBoxProps, LinkActionProps, VisuallyHiddenProps, } from './utils';
package/esm/core/index.js CHANGED
@@ -55,4 +55,4 @@ export { Tooltip } from './Tooltip';
55
55
  export { Tree, TreeNode, TreeNodeExpander } from './Tree';
56
56
  export { Anchor, Body, Headline, Leading, Small, Subheading, Title, Blockquote, Code, Kbd, KbdKeys, Text, } from './Typography';
57
57
  export { Wizard, Stepper, WorkflowDiagram } from './Stepper';
58
- export { getUserColor, useTheme, ColorValue, MiddleTextTruncation, Icon, Flex, } from './utils';
58
+ export { getUserColor, useTheme, ColorValue, MiddleTextTruncation, LinkBox, LinkAction, Icon, Flex, VisuallyHidden, Divider, } from './utils';
@@ -0,0 +1,14 @@
1
+ import React from 'react';
2
+ import '@itwin/itwinui-css/css/utils.css';
3
+ export declare type DividerProps = {
4
+ /**
5
+ * Sets the orientation of the divider
6
+ * @default 'horizontal'
7
+ */
8
+ orientation?: 'horizontal' | 'vertical';
9
+ } & React.ComponentPropsWithRef<'hr'>;
10
+ /**
11
+ * Shows a divider
12
+ */
13
+ export declare const Divider: React.ForwardRefExoticComponent<Pick<DividerProps, "key" | "orientation" | keyof React.HTMLAttributes<HTMLHRElement>> & React.RefAttributes<HTMLHRElement>>;
14
+ export default Divider;
@@ -0,0 +1,17 @@
1
+ /*---------------------------------------------------------------------------------------------
2
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
3
+ * See LICENSE.md in the project root for license terms and full copyright notice.
4
+ *--------------------------------------------------------------------------------------------*/
5
+ import React from 'react';
6
+ import cx from 'classnames';
7
+ import { useTheme } from '../hooks';
8
+ import '@itwin/itwinui-css/css/utils.css';
9
+ /**
10
+ * Shows a divider
11
+ */
12
+ export const Divider = React.forwardRef((props, ref) => {
13
+ const { className, orientation = 'horizontal', ...rest } = props;
14
+ useTheme();
15
+ return (React.createElement("hr", { className: cx('iui-divider', className), "aria-orientation": orientation === 'vertical' ? 'vertical' : undefined, ref: ref, ...rest }));
16
+ });
17
+ export default Divider;
@@ -0,0 +1,30 @@
1
+ import { PolymorphicComponentProps, PolymorphicForwardRefComponent } from '../props';
2
+ import '@itwin/itwinui-css/css/utils.css';
3
+ declare type LinkActionOwnProps = {};
4
+ declare type LinkBoxOwnProps = {};
5
+ export declare type LinkActionProps = PolymorphicComponentProps<'a', LinkActionOwnProps>;
6
+ export declare type LinkBoxProps = PolymorphicComponentProps<'div', LinkBoxOwnProps>;
7
+ /**
8
+ * Polymorphic link action component.
9
+ * It is rendered as `a` by default.
10
+ * @example
11
+ * <LinkBox>
12
+ * <Surface>
13
+ * <LinkAction href='/new-page'>Whole card is clickable</LinkAction>
14
+ * </Surface>
15
+ * </LinkBox>
16
+ */
17
+ export declare const LinkAction: PolymorphicForwardRefComponent<"a", LinkActionOwnProps>;
18
+ /**
19
+ * Polymorphic link box component.
20
+ * Used to wrap around your component to use LinkAction.
21
+ * Rendered as `div` by default
22
+ * @example
23
+ * <LinkBox>
24
+ * <Surface>
25
+ * <LinkAction href='/new-page'>Whole card is clickable</LinkAction>
26
+ * </Surface>
27
+ * </LinkBox>
28
+ */
29
+ export declare const LinkBox: PolymorphicForwardRefComponent<"div", LinkBoxOwnProps>;
30
+ export {};
@@ -0,0 +1,38 @@
1
+ /*---------------------------------------------------------------------------------------------
2
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
3
+ * See LICENSE.md in the project root for license terms and full copyright notice.
4
+ *--------------------------------------------------------------------------------------------*/
5
+ import React from 'react';
6
+ import cx from 'classnames';
7
+ import '@itwin/itwinui-css/css/utils.css';
8
+ /**
9
+ * Polymorphic link action component.
10
+ * It is rendered as `a` by default.
11
+ * @example
12
+ * <LinkBox>
13
+ * <Surface>
14
+ * <LinkAction href='/new-page'>Whole card is clickable</LinkAction>
15
+ * </Surface>
16
+ * </LinkBox>
17
+ */
18
+ export const LinkAction = React.forwardRef((props, ref) => {
19
+ const { as: Element = 'a', className, ...rest } = props;
20
+ return (React.createElement(Element, { ref: ref, className: cx('iui-link-action', className), ...rest }));
21
+ });
22
+ LinkAction.displayName = 'LinkAction';
23
+ /**
24
+ * Polymorphic link box component.
25
+ * Used to wrap around your component to use LinkAction.
26
+ * Rendered as `div` by default
27
+ * @example
28
+ * <LinkBox>
29
+ * <Surface>
30
+ * <LinkAction href='/new-page'>Whole card is clickable</LinkAction>
31
+ * </Surface>
32
+ * </LinkBox>
33
+ */
34
+ export const LinkBox = React.forwardRef((props, ref) => {
35
+ const { as: Element = 'div', className, ...rest } = props;
36
+ return (React.createElement(Element, { ref: ref, className: cx('iui-link-box', className), ...rest }));
37
+ });
38
+ LinkBox.displayName = 'LinkBox';
@@ -34,8 +34,9 @@ export const Resizer = (props) => {
34
34
  const minWidth = parseFloat(getComputedStyle(elementRef.current).minWidth);
35
35
  const minHeight = parseFloat(getComputedStyle(elementRef.current).minHeight);
36
36
  const resizer = event.currentTarget.dataset.iuiResizer;
37
- const originalUserSelect = elementRef.current.ownerDocument.body.style.userSelect;
38
- elementRef.current.ownerDocument.body.style.userSelect = 'none';
37
+ const ownerDocument = elementRef.current.ownerDocument || document;
38
+ const originalUserSelect = ownerDocument.body.style.userSelect;
39
+ ownerDocument.body.style.userSelect = 'none';
39
40
  const onResizePointerMove = (event) => {
40
41
  var _a, _b, _c, _d, _e, _f, _g;
41
42
  if (!elementRef.current) {
@@ -46,8 +47,8 @@ export const Resizer = (props) => {
46
47
  onResizeStart === null || onResizeStart === void 0 ? void 0 : onResizeStart();
47
48
  }
48
49
  const containerRect = (_a = containerRef === null || containerRef === void 0 ? void 0 : containerRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
49
- const clientX = getBoundedValue(event.clientX, (_b = containerRect === null || containerRect === void 0 ? void 0 : containerRect.left) !== null && _b !== void 0 ? _b : 0, (_d = (_c = containerRect === null || containerRect === void 0 ? void 0 : containerRect.right) !== null && _c !== void 0 ? _c : elementRef.current.ownerDocument.documentElement.clientWidth) !== null && _d !== void 0 ? _d : 0);
50
- const clientY = getBoundedValue(event.clientY, (_e = containerRect === null || containerRect === void 0 ? void 0 : containerRect.top) !== null && _e !== void 0 ? _e : 0, (_g = (_f = containerRect === null || containerRect === void 0 ? void 0 : containerRect.bottom) !== null && _f !== void 0 ? _f : elementRef.current.ownerDocument.documentElement.clientHeight) !== null && _g !== void 0 ? _g : 0);
50
+ const clientX = getBoundedValue(event.clientX, (_b = containerRect === null || containerRect === void 0 ? void 0 : containerRect.left) !== null && _b !== void 0 ? _b : 0, (_d = (_c = containerRect === null || containerRect === void 0 ? void 0 : containerRect.right) !== null && _c !== void 0 ? _c : ownerDocument.documentElement.clientWidth) !== null && _d !== void 0 ? _d : 0);
51
+ const clientY = getBoundedValue(event.clientY, (_e = containerRect === null || containerRect === void 0 ? void 0 : containerRect.top) !== null && _e !== void 0 ? _e : 0, (_g = (_f = containerRect === null || containerRect === void 0 ? void 0 : containerRect.bottom) !== null && _f !== void 0 ? _f : ownerDocument.documentElement.clientHeight) !== null && _g !== void 0 ? _g : 0);
51
52
  const diffX = initialPointerX - clientX;
52
53
  const diffY = initialPointerY - clientY;
53
54
  switch (resizer) {
@@ -122,12 +123,11 @@ export const Resizer = (props) => {
122
123
  break;
123
124
  }
124
125
  };
125
- elementRef.current.ownerDocument.addEventListener('pointermove', onResizePointerMove);
126
- elementRef.current.ownerDocument.addEventListener('pointerup', () => {
127
- document.removeEventListener('pointermove', onResizePointerMove);
126
+ ownerDocument.addEventListener('pointermove', onResizePointerMove);
127
+ ownerDocument.addEventListener('pointerup', () => {
128
+ ownerDocument.removeEventListener('pointermove', onResizePointerMove);
128
129
  if (elementRef.current) {
129
- elementRef.current.ownerDocument.body.style.userSelect =
130
- originalUserSelect;
130
+ ownerDocument.body.style.userSelect = originalUserSelect;
131
131
  isResizing.current = false;
132
132
  onResizeEnd === null || onResizeEnd === void 0 ? void 0 : onResizeEnd({
133
133
  width,
@@ -1,10 +1,24 @@
1
- import React from 'react';
2
1
  import '@itwin/itwinui-css/css/utils.css';
3
- export declare type VisuallyHiddenProps = React.ComponentPropsWithRef<'div'>;
2
+ import type { PolymorphicComponentProps, PolymorphicForwardRefComponent } from '../props';
3
+ declare type VisuallyHiddenOwnProps = {
4
+ /**
5
+ * When VisuallyHidden is used with an interactive element (e.g. button),
6
+ * that element will "unhide" (become visible again) when focused.
7
+ *
8
+ * @default true
9
+ */
10
+ unhideOnFocus?: boolean;
11
+ };
12
+ export declare type VisuallyHiddenProps = PolymorphicComponentProps<'span', VisuallyHiddenOwnProps>;
4
13
  /**
5
- * Hides content visually but is still accessible to screen readers.
14
+ * Hides content visually but keeps it still accessible to screen readers
15
+ * and other assistive technologies.
16
+ *
17
+ * @example
18
+ * <div aria-hidden='true'>★★★☆☆</div>
19
+ * <VisuallyHidden>3 stars out of 5</VisuallyHidden>
20
+ *
21
+ * @see https://www.scottohara.me/blog/2017/04/14/inclusively-hidden.html
6
22
  */
7
- export declare const VisuallyHidden: React.ForwardRefExoticComponent<Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
8
- ref?: ((instance: HTMLDivElement | null) => void) | React.RefObject<HTMLDivElement> | null | undefined;
9
- }, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & React.RefAttributes<HTMLDivElement>>;
23
+ export declare const VisuallyHidden: PolymorphicForwardRefComponent<"span", VisuallyHiddenOwnProps>;
10
24
  export default VisuallyHidden;
@@ -7,11 +7,18 @@ import cx from 'classnames';
7
7
  import { useTheme } from '../hooks';
8
8
  import '@itwin/itwinui-css/css/utils.css';
9
9
  /**
10
- * Hides content visually but is still accessible to screen readers.
10
+ * Hides content visually but keeps it still accessible to screen readers
11
+ * and other assistive technologies.
12
+ *
13
+ * @example
14
+ * <div aria-hidden='true'>★★★☆☆</div>
15
+ * <VisuallyHidden>3 stars out of 5</VisuallyHidden>
16
+ *
17
+ * @see https://www.scottohara.me/blog/2017/04/14/inclusively-hidden.html
11
18
  */
12
19
  export const VisuallyHidden = React.forwardRef((props, ref) => {
13
- const { className, ...rest } = props;
20
+ const { as: Element = 'span', className, unhideOnFocus = true, ...rest } = props;
14
21
  useTheme();
15
- return (React.createElement("div", { className: cx('iui-visually-hidden', className), ref: ref, ...rest }));
22
+ return (React.createElement(Element, { className: cx('iui-visually-hidden', className), "data-iui-unhide-on-focus": unhideOnFocus ? true : undefined, ref: ref, ...rest }));
16
23
  });
17
24
  export default VisuallyHidden;
@@ -8,3 +8,5 @@ export * from './VirtualScroll';
8
8
  export * from './VisuallyHidden';
9
9
  export * from './Icon';
10
10
  export * from './Flex';
11
+ export * from './Divider';
12
+ export * from './LinkAction';
@@ -12,3 +12,5 @@ export * from './VirtualScroll';
12
12
  export * from './VisuallyHidden';
13
13
  export * from './Icon';
14
14
  export * from './Flex';
15
+ export * from './Divider';
16
+ export * from './LinkAction';
@@ -3,3 +3,4 @@ export * from './colors';
3
3
  export * from './numbers';
4
4
  export * from './focusable';
5
5
  export * from './styles';
6
+ export * from './supports';
@@ -7,3 +7,4 @@ export * from './colors';
7
7
  export * from './numbers';
8
8
  export * from './focusable';
9
9
  export * from './styles';
10
+ export * from './supports';
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Returns true if the :has selector is supported in the browser
3
+ */
4
+ export declare const supportsHas: () => boolean | undefined;
@@ -0,0 +1,9 @@
1
+ /*---------------------------------------------------------------------------------------------
2
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
3
+ * See LICENSE.md in the project root for license terms and full copyright notice.
4
+ *--------------------------------------------------------------------------------------------*/
5
+ import { getWindow } from './dom';
6
+ /**
7
+ * Returns true if the :has selector is supported in the browser
8
+ */
9
+ export const supportsHas = () => { var _a, _b, _c; return (_c = (_b = (_a = getWindow()) === null || _a === void 0 ? void 0 : _a.CSS) === null || _b === void 0 ? void 0 : _b.supports) === null || _c === void 0 ? void 0 : _c.call(_b, 'selector(:has(+ *))'); };
@@ -10,4 +10,5 @@ export * from './useSafeContext';
10
10
  export * from './useLatestRef';
11
11
  export * from './useIsomorphicLayoutEffect';
12
12
  export * from './useIsThemeAlreadySet';
13
+ export * from './useIsClient';
13
14
  export * from './useId';
@@ -14,4 +14,5 @@ export * from './useSafeContext';
14
14
  export * from './useLatestRef';
15
15
  export * from './useIsomorphicLayoutEffect';
16
16
  export * from './useIsThemeAlreadySet';
17
+ export * from './useIsClient';
17
18
  export * from './useId';
@@ -88,10 +88,11 @@ export const useDragAndDrop = (elementRef, containerRef, enabled = true) => {
88
88
  originalUserSelect.current = elementRef.current.style.userSelect;
89
89
  // Prevents from selecting inner content when dragging.
90
90
  elementRef.current.style.userSelect = 'none';
91
- elementRef.current.ownerDocument.addEventListener('pointermove', onPointerMove.current);
92
- elementRef.current.ownerDocument.addEventListener('pointerup', () => {
91
+ const ownerDocument = elementRef.current.ownerDocument || document;
92
+ ownerDocument.addEventListener('pointermove', onPointerMove.current);
93
+ ownerDocument.addEventListener('pointerup', () => {
93
94
  setTransform(`translate(${translateX.current}px, ${translateY.current}px)`);
94
- document.removeEventListener('pointermove', onPointerMove.current);
95
+ ownerDocument.removeEventListener('pointermove', onPointerMove.current);
95
96
  if (elementRef.current) {
96
97
  elementRef.current.style.userSelect = originalUserSelect.current;
97
98
  }
@@ -0,0 +1 @@
1
+ export declare const useIsClient: () => boolean;
@@ -0,0 +1,12 @@
1
+ /*---------------------------------------------------------------------------------------------
2
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
3
+ * See LICENSE.md in the project root for license terms and full copyright notice.
4
+ *--------------------------------------------------------------------------------------------*/
5
+ import React from 'react';
6
+ export const useIsClient = () => {
7
+ const [isClient, setIsClient] = React.useState(false);
8
+ React.useEffect(() => {
9
+ setIsClient(true);
10
+ }, []);
11
+ return isClient;
12
+ };
@@ -2,6 +2,7 @@
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';
5
6
  import { getDocument, getWindow } from '../functions';
6
7
  import { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect';
7
8
  import { useIsThemeAlreadySet } from './useIsThemeAlreadySet';
@@ -20,6 +21,7 @@ export const useTheme = (theme, themeOptions) => {
20
21
  var _a;
21
22
  const ownerDocument = (_a = themeOptions === null || themeOptions === void 0 ? void 0 : themeOptions.ownerDocument) !== null && _a !== void 0 ? _a : getDocument();
22
23
  const isThemeAlreadySet = useIsThemeAlreadySet(ownerDocument);
24
+ useCorrectRootFontSize();
23
25
  useIsomorphicLayoutEffect(() => {
24
26
  if (!ownerDocument || isThemeAlreadySet.current) {
25
27
  return;
@@ -77,3 +79,22 @@ const handleTheme = (theme, ownerDocument, highContrast) => {
77
79
  (_b = prefersHCQuery === null || prefersHCQuery === void 0 ? void 0 : prefersHCQuery.removeEventListener) === null || _b === void 0 ? void 0 : _b.call(prefersHCQuery, 'change', changeHandler);
78
80
  };
79
81
  };
82
+ let didLogWarning = false;
83
+ let isDev = false;
84
+ // wrapping in try-catch because process might be undefined
85
+ try {
86
+ isDev = process.env.NODE_ENV !== 'production';
87
+ }
88
+ catch (_a) { }
89
+ /** Shows console error if the page changes the root font size */
90
+ const useCorrectRootFontSize = () => {
91
+ React.useEffect(() => {
92
+ if (isDev && !didLogWarning) {
93
+ const rootFontSize = parseInt(getComputedStyle(document.documentElement).fontSize);
94
+ if (rootFontSize < 16) {
95
+ console.error('Root font size must not be overridden. \nSee https://github.com/iTwin/iTwinUI/wiki/iTwinUI-react-v2-migration-guide#relative-font-size');
96
+ didLogWarning = true;
97
+ }
98
+ }
99
+ }, []);
100
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itwin/itwinui-react",
3
- "version": "2.6.1",
3
+ "version": "2.8.0",
4
4
  "author": "Bentley Systems",
5
5
  "license": "MIT",
6
6
  "main": "cjs/index.js",
@@ -62,7 +62,7 @@
62
62
  "dev:types": "concurrently \"tsc -p tsconfig.cjs.json --emitDeclarationOnly --watch --preserveWatchOutput\" \"tsc -p tsconfig.esm.json --emitDeclarationOnly --watch --preserveWatchOutput\""
63
63
  },
64
64
  "dependencies": {
65
- "@itwin/itwinui-css": "^1.7.0",
65
+ "@itwin/itwinui-css": "^1.9.0",
66
66
  "@itwin/itwinui-illustrations-react": "^2.0.0",
67
67
  "@itwin/itwinui-variables": "^2.0.0",
68
68
  "@tippyjs/react": "^4.2.6",