@carbon/react 1.53.0 → 1.54.0-rc.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/.playwright/INTERNAL_AVT_REPORT_DO_NOT_USE.json +1016 -1062
- package/es/components/AiSkeleton/AiSkeletonIcon.js +39 -0
- package/es/components/AiSkeleton/AiSkeletonPlaceholder.js +37 -0
- package/es/components/AiSkeleton/AiSkeletonText.js +51 -0
- package/es/components/ComboBox/ComboBox.js +13 -4
- package/es/components/ComboButton/index.js +1 -1
- package/es/components/ComposedModal/ComposedModal.js +19 -10
- package/es/components/DataTable/DataTable.js +1 -1
- package/es/components/DataTable/TableBatchAction.d.ts +1 -1
- package/es/components/DataTable/TableToolbarMenu.d.ts +5 -1
- package/es/components/DataTable/TableToolbarMenu.js +7 -0
- package/es/components/DatePicker/DatePicker.d.ts +4 -0
- package/es/components/DatePicker/DatePicker.js +37 -0
- package/es/components/IconButton/index.d.ts +1 -1
- package/es/components/IconButton/index.js +1 -1
- package/es/components/ListBox/ListBox.d.ts +8 -0
- package/es/components/ListBox/ListBox.js +15 -3
- package/es/components/Loading/Loading.d.ts +1 -1
- package/es/components/Modal/Modal.js +14 -5
- package/es/components/Notification/Notification.js +18 -6
- package/es/components/Pagination/Pagination.Skeleton.d.ts +25 -0
- package/es/components/Pagination/Pagination.d.ts +102 -0
- package/es/components/Pagination/Pagination.js +13 -14
- package/es/components/Pagination/index.d.ts +10 -0
- package/es/components/Popover/index.d.ts +1 -1
- package/es/components/Popover/index.js +175 -108
- package/es/components/RadioTile/RadioTile.d.ts +55 -0
- package/es/components/RadioTile/RadioTile.js +17 -17
- package/es/components/RadioTile/index.d.ts +10 -0
- package/es/components/Slug/index.js +24 -13
- package/es/components/Stack/HStack.d.ts +10 -0
- package/es/components/Stack/HStack.js +23 -0
- package/es/components/Stack/Stack.d.ts +1 -1
- package/es/components/Stack/Stack.js +2 -2
- package/es/components/Stack/VStack.d.ts +10 -0
- package/es/components/Stack/{index.js → VStack.js} +1 -8
- package/es/components/Stack/index.d.ts +3 -6
- package/es/components/TileGroup/TileGroup.js +30 -24
- package/es/components/Toggletip/index.d.ts +1 -18
- package/es/components/Toggletip/index.js +27 -4
- package/es/components/Tooltip/Tooltip.js +23 -5
- package/es/index.d.ts +2 -0
- package/es/index.js +8 -4
- package/es/internal/FloatingMenu.js +26 -5
- package/es/internal/wrapFocus.js +51 -1
- package/es/tools/createPropAdapter.js +40 -0
- package/lib/components/AiSkeleton/AiSkeletonIcon.js +49 -0
- package/lib/components/AiSkeleton/AiSkeletonPlaceholder.js +47 -0
- package/lib/components/AiSkeleton/AiSkeletonText.js +61 -0
- package/lib/components/ComboBox/ComboBox.js +13 -4
- package/lib/components/ComboButton/index.js +1 -1
- package/lib/components/ComposedModal/ComposedModal.js +17 -8
- package/lib/components/DataTable/DataTable.js +1 -1
- package/lib/components/DataTable/TableBatchAction.d.ts +1 -1
- package/lib/components/DataTable/TableToolbarMenu.d.ts +5 -1
- package/lib/components/DataTable/TableToolbarMenu.js +7 -0
- package/lib/components/DatePicker/DatePicker.d.ts +4 -0
- package/lib/components/DatePicker/DatePicker.js +37 -0
- package/lib/components/IconButton/index.d.ts +1 -1
- package/lib/components/IconButton/index.js +1 -1
- package/lib/components/ListBox/ListBox.d.ts +8 -0
- package/lib/components/ListBox/ListBox.js +15 -3
- package/lib/components/Loading/Loading.d.ts +1 -1
- package/lib/components/Modal/Modal.js +14 -5
- package/lib/components/Notification/Notification.js +15 -3
- package/lib/components/Pagination/Pagination.Skeleton.d.ts +25 -0
- package/lib/components/Pagination/Pagination.d.ts +102 -0
- package/lib/components/Pagination/Pagination.js +13 -14
- package/lib/components/Pagination/index.d.ts +10 -0
- package/lib/components/Popover/index.d.ts +1 -1
- package/lib/components/Popover/index.js +174 -107
- package/lib/components/RadioTile/RadioTile.d.ts +55 -0
- package/lib/components/RadioTile/RadioTile.js +17 -17
- package/lib/components/RadioTile/index.d.ts +10 -0
- package/lib/components/Slug/index.js +24 -13
- package/lib/components/Stack/HStack.d.ts +10 -0
- package/lib/components/Stack/HStack.js +31 -0
- package/lib/components/Stack/Stack.d.ts +1 -1
- package/lib/components/Stack/Stack.js +3 -3
- package/lib/components/Stack/VStack.d.ts +10 -0
- package/lib/components/Stack/{index.js → VStack.js} +0 -8
- package/lib/components/Stack/index.d.ts +3 -6
- package/lib/components/TileGroup/TileGroup.js +30 -24
- package/lib/components/Toggletip/index.d.ts +1 -18
- package/lib/components/Toggletip/index.js +27 -4
- package/lib/components/Tooltip/Tooltip.js +23 -5
- package/lib/index.d.ts +2 -0
- package/lib/index.js +21 -14
- package/lib/internal/FloatingMenu.js +44 -4
- package/lib/internal/wrapFocus.js +51 -0
- package/lib/tools/createPropAdapter.js +44 -0
- package/package.json +9 -7
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright IBM Corp. 2016, 2023
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the Apache-2.0 license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
import React from 'react';
|
|
8
|
+
type ExcludedAttributes = 'id' | 'onChange';
|
|
9
|
+
export interface PaginationPageSize {
|
|
10
|
+
text: string;
|
|
11
|
+
value: number;
|
|
12
|
+
}
|
|
13
|
+
export interface PaginationProps extends Omit<React.HTMLAttributes<HTMLDivElement>, ExcludedAttributes> {
|
|
14
|
+
/**
|
|
15
|
+
* The description for the backward icon.
|
|
16
|
+
*/
|
|
17
|
+
backwardText?: string;
|
|
18
|
+
/**
|
|
19
|
+
* The CSS class names.
|
|
20
|
+
*/
|
|
21
|
+
className?: string;
|
|
22
|
+
/**
|
|
23
|
+
* `true` if the backward/forward buttons, as well as the page select elements, should be disabled.
|
|
24
|
+
*/
|
|
25
|
+
disabled?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* The description for the forward icon.
|
|
28
|
+
*/
|
|
29
|
+
forwardText?: string;
|
|
30
|
+
/**
|
|
31
|
+
* The unique ID of this component instance.
|
|
32
|
+
*/
|
|
33
|
+
id?: string | number;
|
|
34
|
+
/**
|
|
35
|
+
* `true` if the current page should be the last page.
|
|
36
|
+
*/
|
|
37
|
+
isLastPage?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* The function returning a translatable text showing where the current page is,
|
|
40
|
+
* in a manner of the range of items.
|
|
41
|
+
*/
|
|
42
|
+
itemRangeText?: (min: number, max: number, total: number) => string;
|
|
43
|
+
/**
|
|
44
|
+
* A variant of `itemRangeText`, used if the total number of items is unknown.
|
|
45
|
+
*/
|
|
46
|
+
itemText?: (min: number, max: number) => string;
|
|
47
|
+
/**
|
|
48
|
+
* The translatable text indicating the number of items per page.
|
|
49
|
+
*/
|
|
50
|
+
itemsPerPageText?: string;
|
|
51
|
+
/**
|
|
52
|
+
* The callback function called when the current page changes.
|
|
53
|
+
*/
|
|
54
|
+
onChange?: (data: {
|
|
55
|
+
page: number;
|
|
56
|
+
pageSize: number;
|
|
57
|
+
ref?: React.RefObject<any>;
|
|
58
|
+
}) => void;
|
|
59
|
+
/**
|
|
60
|
+
* The current page.
|
|
61
|
+
*/
|
|
62
|
+
page?: number;
|
|
63
|
+
/**
|
|
64
|
+
* `true` if the select box to change the page should be disabled.
|
|
65
|
+
*/
|
|
66
|
+
pageInputDisabled?: boolean;
|
|
67
|
+
pageNumberText?: string;
|
|
68
|
+
/**
|
|
69
|
+
* A function returning PII showing where the current page is.
|
|
70
|
+
*/
|
|
71
|
+
pageRangeText?: (current: number, total: number) => string;
|
|
72
|
+
/**
|
|
73
|
+
* The number dictating how many items a page contains.
|
|
74
|
+
*/
|
|
75
|
+
pageSize?: number;
|
|
76
|
+
/**
|
|
77
|
+
* `true` if the select box to change the items per page should be disabled.
|
|
78
|
+
*/
|
|
79
|
+
pageSizeInputDisabled?: boolean;
|
|
80
|
+
/**
|
|
81
|
+
* The choices for `pageSize`.
|
|
82
|
+
*/
|
|
83
|
+
pageSizes: number[] | PaginationPageSize[];
|
|
84
|
+
/**
|
|
85
|
+
* The translatable text showing the current page.
|
|
86
|
+
*/
|
|
87
|
+
pageText?: (page: number, pagesUnknown?: boolean) => string;
|
|
88
|
+
/**
|
|
89
|
+
* `true` if the total number of items is unknown.
|
|
90
|
+
*/
|
|
91
|
+
pagesUnknown?: boolean;
|
|
92
|
+
/**
|
|
93
|
+
* Specify the size of the Pagination.
|
|
94
|
+
*/
|
|
95
|
+
size?: 'sm' | 'md' | 'lg';
|
|
96
|
+
/**
|
|
97
|
+
* The total number of items.
|
|
98
|
+
*/
|
|
99
|
+
totalItems?: number;
|
|
100
|
+
}
|
|
101
|
+
declare const Pagination: React.ForwardRefExoticComponent<PaginationProps & React.RefAttributes<HTMLDivElement>>;
|
|
102
|
+
export default Pagination;
|
|
@@ -27,7 +27,7 @@ function mapPageSizesToObject(sizes) {
|
|
|
27
27
|
}
|
|
28
28
|
function renderSelectItems(total) {
|
|
29
29
|
let counter = 1;
|
|
30
|
-
|
|
30
|
+
const itemArr = [];
|
|
31
31
|
while (counter <= total) {
|
|
32
32
|
itemArr.push( /*#__PURE__*/React__default.createElement(SelectItem, {
|
|
33
33
|
key: counter,
|
|
@@ -52,7 +52,7 @@ function getPageSize(pageSizes, pageSize) {
|
|
|
52
52
|
const Pagination = /*#__PURE__*/React__default.forwardRef(function Pagination(_ref, ref) {
|
|
53
53
|
let {
|
|
54
54
|
backwardText = 'Previous page',
|
|
55
|
-
className: customClassName,
|
|
55
|
+
className: customClassName = '',
|
|
56
56
|
disabled = false,
|
|
57
57
|
forwardText = 'Next page',
|
|
58
58
|
id,
|
|
@@ -71,11 +71,11 @@ const Pagination = /*#__PURE__*/React__default.forwardRef(function Pagination(_r
|
|
|
71
71
|
pageText = (page, pagesUnknown) => `page ${pagesUnknown ? '' : page}`,
|
|
72
72
|
pagesUnknown = false,
|
|
73
73
|
size = 'md',
|
|
74
|
-
totalItems,
|
|
74
|
+
totalItems = 1,
|
|
75
75
|
...rest
|
|
76
76
|
} = _ref;
|
|
77
77
|
const prefix = usePrefix();
|
|
78
|
-
const inputId = useFallbackId(id);
|
|
78
|
+
const inputId = useFallbackId(id?.toString());
|
|
79
79
|
const backBtnRef = useRef(null);
|
|
80
80
|
const forwardBtnRef = useRef(null);
|
|
81
81
|
const [pageSizes, setPageSizes] = useState(() => {
|
|
@@ -163,14 +163,14 @@ const Pagination = /*#__PURE__*/React__default.forwardRef(function Pagination(_r
|
|
|
163
163
|
// the icon button becomes disabled and the focus shifts to `main`
|
|
164
164
|
// this presents an a11y problem for keyboard & screen reader users
|
|
165
165
|
// instead, we want the focus to shift to the other pagination btn
|
|
166
|
-
if (nextPage === totalPages) {
|
|
166
|
+
if (nextPage === totalPages && backBtnRef?.current) {
|
|
167
167
|
backBtnRef.current.focus();
|
|
168
168
|
}
|
|
169
169
|
if (onChange) {
|
|
170
170
|
onChange({
|
|
171
171
|
page: nextPage,
|
|
172
172
|
pageSize,
|
|
173
|
-
backBtnRef
|
|
173
|
+
ref: backBtnRef
|
|
174
174
|
});
|
|
175
175
|
}
|
|
176
176
|
}
|
|
@@ -182,14 +182,14 @@ const Pagination = /*#__PURE__*/React__default.forwardRef(function Pagination(_r
|
|
|
182
182
|
// the icon button becomes disabled and the focus shifts to `main`
|
|
183
183
|
// this presents an a11y problem for keyboard & screen reader users
|
|
184
184
|
// instead, we want the focus to shift to the other pagination btn
|
|
185
|
-
if (nextPage === 1) {
|
|
185
|
+
if (nextPage === 1 && forwardBtnRef?.current) {
|
|
186
186
|
forwardBtnRef.current.focus();
|
|
187
187
|
}
|
|
188
188
|
if (onChange) {
|
|
189
189
|
onChange({
|
|
190
190
|
page: nextPage,
|
|
191
191
|
pageSize,
|
|
192
|
-
forwardBtnRef
|
|
192
|
+
ref: forwardBtnRef
|
|
193
193
|
});
|
|
194
194
|
}
|
|
195
195
|
}
|
|
@@ -320,10 +320,10 @@ Pagination.propTypes = {
|
|
|
320
320
|
/**
|
|
321
321
|
* The choices for `pageSize`.
|
|
322
322
|
*/
|
|
323
|
-
pageSizes: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.number), PropTypes.arrayOf(PropTypes.shape({
|
|
324
|
-
text: PropTypes.
|
|
325
|
-
value: PropTypes.number
|
|
326
|
-
}))]).isRequired,
|
|
323
|
+
pageSizes: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.number.isRequired), PropTypes.arrayOf(PropTypes.shape({
|
|
324
|
+
text: PropTypes.string.isRequired,
|
|
325
|
+
value: PropTypes.number.isRequired
|
|
326
|
+
}).isRequired)]).isRequired,
|
|
327
327
|
/**
|
|
328
328
|
* The translatable text showing the current page.
|
|
329
329
|
*/
|
|
@@ -341,6 +341,5 @@ Pagination.propTypes = {
|
|
|
341
341
|
*/
|
|
342
342
|
totalItems: PropTypes.number
|
|
343
343
|
};
|
|
344
|
-
var Pagination$1 = Pagination;
|
|
345
344
|
|
|
346
|
-
export { Pagination
|
|
345
|
+
export { Pagination as default };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright IBM Corp. 2016, 2023
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the Apache-2.0 license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
import Pagination from './Pagination';
|
|
8
|
+
export * from './Pagination.Skeleton';
|
|
9
|
+
export default Pagination;
|
|
10
|
+
export { Pagination };
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import React, { type ForwardedRef, type WeakValidationMap, type ElementType } from 'react';
|
|
8
8
|
import { type PolymorphicProps } from '../../types/common';
|
|
9
|
-
export type PopoverAlignment = 'top' | 'top-left' | 'top-right' | 'bottom' | 'bottom-left' | 'bottom-right' | 'left' | 'left-bottom' | 'left-top' | 'right' | 'right-bottom' | 'right-top';
|
|
9
|
+
export type PopoverAlignment = 'top' | 'top-left' | 'top-right' | 'bottom' | 'bottom-left' | 'bottom-right' | 'left' | 'left-bottom' | 'left-top' | 'right' | 'right-bottom' | 'right-top' | 'top-start' | 'top-end' | 'bottom-start' | 'bottom-end' | 'left-end' | 'left-start' | 'right-end' | 'right-start';
|
|
10
10
|
interface PopoverBaseProps {
|
|
11
11
|
/**
|
|
12
12
|
* Specify how the popover should align with the trigger element
|
|
@@ -8,21 +8,27 @@
|
|
|
8
8
|
import { extends as _extends } from '../../_virtual/_rollupPluginBabelHelpers.js';
|
|
9
9
|
import cx from 'classnames';
|
|
10
10
|
import PropTypes from 'prop-types';
|
|
11
|
-
import React__default, { useRef, useMemo,
|
|
11
|
+
import React__default, { useRef, useMemo, useEffect } from 'react';
|
|
12
12
|
import useIsomorphicEffect from '../../internal/useIsomorphicEffect.js';
|
|
13
13
|
import { useMergedRefs } from '../../internal/useMergedRefs.js';
|
|
14
14
|
import { usePrefix } from '../../internal/usePrefix.js';
|
|
15
15
|
import { useWindowEvent } from '../../internal/useEvent.js';
|
|
16
|
+
import { mapPopoverAlignProp } from '../../tools/createPropAdapter.js';
|
|
17
|
+
import { useFloating, offset, flip, arrow, autoUpdate } from '@floating-ui/react';
|
|
16
18
|
|
|
17
19
|
const PopoverContext = /*#__PURE__*/React__default.createContext({
|
|
18
|
-
|
|
20
|
+
setFloating: {
|
|
19
21
|
current: null
|
|
20
|
-
}
|
|
22
|
+
},
|
|
23
|
+
caretRef: {
|
|
24
|
+
current: null
|
|
25
|
+
},
|
|
26
|
+
autoAlign: null
|
|
21
27
|
});
|
|
22
28
|
const Popover = /*#__PURE__*/React__default.forwardRef(function PopoverRenderFunction(_ref, forwardRef) {
|
|
23
29
|
let {
|
|
24
30
|
isTabTip,
|
|
25
|
-
align = isTabTip ? 'bottom-
|
|
31
|
+
align: initialAlign = isTabTip ? 'bottom-start' : 'bottom',
|
|
26
32
|
as: BaseComponent = 'span',
|
|
27
33
|
autoAlign = false,
|
|
28
34
|
caret = isTabTip ? false : true,
|
|
@@ -36,7 +42,9 @@ const Popover = /*#__PURE__*/React__default.forwardRef(function PopoverRenderFun
|
|
|
36
42
|
} = _ref;
|
|
37
43
|
const prefix = usePrefix();
|
|
38
44
|
const floating = useRef(null);
|
|
45
|
+
const caretRef = useRef(null);
|
|
39
46
|
const popover = useRef(null);
|
|
47
|
+
let align = mapPopoverAlignProp(initialAlign);
|
|
40
48
|
|
|
41
49
|
// If the `Popover` is the last focusable item in the tab order, it should also close when the browser window loses focus (#12922)
|
|
42
50
|
useWindowEvent('blur', () => {
|
|
@@ -49,124 +57,150 @@ const Popover = /*#__PURE__*/React__default.forwardRef(function PopoverRenderFun
|
|
|
49
57
|
onRequestClose?.();
|
|
50
58
|
}
|
|
51
59
|
});
|
|
60
|
+
|
|
61
|
+
// Slug styling places a border around the popover content so the caret
|
|
62
|
+
// needs to be placed 1px further outside the popover content. To do so,
|
|
63
|
+
// we look to see if any of the children has a className containing "slug"
|
|
64
|
+
const initialCaretHeight = React__default.Children.toArray(children).some(x => {
|
|
65
|
+
return x?.props?.className?.includes('slug');
|
|
66
|
+
}) ? 7 : 6;
|
|
67
|
+
// These defaults match the defaults defined in packages/styles/scss/components/popover/_popover.scss
|
|
68
|
+
const popoverDimensions = useRef({
|
|
69
|
+
offset: 10,
|
|
70
|
+
caretHeight: initialCaretHeight
|
|
71
|
+
});
|
|
72
|
+
useIsomorphicEffect(() => {
|
|
73
|
+
// The popover is only offset when a caret is present. Technically, the custom properties
|
|
74
|
+
// accessed below can be set by a user even if caret=false, but doing so does not follow
|
|
75
|
+
// the design specification for Popover.
|
|
76
|
+
if (caret && popover.current) {
|
|
77
|
+
// Gather the dimensions of the caret and prefer the values set via custom properties.
|
|
78
|
+
// If a value is not set via a custom property, provide a default value that matches the
|
|
79
|
+
// default values defined in the sass style file
|
|
80
|
+
const getStyle = window.getComputedStyle(popover.current, null);
|
|
81
|
+
const offsetProperty = getStyle.getPropertyValue('--cds-popover-offset');
|
|
82
|
+
const caretProperty = getStyle.getPropertyValue('--cds-popover-caret-height');
|
|
83
|
+
|
|
84
|
+
// Handle if the property values are in px or rem.
|
|
85
|
+
// We want to store just the base number value without a unit suffix
|
|
86
|
+
if (offsetProperty) {
|
|
87
|
+
popoverDimensions.current.offset = offsetProperty.includes('px') ? Number(offsetProperty.split('px', 1)[0]) * 1 : Number(offsetProperty.split('rem', 1)[0]) * 16;
|
|
88
|
+
}
|
|
89
|
+
if (caretProperty) {
|
|
90
|
+
popoverDimensions.current.caretHeight = caretProperty.includes('px') ? Number(caretProperty.split('px', 1)[0]) * 1 : Number(caretProperty.split('rem', 1)[0]) * 16;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
const {
|
|
95
|
+
refs,
|
|
96
|
+
floatingStyles,
|
|
97
|
+
placement,
|
|
98
|
+
middlewareData
|
|
99
|
+
} = useFloating(autoAlign ? {
|
|
100
|
+
placement: align,
|
|
101
|
+
// The floating element is positioned relative to its nearest
|
|
102
|
+
// containing block (usually the viewport). It will in many cases also
|
|
103
|
+
// “break” the floating element out of a clipping ancestor.
|
|
104
|
+
// https://floating-ui.com/docs/misc#clipping
|
|
105
|
+
strategy: 'fixed',
|
|
106
|
+
// Middleware order matters, arrow should be last
|
|
107
|
+
middleware: [offset(!isTabTip ? popoverDimensions?.current?.offset : 0), flip({
|
|
108
|
+
fallbackAxisSideDirection: 'start'
|
|
109
|
+
}), arrow({
|
|
110
|
+
element: caretRef
|
|
111
|
+
})],
|
|
112
|
+
whileElementsMounted: autoUpdate
|
|
113
|
+
} : {} // When autoAlign is turned off, floating-ui will not be used
|
|
114
|
+
);
|
|
115
|
+
|
|
52
116
|
const value = useMemo(() => {
|
|
53
117
|
return {
|
|
54
|
-
floating
|
|
118
|
+
floating,
|
|
119
|
+
setFloating: refs.setFloating,
|
|
120
|
+
caretRef,
|
|
121
|
+
autoAlign: autoAlign
|
|
55
122
|
};
|
|
56
|
-
}, []);
|
|
123
|
+
}, [refs.setFloating, autoAlign]);
|
|
57
124
|
if (isTabTip) {
|
|
58
|
-
const tabTipAlignments = ['bottom-
|
|
125
|
+
const tabTipAlignments = ['bottom-start', 'bottom-end'];
|
|
59
126
|
if (!tabTipAlignments.includes(align)) {
|
|
60
|
-
align = 'bottom-
|
|
127
|
+
align = 'bottom-start';
|
|
61
128
|
}
|
|
62
129
|
}
|
|
130
|
+
useEffect(() => {
|
|
131
|
+
if (autoAlign) {
|
|
132
|
+
Object.keys(floatingStyles).forEach(style => {
|
|
133
|
+
if (refs.floating.current) {
|
|
134
|
+
refs.floating.current.style[style] = floatingStyles[style];
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
if (caret && middlewareData && middlewareData.arrow && caretRef?.current) {
|
|
138
|
+
const {
|
|
139
|
+
x,
|
|
140
|
+
y
|
|
141
|
+
} = middlewareData.arrow;
|
|
142
|
+
const staticSide = {
|
|
143
|
+
top: 'bottom',
|
|
144
|
+
right: 'left',
|
|
145
|
+
bottom: 'top',
|
|
146
|
+
left: 'right'
|
|
147
|
+
}[placement.split('-')[0]];
|
|
148
|
+
caretRef.current.style.left = x != null ? `${x}px` : '';
|
|
149
|
+
caretRef.current.style.top = y != null ? `${y}px` : '';
|
|
150
|
+
|
|
151
|
+
// Ensure the static side gets unset when flipping to other placements' axes.
|
|
152
|
+
caretRef.current.style.right = '';
|
|
153
|
+
caretRef.current.style.bottom = '';
|
|
154
|
+
if (staticSide) {
|
|
155
|
+
caretRef.current.style[staticSide] = `${-popoverDimensions?.current?.caretHeight}px`;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}, [floatingStyles, refs.floating, autoAlign, middlewareData, placement, caret]);
|
|
63
160
|
const ref = useMergedRefs([forwardRef, popover]);
|
|
64
|
-
const
|
|
65
|
-
const [autoAlignment, setAutoAlignment] = useState(align);
|
|
161
|
+
const currentAlignment = autoAlign && placement !== align ? placement : align;
|
|
66
162
|
const className = cx({
|
|
67
163
|
[`${prefix}--popover-container`]: true,
|
|
68
164
|
[`${prefix}--popover--caret`]: caret,
|
|
69
165
|
[`${prefix}--popover--drop-shadow`]: dropShadow,
|
|
70
166
|
[`${prefix}--popover--high-contrast`]: highContrast,
|
|
71
167
|
[`${prefix}--popover--open`]: open,
|
|
72
|
-
[`${prefix}--popover
|
|
73
|
-
[`${prefix}--popover--${
|
|
168
|
+
[`${prefix}--popover--auto-align`]: autoAlign,
|
|
169
|
+
[`${prefix}--popover--${currentAlignment}`]: true,
|
|
74
170
|
[`${prefix}--popover--tab-tip`]: isTabTip
|
|
75
171
|
}, customClassName);
|
|
76
|
-
useIsomorphicEffect(() => {
|
|
77
|
-
if (!open) {
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
if (!autoAlign || isTabTip) {
|
|
81
|
-
setAutoAligned(false);
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
if (!floating.current) {
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
if (autoAligned === true) {
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
const rect = floating.current.getBoundingClientRect();
|
|
91
|
-
|
|
92
|
-
// The conditions, per side, of when the popover is not visible, excluding the popover's internal padding(16)
|
|
93
|
-
const conditions = {
|
|
94
|
-
left: rect.x < -16,
|
|
95
|
-
top: rect.y < -16,
|
|
96
|
-
right: rect.x + (rect.width - 16) > document.documentElement.clientWidth,
|
|
97
|
-
bottom: rect.y + (rect.height - 16) > document.documentElement.clientHeight
|
|
98
|
-
};
|
|
99
|
-
if (!conditions.left && !conditions.top && !conditions.right && !conditions.bottom) {
|
|
100
|
-
setAutoAligned(false);
|
|
101
|
-
return;
|
|
102
|
-
}
|
|
103
|
-
const alignments = ['top', 'top-left', 'right-bottom', 'right', 'right-top', 'bottom-left', 'bottom', 'bottom-right', 'left-top', 'left', 'left-bottom', 'top-right'];
|
|
104
|
-
|
|
105
|
-
// Creates the prioritized list of options depending on ideal alignment coming from `align`
|
|
106
|
-
const options = [align];
|
|
107
|
-
let option = alignments[(alignments.indexOf(align) + 1) % alignments.length];
|
|
108
|
-
while (option) {
|
|
109
|
-
if (options.includes(option)) {
|
|
110
|
-
break;
|
|
111
|
-
}
|
|
112
|
-
options.push(option);
|
|
113
|
-
option = alignments[(alignments.indexOf(option) + 1) % alignments.length];
|
|
114
|
-
}
|
|
115
|
-
function isVisible(alignment) {
|
|
116
|
-
if (!popover.current || !floating.current) {
|
|
117
|
-
return false;
|
|
118
|
-
}
|
|
119
|
-
popover.current.classList.add(`${prefix}--popover--${alignment}`);
|
|
120
|
-
const rect = floating.current.getBoundingClientRect();
|
|
121
|
-
|
|
122
|
-
// Check if popover is not visible to the left of the screen
|
|
123
|
-
if (rect.x < -16) {
|
|
124
|
-
popover.current.classList.remove(`${prefix}--popover--${alignment}`);
|
|
125
|
-
return false;
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// Check if popover is not visible at the top of the screen
|
|
129
|
-
if (rect.y < -16) {
|
|
130
|
-
popover.current.classList.remove(`${prefix}--popover--${alignment}`);
|
|
131
|
-
return false;
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// Check if popover is not visible to right of screen
|
|
135
|
-
if (rect.x + (rect.width - 16) > document.documentElement.clientWidth) {
|
|
136
|
-
popover.current.classList.remove(`${prefix}--popover--${alignment}`);
|
|
137
|
-
return false;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// Check if popover is not visible to bottom of screen
|
|
141
|
-
if (rect.y + (rect.height - 16) > document.documentElement.clientHeight) {
|
|
142
|
-
popover.current.classList.remove(`${prefix}--popover--${alignment}`);
|
|
143
|
-
return false;
|
|
144
|
-
}
|
|
145
|
-
popover.current.classList.remove(`${prefix}--popover--${alignment}`);
|
|
146
|
-
return true;
|
|
147
|
-
}
|
|
148
|
-
let alignment = null;
|
|
149
|
-
for (let i = 0; i < options.length; i++) {
|
|
150
|
-
const option = options[i];
|
|
151
|
-
if (isVisible(option)) {
|
|
152
|
-
alignment = option;
|
|
153
|
-
break;
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
if (alignment) {
|
|
157
|
-
setAutoAligned(true);
|
|
158
|
-
setAutoAlignment(alignment);
|
|
159
|
-
}
|
|
160
|
-
}, [autoAligned, align, autoAlign, prefix, open, isTabTip]);
|
|
161
172
|
const mappedChildren = React__default.Children.map(children, child => {
|
|
162
173
|
const item = child;
|
|
163
|
-
if (item?.type === 'button') {
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
} = item.props;
|
|
174
|
+
if ((item?.type === 'button' || autoAlign && item?.type?.displayName !== 'PopoverContent' || autoAlign && item?.type?.displayName === 'ToggletipButton') && /*#__PURE__*/React__default.isValidElement(item)) {
|
|
175
|
+
const className = item?.props?.className;
|
|
176
|
+
const ref = (item?.props).ref;
|
|
167
177
|
const tabTipClasses = cx(`${prefix}--popover--tab-tip__button`, className);
|
|
168
178
|
return /*#__PURE__*/React__default.cloneElement(item, {
|
|
169
|
-
className: tabTipClasses
|
|
179
|
+
className: isTabTip && item?.type === 'button' ? tabTipClasses : className || '',
|
|
180
|
+
// With cloneElement, if you pass a `ref`, it overrides the original ref.
|
|
181
|
+
// https://react.dev/reference/react/cloneElement#parameters
|
|
182
|
+
// The block below works around this and ensures that the original ref is still
|
|
183
|
+
// called while allowing the floating-ui reference element to be set as well.
|
|
184
|
+
// `useMergedRefs` can't be used here because hooks can't be called from within a callback.
|
|
185
|
+
// More here: https://github.com/facebook/react/issues/8873#issuecomment-489579878
|
|
186
|
+
ref: node => {
|
|
187
|
+
// For a popover, there isn't an explicit trigger component, it's just the first child that's
|
|
188
|
+
// passed in which should *not* be PopoverContent.
|
|
189
|
+
// For a toggletip there is a specific trigger component, ToggletipButton.
|
|
190
|
+
// In either of these caes we want to set this as the reference node for floating-ui autoAlign
|
|
191
|
+
// positioning.
|
|
192
|
+
if (autoAlign && item?.type?.displayName !== 'PopoverContent' || autoAlign && item?.type?.displayName === 'ToggletipButton') {
|
|
193
|
+
// Set the reference element for floating-ui
|
|
194
|
+
refs.setReference(node);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Call the original ref, if any
|
|
198
|
+
if (typeof ref === 'function') {
|
|
199
|
+
ref(node);
|
|
200
|
+
} else if (ref !== null && ref !== undefined) {
|
|
201
|
+
ref.current = node;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
170
204
|
});
|
|
171
205
|
} else {
|
|
172
206
|
return item;
|
|
@@ -178,7 +212,7 @@ const Popover = /*#__PURE__*/React__default.forwardRef(function PopoverRenderFun
|
|
|
178
212
|
}, /*#__PURE__*/React__default.createElement(BaseComponentAsAny, _extends({}, rest, {
|
|
179
213
|
className: className,
|
|
180
214
|
ref: ref
|
|
181
|
-
}), isTabTip ? mappedChildren : children));
|
|
215
|
+
}), autoAlign || isTabTip ? mappedChildren : children));
|
|
182
216
|
});
|
|
183
217
|
|
|
184
218
|
// Note: this displayName is temporarily set so that Storybook ArgTable
|
|
@@ -190,7 +224,28 @@ Popover.propTypes = {
|
|
|
190
224
|
/**
|
|
191
225
|
* Specify how the popover should align with the trigger element
|
|
192
226
|
*/
|
|
193
|
-
align: PropTypes.oneOf(['top', 'top-left',
|
|
227
|
+
align: PropTypes.oneOf(['top', 'top-left',
|
|
228
|
+
// deprecated use top-start instead
|
|
229
|
+
'top-right',
|
|
230
|
+
// deprecated use top-end instead
|
|
231
|
+
|
|
232
|
+
'bottom', 'bottom-left',
|
|
233
|
+
// deprecated use bottom-start instead
|
|
234
|
+
'bottom-right',
|
|
235
|
+
// deprecated use bottom-end instead
|
|
236
|
+
|
|
237
|
+
'left', 'left-bottom',
|
|
238
|
+
// deprecated use left-end instead
|
|
239
|
+
'left-top',
|
|
240
|
+
// deprecated use left-start instead
|
|
241
|
+
|
|
242
|
+
'right', 'right-bottom',
|
|
243
|
+
// deprecated use right-end instead
|
|
244
|
+
'right-top',
|
|
245
|
+
// deprecated use right-start instead
|
|
246
|
+
|
|
247
|
+
// new values to match floating-ui
|
|
248
|
+
'top-start', 'top-end', 'bottom-start', 'bottom-end', 'left-end', 'left-start', 'right-end', 'right-start']),
|
|
194
249
|
/**
|
|
195
250
|
* Provide a custom element or component to render the top-level node for the
|
|
196
251
|
* component.
|
|
@@ -244,19 +299,31 @@ _ref2, forwardRef) {
|
|
|
244
299
|
} = _ref2;
|
|
245
300
|
const prefix = usePrefix();
|
|
246
301
|
const {
|
|
247
|
-
|
|
302
|
+
setFloating,
|
|
303
|
+
caretRef,
|
|
304
|
+
autoAlign
|
|
248
305
|
} = React__default.useContext(PopoverContext);
|
|
249
|
-
const ref = useMergedRefs([
|
|
306
|
+
const ref = useMergedRefs([setFloating, forwardRef]);
|
|
250
307
|
return /*#__PURE__*/React__default.createElement("span", _extends({}, rest, {
|
|
251
308
|
className: `${prefix}--popover`
|
|
252
309
|
}), /*#__PURE__*/React__default.createElement("span", {
|
|
253
310
|
className: cx(`${prefix}--popover-content`, className),
|
|
254
311
|
ref: ref
|
|
255
|
-
}, children
|
|
256
|
-
className:
|
|
312
|
+
}, children, autoAlign && /*#__PURE__*/React__default.createElement("span", {
|
|
313
|
+
className: cx({
|
|
314
|
+
[`${prefix}--popover-caret`]: true,
|
|
315
|
+
[`${prefix}--popover--auto-align`]: true
|
|
316
|
+
}),
|
|
317
|
+
ref: caretRef
|
|
318
|
+
})), !autoAlign && /*#__PURE__*/React__default.createElement("span", {
|
|
319
|
+
className: cx({
|
|
320
|
+
[`${prefix}--popover-caret`]: true
|
|
321
|
+
}),
|
|
322
|
+
ref: caretRef
|
|
257
323
|
}));
|
|
258
324
|
}
|
|
259
325
|
const PopoverContent = /*#__PURE__*/React__default.forwardRef(PopoverContentRenderFunction);
|
|
326
|
+
PopoverContent.displayName = 'PopoverContent';
|
|
260
327
|
PopoverContent.propTypes = {
|
|
261
328
|
/**
|
|
262
329
|
* Provide elements to be rendered inside of the component
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright IBM Corp. 2016, 2023
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the Apache-2.0 license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
import React from 'react';
|
|
8
|
+
export interface RadioTileProps {
|
|
9
|
+
/**
|
|
10
|
+
* Specify whether the `RadioTile` should be checked.
|
|
11
|
+
*/
|
|
12
|
+
checked?: boolean;
|
|
13
|
+
/**
|
|
14
|
+
* The `RadioTile` content.
|
|
15
|
+
*/
|
|
16
|
+
children?: React.ReactNode;
|
|
17
|
+
/**
|
|
18
|
+
* Provide an optional `className` to be applied to the underlying `<label>`.
|
|
19
|
+
*/
|
|
20
|
+
className?: string;
|
|
21
|
+
/**
|
|
22
|
+
* Specify whether the `RadioTile` should be disabled.
|
|
23
|
+
*/
|
|
24
|
+
disabled?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Provide a unique id for the underlying `<input>`.
|
|
27
|
+
*/
|
|
28
|
+
id?: string;
|
|
29
|
+
/**
|
|
30
|
+
* `true` to use the light version. For use on `$layer-01` backgrounds only.
|
|
31
|
+
* Don't use this to make tile background color the same as the container background color.
|
|
32
|
+
*
|
|
33
|
+
* @deprecated This prop is no longer needed and has been deprecated in v11 in favor of the new Layer component. It will be removed in the next major release.
|
|
34
|
+
*/
|
|
35
|
+
light?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Provide a `name` for the underlying `<input>`.
|
|
38
|
+
*/
|
|
39
|
+
name?: string;
|
|
40
|
+
/**
|
|
41
|
+
* Provide an optional `onChange` hook that is called each time the value of
|
|
42
|
+
* the underlying `<input>` changes.
|
|
43
|
+
*/
|
|
44
|
+
onChange?: (value: string | number, name: string | undefined, event: React.ChangeEvent<HTMLInputElement> | React.KeyboardEvent<HTMLInputElement>) => void;
|
|
45
|
+
/**
|
|
46
|
+
* Specify the tab index of the underlying `<input>`.
|
|
47
|
+
*/
|
|
48
|
+
tabIndex?: number;
|
|
49
|
+
/**
|
|
50
|
+
* Specify the value of the underlying `<input>`.
|
|
51
|
+
*/
|
|
52
|
+
value: string | number;
|
|
53
|
+
}
|
|
54
|
+
declare const RadioTile: React.ForwardRefExoticComponent<RadioTileProps & React.RefAttributes<HTMLInputElement>>;
|
|
55
|
+
export default RadioTile;
|