@itwin/itwinui-react 2.2.1 → 2.3.1-dev.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 (48) hide show
  1. package/CHANGELOG.md +45 -0
  2. package/cjs/core/Avatar/Avatar.d.ts +1 -1
  3. package/cjs/core/Badge/Badge.d.ts +2 -1
  4. package/cjs/core/ExpandableBlock/ExpandableBlock.js +1 -5
  5. package/cjs/core/Tabs/Tabs.d.ts +18 -1
  6. package/cjs/core/Tabs/Tabs.js +9 -0
  7. package/cjs/core/Toast/Toast.js +17 -10
  8. package/cjs/core/Toast/Toaster.d.ts +6 -6
  9. package/cjs/core/Toast/Toaster.js +10 -9
  10. package/cjs/core/Typography/Anchor/Anchor.d.ts +18 -1
  11. package/cjs/core/Typography/Anchor/Anchor.js +17 -2
  12. package/cjs/core/Typography/Anchor/index.d.ts +1 -0
  13. package/cjs/core/Typography/index.d.ts +1 -0
  14. package/cjs/core/index.d.ts +3 -3
  15. package/cjs/core/index.js +2 -1
  16. package/cjs/core/utils/components/Icon.d.ts +43 -0
  17. package/cjs/core/utils/components/Icon.js +44 -0
  18. package/cjs/core/utils/components/index.d.ts +1 -0
  19. package/cjs/core/utils/components/index.js +1 -0
  20. package/cjs/core/utils/hooks/useIntersection.js +8 -12
  21. package/cjs/core/utils/index.d.ts +1 -0
  22. package/cjs/core/utils/index.js +1 -0
  23. package/cjs/core/utils/types.d.ts +5 -0
  24. package/cjs/core/utils/types.js +2 -0
  25. package/esm/core/Avatar/Avatar.d.ts +1 -1
  26. package/esm/core/Badge/Badge.d.ts +2 -1
  27. package/esm/core/ExpandableBlock/ExpandableBlock.js +2 -6
  28. package/esm/core/Tabs/Tabs.d.ts +18 -1
  29. package/esm/core/Tabs/Tabs.js +9 -0
  30. package/esm/core/Toast/Toast.js +17 -10
  31. package/esm/core/Toast/Toaster.d.ts +6 -6
  32. package/esm/core/Toast/Toaster.js +10 -9
  33. package/esm/core/Typography/Anchor/Anchor.d.ts +18 -1
  34. package/esm/core/Typography/Anchor/Anchor.js +18 -3
  35. package/esm/core/Typography/Anchor/index.d.ts +1 -0
  36. package/esm/core/Typography/index.d.ts +1 -0
  37. package/esm/core/index.d.ts +3 -3
  38. package/esm/core/index.js +1 -1
  39. package/esm/core/utils/components/Icon.d.ts +43 -0
  40. package/esm/core/utils/components/Icon.js +38 -0
  41. package/esm/core/utils/components/index.d.ts +1 -0
  42. package/esm/core/utils/components/index.js +1 -0
  43. package/esm/core/utils/hooks/useIntersection.js +8 -12
  44. package/esm/core/utils/index.d.ts +1 -0
  45. package/esm/core/utils/index.js +1 -0
  46. package/esm/core/utils/types.d.ts +5 -0
  47. package/esm/core/utils/types.js +1 -0
  48. package/package.json +3 -4
package/CHANGELOG.md CHANGED
@@ -1,5 +1,50 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - c06caffe: Added `actions` prop to `Tabs` to add right/bottom content to the horizontal/vertical tabs.
8
+
9
+ ```tsx
10
+ <Tabs
11
+ // ...
12
+ actions={[
13
+ <Button key={'Small'} size={'small'}>
14
+ Small size button
15
+ </Button>,
16
+ <Button key={'Normal'}>Normal size button</Button>,
17
+ ]}
18
+ >
19
+ // ...
20
+ </Tabs>
21
+ ```
22
+
23
+ - ec26b72d: `Anchor` can now be rendered as a button using `as` prop.
24
+
25
+ ```jsx
26
+ <Anchor as='button' onClick={() => {}}>
27
+ ...
28
+ </Anchor>
29
+ ```
30
+
31
+ - dd13257f: Added new Icon component for displaying svgs
32
+
33
+ - Supports `size` and `fill` props
34
+
35
+ ```tsx
36
+ <Icon size='medium' fill='positive'>
37
+ <svg>...</svg>
38
+ </Icon>
39
+ ```
40
+
41
+ ### Patch Changes
42
+
43
+ - 8e319bea: Removes transitions for `Toast` component when `prefer-reduced-motion` is active
44
+ - 24a0cf94: Fixed an issue where Table's `onBottomReached` callback was not being invoked when using strict mode with react 18.
45
+ - Updated dependencies
46
+ - @itwin/itwinui-css@1.4.0
47
+
3
48
  ## 2.2.1
4
49
 
5
50
  ### Patch Changes
@@ -28,7 +28,7 @@ export declare type AvatarProps = {
28
28
  */
29
29
  abbreviation?: string;
30
30
  /**
31
- * User image to be displayed. MUST be an <img> element!
31
+ * User image to be displayed. MUST be an `<img>` element!
32
32
  */
33
33
  image?: JSX.Element;
34
34
  /**
@@ -1,5 +1,6 @@
1
1
  /// <reference types="react" />
2
2
  import { CommonProps, SoftBackgrounds } from '../utils';
3
+ import type { AnyString } from '../utils';
3
4
  import '@itwin/itwinui-css/css/badge.css';
4
5
  export declare type BadgeProps = {
5
6
  /**
@@ -9,7 +10,7 @@ export declare type BadgeProps = {
9
10
  *
10
11
  * If not specified, a default neutral background will be used.
11
12
  */
12
- backgroundColor?: 'primary' | 'positive' | 'negative' | 'warning' | keyof typeof SoftBackgrounds | (string & {});
13
+ backgroundColor?: 'primary' | 'positive' | 'negative' | 'warning' | keyof typeof SoftBackgrounds | AnyString;
13
14
  /**
14
15
  * Badge label.
15
16
  * Always gets converted to uppercase, and truncated if too long.
@@ -51,11 +51,7 @@ const ExpandableBlock = (props) => {
51
51
  react_1.default.createElement("span", { className: 'iui-expandable-block-label' },
52
52
  react_1.default.createElement("div", { className: 'iui-title' }, title),
53
53
  caption && react_1.default.createElement("div", { className: 'iui-caption' }, caption)),
54
- icon &&
55
- react_1.default.cloneElement(icon, {
56
- className: (0, classnames_1.default)('iui-status-icon', icon.props.className),
57
- 'data-iui-icon-color': status,
58
- })),
54
+ icon && react_1.default.createElement(utils_1.Icon, { fill: status }, icon)),
59
55
  react_1.default.createElement(utils_1.WithCSSTransition, { in: expanded },
60
56
  react_1.default.createElement("div", { className: 'iui-expandable-content' },
61
57
  react_1.default.createElement("div", null, children)))));
@@ -17,6 +17,23 @@ declare type TabsOrientationProps = {
17
17
  orientation: 'vertical';
18
18
  type?: 'default' | 'borderless';
19
19
  };
20
+ declare type TabsTypeProps = {
21
+ /**
22
+ * Type of the tabs.
23
+ *
24
+ * If `orientation = 'vertical'`, `pill` is not applicable.
25
+ * @default 'default'
26
+ */
27
+ type?: 'default' | 'borderless';
28
+ /**
29
+ * Content displayed to the right/bottom of the horizontal/vertical tabs
30
+ *
31
+ * If `type = 'pill'`, `actions` is not applicable.
32
+ */
33
+ actions?: React.ReactNode[];
34
+ } | {
35
+ type: 'pill';
36
+ };
20
37
  export declare type TabsProps = {
21
38
  /**
22
39
  * Elements shown for each tab.
@@ -58,7 +75,7 @@ export declare type TabsProps = {
58
75
  * Content inside the tab panel.
59
76
  */
60
77
  children?: React.ReactNode;
61
- } & TabsOrientationProps;
78
+ } & TabsOrientationProps & TabsTypeProps;
62
79
  /**
63
80
  * @deprecated Since v2, use `TabProps` with `Tabs`
64
81
  */
@@ -41,6 +41,13 @@ const Tab_1 = require("./Tab");
41
41
  * <Tabs labels={tabsWithIcons} type='pill' />
42
42
  */
43
43
  const Tabs = (props) => {
44
+ // Separate actions from props to avoid adding it to the DOM (using {...rest})
45
+ let actions;
46
+ if (props.type !== 'pill' && props.actions) {
47
+ actions = props.actions;
48
+ props = { ...props };
49
+ delete props.actions;
50
+ }
44
51
  const { labels, activeIndex, onTabSelected, focusActivationMode = 'auto', type = 'default', color = 'blue', orientation = 'horizontal', tabsClassName, contentClassName, wrapperClassName, children, ...rest } = props;
45
52
  (0, utils_1.useTheme)();
46
53
  const tablistRef = react_1.default.useRef(null);
@@ -176,6 +183,8 @@ const Tabs = (props) => {
176
183
  },
177
184
  }))));
178
185
  })),
186
+ actions && (react_1.default.createElement("div", { className: 'iui-tabs-actions-wrapper' },
187
+ react_1.default.createElement("div", { className: 'iui-tabs-actions' }, actions))),
179
188
  children && (react_1.default.createElement("div", { className: (0, classnames_1.default)('iui-tabs-content', contentClassName), role: 'tabpanel' }, children))));
180
189
  };
181
190
  exports.Tabs = Tabs;
@@ -14,6 +14,7 @@ const classnames_1 = __importDefault(require("classnames"));
14
14
  const utils_1 = require("../utils");
15
15
  require("@itwin/itwinui-css/css/toast.css");
16
16
  const Buttons_1 = require("../Buttons");
17
+ const isMotionOk = () => { var _a, _b, _c; return (_c = (_b = (_a = (0, utils_1.getWindow)()) === null || _a === void 0 ? void 0 : _a.matchMedia) === null || _b === void 0 ? void 0 : _b.call(_a, '(prefers-reduced-motion: no-preference)')) === null || _c === void 0 ? void 0 : _c.matches; };
17
18
  /**
18
19
  * Generic Toast Component
19
20
  * @example
@@ -92,18 +93,24 @@ const Toast = (props) => {
92
93
  return { translateX, translateY };
93
94
  };
94
95
  return (react_1.default.createElement(react_transition_group_1.Transition, { timeout: { enter: 240, exit: animateOutTo ? 400 : 120 }, in: visible, appear: true, unmountOnExit: true, onEnter: (node) => {
95
- node.style.transform = 'translateY(15%)';
96
- node.style.transitionTimingFunction = 'ease';
96
+ if (isMotionOk()) {
97
+ node.style.transform = 'translateY(15%)';
98
+ node.style.transitionTimingFunction = 'ease';
99
+ }
97
100
  }, onEntered: (node) => {
98
- node.style.transform = 'translateY(0)';
101
+ if (isMotionOk()) {
102
+ node.style.transform = 'translateY(0)';
103
+ }
99
104
  }, onExiting: (node) => {
100
- const { translateX, translateY } = calculateOutAnimation(node);
101
- node.style.transform = animateOutTo
102
- ? `scale(0.9) translate(${translateX}px,${translateY}px)`
103
- : `scale(0.9)`;
104
- node.style.opacity = '0';
105
- node.style.transitionDuration = animateOutTo ? '400ms' : '120ms';
106
- node.style.transitionTimingFunction = 'cubic-bezier(0.4, 0, 1, 1)';
105
+ if (isMotionOk()) {
106
+ const { translateX, translateY } = calculateOutAnimation(node);
107
+ node.style.transform = animateOutTo
108
+ ? `scale(0.9) translate(${translateX}px,${translateY}px)`
109
+ : `scale(0.9)`;
110
+ node.style.opacity = '0';
111
+ node.style.transitionDuration = animateOutTo ? '400ms' : '120ms';
112
+ node.style.transitionTimingFunction = 'cubic-bezier(0.4, 0, 1, 1)';
113
+ }
107
114
  }, onExited: onRemove }, react_1.default.createElement("div", { ref: thisElement, className: 'iui-toast-all', style: {
108
115
  height,
109
116
  ...marginStyle(),
@@ -27,22 +27,22 @@ export default class Toaster {
27
27
  * Set global Toaster settings for toasts order and placement.
28
28
  * Settings will be applied to new toasts on the page.
29
29
  */
30
- setSettings(newSettings: ToasterSettings): void;
30
+ setSettings(newSettings: ToasterSettings): Promise<void>;
31
31
  positive(content: React.ReactNode, options?: ToastOptions): {
32
- close: () => void;
32
+ close: () => Promise<void>;
33
33
  };
34
34
  informational(content: React.ReactNode, options?: ToastOptions): {
35
- close: () => void;
35
+ close: () => Promise<void>;
36
36
  };
37
37
  negative(content: React.ReactNode, options?: ToastOptions): {
38
- close: () => void;
38
+ close: () => Promise<void>;
39
39
  };
40
40
  warning(content: React.ReactNode, options?: ToastOptions): {
41
- close: () => void;
41
+ close: () => Promise<void>;
42
42
  };
43
43
  private createToast;
44
44
  private removeToast;
45
45
  private updateView;
46
46
  private closeToast;
47
- closeAll(): void;
47
+ closeAll(): Promise<void>;
48
48
  }
@@ -83,14 +83,14 @@ class Toaster {
83
83
  * Set global Toaster settings for toasts order and placement.
84
84
  * Settings will be applied to new toasts on the page.
85
85
  */
86
- setSettings(newSettings) {
86
+ async setSettings(newSettings) {
87
87
  var _a, _b, _c;
88
88
  (_a = newSettings.placement) !== null && _a !== void 0 ? _a : (newSettings.placement = this.settings.placement);
89
89
  (_b = newSettings.order) !== null && _b !== void 0 ? _b : (newSettings.order = ((_c = newSettings.placement) === null || _c === void 0 ? void 0 : _c.startsWith('bottom'))
90
90
  ? 'ascending'
91
91
  : 'descending');
92
92
  this.settings = newSettings;
93
- this.asyncInit().then(() => {
93
+ await this.asyncInit().then(() => {
94
94
  var _a, _b;
95
95
  (_a = this.toastsRef.current) === null || _a === void 0 ? void 0 : _a.setPlacement((_b = this.settings.placement) !== null && _b !== void 0 ? _b : 'top');
96
96
  });
@@ -126,36 +126,37 @@ class Toaster {
126
126
  },
127
127
  ...(this.settings.order === 'descending' ? this.toasts : []),
128
128
  ];
129
+ // cannot `await` this, for backwards compat with the return value
129
130
  this.updateView();
130
131
  return { close: () => this.closeToast(currentId) };
131
132
  }
132
- removeToast(id) {
133
+ async removeToast(id) {
133
134
  this.toasts = this.toasts.filter((toast) => toast.id !== id);
134
135
  this.updateView();
135
136
  }
136
- updateView() {
137
- this.asyncInit().then(() => {
137
+ async updateView() {
138
+ await this.asyncInit().then(() => {
138
139
  var _a;
139
140
  (_a = this.toastsRef.current) === null || _a === void 0 ? void 0 : _a.setToasts(this.toasts);
140
141
  });
141
142
  }
142
- closeToast(toastId) {
143
+ async closeToast(toastId) {
143
144
  this.toasts = this.toasts.map((toast) => {
144
145
  return {
145
146
  ...toast,
146
147
  isVisible: toast.id !== toastId,
147
148
  };
148
149
  });
149
- this.updateView();
150
+ await this.updateView();
150
151
  }
151
- closeAll() {
152
+ async closeAll() {
152
153
  this.toasts = this.toasts.map((toast) => {
153
154
  return {
154
155
  ...toast,
155
156
  isVisible: false,
156
157
  };
157
158
  });
158
- this.updateView();
159
+ await this.updateView();
159
160
  }
160
161
  }
161
162
  exports.default = Toaster;
@@ -1,4 +1,21 @@
1
1
  import React from 'react';
2
+ import { PolymorphicComponentProps, PolymorphicForwardRefComponent } from '../../utils';
2
3
  import '@itwin/itwinui-css/css/anchor.css';
3
- export declare const Anchor: React.ForwardRefExoticComponent<Pick<React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>, "key" | keyof React.AnchorHTMLAttributes<HTMLAnchorElement>> & React.RefAttributes<HTMLAnchorElement>>;
4
+ declare type AnchorOwnProps = Record<never, never>;
5
+ export declare type AnchorProps<T extends React.ElementType = 'a'> = PolymorphicComponentProps<T, AnchorOwnProps>;
6
+ /**
7
+ * A consistently styled anchor component.
8
+ *
9
+ * Supports polymorphic `as` prop for use with `Link` components from routers,
10
+ * or to render as a button.
11
+ *
12
+ * @example
13
+ * <Anchor href='/'>Home</Anchor>
14
+ * <Anchor href='/projects'>Projects</Anchor>
15
+ *
16
+ * @example
17
+ * <Anchor as={Link} to='/'>Home</Anchor>
18
+ * <Anchor as='button' onClick={() => {}}>click me</Anchor>
19
+ */
20
+ export declare const Anchor: PolymorphicForwardRefComponent<"a", AnchorOwnProps>;
4
21
  export default Anchor;
@@ -12,8 +12,23 @@ const react_1 = __importDefault(require("react"));
12
12
  const classnames_1 = __importDefault(require("classnames"));
13
13
  const utils_1 = require("../../utils");
14
14
  require("@itwin/itwinui-css/css/anchor.css");
15
- exports.Anchor = react_1.default.forwardRef(({ className, ...rest }, ref) => {
15
+ /**
16
+ * A consistently styled anchor component.
17
+ *
18
+ * Supports polymorphic `as` prop for use with `Link` components from routers,
19
+ * or to render as a button.
20
+ *
21
+ * @example
22
+ * <Anchor href='/'>Home</Anchor>
23
+ * <Anchor href='/projects'>Projects</Anchor>
24
+ *
25
+ * @example
26
+ * <Anchor as={Link} to='/'>Home</Anchor>
27
+ * <Anchor as='button' onClick={() => {}}>click me</Anchor>
28
+ */
29
+ exports.Anchor = react_1.default.forwardRef((props, ref) => {
30
+ const { as: Element = 'a', className, ...rest } = props;
16
31
  (0, utils_1.useTheme)();
17
- return react_1.default.createElement("a", { className: (0, classnames_1.default)('iui-anchor', className), ref: ref, ...rest });
32
+ return (react_1.default.createElement(Element, { className: (0, classnames_1.default)('iui-anchor', className), ref: ref, ...rest }));
18
33
  });
19
34
  exports.default = exports.Anchor;
@@ -1,3 +1,4 @@
1
1
  export { Anchor } from './Anchor';
2
+ export type { AnchorProps } from './Anchor';
2
3
  declare const _default: "./Anchor";
3
4
  export default _default;
@@ -1,4 +1,5 @@
1
1
  export { Anchor } from './Anchor';
2
+ export type { AnchorProps } from './Anchor';
2
3
  export { Headline } from './Headline';
3
4
  export type { HeadlineProps } from './Headline';
4
5
  export { Title } from './Title';
@@ -101,8 +101,8 @@ export type { TooltipProps } from './Tooltip';
101
101
  export { Tree, TreeNode, TreeNodeExpander } from './Tree';
102
102
  export type { TreeProps, TreeNodeProps, TreeNodeExpanderProps, NodeData, NodeRenderProps, } from './Tree';
103
103
  export { Anchor, Body, Headline, Leading, Small, Subheading, Title, Blockquote, Code, Kbd, KbdKeys, Text, } from './Typography';
104
- export type { BodyProps, HeadlineProps, LeadingProps, SmallProps, SubheadingProps, TitleProps, BlockquoteProps, CodeProps, KbdProps, TextProps, } from './Typography';
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, } from './utils';
108
- export type { ThemeType, MiddleTextTruncationProps } from './utils';
107
+ export { getUserColor, useTheme, ColorValue, MiddleTextTruncation, Icon, } from './utils';
108
+ export type { ThemeType, MiddleTextTruncationProps, IconProps } from './utils';
package/cjs/core/index.js CHANGED
@@ -5,7 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.LabeledInput = exports.Label = exports.Input = exports.InformationPanelContent = exports.InformationPanelBody = exports.InformationPanelHeader = exports.InformationPanelWrapper = exports.InformationPanel = exports.HorizontalTabs = exports.Tab = exports.Tabs = exports.VerticalTabs = exports.HeaderLogo = exports.HeaderButton = exports.HeaderBreadcrumbs = exports.Header = exports.defaultFooterElements = exports.Footer = exports.FileUploadTemplate = exports.FileUpload = exports.Fieldset = exports.ExpandableBlock = exports.NonIdealState = exports.ErrorPage = exports.DropdownMenu = exports.Dialog = exports.generateLocalizedStrings = exports.DatePicker = exports.ComboBox = exports.ColorPalette = exports.ColorInputPanel = exports.ColorBuilder = exports.ColorSwatch = exports.ColorPicker = exports.Checkbox = exports.Carousel = exports.ButtonGroup = exports.SplitButton = exports.IdeasButton = exports.IconButton = exports.DropdownButton = exports.Button = exports.Breadcrumbs = exports.Badge = exports.Backdrop = exports.UserIconGroup = exports.AvatarGroup = exports.UserIcon = exports.Avatar = exports.Alert = void 0;
7
7
  exports.Body = exports.Anchor = exports.TreeNodeExpander = exports.TreeNode = exports.Tree = exports.Tooltip = exports.ToggleSwitch = exports.ThemeProvider = exports.toaster = exports.TimePicker = exports.Tile = exports.Textarea = exports.TagContainer = exports.Tag = exports.SelectionColumn = exports.ExpanderColumn = exports.ActionColumn = exports.TablePaginator = exports.EditableCell = exports.DefaultCell = exports.FilterButtonBar = exports.BaseFilter = exports.tableFilters = exports.Table = exports.Surface = exports.StatusMessage = exports.Slider = exports.SkipToContentLink = exports.SidenavSubmenuHeader = exports.SidenavSubmenu = exports.SidenavButton = exports.SideNavigation = exports.Select = exports.RadioTileGroup = exports.RadioTile = exports.Radio = exports.ProgressRadial = exports.ProgressLinear = exports.NotificationMarker = exports.ModalContent = exports.ModalButtonBar = exports.Modal = exports.MenuItemSkeleton = exports.MenuExtraContent = exports.MenuDivider = exports.MenuItem = exports.Menu = exports.LabeledTextarea = exports.LabeledSelect = exports.InputGroup = void 0;
8
- exports.MiddleTextTruncation = exports.ColorValue = exports.useTheme = exports.getUserColor = exports.WorkflowDiagram = exports.Stepper = exports.Wizard = exports.Text = exports.KbdKeys = exports.Kbd = exports.Code = exports.Blockquote = exports.Title = exports.Subheading = exports.Small = exports.Leading = exports.Headline = void 0;
8
+ exports.Icon = exports.MiddleTextTruncation = exports.ColorValue = exports.useTheme = exports.getUserColor = exports.WorkflowDiagram = exports.Stepper = exports.Wizard = exports.Text = exports.KbdKeys = exports.Kbd = exports.Code = exports.Blockquote = exports.Title = exports.Subheading = exports.Small = exports.Leading = exports.Headline = void 0;
9
9
  /*---------------------------------------------------------------------------------------------
10
10
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
11
11
  * See LICENSE.md in the project root for license terms and full copyright notice.
@@ -181,3 +181,4 @@ Object.defineProperty(exports, "getUserColor", { enumerable: true, get: function
181
181
  Object.defineProperty(exports, "useTheme", { enumerable: true, get: function () { return utils_1.useTheme; } });
182
182
  Object.defineProperty(exports, "ColorValue", { enumerable: true, get: function () { return utils_1.ColorValue; } });
183
183
  Object.defineProperty(exports, "MiddleTextTruncation", { enumerable: true, get: function () { return utils_1.MiddleTextTruncation; } });
184
+ Object.defineProperty(exports, "Icon", { enumerable: true, get: function () { return utils_1.Icon; } });
@@ -0,0 +1,43 @@
1
+ import React from 'react';
2
+ import type { AnyString } from '../types';
3
+ import '@itwin/itwinui-css/css/utils.css';
4
+ export declare type IconProps = {
5
+ /**
6
+ * Size of the svg.
7
+ * - 'medium': works well with most text
8
+ * - 'small': smaller than medium
9
+ * - 'large': larger than medium
10
+ * - 'auto': scales with text
11
+ *
12
+ * Also accepts a custom string value that will be used unchanged.
13
+ *
14
+ * @default 'medium'
15
+ */
16
+ size?: 'auto' | 'small' | 'medium' | 'large' | AnyString;
17
+ /**
18
+ * Fill (color) of the svg.
19
+ * Defaults to `--iui-color-icon-muted`. Can be specified to
20
+ * use one of the status colors.
21
+ *
22
+ * Also accepts a custom string value that will be used unchanged.
23
+ *
24
+ * @default 'default'
25
+ */
26
+ fill?: 'default' | 'positive' | 'informational' | 'negative' | 'warning' | AnyString;
27
+ } & React.ComponentProps<'span'>;
28
+ /**
29
+ * A utility component to provide size and fill to svgs.
30
+ * Works well with svgs from `@itwin/itwinui-icons-react`.
31
+ *
32
+ * @example
33
+ * <Icon>
34
+ * <SvgPlaceholder />
35
+ * </Icon>
36
+ *
37
+ * @example
38
+ * <Icon fill='negative'>
39
+ * <SvgStatusError />
40
+ * </Icon>
41
+ */
42
+ export declare const Icon: React.ForwardRefExoticComponent<Pick<IconProps, "key" | "fill" | "size" | keyof React.HTMLAttributes<HTMLSpanElement>> & React.RefAttributes<HTMLSpanElement>>;
43
+ export default Icon;
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.Icon = void 0;
7
+ /*---------------------------------------------------------------------------------------------
8
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
9
+ * See LICENSE.md in the project root for license terms and full copyright notice.
10
+ *--------------------------------------------------------------------------------------------*/
11
+ const react_1 = __importDefault(require("react"));
12
+ const classnames_1 = __importDefault(require("classnames"));
13
+ require("@itwin/itwinui-css/css/utils.css");
14
+ const getSizeValue = (size) => {
15
+ switch (size) {
16
+ case 'small':
17
+ return 's';
18
+ case 'medium':
19
+ return 'm';
20
+ case 'large':
21
+ return 'l';
22
+ default:
23
+ return size;
24
+ }
25
+ };
26
+ /**
27
+ * A utility component to provide size and fill to svgs.
28
+ * Works well with svgs from `@itwin/itwinui-icons-react`.
29
+ *
30
+ * @example
31
+ * <Icon>
32
+ * <SvgPlaceholder />
33
+ * </Icon>
34
+ *
35
+ * @example
36
+ * <Icon fill='negative'>
37
+ * <SvgStatusError />
38
+ * </Icon>
39
+ */
40
+ exports.Icon = react_1.default.forwardRef((props, ref) => {
41
+ const { size = 'medium', fill = 'default', className, ...rest } = props;
42
+ return (react_1.default.createElement("span", { className: (0, classnames_1.default)('iui-svg-icon', className), "data-iui-icon-size": getSizeValue(size), "data-iui-icon-color": fill, ref: ref, ...rest }));
43
+ });
44
+ exports.default = exports.Icon;
@@ -6,3 +6,4 @@ export * from './WithCSSTransition';
6
6
  export * from './MiddleTextTruncation';
7
7
  export * from './VirtualScroll';
8
8
  export * from './VisuallyHidden';
9
+ export * from './Icon';
@@ -26,3 +26,4 @@ __exportStar(require("./WithCSSTransition"), exports);
26
26
  __exportStar(require("./MiddleTextTruncation"), exports);
27
27
  __exportStar(require("./VirtualScroll"), exports);
28
28
  __exportStar(require("./VisuallyHidden"), exports);
29
+ __exportStar(require("./Icon"), exports);
@@ -24,19 +24,15 @@ const dom_1 = require("../functions/dom");
24
24
  */
25
25
  const useIntersection = (onIntersect, options = {}, once = true) => {
26
26
  const { root, rootMargin, threshold } = options;
27
- const observer = react_1.default.useRef();
27
+ const cleanupRef = react_1.default.useRef(() => { });
28
28
  const setRef = react_1.default.useCallback((node) => {
29
- var _a;
30
- if (!((_a = (0, dom_1.getWindow)()) === null || _a === void 0 ? void 0 : _a.IntersectionObserver)) {
29
+ var _a, _b;
30
+ (_a = cleanupRef.current) === null || _a === void 0 ? void 0 : _a.call(cleanupRef);
31
+ cleanupRef.current = () => { }; // ensure it doesn't try to clean up again
32
+ if (!node || !((_b = (0, dom_1.getWindow)()) === null || _b === void 0 ? void 0 : _b.IntersectionObserver)) {
31
33
  return;
32
34
  }
33
- if (observer.current) {
34
- observer.current.disconnect();
35
- }
36
- if (!node) {
37
- return;
38
- }
39
- observer.current = new IntersectionObserver(([entry], obs) => {
35
+ const observer = new IntersectionObserver(([entry], obs) => {
40
36
  if (entry.isIntersecting) {
41
37
  if (once) {
42
38
  obs.disconnect();
@@ -44,9 +40,9 @@ const useIntersection = (onIntersect, options = {}, once = true) => {
44
40
  onIntersect();
45
41
  }
46
42
  }, { root, rootMargin, threshold });
47
- observer.current.observe(node);
43
+ observer.observe(node);
44
+ cleanupRef.current = () => observer.disconnect();
48
45
  }, [onIntersect, once, root, rootMargin, threshold]);
49
- react_1.default.useEffect(() => () => { var _a; return (_a = observer.current) === null || _a === void 0 ? void 0 : _a.disconnect(); }, []);
50
46
  return setRef;
51
47
  };
52
48
  exports.useIntersection = useIntersection;
@@ -4,3 +4,4 @@ export * from './components';
4
4
  export * from './props';
5
5
  export * from './color';
6
6
  export * from './icons';
7
+ export * from './types';
@@ -24,3 +24,4 @@ __exportStar(require("./components"), exports);
24
24
  __exportStar(require("./props"), exports);
25
25
  __exportStar(require("./color"), exports);
26
26
  __exportStar(require("./icons"), exports);
27
+ __exportStar(require("./types"), exports);
@@ -0,0 +1,5 @@
1
+ /**
2
+ * This allows custom strings and keeps intellisense for string unions.
3
+ * See https://github.com/Microsoft/TypeScript/issues/29729
4
+ */
5
+ export declare type AnyString = string & {};
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -28,7 +28,7 @@ export declare type AvatarProps = {
28
28
  */
29
29
  abbreviation?: string;
30
30
  /**
31
- * User image to be displayed. MUST be an <img> element!
31
+ * User image to be displayed. MUST be an `<img>` element!
32
32
  */
33
33
  image?: JSX.Element;
34
34
  /**
@@ -1,5 +1,6 @@
1
1
  /// <reference types="react" />
2
2
  import { CommonProps, SoftBackgrounds } from '../utils';
3
+ import type { AnyString } from '../utils';
3
4
  import '@itwin/itwinui-css/css/badge.css';
4
5
  export declare type BadgeProps = {
5
6
  /**
@@ -9,7 +10,7 @@ export declare type BadgeProps = {
9
10
  *
10
11
  * If not specified, a default neutral background will be used.
11
12
  */
12
- backgroundColor?: 'primary' | 'positive' | 'negative' | 'warning' | keyof typeof SoftBackgrounds | (string & {});
13
+ backgroundColor?: 'primary' | 'positive' | 'negative' | 'warning' | keyof typeof SoftBackgrounds | AnyString;
13
14
  /**
14
15
  * Badge label.
15
16
  * Always gets converted to uppercase, and truncated if too long.
@@ -4,7 +4,7 @@
4
4
  *--------------------------------------------------------------------------------------------*/
5
5
  import cx from 'classnames';
6
6
  import React from 'react';
7
- import { useTheme, StatusIconMap, WithCSSTransition, SvgChevronRight, } from '../utils';
7
+ import { useTheme, StatusIconMap, WithCSSTransition, SvgChevronRight, Icon, } from '../utils';
8
8
  import '@itwin/itwinui-css/css/expandable-block.css';
9
9
  /**
10
10
  * Container that allows content to be hidden behind a brief title and a caption.
@@ -45,11 +45,7 @@ export const ExpandableBlock = (props) => {
45
45
  React.createElement("span", { className: 'iui-expandable-block-label' },
46
46
  React.createElement("div", { className: 'iui-title' }, title),
47
47
  caption && React.createElement("div", { className: 'iui-caption' }, caption)),
48
- icon &&
49
- React.cloneElement(icon, {
50
- className: cx('iui-status-icon', icon.props.className),
51
- 'data-iui-icon-color': status,
52
- })),
48
+ icon && React.createElement(Icon, { fill: status }, icon)),
53
49
  React.createElement(WithCSSTransition, { in: expanded },
54
50
  React.createElement("div", { className: 'iui-expandable-content' },
55
51
  React.createElement("div", null, children)))));
@@ -17,6 +17,23 @@ declare type TabsOrientationProps = {
17
17
  orientation: 'vertical';
18
18
  type?: 'default' | 'borderless';
19
19
  };
20
+ declare type TabsTypeProps = {
21
+ /**
22
+ * Type of the tabs.
23
+ *
24
+ * If `orientation = 'vertical'`, `pill` is not applicable.
25
+ * @default 'default'
26
+ */
27
+ type?: 'default' | 'borderless';
28
+ /**
29
+ * Content displayed to the right/bottom of the horizontal/vertical tabs
30
+ *
31
+ * If `type = 'pill'`, `actions` is not applicable.
32
+ */
33
+ actions?: React.ReactNode[];
34
+ } | {
35
+ type: 'pill';
36
+ };
20
37
  export declare type TabsProps = {
21
38
  /**
22
39
  * Elements shown for each tab.
@@ -58,7 +75,7 @@ export declare type TabsProps = {
58
75
  * Content inside the tab panel.
59
76
  */
60
77
  children?: React.ReactNode;
61
- } & TabsOrientationProps;
78
+ } & TabsOrientationProps & TabsTypeProps;
62
79
  /**
63
80
  * @deprecated Since v2, use `TabProps` with `Tabs`
64
81
  */
@@ -35,6 +35,13 @@ import { Tab } from './Tab';
35
35
  * <Tabs labels={tabsWithIcons} type='pill' />
36
36
  */
37
37
  export const Tabs = (props) => {
38
+ // Separate actions from props to avoid adding it to the DOM (using {...rest})
39
+ let actions;
40
+ if (props.type !== 'pill' && props.actions) {
41
+ actions = props.actions;
42
+ props = { ...props };
43
+ delete props.actions;
44
+ }
38
45
  const { labels, activeIndex, onTabSelected, focusActivationMode = 'auto', type = 'default', color = 'blue', orientation = 'horizontal', tabsClassName, contentClassName, wrapperClassName, children, ...rest } = props;
39
46
  useTheme();
40
47
  const tablistRef = React.useRef(null);
@@ -170,6 +177,8 @@ export const Tabs = (props) => {
170
177
  },
171
178
  }))));
172
179
  })),
180
+ actions && (React.createElement("div", { className: 'iui-tabs-actions-wrapper' },
181
+ React.createElement("div", { className: 'iui-tabs-actions' }, actions))),
173
182
  children && (React.createElement("div", { className: cx('iui-tabs-content', contentClassName), role: 'tabpanel' }, children))));
174
183
  };
175
184
  /**
@@ -8,6 +8,7 @@ import cx from 'classnames';
8
8
  import { getWindow, StatusIconMap, SvgCloseSmall } from '../utils';
9
9
  import '@itwin/itwinui-css/css/toast.css';
10
10
  import { IconButton } from '../Buttons';
11
+ const isMotionOk = () => { var _a, _b, _c; return (_c = (_b = (_a = getWindow()) === null || _a === void 0 ? void 0 : _a.matchMedia) === null || _b === void 0 ? void 0 : _b.call(_a, '(prefers-reduced-motion: no-preference)')) === null || _c === void 0 ? void 0 : _c.matches; };
11
12
  /**
12
13
  * Generic Toast Component
13
14
  * @example
@@ -86,18 +87,24 @@ export const Toast = (props) => {
86
87
  return { translateX, translateY };
87
88
  };
88
89
  return (React.createElement(Transition, { timeout: { enter: 240, exit: animateOutTo ? 400 : 120 }, in: visible, appear: true, unmountOnExit: true, onEnter: (node) => {
89
- node.style.transform = 'translateY(15%)';
90
- node.style.transitionTimingFunction = 'ease';
90
+ if (isMotionOk()) {
91
+ node.style.transform = 'translateY(15%)';
92
+ node.style.transitionTimingFunction = 'ease';
93
+ }
91
94
  }, onEntered: (node) => {
92
- node.style.transform = 'translateY(0)';
95
+ if (isMotionOk()) {
96
+ node.style.transform = 'translateY(0)';
97
+ }
93
98
  }, onExiting: (node) => {
94
- const { translateX, translateY } = calculateOutAnimation(node);
95
- node.style.transform = animateOutTo
96
- ? `scale(0.9) translate(${translateX}px,${translateY}px)`
97
- : `scale(0.9)`;
98
- node.style.opacity = '0';
99
- node.style.transitionDuration = animateOutTo ? '400ms' : '120ms';
100
- node.style.transitionTimingFunction = 'cubic-bezier(0.4, 0, 1, 1)';
99
+ if (isMotionOk()) {
100
+ const { translateX, translateY } = calculateOutAnimation(node);
101
+ node.style.transform = animateOutTo
102
+ ? `scale(0.9) translate(${translateX}px,${translateY}px)`
103
+ : `scale(0.9)`;
104
+ node.style.opacity = '0';
105
+ node.style.transitionDuration = animateOutTo ? '400ms' : '120ms';
106
+ node.style.transitionTimingFunction = 'cubic-bezier(0.4, 0, 1, 1)';
107
+ }
101
108
  }, onExited: onRemove }, React.createElement("div", { ref: thisElement, className: 'iui-toast-all', style: {
102
109
  height,
103
110
  ...marginStyle(),
@@ -27,22 +27,22 @@ export default class Toaster {
27
27
  * Set global Toaster settings for toasts order and placement.
28
28
  * Settings will be applied to new toasts on the page.
29
29
  */
30
- setSettings(newSettings: ToasterSettings): void;
30
+ setSettings(newSettings: ToasterSettings): Promise<void>;
31
31
  positive(content: React.ReactNode, options?: ToastOptions): {
32
- close: () => void;
32
+ close: () => Promise<void>;
33
33
  };
34
34
  informational(content: React.ReactNode, options?: ToastOptions): {
35
- close: () => void;
35
+ close: () => Promise<void>;
36
36
  };
37
37
  negative(content: React.ReactNode, options?: ToastOptions): {
38
- close: () => void;
38
+ close: () => Promise<void>;
39
39
  };
40
40
  warning(content: React.ReactNode, options?: ToastOptions): {
41
- close: () => void;
41
+ close: () => Promise<void>;
42
42
  };
43
43
  private createToast;
44
44
  private removeToast;
45
45
  private updateView;
46
46
  private closeToast;
47
- closeAll(): void;
47
+ closeAll(): Promise<void>;
48
48
  }
@@ -55,14 +55,14 @@ export default class Toaster {
55
55
  * Set global Toaster settings for toasts order and placement.
56
56
  * Settings will be applied to new toasts on the page.
57
57
  */
58
- setSettings(newSettings) {
58
+ async setSettings(newSettings) {
59
59
  var _a, _b, _c;
60
60
  (_a = newSettings.placement) !== null && _a !== void 0 ? _a : (newSettings.placement = this.settings.placement);
61
61
  (_b = newSettings.order) !== null && _b !== void 0 ? _b : (newSettings.order = ((_c = newSettings.placement) === null || _c === void 0 ? void 0 : _c.startsWith('bottom'))
62
62
  ? 'ascending'
63
63
  : 'descending');
64
64
  this.settings = newSettings;
65
- this.asyncInit().then(() => {
65
+ await this.asyncInit().then(() => {
66
66
  var _a, _b;
67
67
  (_a = this.toastsRef.current) === null || _a === void 0 ? void 0 : _a.setPlacement((_b = this.settings.placement) !== null && _b !== void 0 ? _b : 'top');
68
68
  });
@@ -98,35 +98,36 @@ export default class Toaster {
98
98
  },
99
99
  ...(this.settings.order === 'descending' ? this.toasts : []),
100
100
  ];
101
+ // cannot `await` this, for backwards compat with the return value
101
102
  this.updateView();
102
103
  return { close: () => this.closeToast(currentId) };
103
104
  }
104
- removeToast(id) {
105
+ async removeToast(id) {
105
106
  this.toasts = this.toasts.filter((toast) => toast.id !== id);
106
107
  this.updateView();
107
108
  }
108
- updateView() {
109
- this.asyncInit().then(() => {
109
+ async updateView() {
110
+ await this.asyncInit().then(() => {
110
111
  var _a;
111
112
  (_a = this.toastsRef.current) === null || _a === void 0 ? void 0 : _a.setToasts(this.toasts);
112
113
  });
113
114
  }
114
- closeToast(toastId) {
115
+ async closeToast(toastId) {
115
116
  this.toasts = this.toasts.map((toast) => {
116
117
  return {
117
118
  ...toast,
118
119
  isVisible: toast.id !== toastId,
119
120
  };
120
121
  });
121
- this.updateView();
122
+ await this.updateView();
122
123
  }
123
- closeAll() {
124
+ async closeAll() {
124
125
  this.toasts = this.toasts.map((toast) => {
125
126
  return {
126
127
  ...toast,
127
128
  isVisible: false,
128
129
  };
129
130
  });
130
- this.updateView();
131
+ await this.updateView();
131
132
  }
132
133
  }
@@ -1,4 +1,21 @@
1
1
  import React from 'react';
2
+ import { PolymorphicComponentProps, PolymorphicForwardRefComponent } from '../../utils';
2
3
  import '@itwin/itwinui-css/css/anchor.css';
3
- export declare const Anchor: React.ForwardRefExoticComponent<Pick<React.DetailedHTMLProps<React.AnchorHTMLAttributes<HTMLAnchorElement>, HTMLAnchorElement>, "key" | keyof React.AnchorHTMLAttributes<HTMLAnchorElement>> & React.RefAttributes<HTMLAnchorElement>>;
4
+ declare type AnchorOwnProps = Record<never, never>;
5
+ export declare type AnchorProps<T extends React.ElementType = 'a'> = PolymorphicComponentProps<T, AnchorOwnProps>;
6
+ /**
7
+ * A consistently styled anchor component.
8
+ *
9
+ * Supports polymorphic `as` prop for use with `Link` components from routers,
10
+ * or to render as a button.
11
+ *
12
+ * @example
13
+ * <Anchor href='/'>Home</Anchor>
14
+ * <Anchor href='/projects'>Projects</Anchor>
15
+ *
16
+ * @example
17
+ * <Anchor as={Link} to='/'>Home</Anchor>
18
+ * <Anchor as='button' onClick={() => {}}>click me</Anchor>
19
+ */
20
+ export declare const Anchor: PolymorphicForwardRefComponent<"a", AnchorOwnProps>;
4
21
  export default Anchor;
@@ -4,10 +4,25 @@
4
4
  *--------------------------------------------------------------------------------------------*/
5
5
  import React from 'react';
6
6
  import cx from 'classnames';
7
- import { useTheme } from '../../utils';
7
+ import { useTheme, } from '../../utils';
8
8
  import '@itwin/itwinui-css/css/anchor.css';
9
- export const Anchor = React.forwardRef(({ className, ...rest }, ref) => {
9
+ /**
10
+ * A consistently styled anchor component.
11
+ *
12
+ * Supports polymorphic `as` prop for use with `Link` components from routers,
13
+ * or to render as a button.
14
+ *
15
+ * @example
16
+ * <Anchor href='/'>Home</Anchor>
17
+ * <Anchor href='/projects'>Projects</Anchor>
18
+ *
19
+ * @example
20
+ * <Anchor as={Link} to='/'>Home</Anchor>
21
+ * <Anchor as='button' onClick={() => {}}>click me</Anchor>
22
+ */
23
+ export const Anchor = React.forwardRef((props, ref) => {
24
+ const { as: Element = 'a', className, ...rest } = props;
10
25
  useTheme();
11
- return React.createElement("a", { className: cx('iui-anchor', className), ref: ref, ...rest });
26
+ return (React.createElement(Element, { className: cx('iui-anchor', className), ref: ref, ...rest }));
12
27
  });
13
28
  export default Anchor;
@@ -1,3 +1,4 @@
1
1
  export { Anchor } from './Anchor';
2
+ export type { AnchorProps } from './Anchor';
2
3
  declare const _default: "./Anchor";
3
4
  export default _default;
@@ -1,4 +1,5 @@
1
1
  export { Anchor } from './Anchor';
2
+ export type { AnchorProps } from './Anchor';
2
3
  export { Headline } from './Headline';
3
4
  export type { HeadlineProps } from './Headline';
4
5
  export { Title } from './Title';
@@ -101,8 +101,8 @@ export type { TooltipProps } from './Tooltip';
101
101
  export { Tree, TreeNode, TreeNodeExpander } from './Tree';
102
102
  export type { TreeProps, TreeNodeProps, TreeNodeExpanderProps, NodeData, NodeRenderProps, } from './Tree';
103
103
  export { Anchor, Body, Headline, Leading, Small, Subheading, Title, Blockquote, Code, Kbd, KbdKeys, Text, } from './Typography';
104
- export type { BodyProps, HeadlineProps, LeadingProps, SmallProps, SubheadingProps, TitleProps, BlockquoteProps, CodeProps, KbdProps, TextProps, } from './Typography';
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, } from './utils';
108
- export type { ThemeType, MiddleTextTruncationProps } from './utils';
107
+ export { getUserColor, useTheme, ColorValue, MiddleTextTruncation, Icon, } from './utils';
108
+ export type { ThemeType, MiddleTextTruncationProps, IconProps } 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, } from './utils';
58
+ export { getUserColor, useTheme, ColorValue, MiddleTextTruncation, Icon, } from './utils';
@@ -0,0 +1,43 @@
1
+ import React from 'react';
2
+ import type { AnyString } from '../types';
3
+ import '@itwin/itwinui-css/css/utils.css';
4
+ export declare type IconProps = {
5
+ /**
6
+ * Size of the svg.
7
+ * - 'medium': works well with most text
8
+ * - 'small': smaller than medium
9
+ * - 'large': larger than medium
10
+ * - 'auto': scales with text
11
+ *
12
+ * Also accepts a custom string value that will be used unchanged.
13
+ *
14
+ * @default 'medium'
15
+ */
16
+ size?: 'auto' | 'small' | 'medium' | 'large' | AnyString;
17
+ /**
18
+ * Fill (color) of the svg.
19
+ * Defaults to `--iui-color-icon-muted`. Can be specified to
20
+ * use one of the status colors.
21
+ *
22
+ * Also accepts a custom string value that will be used unchanged.
23
+ *
24
+ * @default 'default'
25
+ */
26
+ fill?: 'default' | 'positive' | 'informational' | 'negative' | 'warning' | AnyString;
27
+ } & React.ComponentProps<'span'>;
28
+ /**
29
+ * A utility component to provide size and fill to svgs.
30
+ * Works well with svgs from `@itwin/itwinui-icons-react`.
31
+ *
32
+ * @example
33
+ * <Icon>
34
+ * <SvgPlaceholder />
35
+ * </Icon>
36
+ *
37
+ * @example
38
+ * <Icon fill='negative'>
39
+ * <SvgStatusError />
40
+ * </Icon>
41
+ */
42
+ export declare const Icon: React.ForwardRefExoticComponent<Pick<IconProps, "key" | "fill" | "size" | keyof React.HTMLAttributes<HTMLSpanElement>> & React.RefAttributes<HTMLSpanElement>>;
43
+ export default Icon;
@@ -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
+ const getSizeValue = (size) => {
9
+ switch (size) {
10
+ case 'small':
11
+ return 's';
12
+ case 'medium':
13
+ return 'm';
14
+ case 'large':
15
+ return 'l';
16
+ default:
17
+ return size;
18
+ }
19
+ };
20
+ /**
21
+ * A utility component to provide size and fill to svgs.
22
+ * Works well with svgs from `@itwin/itwinui-icons-react`.
23
+ *
24
+ * @example
25
+ * <Icon>
26
+ * <SvgPlaceholder />
27
+ * </Icon>
28
+ *
29
+ * @example
30
+ * <Icon fill='negative'>
31
+ * <SvgStatusError />
32
+ * </Icon>
33
+ */
34
+ export const Icon = React.forwardRef((props, ref) => {
35
+ const { size = 'medium', fill = 'default', className, ...rest } = props;
36
+ return (React.createElement("span", { className: cx('iui-svg-icon', className), "data-iui-icon-size": getSizeValue(size), "data-iui-icon-color": fill, ref: ref, ...rest }));
37
+ });
38
+ export default Icon;
@@ -6,3 +6,4 @@ export * from './WithCSSTransition';
6
6
  export * from './MiddleTextTruncation';
7
7
  export * from './VirtualScroll';
8
8
  export * from './VisuallyHidden';
9
+ export * from './Icon';
@@ -10,3 +10,4 @@ export * from './WithCSSTransition';
10
10
  export * from './MiddleTextTruncation';
11
11
  export * from './VirtualScroll';
12
12
  export * from './VisuallyHidden';
13
+ export * from './Icon';
@@ -18,19 +18,15 @@ import { getWindow } from '../functions/dom';
18
18
  */
19
19
  export const useIntersection = (onIntersect, options = {}, once = true) => {
20
20
  const { root, rootMargin, threshold } = options;
21
- const observer = React.useRef();
21
+ const cleanupRef = React.useRef(() => { });
22
22
  const setRef = React.useCallback((node) => {
23
- var _a;
24
- if (!((_a = getWindow()) === null || _a === void 0 ? void 0 : _a.IntersectionObserver)) {
23
+ var _a, _b;
24
+ (_a = cleanupRef.current) === null || _a === void 0 ? void 0 : _a.call(cleanupRef);
25
+ cleanupRef.current = () => { }; // ensure it doesn't try to clean up again
26
+ if (!node || !((_b = getWindow()) === null || _b === void 0 ? void 0 : _b.IntersectionObserver)) {
25
27
  return;
26
28
  }
27
- if (observer.current) {
28
- observer.current.disconnect();
29
- }
30
- if (!node) {
31
- return;
32
- }
33
- observer.current = new IntersectionObserver(([entry], obs) => {
29
+ const observer = new IntersectionObserver(([entry], obs) => {
34
30
  if (entry.isIntersecting) {
35
31
  if (once) {
36
32
  obs.disconnect();
@@ -38,8 +34,8 @@ export const useIntersection = (onIntersect, options = {}, once = true) => {
38
34
  onIntersect();
39
35
  }
40
36
  }, { root, rootMargin, threshold });
41
- observer.current.observe(node);
37
+ observer.observe(node);
38
+ cleanupRef.current = () => observer.disconnect();
42
39
  }, [onIntersect, once, root, rootMargin, threshold]);
43
- React.useEffect(() => () => { var _a; return (_a = observer.current) === null || _a === void 0 ? void 0 : _a.disconnect(); }, []);
44
40
  return setRef;
45
41
  };
@@ -4,3 +4,4 @@ export * from './components';
4
4
  export * from './props';
5
5
  export * from './color';
6
6
  export * from './icons';
7
+ export * from './types';
@@ -8,3 +8,4 @@ export * from './components';
8
8
  export * from './props';
9
9
  export * from './color';
10
10
  export * from './icons';
11
+ export * from './types';
@@ -0,0 +1,5 @@
1
+ /**
2
+ * This allows custom strings and keeps intellisense for string unions.
3
+ * See https://github.com/Microsoft/TypeScript/issues/29729
4
+ */
5
+ export declare type AnyString = string & {};
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itwin/itwinui-react",
3
- "version": "2.2.1",
3
+ "version": "2.3.1-dev.0",
4
4
  "author": "Bentley Systems",
5
5
  "license": "MIT",
6
6
  "main": "cjs/index.js",
@@ -59,11 +59,10 @@
59
59
  "dev": "yarn clean:build && concurrently \"yarn dev:esm\" \"yarn dev:cjs\" \"yarn dev:types\"",
60
60
  "dev:esm": "swc src -d esm --watch",
61
61
  "dev:cjs": "swc src -d cjs --watch -C module.type=commonjs",
62
- "dev:types": "concurrently \"tsc -p tsconfig.cjs.json --emitDeclarationOnly --watch --preserveWatchOutput\" \"tsc -p tsconfig.esm.json --emitDeclarationOnly --watch --preserveWatchOutput\"",
63
- "createComponent": "node ../../scripts/createComponent.js"
62
+ "dev:types": "concurrently \"tsc -p tsconfig.cjs.json --emitDeclarationOnly --watch --preserveWatchOutput\" \"tsc -p tsconfig.esm.json --emitDeclarationOnly --watch --preserveWatchOutput\""
64
63
  },
65
64
  "dependencies": {
66
- "@itwin/itwinui-css": "^1.2.0",
65
+ "@itwin/itwinui-css": "^1.4.0",
67
66
  "@itwin/itwinui-illustrations-react": "^2.0.0",
68
67
  "@itwin/itwinui-variables": "^1.0.0",
69
68
  "@tippyjs/react": "^4.2.6",