@reusable-ui/nav-button
Version:
A clickable button for navigation.
78 lines (77 loc) • 3.01 kB
JavaScript
// react:
import {
// react:
default as React, } from 'react';
// reusable-ui core:
import {
// react helper hooks:
useMergeRefs,
// an accessibility management system:
usePropActive, ElementWithAutoActive, } from '@reusable-ui/core'; // a set of reusable-ui packages which are responsible for building any component
// reusable-ui components:
import { Button, } from '@reusable-ui/button'; // a base component
const NavButton = (props) => {
// rest props:
const {
// navigations:
caseSensitive, end,
// components:
buttonComponent = React.createElement(Button, null), ...restButtonProps } = props;
// refs:
const mergedElmRef = useMergeRefs(
// preserves the original `elmRef` from `buttonComponent`:
buttonComponent.props.elmRef,
// preserves the original `elmRef` from `props`:
props.elmRef);
const mergedOuterRef = useMergeRefs(
// preserves the original `outerRef` from `buttonComponent`:
buttonComponent.props.outerRef,
// preserves the original `outerRef` from `props`:
props.outerRef);
// fn props:
const propActive = usePropActive(props, null);
const activeSt = (buttonComponent.props.active ?? propActive) /*controllable*/;
const isControllableActive = activeSt !== null;
// jsx:
/* <Button> */
const navButton = React.cloneElement(buttonComponent,
// props:
{
// other props:
...restButtonProps,
...buttonComponent.props,
// refs:
elmRef: mergedElmRef,
outerRef: mergedOuterRef,
// semantics:
'aria-current': buttonComponent.props['aria-current'] ?? props['aria-current'] ?? 'page',
},
// children:
buttonComponent.props.children ?? props.children);
if (isControllableActive)
return React.cloneElement(navButton,
// props:
{
// states:
active: activeSt,
});
const navButtonProps = navButton.props;
return (React.createElement(ElementWithAutoActive
// other props:
, { ...navButtonProps,
// navigations:
caseSensitive: caseSensitive, end: end,
// components:
elementComponent: // the underlying `<Element>` to be `<Link>`-ed and manipulated of `[active]` & `[aria-current]` props, based on the current page url
// clone navButton element with (almost) blank props:
React.createElement(navButton.type
// identifiers:
, {
// identifiers:
key: navButton.key, ...{
...(('caseSensitive' in navButtonProps) ? { caseSensitive: navButtonProps.caseSensitive } : undefined),
...(('end' in navButtonProps) ? { end: navButtonProps.end } : undefined),
...(('elementComponent' in navButtonProps) ? { elementComponent: navButtonProps.elementComponent } : undefined),
} }) }));
};
export { NavButton, NavButton as default, };