This commit is contained in:
2026-05-25 17:08:18 +08:00
parent df501f6151
commit f1259b71b5
9178 changed files with 1626125 additions and 0 deletions
@@ -0,0 +1,24 @@
import React from 'react';
import type { CSSMotionProps } from '@rc-component/motion';
import type { AlignType, ArrowPos } from '../interface';
export interface UniqueContainerProps {
prefixCls: string;
isMobile: boolean;
ready: boolean;
open: boolean;
align: AlignType;
offsetR: number;
offsetB: number;
offsetX: number;
offsetY: number;
arrowPos?: ArrowPos;
popupSize?: {
width: number;
height: number;
};
motion?: CSSMotionProps;
uniqueContainerClassName?: string;
uniqueContainerStyle?: React.CSSProperties;
}
declare const UniqueContainer: (props: UniqueContainerProps) => React.JSX.Element;
export default UniqueContainer;
@@ -0,0 +1,83 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _react = _interopRequireDefault(require("react"));
var _useOffsetStyle = _interopRequireDefault(require("../hooks/useOffsetStyle"));
var _clsx = require("clsx");
var _motion = _interopRequireDefault(require("@rc-component/motion"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
const UniqueContainer = props => {
const {
prefixCls,
isMobile,
ready,
open,
align,
offsetR,
offsetB,
offsetX,
offsetY,
arrowPos,
popupSize,
motion,
uniqueContainerClassName,
uniqueContainerStyle
} = props;
const containerCls = `${prefixCls}-unique-container`;
const [motionVisible, setMotionVisible] = _react.default.useState(false);
// ========================= Styles =========================
const offsetStyle = (0, _useOffsetStyle.default)(isMobile, ready, open, align, offsetR, offsetB, offsetX, offsetY);
// Cache for offsetStyle when ready is true
const cachedOffsetStyleRef = _react.default.useRef(offsetStyle);
// Update cached offset style when ready is true
if (ready) {
cachedOffsetStyleRef.current = offsetStyle;
}
// Apply popup size if available
const sizeStyle = {};
if (popupSize) {
sizeStyle.width = popupSize.width;
sizeStyle.height = popupSize.height;
}
// ========================= Render =========================
return /*#__PURE__*/_react.default.createElement(_motion.default, _extends({
motionAppear: true,
motionEnter: true,
motionLeave: true,
removeOnLeave: false,
leavedClassName: `${containerCls}-hidden`
}, motion, {
visible: open,
onVisibleChanged: nextVisible => {
setMotionVisible(nextVisible);
}
}), ({
className: motionClassName,
style: motionStyle
}) => {
const cls = (0, _clsx.clsx)(containerCls, motionClassName, uniqueContainerClassName, {
[`${containerCls}-visible`]: motionVisible
});
return /*#__PURE__*/_react.default.createElement("div", {
className: cls,
style: {
'--arrow-x': `${arrowPos?.x || 0}px`,
'--arrow-y': `${arrowPos?.y || 0}px`,
...cachedOffsetStyleRef.current,
...sizeStyle,
...motionStyle,
...uniqueContainerStyle
}
});
});
};
var _default = exports.default = UniqueContainer;
@@ -0,0 +1,9 @@
import * as React from 'react';
import { type UniqueShowOptions } from '../context';
export interface UniqueProviderProps {
children: React.ReactNode;
/** Additional handle options data to do the customize info */
postTriggerProps?: (options: UniqueShowOptions) => UniqueShowOptions;
}
declare const UniqueProvider: ({ children, postTriggerProps, }: UniqueProviderProps) => React.JSX.Element;
export default UniqueProvider;
@@ -0,0 +1,184 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var React = _interopRequireWildcard(require("react"));
var _portal = _interopRequireDefault(require("@rc-component/portal"));
var _context = _interopRequireWildcard(require("../context"));
var _useDelay = _interopRequireDefault(require("../hooks/useDelay"));
var _useAlign = _interopRequireDefault(require("../hooks/useAlign"));
var _Popup = _interopRequireDefault(require("../Popup"));
var _util = require("@rc-component/util");
var _useTargetState = _interopRequireDefault(require("./useTargetState"));
var _findDOMNode = require("@rc-component/util/lib/Dom/findDOMNode");
var _UniqueContainer = _interopRequireDefault(require("./UniqueContainer"));
var _clsx = require("clsx");
var _util2 = require("../util");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
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 UniqueProvider = ({
children,
postTriggerProps
}) => {
const [trigger, open, options, onTargetVisibleChanged] = (0, _useTargetState.default)();
// ========================== Options ===========================
const mergedOptions = React.useMemo(() => {
if (!options || !postTriggerProps) {
return options;
}
return postTriggerProps(options);
}, [options, postTriggerProps]);
// =========================== Popup ============================
const [popupEle, setPopupEle] = React.useState(null);
const [popupSize, setPopupSize] = React.useState(null);
// Used for forwardRef popup. Not use internal
const externalPopupRef = React.useRef(null);
const setPopupRef = (0, _util.useEvent)(node => {
externalPopupRef.current = node;
if ((0, _findDOMNode.isDOM)(node) && popupEle !== node) {
setPopupEle(node);
}
});
// ========================== Register ==========================
// Store the isOpen function from the latest show call
const isOpenRef = React.useRef(null);
const delayInvoke = (0, _useDelay.default)();
const show = (0, _util.useEvent)((showOptions, isOpen) => {
// Store the isOpen function for later use in hide
isOpenRef.current = isOpen;
delayInvoke(() => {
trigger(showOptions);
}, showOptions.delay);
});
const hide = delay => {
delayInvoke(() => {
// Check if we should still hide by calling the isOpen function
// If isOpen returns true, it means another trigger wants to keep it open
if (isOpenRef.current?.()) {
return; // Don't hide if something else wants it open
}
trigger(false);
// Don't clear target, currentNode, options immediately, wait until animation completes
}, delay);
};
// Callback after animation completes
const onVisibleChanged = (0, _util.useEvent)(visible => {
// Call useTargetState callback to handle animation state
onTargetVisibleChanged(visible);
});
// =========================== Align ============================
const [ready, offsetX, offsetY, offsetR, offsetB, arrowX, arrowY,
// scaleX - not used in UniqueProvider
,,
// scaleY - not used in UniqueProvider
alignInfo, onAlign] = (0, _useAlign.default)(open, popupEle, mergedOptions?.target, mergedOptions?.popupPlacement, mergedOptions?.builtinPlacements || {}, mergedOptions?.popupAlign, undefined,
// onPopupAlign
false // isMobile
);
const alignedClassName = React.useMemo(() => {
if (!mergedOptions) {
return '';
}
const baseClassName = (0, _util2.getAlignPopupClassName)(mergedOptions.builtinPlacements || {}, mergedOptions.prefixCls || '', alignInfo, false // alignPoint is false for UniqueProvider
);
return (0, _clsx.clsx)(baseClassName, mergedOptions.getPopupClassNameFromAlign?.(alignInfo));
}, [alignInfo, mergedOptions?.getPopupClassNameFromAlign, mergedOptions?.builtinPlacements, mergedOptions?.prefixCls]);
const contextValue = React.useMemo(() => ({
show,
hide
}), []);
// =========================== Align ============================
React.useEffect(() => {
onAlign();
}, [mergedOptions?.target]);
// =========================== Motion ===========================
const onPrepare = (0, _util.useEvent)(() => {
onAlign();
return Promise.resolve();
});
// ======================== Trigger Context =====================
const subPopupElements = React.useRef({});
const parentContext = React.useContext(_context.default);
const triggerContextValue = React.useMemo(() => ({
registerSubPopup: (id, subPopupEle) => {
subPopupElements.current[id] = subPopupEle;
parentContext?.registerSubPopup(id, subPopupEle);
}
}), [parentContext]);
// =========================== Render ===========================
const prefixCls = mergedOptions?.prefixCls;
return /*#__PURE__*/React.createElement(_context.UniqueContext.Provider, {
value: contextValue
}, children, mergedOptions && /*#__PURE__*/React.createElement(_context.default.Provider, {
value: triggerContextValue
}, /*#__PURE__*/React.createElement(_Popup.default, {
ref: setPopupRef,
portal: _portal.default,
onEsc: mergedOptions.onEsc,
prefixCls: prefixCls,
popup: mergedOptions.popup,
className: (0, _clsx.clsx)(mergedOptions.popupClassName, alignedClassName, `${prefixCls}-unique-controlled`),
style: mergedOptions.popupStyle,
target: mergedOptions.target,
open: open,
keepDom: true,
fresh: true,
autoDestroy: false,
onVisibleChanged: onVisibleChanged,
ready: ready,
offsetX: offsetX,
offsetY: offsetY,
offsetR: offsetR,
offsetB: offsetB,
onAlign: onAlign,
onPrepare: onPrepare,
onResize: size => setPopupSize({
width: size.offsetWidth,
height: size.offsetHeight
}),
arrowPos: {
x: arrowX,
y: arrowY
},
align: alignInfo,
zIndex: mergedOptions.zIndex,
mask: mergedOptions.mask,
arrow: mergedOptions.arrow,
motion: mergedOptions.popupMotion,
maskMotion: mergedOptions.maskMotion,
getPopupContainer: mergedOptions.getPopupContainer
}, /*#__PURE__*/React.createElement(_UniqueContainer.default, {
prefixCls: prefixCls,
isMobile: false,
ready: ready,
open: open,
align: alignInfo,
offsetR: offsetR,
offsetB: offsetB,
offsetX: offsetX,
offsetY: offsetY,
arrowPos: {
x: arrowX,
y: arrowY
},
popupSize: popupSize,
motion: mergedOptions.popupMotion,
uniqueContainerClassName: (0, _clsx.clsx)(mergedOptions.uniqueContainerClassName, alignedClassName),
uniqueContainerStyle: mergedOptions.uniqueContainerStyle
}))));
};
var _default = exports.default = UniqueProvider;
@@ -0,0 +1,16 @@
import type { UniqueShowOptions } from '../context';
/**
* Control the state of popup bind target:
* 1. When set `target`. Do show the popup.
* 2. When `target` is removed. Do hide the popup.
* 3. When `target` change to another one:
* a. We wait motion finish of previous popup.
* b. Then we set new target and show the popup.
* 4. During appear/enter animation, cache new options and apply after animation completes.
*/
export default function useTargetState(): [
trigger: (options: UniqueShowOptions | false) => void,
open: boolean,
cacheOptions: UniqueShowOptions | null,
onVisibleChanged: (visible: boolean) => void
];
@@ -0,0 +1,62 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = useTargetState;
var _react = _interopRequireDefault(require("react"));
var _util = require("@rc-component/util");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* Control the state of popup bind target:
* 1. When set `target`. Do show the popup.
* 2. When `target` is removed. Do hide the popup.
* 3. When `target` change to another one:
* a. We wait motion finish of previous popup.
* b. Then we set new target and show the popup.
* 4. During appear/enter animation, cache new options and apply after animation completes.
*/
function useTargetState() {
const [options, setOptions] = _react.default.useState(null);
const [open, setOpen] = _react.default.useState(false);
const [isAnimating, setIsAnimating] = _react.default.useState(false);
const pendingOptionsRef = _react.default.useRef(null);
const trigger = (0, _util.useEvent)(nextOptions => {
if (nextOptions === false) {
// Clear pending options when hiding
pendingOptionsRef.current = null;
setOpen(false);
} else {
if (isAnimating && open) {
// If animating (appear or enter), cache new options
pendingOptionsRef.current = nextOptions;
} else {
setOpen(true);
// Set new options
setOptions(nextOptions);
pendingOptionsRef.current = null;
// Only mark as animating when transitioning from closed to open
if (!open) {
setIsAnimating(true);
}
}
}
});
const onVisibleChanged = (0, _util.useEvent)(visible => {
if (visible) {
// Animation enter completed, check if there are pending options
setIsAnimating(false);
if (pendingOptionsRef.current) {
// Apply pending options
setOptions(pendingOptionsRef.current);
pendingOptionsRef.current = null;
}
} else {
// Animation leave completed
setIsAnimating(false);
pendingOptionsRef.current = null;
}
});
return [trigger, open, options, onVisibleChanged];
}