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