@carbon-labs/react-ui-shell 0.4.0 → 0.6.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/es/components/HeaderPanel.d.ts +35 -0
- package/es/components/HeaderPanel.js +104 -0
- package/es/components/SideNav.d.ts +29 -16
- package/es/components/SideNav.js +30 -6
- package/es/components/SideNavToggle.d.ts +28 -0
- package/es/components/SideNavToggle.js +52 -0
- package/es/index.d.ts +1 -0
- package/es/index.js +1 -0
- package/es/node_modules/@carbon/icon-helpers/es/index.js +125 -0
- package/es/node_modules/@carbon/icons-react/es/Icon.js +71 -0
- package/es/node_modules/@carbon/icons-react/es/generated/bucket-15.js +3076 -0
- package/es/node_modules/@carbon/icons-react/es/iconPropTypes-4cbeb95d.js +14 -0
- package/lib/components/HeaderPanel.d.ts +35 -0
- package/lib/components/HeaderPanel.js +106 -0
- package/lib/components/SideNav.d.ts +29 -16
- package/lib/components/SideNav.js +50 -5
- package/lib/components/SideNavToggle.d.ts +28 -0
- package/lib/components/SideNavToggle.js +57 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +2 -0
- package/lib/node_modules/@carbon/icon-helpers/es/index.js +128 -0
- package/lib/node_modules/@carbon/icons-react/es/Icon.js +75 -0
- package/lib/node_modules/@carbon/icons-react/es/generated/bucket-15.js +3202 -0
- package/lib/node_modules/@carbon/icons-react/es/iconPropTypes-4cbeb95d.js +16 -0
- package/package.json +2 -2
- package/scss/styles/_side-nav.scss +51 -2
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright IBM Corp. 2025
|
|
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, { ReactNode } from 'react';
|
|
8
|
+
export interface HeaderPanelProps {
|
|
9
|
+
/**
|
|
10
|
+
* Specify whether focus and blur listeners are added. They are by default.
|
|
11
|
+
*/
|
|
12
|
+
addFocusListeners?: boolean;
|
|
13
|
+
/**
|
|
14
|
+
* The content that will render inside of the `HeaderPanel`
|
|
15
|
+
*/
|
|
16
|
+
children?: ReactNode;
|
|
17
|
+
/**
|
|
18
|
+
* Optionally provide a custom class to apply to the underlying `<li>` node
|
|
19
|
+
*/
|
|
20
|
+
className?: string;
|
|
21
|
+
/**
|
|
22
|
+
* Specify whether the panel is expanded
|
|
23
|
+
*/
|
|
24
|
+
expanded?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Provide the `href` to the id of the element on your package that could
|
|
27
|
+
* be target.
|
|
28
|
+
*/
|
|
29
|
+
href?: string;
|
|
30
|
+
/**
|
|
31
|
+
* An optional listener that is called a callback to collapse the HeaderPanel
|
|
32
|
+
*/
|
|
33
|
+
onHeaderPanelFocus?: () => void;
|
|
34
|
+
}
|
|
35
|
+
export declare const HeaderPanel: React.FC<HeaderPanelProps>;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright IBM Corp. 2024
|
|
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
|
+
|
|
8
|
+
import { extends as _extends } from '../_virtual/_rollupPluginBabelHelpers.js';
|
|
9
|
+
import cx from '../_virtual/index.js';
|
|
10
|
+
import PropTypes from 'prop-types';
|
|
11
|
+
import React, { useRef, useState } from 'react';
|
|
12
|
+
import { usePrefix } from '@carbon/react/lib/internal/usePrefix';
|
|
13
|
+
import { keys } from '@carbon/react/lib/internal/keyboard/keys';
|
|
14
|
+
import { match } from '@carbon/react/lib/internal/keyboard/match';
|
|
15
|
+
import { useWindowEvent } from '@carbon/react/lib/internal/useEvent';
|
|
16
|
+
import { useMergedRefs } from '@carbon/react/lib/internal/useMergedRefs';
|
|
17
|
+
|
|
18
|
+
const noopFn = () => {};
|
|
19
|
+
const HeaderPanel = /*#__PURE__*/React.forwardRef(function HeaderPanel(_ref, ref) {
|
|
20
|
+
let {
|
|
21
|
+
children,
|
|
22
|
+
className: customClassName,
|
|
23
|
+
expanded,
|
|
24
|
+
addFocusListeners = true,
|
|
25
|
+
onHeaderPanelFocus = noopFn,
|
|
26
|
+
href,
|
|
27
|
+
...rest
|
|
28
|
+
} = _ref;
|
|
29
|
+
const prefix = usePrefix();
|
|
30
|
+
const headerPanelReference = useRef(null);
|
|
31
|
+
const headerPanelRef = useMergedRefs([headerPanelReference, ref]);
|
|
32
|
+
const controlled = useRef(expanded !== undefined).current;
|
|
33
|
+
const [expandedState, setExpandedState] = useState(expanded);
|
|
34
|
+
const expandedProp = controlled ? expanded : expandedState;
|
|
35
|
+
const [lastClickedElement, setLastClickedElement] = useState(null);
|
|
36
|
+
const className = cx(`${prefix}--header-panel`, {
|
|
37
|
+
[`${prefix}--header-panel--expanded`]: expandedProp,
|
|
38
|
+
[customClassName]: !!customClassName
|
|
39
|
+
});
|
|
40
|
+
const eventHandlers = {};
|
|
41
|
+
if (addFocusListeners) {
|
|
42
|
+
eventHandlers.onBlur = event => {
|
|
43
|
+
if (!event.currentTarget.contains(event.relatedTarget) && !lastClickedElement?.classList?.contains(`${prefix}--switcher__item-link`)) {
|
|
44
|
+
setExpandedState(false);
|
|
45
|
+
setLastClickedElement(null);
|
|
46
|
+
if (expanded) {
|
|
47
|
+
onHeaderPanelFocus();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
eventHandlers.onKeyDown = event => {
|
|
52
|
+
if (match(event, keys.Escape)) {
|
|
53
|
+
setExpandedState(false);
|
|
54
|
+
onHeaderPanelFocus();
|
|
55
|
+
if (href) {
|
|
56
|
+
window.location.href = href;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
useWindowEvent('click', () => {
|
|
62
|
+
const focusedElement = document.activeElement;
|
|
63
|
+
setLastClickedElement(focusedElement);
|
|
64
|
+
const childJsxElement = children;
|
|
65
|
+
if (childJsxElement?.type?.displayName === 'Switcher' && !focusedElement?.closest(`.${prefix}--header-panel--expanded`) && !focusedElement?.closest(`.${prefix}--header__action`) && !headerPanelReference?.current?.classList.contains(`${prefix}--switcher`) && expanded) {
|
|
66
|
+
setExpandedState(false);
|
|
67
|
+
onHeaderPanelFocus();
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
return /*#__PURE__*/React.createElement("div", _extends({}, rest, {
|
|
71
|
+
className: className,
|
|
72
|
+
ref: headerPanelRef
|
|
73
|
+
}, eventHandlers), children);
|
|
74
|
+
});
|
|
75
|
+
HeaderPanel.propTypes = {
|
|
76
|
+
/**
|
|
77
|
+
* Specify whether focus and blur listeners are added. They are by default.
|
|
78
|
+
*/
|
|
79
|
+
addFocusListeners: PropTypes.bool,
|
|
80
|
+
/**
|
|
81
|
+
* The content that will render inside of the `HeaderPanel`
|
|
82
|
+
*/
|
|
83
|
+
children: PropTypes.any,
|
|
84
|
+
/**
|
|
85
|
+
* Optionally provide a custom class to apply to the underlying `<li>` node
|
|
86
|
+
*/
|
|
87
|
+
className: PropTypes.string,
|
|
88
|
+
/**
|
|
89
|
+
* Specify whether the panel is expanded
|
|
90
|
+
*/
|
|
91
|
+
expanded: PropTypes.bool,
|
|
92
|
+
/**
|
|
93
|
+
* Provide the `href` to the id of the element on your package that could
|
|
94
|
+
* be target.
|
|
95
|
+
*/
|
|
96
|
+
href: PropTypes.string,
|
|
97
|
+
/**
|
|
98
|
+
* An optional listener that is called a callback to collapse the HeaderPanel
|
|
99
|
+
*/
|
|
100
|
+
onHeaderPanelFocus: PropTypes.func
|
|
101
|
+
};
|
|
102
|
+
HeaderPanel.displayName = 'HeaderPanel';
|
|
103
|
+
|
|
104
|
+
export { HeaderPanel };
|
|
@@ -5,26 +5,39 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
import React, { type ComponentProps, type FocusEvent, type KeyboardEvent, type MouseEventHandler } from 'react';
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
8
|
+
import { TranslateWithId } from '@carbon/react/lib/types/common';
|
|
9
|
+
export declare enum SIDE_NAV_TYPE {
|
|
10
|
+
DEFAULT = "default",
|
|
11
|
+
RAIL = "rail",
|
|
12
|
+
PANEL = "panel"
|
|
13
|
+
}
|
|
14
|
+
export type TranslationKey = keyof typeof translationIds;
|
|
15
|
+
export declare const translationIds: {
|
|
16
|
+
readonly 'collapse.sidenav': "collapse.sidenav";
|
|
17
|
+
readonly 'expand.sidenav': "expand.sidenav";
|
|
18
|
+
};
|
|
19
|
+
export interface SideNavProps extends ComponentProps<'nav'>, TranslateWithId<TranslationKey> {
|
|
20
|
+
expanded?: boolean;
|
|
21
|
+
defaultExpanded?: boolean;
|
|
22
|
+
isChildOfHeader?: boolean;
|
|
23
|
+
onToggle?: (event: FocusEvent<HTMLElement> | KeyboardEvent<HTMLElement> | boolean, value: boolean) => void;
|
|
24
|
+
href?: string;
|
|
25
|
+
isFixedNav?: boolean;
|
|
26
|
+
isRail?: boolean;
|
|
27
|
+
isPersistent?: boolean;
|
|
28
|
+
addFocusListeners?: boolean;
|
|
29
|
+
addMouseListeners?: boolean;
|
|
30
|
+
onOverlayClick?: MouseEventHandler<HTMLDivElement>;
|
|
31
|
+
onSideNavBlur?: () => void;
|
|
21
32
|
enterDelayMs?: number;
|
|
22
33
|
inert?: boolean;
|
|
23
|
-
isCollapsible: boolean
|
|
24
|
-
hideOverlay: boolean
|
|
34
|
+
isCollapsible: boolean;
|
|
35
|
+
hideOverlay: boolean;
|
|
36
|
+
navType: SIDE_NAV_TYPE;
|
|
25
37
|
}
|
|
26
38
|
interface SideNavContextData {
|
|
27
|
-
isRail?: boolean
|
|
39
|
+
isRail?: boolean;
|
|
40
|
+
navType?: SIDE_NAV_TYPE;
|
|
28
41
|
}
|
|
29
42
|
export declare const SideNavContext: React.Context<SideNavContextData>;
|
|
30
43
|
export declare const SideNav: React.ForwardRefExoticComponent<Omit<SideNavProps, "ref"> & React.RefAttributes<HTMLElement>>;
|
package/es/components/SideNav.js
CHANGED
|
@@ -12,17 +12,31 @@ import PropTypes from 'prop-types';
|
|
|
12
12
|
import { AriaLabelPropType } from '@carbon/react/lib/prop-types/AriaPropTypes';
|
|
13
13
|
import { CARBON_SIDENAV_ITEMS } from './_utils.js';
|
|
14
14
|
import { usePrefix } from '@carbon/react/lib/internal/usePrefix';
|
|
15
|
-
import
|
|
15
|
+
import * as keys from '@carbon/react/lib/internal/keyboard/keys';
|
|
16
16
|
import { match } from '@carbon/react/lib/internal/keyboard/match';
|
|
17
17
|
import { useMergedRefs } from '@carbon/react/lib/internal/useMergedRefs';
|
|
18
18
|
import { useWindowEvent } from '@carbon/react/lib/internal/useEvent';
|
|
19
19
|
import { useDelayedState } from '@carbon/react/lib/internal/useDelayedState';
|
|
20
20
|
import { breakpoints } from '../node_modules/@carbon/layout/es/index.js';
|
|
21
21
|
import { useMatchMedia } from '@carbon/react/lib/internal/useMatchMedia';
|
|
22
|
+
import { SideNavToggle } from './SideNavToggle.js';
|
|
23
|
+
import { SidePanelClose, SidePanelOpen } from '../node_modules/@carbon/icons-react/es/generated/bucket-15.js';
|
|
22
24
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
25
|
+
let SIDE_NAV_TYPE = /*#__PURE__*/function (SIDE_NAV_TYPE) {
|
|
26
|
+
SIDE_NAV_TYPE["DEFAULT"] = "default";
|
|
27
|
+
SIDE_NAV_TYPE["RAIL"] = "rail";
|
|
28
|
+
SIDE_NAV_TYPE["PANEL"] = "panel";
|
|
29
|
+
return SIDE_NAV_TYPE;
|
|
30
|
+
}({});
|
|
31
|
+
const translationIds = {
|
|
32
|
+
'collapse.sidenav': 'collapse.sidenav',
|
|
33
|
+
'expand.sidenav': 'expand.sidenav'
|
|
34
|
+
};
|
|
35
|
+
const defaultTranslations = {
|
|
36
|
+
[translationIds['collapse.sidenav']]: 'Collapse',
|
|
37
|
+
[translationIds['expand.sidenav']]: 'Expand'
|
|
38
|
+
};
|
|
39
|
+
const defaultTranslateWithId = id => defaultTranslations[id];
|
|
26
40
|
const SideNavContext = /*#__PURE__*/createContext({});
|
|
27
41
|
function SideNavRenderFunction(_ref, ref) {
|
|
28
42
|
let {
|
|
@@ -38,6 +52,7 @@ function SideNavRenderFunction(_ref, ref) {
|
|
|
38
52
|
isFixedNav = false,
|
|
39
53
|
isRail,
|
|
40
54
|
isPersistent = true,
|
|
55
|
+
navType = SIDE_NAV_TYPE.DEFAULT,
|
|
41
56
|
addFocusListeners = true,
|
|
42
57
|
addMouseListeners = true,
|
|
43
58
|
onOverlayClick,
|
|
@@ -45,6 +60,7 @@ function SideNavRenderFunction(_ref, ref) {
|
|
|
45
60
|
enterDelayMs = 100,
|
|
46
61
|
isCollapsible = false,
|
|
47
62
|
hideOverlay = false,
|
|
63
|
+
translateWithId: t = defaultTranslateWithId,
|
|
48
64
|
...other
|
|
49
65
|
} = _ref;
|
|
50
66
|
const prefix = usePrefix();
|
|
@@ -56,6 +72,7 @@ function SideNavRenderFunction(_ref, ref) {
|
|
|
56
72
|
const expanded = controlled ? expandedProp : expandedState;
|
|
57
73
|
const sideNavRef = useRef(null);
|
|
58
74
|
const navRef = useMergedRefs([sideNavRef, ref]);
|
|
75
|
+
const sideNavToggleText = expandedState ? t('collapse.sidenav') : t('expand.sidenav');
|
|
59
76
|
const handleToggle = function (event) {
|
|
60
77
|
let value = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : !expanded;
|
|
61
78
|
if (!controlled) {
|
|
@@ -77,6 +94,7 @@ function SideNavRenderFunction(_ref, ref) {
|
|
|
77
94
|
[`${prefix}--side-nav--expanded`]: expanded || expandedViaHoverState,
|
|
78
95
|
[`${prefix}--side-nav--collapsed`]: !expanded && isFixedNav,
|
|
79
96
|
[`${prefix}--side-nav--rail`]: isRail,
|
|
97
|
+
[`${prefix}--side-nav--panel`]: navType === SIDE_NAV_TYPE.PANEL,
|
|
80
98
|
[`${prefix}--side-nav--ux`]: isChildOfHeader,
|
|
81
99
|
[`${prefix}--side-nav--hidden`]: !isPersistent,
|
|
82
100
|
[`${prefix}--side-nav--collapsible`]: isCollapsible
|
|
@@ -110,6 +128,9 @@ function SideNavRenderFunction(_ref, ref) {
|
|
|
110
128
|
}
|
|
111
129
|
};
|
|
112
130
|
eventHandlers.onBlur = event => {
|
|
131
|
+
if (navType === SIDE_NAV_TYPE.PANEL) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
113
134
|
if (!event.currentTarget.contains(event.relatedTarget)) {
|
|
114
135
|
handleToggle(event, false);
|
|
115
136
|
}
|
|
@@ -167,7 +188,10 @@ function SideNavRenderFunction(_ref, ref) {
|
|
|
167
188
|
ref: navRef,
|
|
168
189
|
className: `${prefix}--side-nav__navigation ${className}`,
|
|
169
190
|
inert: !isRail ? expanded || isLg ? undefined : -1 : undefined
|
|
170
|
-
}, accessibilityLabel, eventHandlers, other), childrenToRender
|
|
191
|
+
}, accessibilityLabel, eventHandlers, other), childrenToRender, navType === SIDE_NAV_TYPE.PANEL && /*#__PURE__*/React.createElement(SideNavToggle, {
|
|
192
|
+
renderIcon: expandedState ? SidePanelClose : SidePanelOpen,
|
|
193
|
+
onClick: () => setExpandedState(!expandedState)
|
|
194
|
+
}, sideNavToggleText)));
|
|
171
195
|
}
|
|
172
196
|
const SideNav = /*#__PURE__*/React.forwardRef(SideNavRenderFunction);
|
|
173
197
|
SideNav.displayName = 'SideNav';
|
|
@@ -259,4 +283,4 @@ SideNav.propTypes = {
|
|
|
259
283
|
// translateById: PropTypes.func,
|
|
260
284
|
};
|
|
261
285
|
|
|
262
|
-
export { SideNav, SideNavContext };
|
|
286
|
+
export { SIDE_NAV_TYPE, SideNav, SideNavContext, translationIds };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright IBM Corp. 2025
|
|
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, { ReactNode } from 'react';
|
|
8
|
+
interface SideNavToggleProps {
|
|
9
|
+
/**
|
|
10
|
+
* Specify the text content for the link
|
|
11
|
+
*/
|
|
12
|
+
children: ReactNode;
|
|
13
|
+
/**
|
|
14
|
+
* Provide an optional function to be called when the item is clicked.
|
|
15
|
+
*/
|
|
16
|
+
onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;
|
|
17
|
+
/**
|
|
18
|
+
* A custom icon to render next to the SideNavToggle title. This can be a function returning JSX or JSX itself.
|
|
19
|
+
*/
|
|
20
|
+
renderIcon?: React.ComponentType;
|
|
21
|
+
/**
|
|
22
|
+
* The tabIndex for the button element.
|
|
23
|
+
* If not specified, the default validation will be applied.
|
|
24
|
+
*/
|
|
25
|
+
tabIndex?: number;
|
|
26
|
+
}
|
|
27
|
+
export declare const SideNavToggle: React.ForwardRefExoticComponent<SideNavToggleProps & React.RefAttributes<HTMLElement>>;
|
|
28
|
+
export default SideNavToggle;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright IBM Corp. 2024
|
|
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
|
+
|
|
8
|
+
import { extends as _extends } from '../_virtual/_rollupPluginBabelHelpers.js';
|
|
9
|
+
import PropTypes from 'prop-types';
|
|
10
|
+
import React from 'react';
|
|
11
|
+
import { SideNavIcon } from '@carbon/react';
|
|
12
|
+
import { usePrefix } from '@carbon/react/lib/internal/usePrefix';
|
|
13
|
+
|
|
14
|
+
const SideNavToggle = /*#__PURE__*/React.forwardRef(function SideNavToggle(_ref, ref) {
|
|
15
|
+
let {
|
|
16
|
+
renderIcon: IconElement,
|
|
17
|
+
tabIndex,
|
|
18
|
+
children,
|
|
19
|
+
...rest
|
|
20
|
+
} = _ref;
|
|
21
|
+
const prefix = usePrefix();
|
|
22
|
+
return /*#__PURE__*/React.createElement("button", _extends({
|
|
23
|
+
className: `${prefix}--side-nav__toggle`,
|
|
24
|
+
ref: ref,
|
|
25
|
+
type: "button",
|
|
26
|
+
tabIndex: tabIndex ?? 0
|
|
27
|
+
}, rest), IconElement && /*#__PURE__*/React.createElement(SideNavIcon, null, /*#__PURE__*/React.createElement(IconElement, null)), /*#__PURE__*/React.createElement("span", {
|
|
28
|
+
className: `${prefix}--side-nav__toggle-text`
|
|
29
|
+
}, children));
|
|
30
|
+
});
|
|
31
|
+
SideNavToggle.displayName = 'SideNavToggle';
|
|
32
|
+
SideNavToggle.propTypes = {
|
|
33
|
+
/**
|
|
34
|
+
* Specify the text content for the toggle
|
|
35
|
+
*/
|
|
36
|
+
children: PropTypes.element,
|
|
37
|
+
/**
|
|
38
|
+
* Provide an optional function to be called when clicked
|
|
39
|
+
*/
|
|
40
|
+
onClick: PropTypes.func,
|
|
41
|
+
/**
|
|
42
|
+
* Pass in a custom icon to render next to the `SideNavToggle` title
|
|
43
|
+
*/
|
|
44
|
+
// @ts-expect-error - PropTypes are unable to cover this case.
|
|
45
|
+
renderIcon: PropTypes.oneOfType([PropTypes.func, PropTypes.object]),
|
|
46
|
+
/**
|
|
47
|
+
* Optional prop to specify the tabIndex of the button. If undefined, it will be applied default validation
|
|
48
|
+
*/
|
|
49
|
+
tabIndex: PropTypes.number
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export { SideNavToggle, SideNavToggle as default };
|
package/es/index.d.ts
CHANGED
package/es/index.js
CHANGED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright IBM Corp. 2024
|
|
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
|
+
|
|
8
|
+
function _defineProperty(e, r, t) {
|
|
9
|
+
return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
|
|
10
|
+
value: t,
|
|
11
|
+
enumerable: !0,
|
|
12
|
+
configurable: !0,
|
|
13
|
+
writable: !0
|
|
14
|
+
}) : e[r] = t, e;
|
|
15
|
+
}
|
|
16
|
+
function ownKeys(e, r) {
|
|
17
|
+
var t = Object.keys(e);
|
|
18
|
+
if (Object.getOwnPropertySymbols) {
|
|
19
|
+
var o = Object.getOwnPropertySymbols(e);
|
|
20
|
+
r && (o = o.filter(function (r) {
|
|
21
|
+
return Object.getOwnPropertyDescriptor(e, r).enumerable;
|
|
22
|
+
})), t.push.apply(t, o);
|
|
23
|
+
}
|
|
24
|
+
return t;
|
|
25
|
+
}
|
|
26
|
+
function _objectSpread2(e) {
|
|
27
|
+
for (var r = 1; r < arguments.length; r++) {
|
|
28
|
+
var t = null != arguments[r] ? arguments[r] : {};
|
|
29
|
+
r % 2 ? ownKeys(Object(t), !0).forEach(function (r) {
|
|
30
|
+
_defineProperty(e, r, t[r]);
|
|
31
|
+
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) {
|
|
32
|
+
Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r));
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
return e;
|
|
36
|
+
}
|
|
37
|
+
function _objectWithoutProperties(e, t) {
|
|
38
|
+
if (null == e) return {};
|
|
39
|
+
var o,
|
|
40
|
+
r,
|
|
41
|
+
i = _objectWithoutPropertiesLoose(e, t);
|
|
42
|
+
if (Object.getOwnPropertySymbols) {
|
|
43
|
+
var s = Object.getOwnPropertySymbols(e);
|
|
44
|
+
for (r = 0; r < s.length; r++) o = s[r], t.includes(o) || {}.propertyIsEnumerable.call(e, o) && (i[o] = e[o]);
|
|
45
|
+
}
|
|
46
|
+
return i;
|
|
47
|
+
}
|
|
48
|
+
function _objectWithoutPropertiesLoose(r, e) {
|
|
49
|
+
if (null == r) return {};
|
|
50
|
+
var t = {};
|
|
51
|
+
for (var n in r) if ({}.hasOwnProperty.call(r, n)) {
|
|
52
|
+
if (e.includes(n)) continue;
|
|
53
|
+
t[n] = r[n];
|
|
54
|
+
}
|
|
55
|
+
return t;
|
|
56
|
+
}
|
|
57
|
+
function _toPrimitive(t, r) {
|
|
58
|
+
if ("object" != typeof t || !t) return t;
|
|
59
|
+
var e = t[Symbol.toPrimitive];
|
|
60
|
+
if (void 0 !== e) {
|
|
61
|
+
var i = e.call(t, r || "default");
|
|
62
|
+
if ("object" != typeof i) return i;
|
|
63
|
+
throw new TypeError("@@toPrimitive must return a primitive value.");
|
|
64
|
+
}
|
|
65
|
+
return ("string" === r ? String : Number)(t);
|
|
66
|
+
}
|
|
67
|
+
function _toPropertyKey(t) {
|
|
68
|
+
var i = _toPrimitive(t, "string");
|
|
69
|
+
return "symbol" == typeof i ? i : i + "";
|
|
70
|
+
}
|
|
71
|
+
var _excluded = ["width", "height", "viewBox"],
|
|
72
|
+
_excluded2 = ["tabindex"];
|
|
73
|
+
/**
|
|
74
|
+
* Copyright IBM Corp. 2018, 2024
|
|
75
|
+
*
|
|
76
|
+
* This source code is licensed under the Apache-2.0 license found in the
|
|
77
|
+
* LICENSE file in the root directory of this source tree.
|
|
78
|
+
*/
|
|
79
|
+
|
|
80
|
+
var defaultAttributes = {
|
|
81
|
+
// Reference:
|
|
82
|
+
// https://github.com/IBM/carbon-components-react/issues/1392
|
|
83
|
+
// https://github.com/PolymerElements/iron-iconset-svg/pull/47
|
|
84
|
+
// `focusable` is a string attribute which is why we do not use a boolean here
|
|
85
|
+
focusable: 'false',
|
|
86
|
+
preserveAspectRatio: 'xMidYMid meet'
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Get supplementary HTML attributes for a given <svg> element based on existing
|
|
91
|
+
* attributes.
|
|
92
|
+
*/
|
|
93
|
+
function getAttributes() {
|
|
94
|
+
var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
|
|
95
|
+
width = _ref.width,
|
|
96
|
+
height = _ref.height,
|
|
97
|
+
_ref$viewBox = _ref.viewBox,
|
|
98
|
+
viewBox = _ref$viewBox === void 0 ? "0 0 ".concat(width, " ").concat(height) : _ref$viewBox,
|
|
99
|
+
attributes = _objectWithoutProperties(_ref, _excluded);
|
|
100
|
+
var tabindex = attributes.tabindex,
|
|
101
|
+
rest = _objectWithoutProperties(attributes, _excluded2);
|
|
102
|
+
var iconAttributes = _objectSpread2(_objectSpread2(_objectSpread2({}, defaultAttributes), rest), {}, {
|
|
103
|
+
width: width,
|
|
104
|
+
height: height,
|
|
105
|
+
viewBox: viewBox
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
// TODO: attributes.title assumes that the consumer will implement <title> and
|
|
109
|
+
// correctly set `aria-labelledby`.
|
|
110
|
+
if (iconAttributes['aria-label'] || iconAttributes['aria-labelledby'] || iconAttributes.title) {
|
|
111
|
+
iconAttributes.role = 'img';
|
|
112
|
+
|
|
113
|
+
// Reference:
|
|
114
|
+
// https://allyjs.io/tutorials/focusing-in-svg.html
|
|
115
|
+
if (tabindex !== undefined && tabindex !== null) {
|
|
116
|
+
iconAttributes.focusable = 'true';
|
|
117
|
+
iconAttributes.tabindex = tabindex;
|
|
118
|
+
}
|
|
119
|
+
} else {
|
|
120
|
+
iconAttributes['aria-hidden'] = true;
|
|
121
|
+
}
|
|
122
|
+
return iconAttributes;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export { defaultAttributes, getAttributes };
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright IBM Corp. 2024
|
|
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
|
+
|
|
8
|
+
import { getAttributes } from '../../icon-helpers/es/index.js';
|
|
9
|
+
import PropTypes from 'prop-types';
|
|
10
|
+
import React from 'react';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Copyright IBM Corp. 2019, 2023
|
|
14
|
+
*
|
|
15
|
+
* This source code is licensed under the Apache-2.0 license found in the
|
|
16
|
+
* LICENSE file in the root directory of this source tree.
|
|
17
|
+
*/
|
|
18
|
+
const Icon = /*#__PURE__*/React.forwardRef(function Icon(_ref, ref) {
|
|
19
|
+
let {
|
|
20
|
+
className,
|
|
21
|
+
children,
|
|
22
|
+
tabIndex,
|
|
23
|
+
xmlns = 'http://www.w3.org/2000/svg',
|
|
24
|
+
preserveAspectRatio = 'xMidYMid meet',
|
|
25
|
+
...rest
|
|
26
|
+
} = _ref;
|
|
27
|
+
const {
|
|
28
|
+
tabindex,
|
|
29
|
+
...attrs
|
|
30
|
+
} = getAttributes({
|
|
31
|
+
...rest,
|
|
32
|
+
tabindex: tabIndex
|
|
33
|
+
});
|
|
34
|
+
const props = attrs;
|
|
35
|
+
if (className) {
|
|
36
|
+
props.className = className;
|
|
37
|
+
}
|
|
38
|
+
if (tabindex !== undefined && tabindex !== null) {
|
|
39
|
+
if (typeof tabindex === 'number') {
|
|
40
|
+
props.tabIndex = tabindex;
|
|
41
|
+
} else {
|
|
42
|
+
props.tabIndex = Number(tabIndex);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (ref) {
|
|
46
|
+
props.ref = ref;
|
|
47
|
+
}
|
|
48
|
+
if (xmlns) {
|
|
49
|
+
props.xmlns = xmlns;
|
|
50
|
+
}
|
|
51
|
+
if (preserveAspectRatio) {
|
|
52
|
+
props.preserveAspectRatio = preserveAspectRatio;
|
|
53
|
+
}
|
|
54
|
+
return /*#__PURE__*/React.createElement('svg', props, children);
|
|
55
|
+
});
|
|
56
|
+
Icon.displayName = 'Icon';
|
|
57
|
+
Icon.propTypes = {
|
|
58
|
+
'aria-hidden': PropTypes.oneOfType([PropTypes.bool, PropTypes.oneOf(['true', 'false'])]),
|
|
59
|
+
'aria-label': PropTypes.string,
|
|
60
|
+
'aria-labelledby': PropTypes.string,
|
|
61
|
+
children: PropTypes.node,
|
|
62
|
+
className: PropTypes.string,
|
|
63
|
+
height: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
|
64
|
+
preserveAspectRatio: PropTypes.string,
|
|
65
|
+
tabIndex: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
|
66
|
+
viewBox: PropTypes.string,
|
|
67
|
+
width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
|
68
|
+
xmlns: PropTypes.string
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
export { Icon as default };
|