1
This commit is contained in:
+3
@@ -0,0 +1,3 @@
|
||||
import type { TabsProps } from '..';
|
||||
import type { AnimatedConfig } from '../interface';
|
||||
export default function useAnimateConfig(animated?: TabsProps['animated']): AnimatedConfig;
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = useAnimateConfig;
|
||||
var _warning = _interopRequireDefault(require("@rc-component/util/lib/warning"));
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
function useAnimateConfig(animated = {
|
||||
inkBar: true,
|
||||
tabPane: false
|
||||
}) {
|
||||
let mergedAnimated;
|
||||
if (animated === false) {
|
||||
mergedAnimated = {
|
||||
inkBar: false,
|
||||
tabPane: false
|
||||
};
|
||||
} else if (animated === true) {
|
||||
mergedAnimated = {
|
||||
inkBar: true,
|
||||
tabPane: false
|
||||
};
|
||||
} else {
|
||||
mergedAnimated = {
|
||||
inkBar: true,
|
||||
...(typeof animated === 'object' ? animated : {})
|
||||
};
|
||||
}
|
||||
|
||||
// Enable tabPane animation if provide motion
|
||||
if (mergedAnimated.tabPaneMotion && mergedAnimated.tabPane === undefined) {
|
||||
mergedAnimated.tabPane = true;
|
||||
}
|
||||
if (!mergedAnimated.tabPaneMotion && mergedAnimated.tabPane) {
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
(0, _warning.default)(false, '`animated.tabPane` is true but `animated.tabPaneMotion` is not provided. Motion will not work.');
|
||||
}
|
||||
mergedAnimated.tabPane = false;
|
||||
}
|
||||
return mergedAnimated;
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
import React from 'react';
|
||||
import type { TabOffset } from '../interface';
|
||||
export type GetIndicatorSize = number | ((origin: number) => number);
|
||||
interface UseIndicatorOptions {
|
||||
activeTabOffset: TabOffset;
|
||||
horizontal: boolean;
|
||||
rtl: boolean;
|
||||
indicator?: {
|
||||
size?: GetIndicatorSize;
|
||||
align?: 'start' | 'center' | 'end';
|
||||
};
|
||||
}
|
||||
declare const useIndicator: (options: UseIndicatorOptions) => {
|
||||
style: React.CSSProperties;
|
||||
};
|
||||
export default useIndicator;
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = void 0;
|
||||
var _raf = _interopRequireDefault(require("@rc-component/util/lib/raf"));
|
||||
var _react = _interopRequireWildcard(require("react"));
|
||||
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 && Object.prototype.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 _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
const useIndicator = options => {
|
||||
const {
|
||||
activeTabOffset,
|
||||
horizontal,
|
||||
rtl,
|
||||
indicator = {}
|
||||
} = options;
|
||||
const {
|
||||
size,
|
||||
align = 'center'
|
||||
} = indicator;
|
||||
const [inkStyle, setInkStyle] = (0, _react.useState)();
|
||||
const inkBarRafRef = (0, _react.useRef)();
|
||||
const getLength = _react.default.useCallback(origin => {
|
||||
if (typeof size === 'function') {
|
||||
return size(origin);
|
||||
}
|
||||
if (typeof size === 'number') {
|
||||
return size;
|
||||
}
|
||||
return origin;
|
||||
}, [size]);
|
||||
|
||||
// Delay set ink style to avoid remove tab blink
|
||||
function cleanInkBarRaf() {
|
||||
_raf.default.cancel(inkBarRafRef.current);
|
||||
}
|
||||
(0, _react.useEffect)(() => {
|
||||
const newInkStyle = {};
|
||||
if (activeTabOffset) {
|
||||
if (horizontal) {
|
||||
newInkStyle.width = getLength(activeTabOffset.width);
|
||||
const key = rtl ? 'right' : 'left';
|
||||
if (align === 'start') {
|
||||
newInkStyle[key] = activeTabOffset[key];
|
||||
}
|
||||
if (align === 'center') {
|
||||
newInkStyle[key] = activeTabOffset[key] + activeTabOffset.width / 2;
|
||||
newInkStyle.transform = rtl ? 'translateX(50%)' : 'translateX(-50%)';
|
||||
}
|
||||
if (align === 'end') {
|
||||
newInkStyle[key] = activeTabOffset[key] + activeTabOffset.width;
|
||||
newInkStyle.transform = 'translateX(-100%)';
|
||||
}
|
||||
} else {
|
||||
newInkStyle.height = getLength(activeTabOffset.height);
|
||||
if (align === 'start') {
|
||||
newInkStyle.top = activeTabOffset.top;
|
||||
}
|
||||
if (align === 'center') {
|
||||
newInkStyle.top = activeTabOffset.top + activeTabOffset.height / 2;
|
||||
newInkStyle.transform = 'translateY(-50%)';
|
||||
}
|
||||
if (align === 'end') {
|
||||
newInkStyle.top = activeTabOffset.top + activeTabOffset.height;
|
||||
newInkStyle.transform = 'translateY(-100%)';
|
||||
}
|
||||
}
|
||||
}
|
||||
cleanInkBarRaf();
|
||||
inkBarRafRef.current = (0, _raf.default)(() => {
|
||||
// Avoid jitter caused by tiny numerical differences
|
||||
// fix https://github.com/ant-design/ant-design/issues/53378
|
||||
const isEqual = inkStyle && newInkStyle && Object.keys(newInkStyle).every(key => {
|
||||
const newValue = newInkStyle[key];
|
||||
const oldValue = inkStyle[key];
|
||||
return typeof newValue === 'number' && typeof oldValue === 'number' ? Math.round(newValue) === Math.round(oldValue) : newValue === oldValue;
|
||||
});
|
||||
if (!isEqual) {
|
||||
setInkStyle(newInkStyle);
|
||||
}
|
||||
});
|
||||
return cleanInkBarRaf;
|
||||
}, [JSON.stringify(activeTabOffset), horizontal, rtl, align, getLength]);
|
||||
return {
|
||||
style: inkStyle
|
||||
};
|
||||
};
|
||||
var _default = exports.default = useIndicator;
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
import type { Tab, TabOffsetMap, TabSizeMap } from '../interface';
|
||||
export default function useOffsets(tabs: Tab[], tabSizes: TabSizeMap, holderScrollWidth: number): TabOffsetMap;
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = useOffsets;
|
||||
var _react = require("react");
|
||||
const DEFAULT_SIZE = {
|
||||
width: 0,
|
||||
height: 0,
|
||||
left: 0,
|
||||
top: 0
|
||||
};
|
||||
function useOffsets(tabs, tabSizes, holderScrollWidth) {
|
||||
return (0, _react.useMemo)(() => {
|
||||
const map = new Map();
|
||||
const lastOffset = tabSizes.get(tabs[0]?.key) || DEFAULT_SIZE;
|
||||
const rightOffset = lastOffset.left + lastOffset.width;
|
||||
for (let i = 0; i < tabs.length; i += 1) {
|
||||
const {
|
||||
key
|
||||
} = tabs[i];
|
||||
let data = tabSizes.get(key);
|
||||
|
||||
// Reuse last one when not exist yet
|
||||
if (!data) {
|
||||
data = tabSizes.get(tabs[i - 1]?.key) || DEFAULT_SIZE;
|
||||
}
|
||||
const entity = map.get(key) || {
|
||||
...data
|
||||
};
|
||||
|
||||
// Right
|
||||
entity.right = rightOffset - entity.left - entity.width;
|
||||
|
||||
// Update entity
|
||||
map.set(key, entity);
|
||||
}
|
||||
return map;
|
||||
}, [tabs.map(tab => tab.key).join('_'), tabSizes, holderScrollWidth]);
|
||||
}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
type Updater<T> = (prev: T) => T;
|
||||
export default function useSyncState<T>(defaultState: T, onChange: (newValue: T, prevValue: T) => void): [T, (updater: T | Updater<T>) => void];
|
||||
export {};
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = useSyncState;
|
||||
var React = _interopRequireWildcard(require("react"));
|
||||
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 && Object.prototype.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 useSyncState(defaultState, onChange) {
|
||||
const stateRef = React.useRef(defaultState);
|
||||
const [, forceUpdate] = React.useState({});
|
||||
function setState(updater) {
|
||||
const newValue = typeof updater === 'function' ? updater(stateRef.current) : updater;
|
||||
if (newValue !== stateRef.current) {
|
||||
onChange(newValue, stateRef.current);
|
||||
}
|
||||
stateRef.current = newValue;
|
||||
forceUpdate({});
|
||||
}
|
||||
return [stateRef.current, setState];
|
||||
}
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
import * as React from 'react';
|
||||
export default function useTouchMove(ref: React.RefObject<HTMLDivElement>, onOffset: (offsetX: number, offsetY: number) => boolean): void;
|
||||
+154
@@ -0,0 +1,154 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = useTouchMove;
|
||||
var _react = _interopRequireWildcard(require("react"));
|
||||
var React = _react;
|
||||
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 && Object.prototype.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; }
|
||||
const MIN_SWIPE_DISTANCE = 0.1;
|
||||
const STOP_SWIPE_DISTANCE = 0.01;
|
||||
const REFRESH_INTERVAL = 20;
|
||||
const SPEED_OFF_MULTIPLE = 0.995 ** REFRESH_INTERVAL;
|
||||
|
||||
// ================================= Hook =================================
|
||||
function useTouchMove(ref, onOffset) {
|
||||
const [touchPosition, setTouchPosition] = (0, _react.useState)();
|
||||
const [lastTimestamp, setLastTimestamp] = (0, _react.useState)(0);
|
||||
const [lastTimeDiff, setLastTimeDiff] = (0, _react.useState)(0);
|
||||
const [lastOffset, setLastOffset] = (0, _react.useState)();
|
||||
const motionRef = (0, _react.useRef)();
|
||||
|
||||
// ========================= Events =========================
|
||||
// >>> Touch events
|
||||
function onTouchStart(e) {
|
||||
const {
|
||||
screenX,
|
||||
screenY
|
||||
} = e.touches[0];
|
||||
setTouchPosition({
|
||||
x: screenX,
|
||||
y: screenY
|
||||
});
|
||||
window.clearInterval(motionRef.current);
|
||||
}
|
||||
function onTouchMove(e) {
|
||||
if (!touchPosition) return;
|
||||
|
||||
// e.preventDefault();
|
||||
const {
|
||||
screenX,
|
||||
screenY
|
||||
} = e.touches[0];
|
||||
setTouchPosition({
|
||||
x: screenX,
|
||||
y: screenY
|
||||
});
|
||||
const offsetX = screenX - touchPosition.x;
|
||||
const offsetY = screenY - touchPosition.y;
|
||||
onOffset(offsetX, offsetY);
|
||||
const now = Date.now();
|
||||
setLastTimestamp(now);
|
||||
setLastTimeDiff(now - lastTimestamp);
|
||||
setLastOffset({
|
||||
x: offsetX,
|
||||
y: offsetY
|
||||
});
|
||||
}
|
||||
function onTouchEnd() {
|
||||
if (!touchPosition) return;
|
||||
setTouchPosition(null);
|
||||
setLastOffset(null);
|
||||
|
||||
// Swipe if needed
|
||||
if (lastOffset) {
|
||||
const distanceX = lastOffset.x / lastTimeDiff;
|
||||
const distanceY = lastOffset.y / lastTimeDiff;
|
||||
const absX = Math.abs(distanceX);
|
||||
const absY = Math.abs(distanceY);
|
||||
|
||||
// Skip swipe if low distance
|
||||
if (Math.max(absX, absY) < MIN_SWIPE_DISTANCE) return;
|
||||
let currentX = distanceX;
|
||||
let currentY = distanceY;
|
||||
motionRef.current = window.setInterval(() => {
|
||||
if (Math.abs(currentX) < STOP_SWIPE_DISTANCE && Math.abs(currentY) < STOP_SWIPE_DISTANCE) {
|
||||
window.clearInterval(motionRef.current);
|
||||
return;
|
||||
}
|
||||
currentX *= SPEED_OFF_MULTIPLE;
|
||||
currentY *= SPEED_OFF_MULTIPLE;
|
||||
onOffset(currentX * REFRESH_INTERVAL, currentY * REFRESH_INTERVAL);
|
||||
}, REFRESH_INTERVAL);
|
||||
}
|
||||
}
|
||||
|
||||
// >>> Wheel event
|
||||
const lastWheelDirectionRef = (0, _react.useRef)();
|
||||
function onWheel(e) {
|
||||
const {
|
||||
deltaX,
|
||||
deltaY
|
||||
} = e;
|
||||
|
||||
// Convert both to x & y since wheel only happened on PC
|
||||
let mixed = 0;
|
||||
const absX = Math.abs(deltaX);
|
||||
const absY = Math.abs(deltaY);
|
||||
if (absX === absY) {
|
||||
mixed = lastWheelDirectionRef.current === 'x' ? deltaX : deltaY;
|
||||
} else if (absX > absY) {
|
||||
mixed = deltaX;
|
||||
lastWheelDirectionRef.current = 'x';
|
||||
} else {
|
||||
mixed = deltaY;
|
||||
lastWheelDirectionRef.current = 'y';
|
||||
}
|
||||
if (onOffset(-mixed, -mixed)) {
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
// ========================= Effect =========================
|
||||
const touchEventsRef = (0, _react.useRef)(null);
|
||||
touchEventsRef.current = {
|
||||
onTouchStart,
|
||||
onTouchMove,
|
||||
onTouchEnd,
|
||||
onWheel
|
||||
};
|
||||
React.useEffect(() => {
|
||||
function onProxyTouchStart(e) {
|
||||
touchEventsRef.current.onTouchStart(e);
|
||||
}
|
||||
function onProxyTouchMove(e) {
|
||||
touchEventsRef.current.onTouchMove(e);
|
||||
}
|
||||
function onProxyTouchEnd(e) {
|
||||
touchEventsRef.current.onTouchEnd(e);
|
||||
}
|
||||
function onProxyWheel(e) {
|
||||
touchEventsRef.current.onWheel(e);
|
||||
}
|
||||
document.addEventListener('touchmove', onProxyTouchMove, {
|
||||
passive: false
|
||||
});
|
||||
document.addEventListener('touchend', onProxyTouchEnd, {
|
||||
passive: true
|
||||
});
|
||||
|
||||
// No need to clean up since element removed
|
||||
ref.current.addEventListener('touchstart', onProxyTouchStart, {
|
||||
passive: true
|
||||
});
|
||||
ref.current.addEventListener('wheel', onProxyWheel, {
|
||||
passive: false
|
||||
});
|
||||
return () => {
|
||||
document.removeEventListener('touchmove', onProxyTouchMove);
|
||||
document.removeEventListener('touchend', onProxyTouchEnd);
|
||||
};
|
||||
}, []);
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* Help to merge callback with `useLayoutEffect`.
|
||||
* One time will only trigger once.
|
||||
*/
|
||||
export default function useUpdate(callback: VoidFunction): () => void;
|
||||
type Callback<T> = (ori: T) => T;
|
||||
export declare function useUpdateState<T>(defaultState: T | (() => T)): [T, (updater: Callback<T>) => void];
|
||||
export {};
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = useUpdate;
|
||||
exports.useUpdateState = useUpdateState;
|
||||
var _useLayoutEffect = require("@rc-component/util/lib/hooks/useLayoutEffect");
|
||||
var _react = require("react");
|
||||
/**
|
||||
* Help to merge callback with `useLayoutEffect`.
|
||||
* One time will only trigger once.
|
||||
*/
|
||||
function useUpdate(callback) {
|
||||
const [count, setCount] = (0, _react.useState)(0);
|
||||
const effectRef = (0, _react.useRef)(0);
|
||||
const callbackRef = (0, _react.useRef)();
|
||||
callbackRef.current = callback;
|
||||
|
||||
// Trigger on `useLayoutEffect`
|
||||
(0, _useLayoutEffect.useLayoutUpdateEffect)(() => {
|
||||
callbackRef.current?.();
|
||||
}, [count]);
|
||||
|
||||
// Trigger to update count
|
||||
return () => {
|
||||
if (effectRef.current !== count) {
|
||||
return;
|
||||
}
|
||||
effectRef.current += 1;
|
||||
setCount(effectRef.current);
|
||||
};
|
||||
}
|
||||
function useUpdateState(defaultState) {
|
||||
const batchRef = (0, _react.useRef)([]);
|
||||
const [, forceUpdate] = (0, _react.useState)({});
|
||||
const state = (0, _react.useRef)(typeof defaultState === 'function' ? defaultState() : defaultState);
|
||||
const flushUpdate = useUpdate(() => {
|
||||
let current = state.current;
|
||||
batchRef.current.forEach(callback => {
|
||||
current = callback(current);
|
||||
});
|
||||
batchRef.current = [];
|
||||
state.current = current;
|
||||
forceUpdate({});
|
||||
});
|
||||
function updater(callback) {
|
||||
batchRef.current.push(callback);
|
||||
flushUpdate();
|
||||
}
|
||||
return [state.current, updater];
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
import type { Tab, TabOffsetMap } from '../interface';
|
||||
import type { TabNavListProps } from '../TabNavList';
|
||||
export type ContainerSizeInfo = [width: number, height: number, left: number, top: number];
|
||||
export default function useVisibleRange(tabOffsets: TabOffsetMap, visibleTabContentValue: number, transform: number, tabContentSizeValue: number, addNodeSizeValue: number, operationNodeSizeValue: number, { tabs, tabPosition, rtl }: {
|
||||
tabs: Tab[];
|
||||
} & TabNavListProps): [visibleStart: number, visibleEnd: number];
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.default = useVisibleRange;
|
||||
var _react = require("react");
|
||||
const DEFAULT_SIZE = {
|
||||
width: 0,
|
||||
height: 0,
|
||||
left: 0,
|
||||
top: 0,
|
||||
right: 0
|
||||
};
|
||||
function useVisibleRange(tabOffsets, visibleTabContentValue, transform, tabContentSizeValue, addNodeSizeValue, operationNodeSizeValue, {
|
||||
tabs,
|
||||
tabPosition,
|
||||
rtl
|
||||
}) {
|
||||
let charUnit;
|
||||
let position;
|
||||
let transformSize;
|
||||
if (['top', 'bottom'].includes(tabPosition)) {
|
||||
charUnit = 'width';
|
||||
position = rtl ? 'right' : 'left';
|
||||
transformSize = Math.abs(transform);
|
||||
} else {
|
||||
charUnit = 'height';
|
||||
position = 'top';
|
||||
transformSize = -transform;
|
||||
}
|
||||
return (0, _react.useMemo)(() => {
|
||||
if (!tabs.length) {
|
||||
return [0, 0];
|
||||
}
|
||||
const len = tabs.length;
|
||||
let endIndex = len;
|
||||
for (let i = 0; i < len; i += 1) {
|
||||
const offset = tabOffsets.get(tabs[i].key) || DEFAULT_SIZE;
|
||||
if (Math.floor(offset[position] + offset[charUnit]) > Math.floor(transformSize + visibleTabContentValue)) {
|
||||
endIndex = i - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
let startIndex = 0;
|
||||
for (let i = len - 1; i >= 0; i -= 1) {
|
||||
const offset = tabOffsets.get(tabs[i].key) || DEFAULT_SIZE;
|
||||
if (offset[position] < transformSize) {
|
||||
startIndex = i + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return startIndex > endIndex ? [0, -1] : [startIndex, endIndex];
|
||||
}, [tabOffsets, visibleTabContentValue, tabContentSizeValue, addNodeSizeValue, operationNodeSizeValue, transformSize, tabPosition, tabs.map(tab => tab.key).join('_'), rtl]);
|
||||
}
|
||||
Reference in New Issue
Block a user