135 lines
5.9 KiB
JavaScript
135 lines
5.9 KiB
JavaScript
'use client';
|
|
"use strict";
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
Object.defineProperty(exports, "useTabAnimatedIndicatorStyles_unstable", {
|
|
enumerable: true,
|
|
get: function() {
|
|
return useTabAnimatedIndicatorStyles_unstable;
|
|
}
|
|
});
|
|
const _interop_require_wildcard = require("@swc/helpers/_/_interop_require_wildcard");
|
|
const _react = /*#__PURE__*/ _interop_require_wildcard._(require("react"));
|
|
const _react1 = require("@griffel/react");
|
|
const _TabListContext = require("../TabList/TabListContext");
|
|
const _reacttheme = require("@fluentui/react-theme");
|
|
const _reactutilities = require("@fluentui/react-utilities");
|
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
const tabIndicatorCssVars_unstable = {
|
|
offsetVar: '--fui-Tab__indicator--offset',
|
|
scaleVar: '--fui-Tab__indicator--scale'
|
|
};
|
|
const useActiveIndicatorStyles = (0, _react1.makeStyles)({
|
|
base: {
|
|
// overflow is required to allow the selection indicator to animate outside the tab area.
|
|
overflow: 'visible'
|
|
},
|
|
animated: {
|
|
'::after': {
|
|
transitionProperty: 'transform',
|
|
transitionDuration: `${_reacttheme.tokens.durationSlow}`,
|
|
transitionTimingFunction: `${_reacttheme.tokens.curveDecelerateMax}`
|
|
},
|
|
'@media (prefers-reduced-motion: reduce)': {
|
|
'::after': {
|
|
transitionProperty: 'none',
|
|
transitionDuration: '0.01ms'
|
|
}
|
|
}
|
|
},
|
|
horizontal: {
|
|
'::after': {
|
|
transformOrigin: 'left',
|
|
transform: `translateX(var(${tabIndicatorCssVars_unstable.offsetVar}))
|
|
scaleX(var(${tabIndicatorCssVars_unstable.scaleVar}))`
|
|
}
|
|
},
|
|
vertical: {
|
|
'::after': {
|
|
transformOrigin: 'top',
|
|
transform: `translateY(var(${tabIndicatorCssVars_unstable.offsetVar}))
|
|
scaleY(var(${tabIndicatorCssVars_unstable.scaleVar}))`
|
|
}
|
|
}
|
|
});
|
|
const calculateTabRect = (element)=>{
|
|
if (element) {
|
|
var _element_parentElement;
|
|
const parentRect = ((_element_parentElement = element.parentElement) === null || _element_parentElement === void 0 ? void 0 : _element_parentElement.getBoundingClientRect()) || {
|
|
x: 0,
|
|
y: 0,
|
|
width: 0,
|
|
height: 0
|
|
};
|
|
const tabRect = element.getBoundingClientRect();
|
|
return {
|
|
x: tabRect.x - parentRect.x,
|
|
y: tabRect.y - parentRect.y,
|
|
width: tabRect.width,
|
|
height: tabRect.height
|
|
};
|
|
}
|
|
return undefined;
|
|
};
|
|
const getRegisteredTabRect = (registeredTabs, value)=>{
|
|
var _registeredTabs_JSON_stringify;
|
|
const element = isValueDefined(value) ? (_registeredTabs_JSON_stringify = registeredTabs[JSON.stringify(value)]) === null || _registeredTabs_JSON_stringify === void 0 ? void 0 : _registeredTabs_JSON_stringify.ref.current : undefined;
|
|
return element ? calculateTabRect(element) : undefined;
|
|
};
|
|
// eslint-disable-next-line eqeqeq
|
|
const isValueDefined = (value)=>value != null;
|
|
const useTabAnimatedIndicatorStyles_unstable = (state)=>{
|
|
const { disabled, selected, vertical } = state;
|
|
const activeIndicatorStyles = useActiveIndicatorStyles();
|
|
const [lastAnimatedFrom, setLastAnimatedFrom] = _react.useState();
|
|
const [animationValues, setAnimationValues] = _react.useState({
|
|
offset: 0,
|
|
scale: 1
|
|
});
|
|
const getRegisteredTabs = (0, _TabListContext.useTabListContext_unstable)((ctx)=>ctx.getRegisteredTabs);
|
|
const [requestAnimationFrame] = (0, _reactutilities.useAnimationFrame)();
|
|
if (selected) {
|
|
const { previousSelectedValue, selectedValue, registeredTabs } = getRegisteredTabs();
|
|
if (isValueDefined(previousSelectedValue) && lastAnimatedFrom !== previousSelectedValue) {
|
|
const previousSelectedTabRect = getRegisteredTabRect(registeredTabs, previousSelectedValue);
|
|
const selectedTabRect = getRegisteredTabRect(registeredTabs, selectedValue);
|
|
if (selectedTabRect && previousSelectedTabRect) {
|
|
const offset = vertical ? previousSelectedTabRect.y - selectedTabRect.y : previousSelectedTabRect.x - selectedTabRect.x;
|
|
const scale = vertical ? previousSelectedTabRect.height / selectedTabRect.height : previousSelectedTabRect.width / selectedTabRect.width;
|
|
setAnimationValues({
|
|
offset,
|
|
scale
|
|
});
|
|
setLastAnimatedFrom(previousSelectedValue);
|
|
// Reset the animation values after the animation is complete
|
|
requestAnimationFrame(()=>setAnimationValues({
|
|
offset: 0,
|
|
scale: 1
|
|
}));
|
|
}
|
|
}
|
|
} else if (isValueDefined(lastAnimatedFrom)) {
|
|
// need to clear the last animated from so that if this tab is selected again
|
|
// from the same previous tab as last time, that animation still happens.
|
|
setLastAnimatedFrom(undefined);
|
|
}
|
|
// do not apply any animation if the tab is disabled
|
|
if (disabled) {
|
|
return state;
|
|
}
|
|
// the animation should only happen as the selection indicator returns to its
|
|
// original position and not when set at the previous tabs position.
|
|
const animating = animationValues.offset === 0 && animationValues.scale === 1;
|
|
state.root.className = (0, _react1.mergeClasses)(state.root.className, selected && activeIndicatorStyles.base, selected && animating && activeIndicatorStyles.animated, selected && (vertical ? activeIndicatorStyles.vertical : activeIndicatorStyles.horizontal));
|
|
const rootCssVars = {
|
|
[tabIndicatorCssVars_unstable.offsetVar]: `${animationValues.offset}px`,
|
|
[tabIndicatorCssVars_unstable.scaleVar]: `${animationValues.scale}`
|
|
};
|
|
state.root.style = {
|
|
...rootCssVars,
|
|
...state.root.style
|
|
};
|
|
return state;
|
|
};
|