@base-ui-components/react
Version:
Base UI is a library of headless ('unstyled') React components and low-level hooks. You gain complete control over your app's CSS and accessibility features.
124 lines (123 loc) • 4.68 kB
JavaScript
;
'use client';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.useTabsList = useTabsList;
var React = _interopRequireWildcard(require("react"));
var _mergeReactProps = require("../../utils/mergeReactProps");
var _useEnhancedEffect = require("../../utils/useEnhancedEffect");
var _useForkRef = require("../../utils/useForkRef");
var _useEventCallback = require("../../utils/useEventCallback");
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
function useTabsList(parameters) {
const {
getTabElementBySelectedValue,
onValueChange,
orientation,
rootRef: externalRef,
tabsListRef,
value: selectedTabValue
} = parameters;
const detectActivationDirection = useActivationDirectionDetector(
// the old value
selectedTabValue, orientation, tabsListRef, getTabElementBySelectedValue);
const onTabActivation = (0, _useEventCallback.useEventCallback)((newValue, event) => {
if (newValue !== selectedTabValue) {
const activationDirection = detectActivationDirection(newValue);
onValueChange(newValue, activationDirection, event);
}
});
const handleRef = (0, _useForkRef.useForkRef)(tabsListRef, externalRef);
const getRootProps = React.useCallback((otherProps = {}) => {
return (0, _mergeReactProps.mergeReactProps)(otherProps, {
'aria-orientation': orientation === 'vertical' ? 'vertical' : undefined,
ref: handleRef,
role: 'tablist'
});
}, [handleRef, orientation]);
return {
getRootProps,
onTabActivation,
rootRef: handleRef,
tabsListRef
};
}
function getInset(tab, tabsList) {
const {
left: tabLeft,
top: tabTop
} = tab.getBoundingClientRect();
const {
left: listLeft,
top: listTop
} = tabsList.getBoundingClientRect();
const left = tabLeft - listLeft;
const top = tabTop - listTop;
return {
left,
top
};
}
function useActivationDirectionDetector(
// the old value
selectedTabValue, orientation, tabsListRef, getTabElement) {
const previousTabEdge = React.useRef(null);
(0, _useEnhancedEffect.useEnhancedEffect)(() => {
// Whenever orientation changes, reset the state.
if (selectedTabValue == null || tabsListRef.current == null) {
previousTabEdge.current = null;
return;
}
const activeTab = getTabElement(selectedTabValue);
if (activeTab == null) {
previousTabEdge.current = null;
return;
}
const {
left,
top
} = getInset(activeTab, tabsListRef.current);
previousTabEdge.current = orientation === 'horizontal' ? left : top;
}, [orientation, getTabElement, tabsListRef, selectedTabValue]);
return React.useCallback(newValue => {
if (newValue === selectedTabValue) {
return 'none';
}
if (newValue == null) {
previousTabEdge.current = null;
return 'none';
}
if (newValue != null && tabsListRef.current != null) {
const selectedTabElement = getTabElement(newValue);
if (selectedTabElement != null) {
const {
left,
top
} = getInset(selectedTabElement, tabsListRef.current);
if (previousTabEdge.current == null) {
previousTabEdge.current = orientation === 'horizontal' ? left : top;
return 'none';
}
if (orientation === 'horizontal') {
if (left < previousTabEdge.current) {
previousTabEdge.current = left;
return 'left';
}
if (left > previousTabEdge.current) {
previousTabEdge.current = left;
return 'right';
}
} else if (top < previousTabEdge.current) {
previousTabEdge.current = top;
return 'up';
} else if (top > previousTabEdge.current) {
previousTabEdge.current = top;
return 'down';
}
}
}
return 'none';
}, [getTabElement, orientation, previousTabEdge, tabsListRef, selectedTabValue]);
}