@itcase/storybook-config 1.2.45 → 1.2.47
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{Notification-9brero6A.js → Notification-CjVZJ18f.js} +3660 -11
- package/dist/{Notification-B-qQJcvG.js → Notification-DcTliQqo.js} +3671 -22
- package/dist/cjs/decorators/withNextDecorator.js +2 -1
- package/dist/cjs/decorators/withUiDecorator.js +2 -1
- package/dist/cjs/decorators.js +2 -1
- package/dist/config/config/mainConfigNextJsVite.js +2 -1
- package/dist/config/config/mainConfigReactNative.js +1 -0
- package/dist/config/config/mainConfigReactNativeWeb.js +4 -0
- package/dist/config/config/mainConfigVite.js +6 -5
- package/dist/css/preview.css +1 -1
- package/dist/decorators/withNextDecorator.js +2 -1
- package/dist/decorators/withUiDecorator.js +2 -1
- package/dist/decorators.js +2 -1
- package/package.json +32 -32
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var React = require('react');
|
|
4
|
+
var reactDom = require('react-dom');
|
|
4
5
|
var camelCase = require('lodash/camelCase');
|
|
5
6
|
var castArray = require('lodash/castArray');
|
|
6
7
|
var upperFirst = require('lodash/upperFirst');
|
|
@@ -1395,6 +1396,3654 @@ var jsxRuntimeExports = requireJsxRuntime();
|
|
|
1395
1396
|
|
|
1396
1397
|
function r(e){var t,f,n="";if("string"==typeof e||"number"==typeof e)n+=e;else if("object"==typeof e)if(Array.isArray(e)){var o=e.length;for(t=0;t<o;t++)e[t]&&(f=r(e[t]))&&(n&&(n+=" "),n+=f);}else for(f in e)e[f]&&(n&&(n+=" "),n+=f);return n}function clsx(){for(var e,t,f=0,n="",o=arguments.length;f<o;f++)(e=arguments[f])&&(t=r(e))&&(n&&(n+=" "),n+=t);return n}
|
|
1397
1398
|
|
|
1399
|
+
function canUseDom() {
|
|
1400
|
+
return !!(typeof window !== 'undefined' && window.document && window.document.createElement);
|
|
1401
|
+
}
|
|
1402
|
+
|
|
1403
|
+
var reactIs$1 = {exports: {}};
|
|
1404
|
+
|
|
1405
|
+
var reactIs_production_min$1 = {};
|
|
1406
|
+
|
|
1407
|
+
/**
|
|
1408
|
+
* @license React
|
|
1409
|
+
* react-is.production.min.js
|
|
1410
|
+
*
|
|
1411
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
1412
|
+
*
|
|
1413
|
+
* This source code is licensed under the MIT license found in the
|
|
1414
|
+
* LICENSE file in the root directory of this source tree.
|
|
1415
|
+
*/
|
|
1416
|
+
|
|
1417
|
+
var hasRequiredReactIs_production_min$1;
|
|
1418
|
+
|
|
1419
|
+
function requireReactIs_production_min$1 () {
|
|
1420
|
+
if (hasRequiredReactIs_production_min$1) return reactIs_production_min$1;
|
|
1421
|
+
hasRequiredReactIs_production_min$1 = 1;
|
|
1422
|
+
var b=Symbol.for("react.element"),c=Symbol.for("react.portal"),d=Symbol.for("react.fragment"),e=Symbol.for("react.strict_mode"),f=Symbol.for("react.profiler"),g=Symbol.for("react.provider"),h=Symbol.for("react.context"),k=Symbol.for("react.server_context"),l=Symbol.for("react.forward_ref"),m=Symbol.for("react.suspense"),n=Symbol.for("react.suspense_list"),p=Symbol.for("react.memo"),q=Symbol.for("react.lazy"),t=Symbol.for("react.offscreen"),u;u=Symbol.for("react.module.reference");
|
|
1423
|
+
function v(a){if("object"===typeof a&&null!==a){var r=a.$$typeof;switch(r){case b:switch(a=a.type,a){case d:case f:case e:case m:case n:return a;default:switch(a=a&&a.$$typeof,a){case k:case h:case l:case q:case p:case g:return a;default:return r}}case c:return r}}}reactIs_production_min$1.ContextConsumer=h;reactIs_production_min$1.ContextProvider=g;reactIs_production_min$1.Element=b;reactIs_production_min$1.ForwardRef=l;reactIs_production_min$1.Fragment=d;reactIs_production_min$1.Lazy=q;reactIs_production_min$1.Memo=p;reactIs_production_min$1.Portal=c;reactIs_production_min$1.Profiler=f;reactIs_production_min$1.StrictMode=e;reactIs_production_min$1.Suspense=m;
|
|
1424
|
+
reactIs_production_min$1.SuspenseList=n;reactIs_production_min$1.isAsyncMode=function(){return false};reactIs_production_min$1.isConcurrentMode=function(){return false};reactIs_production_min$1.isContextConsumer=function(a){return v(a)===h};reactIs_production_min$1.isContextProvider=function(a){return v(a)===g};reactIs_production_min$1.isElement=function(a){return "object"===typeof a&&null!==a&&a.$$typeof===b};reactIs_production_min$1.isForwardRef=function(a){return v(a)===l};reactIs_production_min$1.isFragment=function(a){return v(a)===d};reactIs_production_min$1.isLazy=function(a){return v(a)===q};reactIs_production_min$1.isMemo=function(a){return v(a)===p};
|
|
1425
|
+
reactIs_production_min$1.isPortal=function(a){return v(a)===c};reactIs_production_min$1.isProfiler=function(a){return v(a)===f};reactIs_production_min$1.isStrictMode=function(a){return v(a)===e};reactIs_production_min$1.isSuspense=function(a){return v(a)===m};reactIs_production_min$1.isSuspenseList=function(a){return v(a)===n};
|
|
1426
|
+
reactIs_production_min$1.isValidElementType=function(a){return "string"===typeof a||"function"===typeof a||a===d||a===f||a===e||a===m||a===n||a===t||"object"===typeof a&&null!==a&&(a.$$typeof===q||a.$$typeof===p||a.$$typeof===g||a.$$typeof===h||a.$$typeof===l||a.$$typeof===u||void 0!==a.getModuleId)?true:false};reactIs_production_min$1.typeOf=v;
|
|
1427
|
+
return reactIs_production_min$1;
|
|
1428
|
+
}
|
|
1429
|
+
|
|
1430
|
+
var reactIs_development$1 = {};
|
|
1431
|
+
|
|
1432
|
+
/**
|
|
1433
|
+
* @license React
|
|
1434
|
+
* react-is.development.js
|
|
1435
|
+
*
|
|
1436
|
+
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
1437
|
+
*
|
|
1438
|
+
* This source code is licensed under the MIT license found in the
|
|
1439
|
+
* LICENSE file in the root directory of this source tree.
|
|
1440
|
+
*/
|
|
1441
|
+
|
|
1442
|
+
var hasRequiredReactIs_development$1;
|
|
1443
|
+
|
|
1444
|
+
function requireReactIs_development$1 () {
|
|
1445
|
+
if (hasRequiredReactIs_development$1) return reactIs_development$1;
|
|
1446
|
+
hasRequiredReactIs_development$1 = 1;
|
|
1447
|
+
|
|
1448
|
+
if (process.env.NODE_ENV !== "production") {
|
|
1449
|
+
(function() {
|
|
1450
|
+
|
|
1451
|
+
// ATTENTION
|
|
1452
|
+
// When adding new symbols to this file,
|
|
1453
|
+
// Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols'
|
|
1454
|
+
// The Symbol used to tag the ReactElement-like types.
|
|
1455
|
+
var REACT_ELEMENT_TYPE = Symbol.for('react.element');
|
|
1456
|
+
var REACT_PORTAL_TYPE = Symbol.for('react.portal');
|
|
1457
|
+
var REACT_FRAGMENT_TYPE = Symbol.for('react.fragment');
|
|
1458
|
+
var REACT_STRICT_MODE_TYPE = Symbol.for('react.strict_mode');
|
|
1459
|
+
var REACT_PROFILER_TYPE = Symbol.for('react.profiler');
|
|
1460
|
+
var REACT_PROVIDER_TYPE = Symbol.for('react.provider');
|
|
1461
|
+
var REACT_CONTEXT_TYPE = Symbol.for('react.context');
|
|
1462
|
+
var REACT_SERVER_CONTEXT_TYPE = Symbol.for('react.server_context');
|
|
1463
|
+
var REACT_FORWARD_REF_TYPE = Symbol.for('react.forward_ref');
|
|
1464
|
+
var REACT_SUSPENSE_TYPE = Symbol.for('react.suspense');
|
|
1465
|
+
var REACT_SUSPENSE_LIST_TYPE = Symbol.for('react.suspense_list');
|
|
1466
|
+
var REACT_MEMO_TYPE = Symbol.for('react.memo');
|
|
1467
|
+
var REACT_LAZY_TYPE = Symbol.for('react.lazy');
|
|
1468
|
+
var REACT_OFFSCREEN_TYPE = Symbol.for('react.offscreen');
|
|
1469
|
+
|
|
1470
|
+
// -----------------------------------------------------------------------------
|
|
1471
|
+
|
|
1472
|
+
var enableScopeAPI = false; // Experimental Create Event Handle API.
|
|
1473
|
+
var enableCacheElement = false;
|
|
1474
|
+
var enableTransitionTracing = false; // No known bugs, but needs performance testing
|
|
1475
|
+
|
|
1476
|
+
var enableLegacyHidden = false; // Enables unstable_avoidThisFallback feature in Fiber
|
|
1477
|
+
// stuff. Intended to enable React core members to more easily debug scheduling
|
|
1478
|
+
// issues in DEV builds.
|
|
1479
|
+
|
|
1480
|
+
var enableDebugTracing = false; // Track which Fiber(s) schedule render work.
|
|
1481
|
+
|
|
1482
|
+
var REACT_MODULE_REFERENCE;
|
|
1483
|
+
|
|
1484
|
+
{
|
|
1485
|
+
REACT_MODULE_REFERENCE = Symbol.for('react.module.reference');
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1488
|
+
function isValidElementType(type) {
|
|
1489
|
+
if (typeof type === 'string' || typeof type === 'function') {
|
|
1490
|
+
return true;
|
|
1491
|
+
} // Note: typeof might be other than 'symbol' or 'number' (e.g. if it's a polyfill).
|
|
1492
|
+
|
|
1493
|
+
|
|
1494
|
+
if (type === REACT_FRAGMENT_TYPE || type === REACT_PROFILER_TYPE || enableDebugTracing || type === REACT_STRICT_MODE_TYPE || type === REACT_SUSPENSE_TYPE || type === REACT_SUSPENSE_LIST_TYPE || enableLegacyHidden || type === REACT_OFFSCREEN_TYPE || enableScopeAPI || enableCacheElement || enableTransitionTracing ) {
|
|
1495
|
+
return true;
|
|
1496
|
+
}
|
|
1497
|
+
|
|
1498
|
+
if (typeof type === 'object' && type !== null) {
|
|
1499
|
+
if (type.$$typeof === REACT_LAZY_TYPE || type.$$typeof === REACT_MEMO_TYPE || type.$$typeof === REACT_PROVIDER_TYPE || type.$$typeof === REACT_CONTEXT_TYPE || type.$$typeof === REACT_FORWARD_REF_TYPE || // This needs to include all possible module reference object
|
|
1500
|
+
// types supported by any Flight configuration anywhere since
|
|
1501
|
+
// we don't know which Flight build this will end up being used
|
|
1502
|
+
// with.
|
|
1503
|
+
type.$$typeof === REACT_MODULE_REFERENCE || type.getModuleId !== undefined) {
|
|
1504
|
+
return true;
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1508
|
+
return false;
|
|
1509
|
+
}
|
|
1510
|
+
|
|
1511
|
+
function typeOf(object) {
|
|
1512
|
+
if (typeof object === 'object' && object !== null) {
|
|
1513
|
+
var $$typeof = object.$$typeof;
|
|
1514
|
+
|
|
1515
|
+
switch ($$typeof) {
|
|
1516
|
+
case REACT_ELEMENT_TYPE:
|
|
1517
|
+
var type = object.type;
|
|
1518
|
+
|
|
1519
|
+
switch (type) {
|
|
1520
|
+
case REACT_FRAGMENT_TYPE:
|
|
1521
|
+
case REACT_PROFILER_TYPE:
|
|
1522
|
+
case REACT_STRICT_MODE_TYPE:
|
|
1523
|
+
case REACT_SUSPENSE_TYPE:
|
|
1524
|
+
case REACT_SUSPENSE_LIST_TYPE:
|
|
1525
|
+
return type;
|
|
1526
|
+
|
|
1527
|
+
default:
|
|
1528
|
+
var $$typeofType = type && type.$$typeof;
|
|
1529
|
+
|
|
1530
|
+
switch ($$typeofType) {
|
|
1531
|
+
case REACT_SERVER_CONTEXT_TYPE:
|
|
1532
|
+
case REACT_CONTEXT_TYPE:
|
|
1533
|
+
case REACT_FORWARD_REF_TYPE:
|
|
1534
|
+
case REACT_LAZY_TYPE:
|
|
1535
|
+
case REACT_MEMO_TYPE:
|
|
1536
|
+
case REACT_PROVIDER_TYPE:
|
|
1537
|
+
return $$typeofType;
|
|
1538
|
+
|
|
1539
|
+
default:
|
|
1540
|
+
return $$typeof;
|
|
1541
|
+
}
|
|
1542
|
+
|
|
1543
|
+
}
|
|
1544
|
+
|
|
1545
|
+
case REACT_PORTAL_TYPE:
|
|
1546
|
+
return $$typeof;
|
|
1547
|
+
}
|
|
1548
|
+
}
|
|
1549
|
+
|
|
1550
|
+
return undefined;
|
|
1551
|
+
}
|
|
1552
|
+
var ContextConsumer = REACT_CONTEXT_TYPE;
|
|
1553
|
+
var ContextProvider = REACT_PROVIDER_TYPE;
|
|
1554
|
+
var Element = REACT_ELEMENT_TYPE;
|
|
1555
|
+
var ForwardRef = REACT_FORWARD_REF_TYPE;
|
|
1556
|
+
var Fragment = REACT_FRAGMENT_TYPE;
|
|
1557
|
+
var Lazy = REACT_LAZY_TYPE;
|
|
1558
|
+
var Memo = REACT_MEMO_TYPE;
|
|
1559
|
+
var Portal = REACT_PORTAL_TYPE;
|
|
1560
|
+
var Profiler = REACT_PROFILER_TYPE;
|
|
1561
|
+
var StrictMode = REACT_STRICT_MODE_TYPE;
|
|
1562
|
+
var Suspense = REACT_SUSPENSE_TYPE;
|
|
1563
|
+
var SuspenseList = REACT_SUSPENSE_LIST_TYPE;
|
|
1564
|
+
var hasWarnedAboutDeprecatedIsAsyncMode = false;
|
|
1565
|
+
var hasWarnedAboutDeprecatedIsConcurrentMode = false; // AsyncMode should be deprecated
|
|
1566
|
+
|
|
1567
|
+
function isAsyncMode(object) {
|
|
1568
|
+
{
|
|
1569
|
+
if (!hasWarnedAboutDeprecatedIsAsyncMode) {
|
|
1570
|
+
hasWarnedAboutDeprecatedIsAsyncMode = true; // Using console['warn'] to evade Babel and ESLint
|
|
1571
|
+
|
|
1572
|
+
console['warn']('The ReactIs.isAsyncMode() alias has been deprecated, ' + 'and will be removed in React 18+.');
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
|
|
1576
|
+
return false;
|
|
1577
|
+
}
|
|
1578
|
+
function isConcurrentMode(object) {
|
|
1579
|
+
{
|
|
1580
|
+
if (!hasWarnedAboutDeprecatedIsConcurrentMode) {
|
|
1581
|
+
hasWarnedAboutDeprecatedIsConcurrentMode = true; // Using console['warn'] to evade Babel and ESLint
|
|
1582
|
+
|
|
1583
|
+
console['warn']('The ReactIs.isConcurrentMode() alias has been deprecated, ' + 'and will be removed in React 18+.');
|
|
1584
|
+
}
|
|
1585
|
+
}
|
|
1586
|
+
|
|
1587
|
+
return false;
|
|
1588
|
+
}
|
|
1589
|
+
function isContextConsumer(object) {
|
|
1590
|
+
return typeOf(object) === REACT_CONTEXT_TYPE;
|
|
1591
|
+
}
|
|
1592
|
+
function isContextProvider(object) {
|
|
1593
|
+
return typeOf(object) === REACT_PROVIDER_TYPE;
|
|
1594
|
+
}
|
|
1595
|
+
function isElement(object) {
|
|
1596
|
+
return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE;
|
|
1597
|
+
}
|
|
1598
|
+
function isForwardRef(object) {
|
|
1599
|
+
return typeOf(object) === REACT_FORWARD_REF_TYPE;
|
|
1600
|
+
}
|
|
1601
|
+
function isFragment(object) {
|
|
1602
|
+
return typeOf(object) === REACT_FRAGMENT_TYPE;
|
|
1603
|
+
}
|
|
1604
|
+
function isLazy(object) {
|
|
1605
|
+
return typeOf(object) === REACT_LAZY_TYPE;
|
|
1606
|
+
}
|
|
1607
|
+
function isMemo(object) {
|
|
1608
|
+
return typeOf(object) === REACT_MEMO_TYPE;
|
|
1609
|
+
}
|
|
1610
|
+
function isPortal(object) {
|
|
1611
|
+
return typeOf(object) === REACT_PORTAL_TYPE;
|
|
1612
|
+
}
|
|
1613
|
+
function isProfiler(object) {
|
|
1614
|
+
return typeOf(object) === REACT_PROFILER_TYPE;
|
|
1615
|
+
}
|
|
1616
|
+
function isStrictMode(object) {
|
|
1617
|
+
return typeOf(object) === REACT_STRICT_MODE_TYPE;
|
|
1618
|
+
}
|
|
1619
|
+
function isSuspense(object) {
|
|
1620
|
+
return typeOf(object) === REACT_SUSPENSE_TYPE;
|
|
1621
|
+
}
|
|
1622
|
+
function isSuspenseList(object) {
|
|
1623
|
+
return typeOf(object) === REACT_SUSPENSE_LIST_TYPE;
|
|
1624
|
+
}
|
|
1625
|
+
|
|
1626
|
+
reactIs_development$1.ContextConsumer = ContextConsumer;
|
|
1627
|
+
reactIs_development$1.ContextProvider = ContextProvider;
|
|
1628
|
+
reactIs_development$1.Element = Element;
|
|
1629
|
+
reactIs_development$1.ForwardRef = ForwardRef;
|
|
1630
|
+
reactIs_development$1.Fragment = Fragment;
|
|
1631
|
+
reactIs_development$1.Lazy = Lazy;
|
|
1632
|
+
reactIs_development$1.Memo = Memo;
|
|
1633
|
+
reactIs_development$1.Portal = Portal;
|
|
1634
|
+
reactIs_development$1.Profiler = Profiler;
|
|
1635
|
+
reactIs_development$1.StrictMode = StrictMode;
|
|
1636
|
+
reactIs_development$1.Suspense = Suspense;
|
|
1637
|
+
reactIs_development$1.SuspenseList = SuspenseList;
|
|
1638
|
+
reactIs_development$1.isAsyncMode = isAsyncMode;
|
|
1639
|
+
reactIs_development$1.isConcurrentMode = isConcurrentMode;
|
|
1640
|
+
reactIs_development$1.isContextConsumer = isContextConsumer;
|
|
1641
|
+
reactIs_development$1.isContextProvider = isContextProvider;
|
|
1642
|
+
reactIs_development$1.isElement = isElement;
|
|
1643
|
+
reactIs_development$1.isForwardRef = isForwardRef;
|
|
1644
|
+
reactIs_development$1.isFragment = isFragment;
|
|
1645
|
+
reactIs_development$1.isLazy = isLazy;
|
|
1646
|
+
reactIs_development$1.isMemo = isMemo;
|
|
1647
|
+
reactIs_development$1.isPortal = isPortal;
|
|
1648
|
+
reactIs_development$1.isProfiler = isProfiler;
|
|
1649
|
+
reactIs_development$1.isStrictMode = isStrictMode;
|
|
1650
|
+
reactIs_development$1.isSuspense = isSuspense;
|
|
1651
|
+
reactIs_development$1.isSuspenseList = isSuspenseList;
|
|
1652
|
+
reactIs_development$1.isValidElementType = isValidElementType;
|
|
1653
|
+
reactIs_development$1.typeOf = typeOf;
|
|
1654
|
+
})();
|
|
1655
|
+
}
|
|
1656
|
+
return reactIs_development$1;
|
|
1657
|
+
}
|
|
1658
|
+
|
|
1659
|
+
var hasRequiredReactIs$1;
|
|
1660
|
+
|
|
1661
|
+
function requireReactIs$1 () {
|
|
1662
|
+
if (hasRequiredReactIs$1) return reactIs$1.exports;
|
|
1663
|
+
hasRequiredReactIs$1 = 1;
|
|
1664
|
+
|
|
1665
|
+
if (process.env.NODE_ENV === 'production') {
|
|
1666
|
+
reactIs$1.exports = requireReactIs_production_min$1();
|
|
1667
|
+
} else {
|
|
1668
|
+
reactIs$1.exports = requireReactIs_development$1();
|
|
1669
|
+
}
|
|
1670
|
+
return reactIs$1.exports;
|
|
1671
|
+
}
|
|
1672
|
+
|
|
1673
|
+
var reactIsExports = requireReactIs$1();
|
|
1674
|
+
|
|
1675
|
+
function useMemo(getValue, condition, shouldUpdate) {
|
|
1676
|
+
const cacheRef = React__namespace.useRef({});
|
|
1677
|
+
if (!('value' in cacheRef.current) || shouldUpdate(cacheRef.current.condition, condition)) {
|
|
1678
|
+
cacheRef.current.value = getValue();
|
|
1679
|
+
cacheRef.current.condition = condition;
|
|
1680
|
+
}
|
|
1681
|
+
return cacheRef.current.value;
|
|
1682
|
+
}
|
|
1683
|
+
|
|
1684
|
+
const REACT_ELEMENT_TYPE_18 = Symbol.for('react.element');
|
|
1685
|
+
const REACT_ELEMENT_TYPE_19 = Symbol.for('react.transitional.element');
|
|
1686
|
+
const REACT_FRAGMENT_TYPE = Symbol.for('react.fragment');
|
|
1687
|
+
|
|
1688
|
+
/**
|
|
1689
|
+
* Compatible with React 18 or 19 to check if node is a Fragment.
|
|
1690
|
+
*/
|
|
1691
|
+
function isFragment(object) {
|
|
1692
|
+
return (
|
|
1693
|
+
// Base object type
|
|
1694
|
+
object && typeof object === 'object' && (
|
|
1695
|
+
// React Element type
|
|
1696
|
+
object.$$typeof === REACT_ELEMENT_TYPE_18 || object.$$typeof === REACT_ELEMENT_TYPE_19) &&
|
|
1697
|
+
// React Fragment type
|
|
1698
|
+
object.type === REACT_FRAGMENT_TYPE
|
|
1699
|
+
);
|
|
1700
|
+
}
|
|
1701
|
+
|
|
1702
|
+
const ReactMajorVersion = Number(React.version.split('.')[0]);
|
|
1703
|
+
const fillRef = (ref, node) => {
|
|
1704
|
+
if (typeof ref === 'function') {
|
|
1705
|
+
ref(node);
|
|
1706
|
+
} else if (typeof ref === 'object' && ref && 'current' in ref) {
|
|
1707
|
+
ref.current = node;
|
|
1708
|
+
}
|
|
1709
|
+
};
|
|
1710
|
+
|
|
1711
|
+
/**
|
|
1712
|
+
* Merge refs into one ref function to support ref passing.
|
|
1713
|
+
*/
|
|
1714
|
+
const composeRef = (...refs) => {
|
|
1715
|
+
const refList = refs.filter(Boolean);
|
|
1716
|
+
if (refList.length <= 1) {
|
|
1717
|
+
return refList[0];
|
|
1718
|
+
}
|
|
1719
|
+
return node => {
|
|
1720
|
+
refs.forEach(ref => {
|
|
1721
|
+
fillRef(ref, node);
|
|
1722
|
+
});
|
|
1723
|
+
};
|
|
1724
|
+
};
|
|
1725
|
+
const useComposeRef = (...refs) => {
|
|
1726
|
+
return useMemo(() => composeRef(...refs),
|
|
1727
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1728
|
+
refs, (prev, next) => prev.length !== next.length || prev.every((ref, i) => ref !== next[i]));
|
|
1729
|
+
};
|
|
1730
|
+
const supportRef = nodeOrComponent => {
|
|
1731
|
+
if (!nodeOrComponent) {
|
|
1732
|
+
return false;
|
|
1733
|
+
}
|
|
1734
|
+
|
|
1735
|
+
// React 19 no need `forwardRef` anymore. So just pass if is a React element.
|
|
1736
|
+
if (isReactElement(nodeOrComponent) && ReactMajorVersion >= 19) {
|
|
1737
|
+
return true;
|
|
1738
|
+
}
|
|
1739
|
+
const type = reactIsExports.isMemo(nodeOrComponent) ? nodeOrComponent.type.type : nodeOrComponent.type;
|
|
1740
|
+
|
|
1741
|
+
// Function component node
|
|
1742
|
+
if (typeof type === 'function' && !type.prototype?.render && type.$$typeof !== reactIsExports.ForwardRef) {
|
|
1743
|
+
return false;
|
|
1744
|
+
}
|
|
1745
|
+
|
|
1746
|
+
// Class component
|
|
1747
|
+
if (typeof nodeOrComponent === 'function' && !nodeOrComponent.prototype?.render && nodeOrComponent.$$typeof !== reactIsExports.ForwardRef) {
|
|
1748
|
+
return false;
|
|
1749
|
+
}
|
|
1750
|
+
return true;
|
|
1751
|
+
};
|
|
1752
|
+
function isReactElement(node) {
|
|
1753
|
+
return /*#__PURE__*/React.isValidElement(node) && !isFragment(node);
|
|
1754
|
+
}
|
|
1755
|
+
|
|
1756
|
+
/**
|
|
1757
|
+
* In React 19. `ref` is not a property from node.
|
|
1758
|
+
* But a property from `props.ref`.
|
|
1759
|
+
* To check if `props.ref` exist or fallback to `ref`.
|
|
1760
|
+
*/
|
|
1761
|
+
const getNodeRef = node => {
|
|
1762
|
+
if (node && isReactElement(node)) {
|
|
1763
|
+
const ele = node;
|
|
1764
|
+
|
|
1765
|
+
// Source from:
|
|
1766
|
+
// https://github.com/mui/material-ui/blob/master/packages/mui-utils/src/getReactNodeRef/getReactNodeRef.ts
|
|
1767
|
+
return ele.props.propertyIsEnumerable('ref') ? ele.props.ref : ele.ref;
|
|
1768
|
+
}
|
|
1769
|
+
return null;
|
|
1770
|
+
};
|
|
1771
|
+
|
|
1772
|
+
/* eslint-disable no-console */
|
|
1773
|
+
let warned = {};
|
|
1774
|
+
const preWarningFns = [];
|
|
1775
|
+
|
|
1776
|
+
/**
|
|
1777
|
+
* Pre warning enable you to parse content before console.error.
|
|
1778
|
+
* Modify to null will prevent warning.
|
|
1779
|
+
*/
|
|
1780
|
+
const preMessage = fn => {
|
|
1781
|
+
preWarningFns.push(fn);
|
|
1782
|
+
};
|
|
1783
|
+
|
|
1784
|
+
/**
|
|
1785
|
+
* Warning if condition not match.
|
|
1786
|
+
* @param valid Condition
|
|
1787
|
+
* @param message Warning message
|
|
1788
|
+
* @example
|
|
1789
|
+
* ```js
|
|
1790
|
+
* warning(false, 'some error'); // print some error
|
|
1791
|
+
* warning(true, 'some error'); // print nothing
|
|
1792
|
+
* warning(1 === 2, 'some error'); // print some error
|
|
1793
|
+
* ```
|
|
1794
|
+
*/
|
|
1795
|
+
function warning(valid, message) {
|
|
1796
|
+
if (process.env.NODE_ENV !== 'production' && !valid && console !== undefined) {
|
|
1797
|
+
const finalMessage = preWarningFns.reduce((msg, preMessageFn) => preMessageFn(msg ?? '', 'warning'), message);
|
|
1798
|
+
if (finalMessage) {
|
|
1799
|
+
console.error(`Warning: ${finalMessage}`);
|
|
1800
|
+
}
|
|
1801
|
+
}
|
|
1802
|
+
}
|
|
1803
|
+
|
|
1804
|
+
/** @see Similar to {@link warning} */
|
|
1805
|
+
function note(valid, message) {
|
|
1806
|
+
if (process.env.NODE_ENV !== 'production' && !valid && console !== undefined) {
|
|
1807
|
+
const finalMessage = preWarningFns.reduce((msg, preMessageFn) => preMessageFn(msg ?? '', 'note'), message);
|
|
1808
|
+
if (finalMessage) {
|
|
1809
|
+
console.warn(`Note: ${finalMessage}`);
|
|
1810
|
+
}
|
|
1811
|
+
}
|
|
1812
|
+
}
|
|
1813
|
+
function resetWarned() {
|
|
1814
|
+
warned = {};
|
|
1815
|
+
}
|
|
1816
|
+
function call(method, valid, message) {
|
|
1817
|
+
if (!valid && !warned[message]) {
|
|
1818
|
+
method(false, message);
|
|
1819
|
+
warned[message] = true;
|
|
1820
|
+
}
|
|
1821
|
+
}
|
|
1822
|
+
|
|
1823
|
+
/** @see Same as {@link warning}, but only warn once for the same message */
|
|
1824
|
+
function warningOnce(valid, message) {
|
|
1825
|
+
call(warning, valid, message);
|
|
1826
|
+
}
|
|
1827
|
+
|
|
1828
|
+
/** @see Same as {@link warning}, but only warn once for the same message */
|
|
1829
|
+
function noteOnce(valid, message) {
|
|
1830
|
+
call(note, valid, message);
|
|
1831
|
+
}
|
|
1832
|
+
warningOnce.preMessage = preMessage;
|
|
1833
|
+
warningOnce.resetWarned = resetWarned;
|
|
1834
|
+
warningOnce.noteOnce = noteOnce;
|
|
1835
|
+
|
|
1836
|
+
const OrderContext = /*#__PURE__*/React__namespace.createContext(null);
|
|
1837
|
+
|
|
1838
|
+
let inline = false;
|
|
1839
|
+
function inlineMock(nextInline) {
|
|
1840
|
+
return inline;
|
|
1841
|
+
}
|
|
1842
|
+
|
|
1843
|
+
/**
|
|
1844
|
+
* Wrap `React.useLayoutEffect` which will not throw warning message in test env
|
|
1845
|
+
*/
|
|
1846
|
+
const useInternalLayoutEffect = process.env.NODE_ENV !== 'test' && canUseDom() ? React__namespace.useLayoutEffect : React__namespace.useEffect;
|
|
1847
|
+
const useLayoutEffect = (callback, deps) => {
|
|
1848
|
+
const firstMountRef = React__namespace.useRef(true);
|
|
1849
|
+
useInternalLayoutEffect(() => {
|
|
1850
|
+
return callback(firstMountRef.current);
|
|
1851
|
+
}, deps);
|
|
1852
|
+
|
|
1853
|
+
// We tell react that first mount has passed
|
|
1854
|
+
useInternalLayoutEffect(() => {
|
|
1855
|
+
firstMountRef.current = false;
|
|
1856
|
+
return () => {
|
|
1857
|
+
firstMountRef.current = true;
|
|
1858
|
+
};
|
|
1859
|
+
}, []);
|
|
1860
|
+
};
|
|
1861
|
+
|
|
1862
|
+
const EMPTY_LIST = [];
|
|
1863
|
+
|
|
1864
|
+
/**
|
|
1865
|
+
* Will add `div` to document. Nest call will keep order
|
|
1866
|
+
* @param render Render DOM in document
|
|
1867
|
+
*/
|
|
1868
|
+
function useDom(render, debug) {
|
|
1869
|
+
const [ele] = React__namespace.useState(() => {
|
|
1870
|
+
if (!canUseDom()) {
|
|
1871
|
+
return null;
|
|
1872
|
+
}
|
|
1873
|
+
const defaultEle = document.createElement('div');
|
|
1874
|
+
if (process.env.NODE_ENV !== 'production' && debug) {
|
|
1875
|
+
defaultEle.setAttribute('data-debug', debug);
|
|
1876
|
+
}
|
|
1877
|
+
return defaultEle;
|
|
1878
|
+
});
|
|
1879
|
+
|
|
1880
|
+
// ========================== Order ==========================
|
|
1881
|
+
const appendedRef = React__namespace.useRef(false);
|
|
1882
|
+
const queueCreate = React__namespace.useContext(OrderContext);
|
|
1883
|
+
const [queue, setQueue] = React__namespace.useState(EMPTY_LIST);
|
|
1884
|
+
const mergedQueueCreate = queueCreate || (appendedRef.current ? undefined : appendFn => {
|
|
1885
|
+
setQueue(origin => {
|
|
1886
|
+
const newQueue = [appendFn, ...origin];
|
|
1887
|
+
return newQueue;
|
|
1888
|
+
});
|
|
1889
|
+
});
|
|
1890
|
+
|
|
1891
|
+
// =========================== DOM ===========================
|
|
1892
|
+
function append() {
|
|
1893
|
+
if (!ele.parentElement) {
|
|
1894
|
+
document.body.appendChild(ele);
|
|
1895
|
+
}
|
|
1896
|
+
appendedRef.current = true;
|
|
1897
|
+
}
|
|
1898
|
+
function cleanup() {
|
|
1899
|
+
ele.parentElement?.removeChild(ele);
|
|
1900
|
+
appendedRef.current = false;
|
|
1901
|
+
}
|
|
1902
|
+
useLayoutEffect(() => {
|
|
1903
|
+
if (render) {
|
|
1904
|
+
if (queueCreate) {
|
|
1905
|
+
queueCreate(append);
|
|
1906
|
+
} else {
|
|
1907
|
+
append();
|
|
1908
|
+
}
|
|
1909
|
+
} else {
|
|
1910
|
+
cleanup();
|
|
1911
|
+
}
|
|
1912
|
+
return cleanup;
|
|
1913
|
+
}, [render]);
|
|
1914
|
+
useLayoutEffect(() => {
|
|
1915
|
+
if (queue.length) {
|
|
1916
|
+
queue.forEach(appendFn => appendFn());
|
|
1917
|
+
setQueue(EMPTY_LIST);
|
|
1918
|
+
}
|
|
1919
|
+
}, [queue]);
|
|
1920
|
+
return [ele, mergedQueueCreate];
|
|
1921
|
+
}
|
|
1922
|
+
|
|
1923
|
+
function contains(root, n) {
|
|
1924
|
+
if (!root) {
|
|
1925
|
+
return false;
|
|
1926
|
+
}
|
|
1927
|
+
|
|
1928
|
+
// Use native if support
|
|
1929
|
+
if (root.contains) {
|
|
1930
|
+
return root.contains(n);
|
|
1931
|
+
}
|
|
1932
|
+
|
|
1933
|
+
// `document.contains` not support with IE11
|
|
1934
|
+
let node = n;
|
|
1935
|
+
while (node) {
|
|
1936
|
+
if (node === root) {
|
|
1937
|
+
return true;
|
|
1938
|
+
}
|
|
1939
|
+
node = node.parentNode;
|
|
1940
|
+
}
|
|
1941
|
+
return false;
|
|
1942
|
+
}
|
|
1943
|
+
|
|
1944
|
+
const APPEND_ORDER = 'data-rc-order';
|
|
1945
|
+
const APPEND_PRIORITY = 'data-rc-priority';
|
|
1946
|
+
const MARK_KEY = `rc-util-key`;
|
|
1947
|
+
const containerCache = new Map();
|
|
1948
|
+
function getMark({
|
|
1949
|
+
mark
|
|
1950
|
+
} = {}) {
|
|
1951
|
+
if (mark) {
|
|
1952
|
+
return mark.startsWith('data-') ? mark : `data-${mark}`;
|
|
1953
|
+
}
|
|
1954
|
+
return MARK_KEY;
|
|
1955
|
+
}
|
|
1956
|
+
function getContainer(option) {
|
|
1957
|
+
if (option.attachTo) {
|
|
1958
|
+
return option.attachTo;
|
|
1959
|
+
}
|
|
1960
|
+
const head = document.querySelector('head');
|
|
1961
|
+
return head || document.body;
|
|
1962
|
+
}
|
|
1963
|
+
function getOrder(prepend) {
|
|
1964
|
+
if (prepend === 'queue') {
|
|
1965
|
+
return 'prependQueue';
|
|
1966
|
+
}
|
|
1967
|
+
return prepend ? 'prepend' : 'append';
|
|
1968
|
+
}
|
|
1969
|
+
|
|
1970
|
+
/**
|
|
1971
|
+
* Find style which inject by rc-util
|
|
1972
|
+
*/
|
|
1973
|
+
function findStyles(container) {
|
|
1974
|
+
return Array.from((containerCache.get(container) || container).children).filter(node => node.tagName === 'STYLE');
|
|
1975
|
+
}
|
|
1976
|
+
function injectCSS(css, option = {}) {
|
|
1977
|
+
if (!canUseDom()) {
|
|
1978
|
+
return null;
|
|
1979
|
+
}
|
|
1980
|
+
const {
|
|
1981
|
+
csp,
|
|
1982
|
+
prepend,
|
|
1983
|
+
priority = 0
|
|
1984
|
+
} = option;
|
|
1985
|
+
const mergedOrder = getOrder(prepend);
|
|
1986
|
+
const isPrependQueue = mergedOrder === 'prependQueue';
|
|
1987
|
+
const styleNode = document.createElement('style');
|
|
1988
|
+
styleNode.setAttribute(APPEND_ORDER, mergedOrder);
|
|
1989
|
+
if (isPrependQueue && priority) {
|
|
1990
|
+
styleNode.setAttribute(APPEND_PRIORITY, `${priority}`);
|
|
1991
|
+
}
|
|
1992
|
+
if (csp?.nonce) {
|
|
1993
|
+
styleNode.nonce = csp?.nonce;
|
|
1994
|
+
}
|
|
1995
|
+
styleNode.innerHTML = css;
|
|
1996
|
+
const container = getContainer(option);
|
|
1997
|
+
const {
|
|
1998
|
+
firstChild
|
|
1999
|
+
} = container;
|
|
2000
|
+
if (prepend) {
|
|
2001
|
+
// If is queue `prepend`, it will prepend first style and then append rest style
|
|
2002
|
+
if (isPrependQueue) {
|
|
2003
|
+
const existStyle = (option.styles || findStyles(container)).filter(node => {
|
|
2004
|
+
// Ignore style which not injected by rc-util with prepend
|
|
2005
|
+
if (!['prepend', 'prependQueue'].includes(node.getAttribute(APPEND_ORDER))) {
|
|
2006
|
+
return false;
|
|
2007
|
+
}
|
|
2008
|
+
|
|
2009
|
+
// Ignore style which priority less then new style
|
|
2010
|
+
const nodePriority = Number(node.getAttribute(APPEND_PRIORITY) || 0);
|
|
2011
|
+
return priority >= nodePriority;
|
|
2012
|
+
});
|
|
2013
|
+
if (existStyle.length) {
|
|
2014
|
+
container.insertBefore(styleNode, existStyle[existStyle.length - 1].nextSibling);
|
|
2015
|
+
return styleNode;
|
|
2016
|
+
}
|
|
2017
|
+
}
|
|
2018
|
+
|
|
2019
|
+
// Use `insertBefore` as `prepend`
|
|
2020
|
+
container.insertBefore(styleNode, firstChild);
|
|
2021
|
+
} else {
|
|
2022
|
+
container.appendChild(styleNode);
|
|
2023
|
+
}
|
|
2024
|
+
return styleNode;
|
|
2025
|
+
}
|
|
2026
|
+
function findExistNode(key, option = {}) {
|
|
2027
|
+
let {
|
|
2028
|
+
styles
|
|
2029
|
+
} = option;
|
|
2030
|
+
styles ||= findStyles(getContainer(option));
|
|
2031
|
+
return styles.find(node => node.getAttribute(getMark(option)) === key);
|
|
2032
|
+
}
|
|
2033
|
+
function removeCSS(key, option = {}) {
|
|
2034
|
+
const existNode = findExistNode(key, option);
|
|
2035
|
+
if (existNode) {
|
|
2036
|
+
const container = getContainer(option);
|
|
2037
|
+
container.removeChild(existNode);
|
|
2038
|
+
}
|
|
2039
|
+
}
|
|
2040
|
+
|
|
2041
|
+
/**
|
|
2042
|
+
* qiankun will inject `appendChild` to insert into other
|
|
2043
|
+
*/
|
|
2044
|
+
function syncRealContainer(container, option) {
|
|
2045
|
+
const cachedRealContainer = containerCache.get(container);
|
|
2046
|
+
|
|
2047
|
+
// Find real container when not cached or cached container removed
|
|
2048
|
+
if (!cachedRealContainer || !contains(document, cachedRealContainer)) {
|
|
2049
|
+
const placeholderStyle = injectCSS('', option);
|
|
2050
|
+
const {
|
|
2051
|
+
parentNode
|
|
2052
|
+
} = placeholderStyle;
|
|
2053
|
+
containerCache.set(container, parentNode);
|
|
2054
|
+
container.removeChild(placeholderStyle);
|
|
2055
|
+
}
|
|
2056
|
+
}
|
|
2057
|
+
function updateCSS(css, key, originOption = {}) {
|
|
2058
|
+
const container = getContainer(originOption);
|
|
2059
|
+
const styles = findStyles(container);
|
|
2060
|
+
const option = {
|
|
2061
|
+
...originOption,
|
|
2062
|
+
styles
|
|
2063
|
+
};
|
|
2064
|
+
|
|
2065
|
+
// Sync real parent
|
|
2066
|
+
syncRealContainer(container, option);
|
|
2067
|
+
const existNode = findExistNode(key, option);
|
|
2068
|
+
if (existNode) {
|
|
2069
|
+
if (option.csp?.nonce && existNode.nonce !== option.csp?.nonce) {
|
|
2070
|
+
existNode.nonce = option.csp?.nonce;
|
|
2071
|
+
}
|
|
2072
|
+
if (existNode.innerHTML !== css) {
|
|
2073
|
+
existNode.innerHTML = css;
|
|
2074
|
+
}
|
|
2075
|
+
return existNode;
|
|
2076
|
+
}
|
|
2077
|
+
const newNode = injectCSS(css, option);
|
|
2078
|
+
newNode.setAttribute(getMark(option), key);
|
|
2079
|
+
return newNode;
|
|
2080
|
+
}
|
|
2081
|
+
|
|
2082
|
+
/* eslint-disable no-param-reassign */
|
|
2083
|
+
function measureScrollbarSize(ele) {
|
|
2084
|
+
const randomId = `rc-scrollbar-measure-${Math.random().toString(36).substring(7)}`;
|
|
2085
|
+
const measureEle = document.createElement('div');
|
|
2086
|
+
measureEle.id = randomId;
|
|
2087
|
+
|
|
2088
|
+
// Create Style
|
|
2089
|
+
const measureStyle = measureEle.style;
|
|
2090
|
+
measureStyle.position = 'absolute';
|
|
2091
|
+
measureStyle.left = '0';
|
|
2092
|
+
measureStyle.top = '0';
|
|
2093
|
+
measureStyle.width = '100px';
|
|
2094
|
+
measureStyle.height = '100px';
|
|
2095
|
+
measureStyle.overflow = 'scroll';
|
|
2096
|
+
|
|
2097
|
+
// Clone Style if needed
|
|
2098
|
+
let fallbackWidth;
|
|
2099
|
+
let fallbackHeight;
|
|
2100
|
+
if (ele) {
|
|
2101
|
+
const targetStyle = getComputedStyle(ele);
|
|
2102
|
+
measureStyle.scrollbarColor = targetStyle.scrollbarColor;
|
|
2103
|
+
measureStyle.scrollbarWidth = targetStyle.scrollbarWidth;
|
|
2104
|
+
|
|
2105
|
+
// Set Webkit style
|
|
2106
|
+
const webkitScrollbarStyle = getComputedStyle(ele, '::-webkit-scrollbar');
|
|
2107
|
+
const width = parseInt(webkitScrollbarStyle.width, 10);
|
|
2108
|
+
const height = parseInt(webkitScrollbarStyle.height, 10);
|
|
2109
|
+
|
|
2110
|
+
// Try wrap to handle CSP case
|
|
2111
|
+
try {
|
|
2112
|
+
const widthStyle = width ? `width: ${webkitScrollbarStyle.width};` : '';
|
|
2113
|
+
const heightStyle = height ? `height: ${webkitScrollbarStyle.height};` : '';
|
|
2114
|
+
updateCSS(`
|
|
2115
|
+
#${randomId}::-webkit-scrollbar {
|
|
2116
|
+
${widthStyle}
|
|
2117
|
+
${heightStyle}
|
|
2118
|
+
}`, randomId);
|
|
2119
|
+
} catch (e) {
|
|
2120
|
+
// Can't wrap, just log error
|
|
2121
|
+
console.error(e);
|
|
2122
|
+
|
|
2123
|
+
// Get from style directly
|
|
2124
|
+
fallbackWidth = width;
|
|
2125
|
+
fallbackHeight = height;
|
|
2126
|
+
}
|
|
2127
|
+
}
|
|
2128
|
+
document.body.appendChild(measureEle);
|
|
2129
|
+
|
|
2130
|
+
// Measure. Get fallback style if provided
|
|
2131
|
+
const scrollWidth = ele && fallbackWidth && !Number.isNaN(fallbackWidth) ? fallbackWidth : measureEle.offsetWidth - measureEle.clientWidth;
|
|
2132
|
+
const scrollHeight = ele && fallbackHeight && !Number.isNaN(fallbackHeight) ? fallbackHeight : measureEle.offsetHeight - measureEle.clientHeight;
|
|
2133
|
+
|
|
2134
|
+
// Clean up
|
|
2135
|
+
document.body.removeChild(measureEle);
|
|
2136
|
+
removeCSS(randomId);
|
|
2137
|
+
return {
|
|
2138
|
+
width: scrollWidth,
|
|
2139
|
+
height: scrollHeight
|
|
2140
|
+
};
|
|
2141
|
+
}
|
|
2142
|
+
function getTargetScrollBarSize(target) {
|
|
2143
|
+
if (typeof document === 'undefined' || !target || !(target instanceof Element)) {
|
|
2144
|
+
return {
|
|
2145
|
+
width: 0,
|
|
2146
|
+
height: 0
|
|
2147
|
+
};
|
|
2148
|
+
}
|
|
2149
|
+
return measureScrollbarSize(target);
|
|
2150
|
+
}
|
|
2151
|
+
|
|
2152
|
+
/**
|
|
2153
|
+
* Test usage export. Do not use in your production
|
|
2154
|
+
*/
|
|
2155
|
+
function isBodyOverflowing() {
|
|
2156
|
+
return document.body.scrollHeight > (window.innerHeight || document.documentElement.clientHeight) && window.innerWidth > document.body.offsetWidth;
|
|
2157
|
+
}
|
|
2158
|
+
|
|
2159
|
+
const UNIQUE_ID = `rc-util-locker-${Date.now()}`;
|
|
2160
|
+
let uuid$1 = 0;
|
|
2161
|
+
function useScrollLocker(lock) {
|
|
2162
|
+
const mergedLock = !!lock;
|
|
2163
|
+
const [id] = React__namespace.useState(() => {
|
|
2164
|
+
uuid$1 += 1;
|
|
2165
|
+
return `${UNIQUE_ID}_${uuid$1}`;
|
|
2166
|
+
});
|
|
2167
|
+
useLayoutEffect(() => {
|
|
2168
|
+
if (mergedLock) {
|
|
2169
|
+
const scrollbarSize = getTargetScrollBarSize(document.body).width;
|
|
2170
|
+
const isOverflow = isBodyOverflowing();
|
|
2171
|
+
updateCSS(`
|
|
2172
|
+
html body {
|
|
2173
|
+
overflow-y: hidden;
|
|
2174
|
+
${isOverflow ? `width: calc(100% - ${scrollbarSize}px);` : ''}
|
|
2175
|
+
}`, id);
|
|
2176
|
+
} else {
|
|
2177
|
+
removeCSS(id);
|
|
2178
|
+
}
|
|
2179
|
+
return () => {
|
|
2180
|
+
removeCSS(id);
|
|
2181
|
+
};
|
|
2182
|
+
}, [mergedLock, id]);
|
|
2183
|
+
}
|
|
2184
|
+
|
|
2185
|
+
const useEvent = callback => {
|
|
2186
|
+
const fnRef = React__namespace.useRef(callback);
|
|
2187
|
+
fnRef.current = callback;
|
|
2188
|
+
const memoFn = React__namespace.useCallback((...args) => fnRef.current?.(...args), []);
|
|
2189
|
+
return memoFn;
|
|
2190
|
+
};
|
|
2191
|
+
|
|
2192
|
+
/**
|
|
2193
|
+
* Same as React.useState but `setState` accept `ignoreDestroy` param to not to setState after destroyed.
|
|
2194
|
+
* We do not make this auto is to avoid real memory leak.
|
|
2195
|
+
* Developer should confirm it's safe to ignore themselves.
|
|
2196
|
+
*/
|
|
2197
|
+
const useSafeState = defaultValue => {
|
|
2198
|
+
const destroyRef = React__namespace.useRef(false);
|
|
2199
|
+
const [value, setValue] = React__namespace.useState(defaultValue);
|
|
2200
|
+
React__namespace.useEffect(() => {
|
|
2201
|
+
destroyRef.current = false;
|
|
2202
|
+
return () => {
|
|
2203
|
+
destroyRef.current = true;
|
|
2204
|
+
};
|
|
2205
|
+
}, []);
|
|
2206
|
+
function safeSetState(updater, ignoreDestroy) {
|
|
2207
|
+
if (ignoreDestroy && destroyRef.current) {
|
|
2208
|
+
return;
|
|
2209
|
+
}
|
|
2210
|
+
setValue(updater);
|
|
2211
|
+
}
|
|
2212
|
+
return [value, safeSetState];
|
|
2213
|
+
};
|
|
2214
|
+
|
|
2215
|
+
/**
|
|
2216
|
+
* Similar to `useState` but will use props value if provided.
|
|
2217
|
+
* From React 18, we do not need safe `useState` since it will not throw for unmounted update.
|
|
2218
|
+
* This hooks remove the `onChange` & `postState` logic since we only need basic merged state logic.
|
|
2219
|
+
*/
|
|
2220
|
+
function useControlledState(defaultStateValue, value) {
|
|
2221
|
+
const [innerValue, setInnerValue] = React.useState(defaultStateValue);
|
|
2222
|
+
const mergedValue = value !== undefined ? value : innerValue;
|
|
2223
|
+
useLayoutEffect(mount => {
|
|
2224
|
+
if (!mount) {
|
|
2225
|
+
setInnerValue(value);
|
|
2226
|
+
}
|
|
2227
|
+
}, [value]);
|
|
2228
|
+
return [
|
|
2229
|
+
// Value
|
|
2230
|
+
mergedValue,
|
|
2231
|
+
// Update function
|
|
2232
|
+
setInnerValue];
|
|
2233
|
+
}
|
|
2234
|
+
|
|
2235
|
+
function toArray$1(children, option = {}) {
|
|
2236
|
+
let ret = [];
|
|
2237
|
+
React.Children.forEach(children, child => {
|
|
2238
|
+
if ((child === undefined || child === null) && !option.keepEmpty) {
|
|
2239
|
+
return;
|
|
2240
|
+
}
|
|
2241
|
+
if (Array.isArray(child)) {
|
|
2242
|
+
ret = ret.concat(toArray$1(child));
|
|
2243
|
+
} else if (isFragment(child) && child.props) {
|
|
2244
|
+
ret = ret.concat(toArray$1(child.props.children, option));
|
|
2245
|
+
} else {
|
|
2246
|
+
ret.push(child);
|
|
2247
|
+
}
|
|
2248
|
+
});
|
|
2249
|
+
return ret;
|
|
2250
|
+
}
|
|
2251
|
+
|
|
2252
|
+
function getUseId() {
|
|
2253
|
+
// We need fully clone React function here to avoid webpack warning React 17 do not export `useId`
|
|
2254
|
+
const fullClone = {
|
|
2255
|
+
...React__namespace
|
|
2256
|
+
};
|
|
2257
|
+
return fullClone.useId;
|
|
2258
|
+
}
|
|
2259
|
+
let uuid = 0;
|
|
2260
|
+
const useOriginId = getUseId();
|
|
2261
|
+
var useId = useOriginId ?
|
|
2262
|
+
// Use React `useId`
|
|
2263
|
+
function useId(id) {
|
|
2264
|
+
const reactId = useOriginId();
|
|
2265
|
+
|
|
2266
|
+
// Developer passed id is single source of truth
|
|
2267
|
+
if (id) {
|
|
2268
|
+
return id;
|
|
2269
|
+
}
|
|
2270
|
+
|
|
2271
|
+
// Test env always return mock id
|
|
2272
|
+
if (process.env.NODE_ENV === 'test') {
|
|
2273
|
+
return 'test-id';
|
|
2274
|
+
}
|
|
2275
|
+
return reactId;
|
|
2276
|
+
} :
|
|
2277
|
+
// Use compatible of `useId`
|
|
2278
|
+
function useCompatId(id) {
|
|
2279
|
+
// Inner id for accessibility usage. Only work in client side
|
|
2280
|
+
const [innerId, setInnerId] = React__namespace.useState('ssr-id');
|
|
2281
|
+
React__namespace.useEffect(() => {
|
|
2282
|
+
const nextId = uuid;
|
|
2283
|
+
uuid += 1;
|
|
2284
|
+
setInnerId(`rc_unique_${nextId}`);
|
|
2285
|
+
}, []);
|
|
2286
|
+
|
|
2287
|
+
// Developer passed id is single source of truth
|
|
2288
|
+
if (id) {
|
|
2289
|
+
return id;
|
|
2290
|
+
}
|
|
2291
|
+
|
|
2292
|
+
// Test env always return mock id
|
|
2293
|
+
if (process.env.NODE_ENV === 'test') {
|
|
2294
|
+
return 'test-id';
|
|
2295
|
+
}
|
|
2296
|
+
|
|
2297
|
+
// Return react native id or inner id
|
|
2298
|
+
return innerId;
|
|
2299
|
+
};
|
|
2300
|
+
|
|
2301
|
+
let stack = [];
|
|
2302
|
+
const IME_LOCK_DURATION = 200;
|
|
2303
|
+
let lastCompositionEndTime = 0;
|
|
2304
|
+
|
|
2305
|
+
// Export for testing
|
|
2306
|
+
process.env.NODE_ENV === 'test' ? () => ({
|
|
2307
|
+
stack,
|
|
2308
|
+
reset: () => {
|
|
2309
|
+
// Not reset stack to ensure effect will clean up correctly
|
|
2310
|
+
lastCompositionEndTime = 0;
|
|
2311
|
+
}
|
|
2312
|
+
}) : null;
|
|
2313
|
+
|
|
2314
|
+
// Global event handlers
|
|
2315
|
+
const onGlobalKeyDown = event => {
|
|
2316
|
+
if (event.key === 'Escape' && !event.isComposing) {
|
|
2317
|
+
const now = Date.now();
|
|
2318
|
+
if (now - lastCompositionEndTime < IME_LOCK_DURATION) {
|
|
2319
|
+
return;
|
|
2320
|
+
}
|
|
2321
|
+
const len = stack.length;
|
|
2322
|
+
for (let i = len - 1; i >= 0; i -= 1) {
|
|
2323
|
+
stack[i].onEsc({
|
|
2324
|
+
top: i === len - 1,
|
|
2325
|
+
event
|
|
2326
|
+
});
|
|
2327
|
+
}
|
|
2328
|
+
}
|
|
2329
|
+
};
|
|
2330
|
+
const onGlobalCompositionEnd = () => {
|
|
2331
|
+
lastCompositionEndTime = Date.now();
|
|
2332
|
+
};
|
|
2333
|
+
function attachGlobalEventListeners() {
|
|
2334
|
+
window.addEventListener('keydown', onGlobalKeyDown);
|
|
2335
|
+
window.addEventListener('compositionend', onGlobalCompositionEnd);
|
|
2336
|
+
}
|
|
2337
|
+
function detachGlobalEventListeners() {
|
|
2338
|
+
if (stack.length === 0) {
|
|
2339
|
+
window.removeEventListener('keydown', onGlobalKeyDown);
|
|
2340
|
+
window.removeEventListener('compositionend', onGlobalCompositionEnd);
|
|
2341
|
+
}
|
|
2342
|
+
}
|
|
2343
|
+
function useEscKeyDown(open, onEsc) {
|
|
2344
|
+
const id = useId();
|
|
2345
|
+
const onEventEsc = useEvent(onEsc);
|
|
2346
|
+
const ensure = () => {
|
|
2347
|
+
if (!stack.find(item => item.id === id)) {
|
|
2348
|
+
stack.push({
|
|
2349
|
+
id,
|
|
2350
|
+
onEsc: onEventEsc
|
|
2351
|
+
});
|
|
2352
|
+
}
|
|
2353
|
+
};
|
|
2354
|
+
const clear = () => {
|
|
2355
|
+
stack = stack.filter(item => item.id !== id);
|
|
2356
|
+
};
|
|
2357
|
+
React.useMemo(() => {
|
|
2358
|
+
if (open) {
|
|
2359
|
+
ensure();
|
|
2360
|
+
} else if (!open) {
|
|
2361
|
+
clear();
|
|
2362
|
+
}
|
|
2363
|
+
}, [open]);
|
|
2364
|
+
React.useEffect(() => {
|
|
2365
|
+
if (open) {
|
|
2366
|
+
ensure();
|
|
2367
|
+
// Attach global event listeners
|
|
2368
|
+
attachGlobalEventListeners();
|
|
2369
|
+
return () => {
|
|
2370
|
+
clear();
|
|
2371
|
+
// Remove global event listeners if instances is empty
|
|
2372
|
+
detachGlobalEventListeners();
|
|
2373
|
+
};
|
|
2374
|
+
}
|
|
2375
|
+
}, [open]);
|
|
2376
|
+
}
|
|
2377
|
+
|
|
2378
|
+
const getPortalContainer = getContainer => {
|
|
2379
|
+
if (getContainer === false) {
|
|
2380
|
+
return false;
|
|
2381
|
+
}
|
|
2382
|
+
if (!canUseDom() || !getContainer) {
|
|
2383
|
+
return null;
|
|
2384
|
+
}
|
|
2385
|
+
if (typeof getContainer === 'string') {
|
|
2386
|
+
return document.querySelector(getContainer);
|
|
2387
|
+
}
|
|
2388
|
+
if (typeof getContainer === 'function') {
|
|
2389
|
+
return getContainer();
|
|
2390
|
+
}
|
|
2391
|
+
return getContainer;
|
|
2392
|
+
};
|
|
2393
|
+
const Portal = /*#__PURE__*/React__namespace.forwardRef((props, ref) => {
|
|
2394
|
+
const {
|
|
2395
|
+
open,
|
|
2396
|
+
autoLock,
|
|
2397
|
+
getContainer,
|
|
2398
|
+
debug,
|
|
2399
|
+
autoDestroy = true,
|
|
2400
|
+
children,
|
|
2401
|
+
onEsc
|
|
2402
|
+
} = props;
|
|
2403
|
+
const [shouldRender, setShouldRender] = React__namespace.useState(open);
|
|
2404
|
+
const mergedRender = shouldRender || open;
|
|
2405
|
+
|
|
2406
|
+
// ========================= Warning =========================
|
|
2407
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
2408
|
+
warningOnce(canUseDom() || !open, `Portal only work in client side. Please call 'useEffect' to show Portal instead default render in SSR.`);
|
|
2409
|
+
}
|
|
2410
|
+
|
|
2411
|
+
// ====================== Should Render ======================
|
|
2412
|
+
React__namespace.useEffect(() => {
|
|
2413
|
+
if (autoDestroy || open) {
|
|
2414
|
+
setShouldRender(open);
|
|
2415
|
+
}
|
|
2416
|
+
}, [open, autoDestroy]);
|
|
2417
|
+
|
|
2418
|
+
// ======================== Container ========================
|
|
2419
|
+
const [innerContainer, setInnerContainer] = React__namespace.useState(() => getPortalContainer(getContainer));
|
|
2420
|
+
React__namespace.useEffect(() => {
|
|
2421
|
+
const customizeContainer = getPortalContainer(getContainer);
|
|
2422
|
+
|
|
2423
|
+
// Tell component that we check this in effect which is safe to be `null`
|
|
2424
|
+
setInnerContainer(() =>
|
|
2425
|
+
// React do the state update even the value is the same,
|
|
2426
|
+
// Use function call to force React to compare update
|
|
2427
|
+
customizeContainer ?? null);
|
|
2428
|
+
});
|
|
2429
|
+
const [defaultContainer, queueCreate] = useDom(mergedRender && !innerContainer, debug);
|
|
2430
|
+
const mergedContainer = innerContainer ?? defaultContainer;
|
|
2431
|
+
|
|
2432
|
+
// ========================= Locker ==========================
|
|
2433
|
+
useScrollLocker(autoLock && open && canUseDom() && (mergedContainer === defaultContainer || mergedContainer === document.body));
|
|
2434
|
+
|
|
2435
|
+
// ========================= Esc Keydown ==========================
|
|
2436
|
+
useEscKeyDown(open, onEsc);
|
|
2437
|
+
|
|
2438
|
+
// =========================== Ref ===========================
|
|
2439
|
+
let childRef = null;
|
|
2440
|
+
if (children && supportRef(children) && ref) {
|
|
2441
|
+
childRef = getNodeRef(children);
|
|
2442
|
+
}
|
|
2443
|
+
const mergedRef = useComposeRef(childRef, ref);
|
|
2444
|
+
|
|
2445
|
+
// ========================= Render ==========================
|
|
2446
|
+
// Do not render when nothing need render
|
|
2447
|
+
// When innerContainer is `undefined`, it may not ready since user use ref in the same render
|
|
2448
|
+
if (!mergedRender || !canUseDom() || innerContainer === undefined) {
|
|
2449
|
+
return null;
|
|
2450
|
+
}
|
|
2451
|
+
|
|
2452
|
+
// Render inline
|
|
2453
|
+
const renderInline = mergedContainer === false || inlineMock();
|
|
2454
|
+
let reffedChildren = children;
|
|
2455
|
+
if (ref) {
|
|
2456
|
+
reffedChildren = /*#__PURE__*/React__namespace.cloneElement(children, {
|
|
2457
|
+
ref: mergedRef
|
|
2458
|
+
});
|
|
2459
|
+
}
|
|
2460
|
+
return /*#__PURE__*/React__namespace.createElement(OrderContext.Provider, {
|
|
2461
|
+
value: queueCreate
|
|
2462
|
+
}, renderInline ? reffedChildren : /*#__PURE__*/reactDom.createPortal(reffedChildren, mergedContainer));
|
|
2463
|
+
});
|
|
2464
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
2465
|
+
Portal.displayName = 'Portal';
|
|
2466
|
+
}
|
|
2467
|
+
|
|
2468
|
+
function isDOM(node) {
|
|
2469
|
+
// https://developer.mozilla.org/en-US/docs/Web/API/Element
|
|
2470
|
+
// Since XULElement is also subclass of Element, we only need HTMLElement and SVGElement
|
|
2471
|
+
return node instanceof HTMLElement || node instanceof SVGElement;
|
|
2472
|
+
}
|
|
2473
|
+
|
|
2474
|
+
/**
|
|
2475
|
+
* Retrieves a DOM node via a ref, and does not invoke `findDOMNode`.
|
|
2476
|
+
*/
|
|
2477
|
+
function getDOM(node) {
|
|
2478
|
+
if (node && typeof node === 'object' && isDOM(node.nativeElement)) {
|
|
2479
|
+
return node.nativeElement;
|
|
2480
|
+
}
|
|
2481
|
+
if (isDOM(node)) {
|
|
2482
|
+
return node;
|
|
2483
|
+
}
|
|
2484
|
+
return null;
|
|
2485
|
+
}
|
|
2486
|
+
|
|
2487
|
+
const CollectionContext = /*#__PURE__*/React__namespace.createContext(null);
|
|
2488
|
+
/**
|
|
2489
|
+
* Collect all the resize event from children ResizeObserver
|
|
2490
|
+
*/
|
|
2491
|
+
function Collection({
|
|
2492
|
+
children,
|
|
2493
|
+
onBatchResize
|
|
2494
|
+
}) {
|
|
2495
|
+
const resizeIdRef = React__namespace.useRef(0);
|
|
2496
|
+
const resizeInfosRef = React__namespace.useRef([]);
|
|
2497
|
+
const onCollectionResize = React__namespace.useContext(CollectionContext);
|
|
2498
|
+
const onResize = React__namespace.useCallback((size, element, data) => {
|
|
2499
|
+
resizeIdRef.current += 1;
|
|
2500
|
+
const currentId = resizeIdRef.current;
|
|
2501
|
+
resizeInfosRef.current.push({
|
|
2502
|
+
size,
|
|
2503
|
+
element,
|
|
2504
|
+
data
|
|
2505
|
+
});
|
|
2506
|
+
Promise.resolve().then(() => {
|
|
2507
|
+
if (currentId === resizeIdRef.current) {
|
|
2508
|
+
onBatchResize?.(resizeInfosRef.current);
|
|
2509
|
+
resizeInfosRef.current = [];
|
|
2510
|
+
}
|
|
2511
|
+
});
|
|
2512
|
+
|
|
2513
|
+
// Continue bubbling if parent exist
|
|
2514
|
+
onCollectionResize?.(size, element, data);
|
|
2515
|
+
}, [onBatchResize, onCollectionResize]);
|
|
2516
|
+
return /*#__PURE__*/React__namespace.createElement(CollectionContext.Provider, {
|
|
2517
|
+
value: onResize
|
|
2518
|
+
}, children);
|
|
2519
|
+
}
|
|
2520
|
+
|
|
2521
|
+
// =============================== Const ===============================
|
|
2522
|
+
const elementListeners = new Map();
|
|
2523
|
+
function onResize(entities) {
|
|
2524
|
+
entities.forEach(entity => {
|
|
2525
|
+
const {
|
|
2526
|
+
target
|
|
2527
|
+
} = entity;
|
|
2528
|
+
elementListeners.get(target)?.forEach(listener => listener(target));
|
|
2529
|
+
});
|
|
2530
|
+
}
|
|
2531
|
+
|
|
2532
|
+
// Delay create ResizeObserver since it's not supported in server side
|
|
2533
|
+
let observer;
|
|
2534
|
+
function ensureResizeObserver() {
|
|
2535
|
+
if (!observer) {
|
|
2536
|
+
observer = new ResizeObserver(onResize);
|
|
2537
|
+
}
|
|
2538
|
+
return observer;
|
|
2539
|
+
}
|
|
2540
|
+
|
|
2541
|
+
// Dev env only
|
|
2542
|
+
process.env.NODE_ENV !== 'production' ? elementListeners : null; // eslint-disable-line
|
|
2543
|
+
process.env.NODE_ENV !== 'production' ? onResize : null; // eslint-disable-line
|
|
2544
|
+
|
|
2545
|
+
// ============================== Observe ==============================
|
|
2546
|
+
function observe(element, callback) {
|
|
2547
|
+
if (!elementListeners.has(element)) {
|
|
2548
|
+
elementListeners.set(element, new Set());
|
|
2549
|
+
ensureResizeObserver().observe(element);
|
|
2550
|
+
}
|
|
2551
|
+
elementListeners.get(element).add(callback);
|
|
2552
|
+
}
|
|
2553
|
+
function unobserve(element, callback) {
|
|
2554
|
+
if (elementListeners.has(element)) {
|
|
2555
|
+
elementListeners.get(element).delete(callback);
|
|
2556
|
+
if (!elementListeners.get(element).size) {
|
|
2557
|
+
ensureResizeObserver().unobserve(element);
|
|
2558
|
+
elementListeners.delete(element);
|
|
2559
|
+
}
|
|
2560
|
+
}
|
|
2561
|
+
}
|
|
2562
|
+
|
|
2563
|
+
function useResizeObserver(enabled, getTarget, onDelayResize, onSyncResize) {
|
|
2564
|
+
// ============================= Size =============================
|
|
2565
|
+
const sizeRef = React__namespace.useRef({
|
|
2566
|
+
width: -1,
|
|
2567
|
+
height: -1,
|
|
2568
|
+
offsetWidth: -1,
|
|
2569
|
+
offsetHeight: -1
|
|
2570
|
+
});
|
|
2571
|
+
|
|
2572
|
+
// =========================== Observe ============================
|
|
2573
|
+
|
|
2574
|
+
// Handler
|
|
2575
|
+
const onInternalResize = useEvent(target => {
|
|
2576
|
+
const {
|
|
2577
|
+
width,
|
|
2578
|
+
height
|
|
2579
|
+
} = target.getBoundingClientRect();
|
|
2580
|
+
const {
|
|
2581
|
+
offsetWidth,
|
|
2582
|
+
offsetHeight
|
|
2583
|
+
} = target;
|
|
2584
|
+
|
|
2585
|
+
/**
|
|
2586
|
+
* Resize observer trigger when content size changed.
|
|
2587
|
+
* In most case we just care about element size,
|
|
2588
|
+
* let's use `boundary` instead of `contentRect` here to avoid shaking.
|
|
2589
|
+
*/
|
|
2590
|
+
const fixedWidth = Math.floor(width);
|
|
2591
|
+
const fixedHeight = Math.floor(height);
|
|
2592
|
+
if (sizeRef.current.width !== fixedWidth || sizeRef.current.height !== fixedHeight || sizeRef.current.offsetWidth !== offsetWidth || sizeRef.current.offsetHeight !== offsetHeight) {
|
|
2593
|
+
const size = {
|
|
2594
|
+
width: fixedWidth,
|
|
2595
|
+
height: fixedHeight,
|
|
2596
|
+
offsetWidth,
|
|
2597
|
+
offsetHeight
|
|
2598
|
+
};
|
|
2599
|
+
sizeRef.current = size;
|
|
2600
|
+
|
|
2601
|
+
// IE is strange, right?
|
|
2602
|
+
const mergedOffsetWidth = offsetWidth === Math.round(width) ? width : offsetWidth;
|
|
2603
|
+
const mergedOffsetHeight = offsetHeight === Math.round(height) ? height : offsetHeight;
|
|
2604
|
+
const sizeInfo = {
|
|
2605
|
+
...size,
|
|
2606
|
+
offsetWidth: mergedOffsetWidth,
|
|
2607
|
+
offsetHeight: mergedOffsetHeight
|
|
2608
|
+
};
|
|
2609
|
+
|
|
2610
|
+
// Call the callback immediately, let the caller decide whether to defer
|
|
2611
|
+
// onResize(sizeInfo, target);
|
|
2612
|
+
onSyncResize?.(sizeInfo, target);
|
|
2613
|
+
|
|
2614
|
+
// defer the callback but not defer to next frame
|
|
2615
|
+
Promise.resolve().then(() => {
|
|
2616
|
+
onDelayResize?.(sizeInfo, target);
|
|
2617
|
+
});
|
|
2618
|
+
}
|
|
2619
|
+
});
|
|
2620
|
+
|
|
2621
|
+
// Dynamic observe
|
|
2622
|
+
const isFuncTarget = typeof getTarget === 'function';
|
|
2623
|
+
React__namespace.useEffect(() => {
|
|
2624
|
+
const target = isFuncTarget ? getTarget() : getTarget;
|
|
2625
|
+
if (target && enabled) {
|
|
2626
|
+
observe(target, onInternalResize);
|
|
2627
|
+
}
|
|
2628
|
+
return () => {
|
|
2629
|
+
if (target) {
|
|
2630
|
+
unobserve(target, onInternalResize);
|
|
2631
|
+
}
|
|
2632
|
+
};
|
|
2633
|
+
}, [enabled,
|
|
2634
|
+
// When is function, no need to watch it
|
|
2635
|
+
isFuncTarget ? 0 : getTarget]);
|
|
2636
|
+
}
|
|
2637
|
+
|
|
2638
|
+
function SingleObserver(props, ref) {
|
|
2639
|
+
const {
|
|
2640
|
+
children,
|
|
2641
|
+
disabled,
|
|
2642
|
+
onResize,
|
|
2643
|
+
data
|
|
2644
|
+
} = props;
|
|
2645
|
+
const elementRef = React__namespace.useRef(null);
|
|
2646
|
+
const onCollectionResize = React__namespace.useContext(CollectionContext);
|
|
2647
|
+
|
|
2648
|
+
// =========================== Children ===========================
|
|
2649
|
+
const isRenderProps = typeof children === 'function';
|
|
2650
|
+
const mergedChildren = isRenderProps ? children(elementRef) : children;
|
|
2651
|
+
|
|
2652
|
+
// ============================= Ref ==============================
|
|
2653
|
+
const canRef = !isRenderProps && /*#__PURE__*/React__namespace.isValidElement(mergedChildren) && supportRef(mergedChildren);
|
|
2654
|
+
const originRef = canRef ? getNodeRef(mergedChildren) : null;
|
|
2655
|
+
const mergedRef = useComposeRef(originRef, elementRef);
|
|
2656
|
+
const getDomElement = () => {
|
|
2657
|
+
return getDOM(elementRef.current);
|
|
2658
|
+
};
|
|
2659
|
+
React__namespace.useImperativeHandle(ref, () => getDomElement());
|
|
2660
|
+
|
|
2661
|
+
// =========================== Observe ============================
|
|
2662
|
+
useResizeObserver(!disabled, getDomElement, onResize, (sizeInfo, target) => {
|
|
2663
|
+
onCollectionResize?.(sizeInfo, target, data);
|
|
2664
|
+
});
|
|
2665
|
+
|
|
2666
|
+
// ============================ Render ============================
|
|
2667
|
+
return canRef ? /*#__PURE__*/React__namespace.cloneElement(mergedChildren, {
|
|
2668
|
+
ref: mergedRef
|
|
2669
|
+
}) : mergedChildren;
|
|
2670
|
+
}
|
|
2671
|
+
const RefSingleObserver = /*#__PURE__*/React__namespace.forwardRef(SingleObserver);
|
|
2672
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
2673
|
+
RefSingleObserver.displayName = 'SingleObserver';
|
|
2674
|
+
}
|
|
2675
|
+
|
|
2676
|
+
function _extends$2() { _extends$2 = 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$2.apply(this, arguments); }
|
|
2677
|
+
const INTERNAL_PREFIX_KEY = 'rc-observer-key';
|
|
2678
|
+
function ResizeObserver$1(props, ref) {
|
|
2679
|
+
const {
|
|
2680
|
+
children
|
|
2681
|
+
} = props;
|
|
2682
|
+
const childNodes = typeof children === 'function' ? [children] : toArray$1(children);
|
|
2683
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
2684
|
+
if (childNodes.length > 1) {
|
|
2685
|
+
warning(false, 'Find more than one child node with `children` in ResizeObserver. Please use ResizeObserver.Collection instead.');
|
|
2686
|
+
} else if (childNodes.length === 0) {
|
|
2687
|
+
warning(false, '`children` of ResizeObserver is empty. Nothing is in observe.');
|
|
2688
|
+
}
|
|
2689
|
+
}
|
|
2690
|
+
return childNodes.map((child, index) => {
|
|
2691
|
+
const key = child?.key || `${INTERNAL_PREFIX_KEY}-${index}`;
|
|
2692
|
+
return /*#__PURE__*/React__namespace.createElement(RefSingleObserver, _extends$2({}, props, {
|
|
2693
|
+
key: key,
|
|
2694
|
+
ref: index === 0 ? ref : undefined
|
|
2695
|
+
}), child);
|
|
2696
|
+
});
|
|
2697
|
+
}
|
|
2698
|
+
const RefResizeObserver = /*#__PURE__*/React__namespace.forwardRef(ResizeObserver$1);
|
|
2699
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
2700
|
+
RefResizeObserver.displayName = 'ResizeObserver';
|
|
2701
|
+
}
|
|
2702
|
+
RefResizeObserver.Collection = Collection;
|
|
2703
|
+
|
|
2704
|
+
function getRoot(ele) {
|
|
2705
|
+
return ele?.getRootNode?.();
|
|
2706
|
+
}
|
|
2707
|
+
|
|
2708
|
+
/**
|
|
2709
|
+
* Check if is in shadowRoot
|
|
2710
|
+
*/
|
|
2711
|
+
function inShadow(ele) {
|
|
2712
|
+
return getRoot(ele) instanceof ShadowRoot;
|
|
2713
|
+
}
|
|
2714
|
+
|
|
2715
|
+
/**
|
|
2716
|
+
* Return shadowRoot if possible
|
|
2717
|
+
*/
|
|
2718
|
+
function getShadowRoot(ele) {
|
|
2719
|
+
return inShadow(ele) ? getRoot(ele) : null;
|
|
2720
|
+
}
|
|
2721
|
+
|
|
2722
|
+
const Context$1 = /*#__PURE__*/React__namespace.createContext({});
|
|
2723
|
+
|
|
2724
|
+
/**
|
|
2725
|
+
* Same as React.useState but will always get latest state.
|
|
2726
|
+
* This is useful when React merge multiple state updates into one.
|
|
2727
|
+
* e.g. onTransitionEnd trigger multiple event at once will be merged state update in React.
|
|
2728
|
+
*/
|
|
2729
|
+
function useSyncState(defaultValue) {
|
|
2730
|
+
const [, forceUpdate] = React__namespace.useReducer(x => x + 1, 0);
|
|
2731
|
+
const currentValueRef = React__namespace.useRef(defaultValue);
|
|
2732
|
+
const getValue = useEvent(() => {
|
|
2733
|
+
return currentValueRef.current;
|
|
2734
|
+
});
|
|
2735
|
+
const setValue = useEvent(updater => {
|
|
2736
|
+
currentValueRef.current = typeof updater === 'function' ? updater(currentValueRef.current) : updater;
|
|
2737
|
+
forceUpdate();
|
|
2738
|
+
});
|
|
2739
|
+
return [getValue, setValue];
|
|
2740
|
+
}
|
|
2741
|
+
|
|
2742
|
+
const STATUS_NONE = 'none';
|
|
2743
|
+
const STATUS_APPEAR = 'appear';
|
|
2744
|
+
const STATUS_ENTER = 'enter';
|
|
2745
|
+
const STATUS_LEAVE = 'leave';
|
|
2746
|
+
const STEP_NONE = 'none';
|
|
2747
|
+
const STEP_PREPARE = 'prepare';
|
|
2748
|
+
const STEP_START = 'start';
|
|
2749
|
+
const STEP_ACTIVE = 'active';
|
|
2750
|
+
const STEP_ACTIVATED = 'end';
|
|
2751
|
+
/**
|
|
2752
|
+
* Used for disabled motion case.
|
|
2753
|
+
* Prepare stage will still work but start & active will be skipped.
|
|
2754
|
+
*/
|
|
2755
|
+
const STEP_PREPARED = 'prepared';
|
|
2756
|
+
|
|
2757
|
+
// ================= Transition =================
|
|
2758
|
+
// Event wrapper. Copy from react source code
|
|
2759
|
+
function makePrefixMap(styleProp, eventName) {
|
|
2760
|
+
const prefixes = {};
|
|
2761
|
+
prefixes[styleProp.toLowerCase()] = eventName.toLowerCase();
|
|
2762
|
+
prefixes[`Webkit${styleProp}`] = `webkit${eventName}`;
|
|
2763
|
+
prefixes[`Moz${styleProp}`] = `moz${eventName}`;
|
|
2764
|
+
prefixes[`ms${styleProp}`] = `MS${eventName}`;
|
|
2765
|
+
prefixes[`O${styleProp}`] = `o${eventName.toLowerCase()}`;
|
|
2766
|
+
return prefixes;
|
|
2767
|
+
}
|
|
2768
|
+
function getVendorPrefixes(domSupport, win) {
|
|
2769
|
+
const prefixes = {
|
|
2770
|
+
animationend: makePrefixMap('Animation', 'AnimationEnd'),
|
|
2771
|
+
transitionend: makePrefixMap('Transition', 'TransitionEnd')
|
|
2772
|
+
};
|
|
2773
|
+
if (domSupport) {
|
|
2774
|
+
if (!('AnimationEvent' in win)) {
|
|
2775
|
+
delete prefixes.animationend.animation;
|
|
2776
|
+
}
|
|
2777
|
+
if (!('TransitionEvent' in win)) {
|
|
2778
|
+
delete prefixes.transitionend.transition;
|
|
2779
|
+
}
|
|
2780
|
+
}
|
|
2781
|
+
return prefixes;
|
|
2782
|
+
}
|
|
2783
|
+
const vendorPrefixes = getVendorPrefixes(canUseDom(), typeof window !== 'undefined' ? window : {});
|
|
2784
|
+
let style = {};
|
|
2785
|
+
if (canUseDom()) {
|
|
2786
|
+
({
|
|
2787
|
+
style
|
|
2788
|
+
} = document.createElement('div'));
|
|
2789
|
+
}
|
|
2790
|
+
const prefixedEventNames = {};
|
|
2791
|
+
function getVendorPrefixedEventName(eventName) {
|
|
2792
|
+
if (prefixedEventNames[eventName]) {
|
|
2793
|
+
return prefixedEventNames[eventName];
|
|
2794
|
+
}
|
|
2795
|
+
const prefixMap = vendorPrefixes[eventName];
|
|
2796
|
+
if (prefixMap) {
|
|
2797
|
+
const stylePropList = Object.keys(prefixMap);
|
|
2798
|
+
const len = stylePropList.length;
|
|
2799
|
+
for (let i = 0; i < len; i += 1) {
|
|
2800
|
+
const styleProp = stylePropList[i];
|
|
2801
|
+
if (Object.prototype.hasOwnProperty.call(prefixMap, styleProp) && styleProp in style) {
|
|
2802
|
+
prefixedEventNames[eventName] = prefixMap[styleProp];
|
|
2803
|
+
return prefixedEventNames[eventName];
|
|
2804
|
+
}
|
|
2805
|
+
}
|
|
2806
|
+
}
|
|
2807
|
+
return '';
|
|
2808
|
+
}
|
|
2809
|
+
const internalAnimationEndName = getVendorPrefixedEventName('animationend');
|
|
2810
|
+
const internalTransitionEndName = getVendorPrefixedEventName('transitionend');
|
|
2811
|
+
const supportTransition = !!(internalAnimationEndName && internalTransitionEndName);
|
|
2812
|
+
const animationEndName = internalAnimationEndName || 'animationend';
|
|
2813
|
+
const transitionEndName = internalTransitionEndName || 'transitionend';
|
|
2814
|
+
function getTransitionName(transitionName, transitionType) {
|
|
2815
|
+
if (!transitionName) return null;
|
|
2816
|
+
if (typeof transitionName === 'object') {
|
|
2817
|
+
const type = transitionType.replace(/-\w/g, match => match[1].toUpperCase());
|
|
2818
|
+
return transitionName[type];
|
|
2819
|
+
}
|
|
2820
|
+
return `${transitionName}-${transitionType}`;
|
|
2821
|
+
}
|
|
2822
|
+
|
|
2823
|
+
var useDomMotionEvents = (onInternalMotionEnd => {
|
|
2824
|
+
const cacheElementRef = React.useRef();
|
|
2825
|
+
|
|
2826
|
+
// Remove events
|
|
2827
|
+
function removeMotionEvents(element) {
|
|
2828
|
+
if (element) {
|
|
2829
|
+
element.removeEventListener(transitionEndName, onInternalMotionEnd);
|
|
2830
|
+
element.removeEventListener(animationEndName, onInternalMotionEnd);
|
|
2831
|
+
}
|
|
2832
|
+
}
|
|
2833
|
+
|
|
2834
|
+
// Patch events
|
|
2835
|
+
function patchMotionEvents(element) {
|
|
2836
|
+
if (cacheElementRef.current && cacheElementRef.current !== element) {
|
|
2837
|
+
removeMotionEvents(cacheElementRef.current);
|
|
2838
|
+
}
|
|
2839
|
+
if (element && element !== cacheElementRef.current) {
|
|
2840
|
+
element.addEventListener(transitionEndName, onInternalMotionEnd);
|
|
2841
|
+
element.addEventListener(animationEndName, onInternalMotionEnd);
|
|
2842
|
+
|
|
2843
|
+
// Save as cache in case dom removed trigger by `motionDeadline`
|
|
2844
|
+
cacheElementRef.current = element;
|
|
2845
|
+
}
|
|
2846
|
+
}
|
|
2847
|
+
|
|
2848
|
+
// Clean up when removed
|
|
2849
|
+
React__namespace.useEffect(() => () => {
|
|
2850
|
+
removeMotionEvents(cacheElementRef.current);
|
|
2851
|
+
cacheElementRef.current = null;
|
|
2852
|
+
}, []);
|
|
2853
|
+
return [patchMotionEvents, removeMotionEvents];
|
|
2854
|
+
});
|
|
2855
|
+
|
|
2856
|
+
// It's safe to use `useLayoutEffect` but the warning is annoying
|
|
2857
|
+
const useIsomorphicLayoutEffect = canUseDom() ? React.useLayoutEffect : React.useEffect;
|
|
2858
|
+
|
|
2859
|
+
let raf = callback => +setTimeout(callback, 16);
|
|
2860
|
+
let caf = num => clearTimeout(num);
|
|
2861
|
+
if (typeof window !== 'undefined' && 'requestAnimationFrame' in window) {
|
|
2862
|
+
raf = callback => window.requestAnimationFrame(callback);
|
|
2863
|
+
caf = handle => window.cancelAnimationFrame(handle);
|
|
2864
|
+
}
|
|
2865
|
+
let rafUUID = 0;
|
|
2866
|
+
const rafIds = new Map();
|
|
2867
|
+
function cleanup(id) {
|
|
2868
|
+
rafIds.delete(id);
|
|
2869
|
+
}
|
|
2870
|
+
const wrapperRaf = (callback, times = 1) => {
|
|
2871
|
+
rafUUID += 1;
|
|
2872
|
+
const id = rafUUID;
|
|
2873
|
+
function callRef(leftTimes) {
|
|
2874
|
+
if (leftTimes === 0) {
|
|
2875
|
+
// Clean up
|
|
2876
|
+
cleanup(id);
|
|
2877
|
+
|
|
2878
|
+
// Trigger
|
|
2879
|
+
callback();
|
|
2880
|
+
} else {
|
|
2881
|
+
// Next raf
|
|
2882
|
+
const realId = raf(() => {
|
|
2883
|
+
callRef(leftTimes - 1);
|
|
2884
|
+
});
|
|
2885
|
+
|
|
2886
|
+
// Bind real raf id
|
|
2887
|
+
rafIds.set(id, realId);
|
|
2888
|
+
}
|
|
2889
|
+
}
|
|
2890
|
+
callRef(times);
|
|
2891
|
+
return id;
|
|
2892
|
+
};
|
|
2893
|
+
wrapperRaf.cancel = id => {
|
|
2894
|
+
const realId = rafIds.get(id);
|
|
2895
|
+
cleanup(id);
|
|
2896
|
+
return caf(realId);
|
|
2897
|
+
};
|
|
2898
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
2899
|
+
wrapperRaf.ids = () => rafIds;
|
|
2900
|
+
}
|
|
2901
|
+
|
|
2902
|
+
var useNextFrame = (() => {
|
|
2903
|
+
const nextFrameRef = React__namespace.useRef(null);
|
|
2904
|
+
function cancelNextFrame() {
|
|
2905
|
+
wrapperRaf.cancel(nextFrameRef.current);
|
|
2906
|
+
}
|
|
2907
|
+
function nextFrame(callback, delay = 2) {
|
|
2908
|
+
cancelNextFrame();
|
|
2909
|
+
const nextFrameId = wrapperRaf(() => {
|
|
2910
|
+
if (delay <= 1) {
|
|
2911
|
+
callback({
|
|
2912
|
+
isCanceled: () => nextFrameId !== nextFrameRef.current
|
|
2913
|
+
});
|
|
2914
|
+
} else {
|
|
2915
|
+
nextFrame(callback, delay - 1);
|
|
2916
|
+
}
|
|
2917
|
+
});
|
|
2918
|
+
nextFrameRef.current = nextFrameId;
|
|
2919
|
+
}
|
|
2920
|
+
React__namespace.useEffect(() => () => {
|
|
2921
|
+
cancelNextFrame();
|
|
2922
|
+
}, []);
|
|
2923
|
+
return [nextFrame, cancelNextFrame];
|
|
2924
|
+
});
|
|
2925
|
+
|
|
2926
|
+
const FULL_STEP_QUEUE = [STEP_PREPARE, STEP_START, STEP_ACTIVE, STEP_ACTIVATED];
|
|
2927
|
+
const SIMPLE_STEP_QUEUE = [STEP_PREPARE, STEP_PREPARED];
|
|
2928
|
+
|
|
2929
|
+
/** Skip current step */
|
|
2930
|
+
const SkipStep = false;
|
|
2931
|
+
/** Current step should be update in */
|
|
2932
|
+
const DoStep = true;
|
|
2933
|
+
function isActive(step) {
|
|
2934
|
+
return step === STEP_ACTIVE || step === STEP_ACTIVATED;
|
|
2935
|
+
}
|
|
2936
|
+
var useStepQueue = ((status, prepareOnly, callback) => {
|
|
2937
|
+
const [step, setStep] = useSafeState(STEP_NONE);
|
|
2938
|
+
const [nextFrame, cancelNextFrame] = useNextFrame();
|
|
2939
|
+
function startQueue() {
|
|
2940
|
+
setStep(STEP_PREPARE, true);
|
|
2941
|
+
}
|
|
2942
|
+
const STEP_QUEUE = prepareOnly ? SIMPLE_STEP_QUEUE : FULL_STEP_QUEUE;
|
|
2943
|
+
useIsomorphicLayoutEffect(() => {
|
|
2944
|
+
if (step !== STEP_NONE && step !== STEP_ACTIVATED) {
|
|
2945
|
+
const index = STEP_QUEUE.indexOf(step);
|
|
2946
|
+
const nextStep = STEP_QUEUE[index + 1];
|
|
2947
|
+
const result = callback(step);
|
|
2948
|
+
if (result === SkipStep) {
|
|
2949
|
+
// Skip when no needed
|
|
2950
|
+
setStep(nextStep, true);
|
|
2951
|
+
} else if (nextStep) {
|
|
2952
|
+
// Do as frame for step update
|
|
2953
|
+
nextFrame(info => {
|
|
2954
|
+
function doNext() {
|
|
2955
|
+
// Skip since current queue is ood
|
|
2956
|
+
if (info.isCanceled()) return;
|
|
2957
|
+
setStep(nextStep, true);
|
|
2958
|
+
}
|
|
2959
|
+
if (result === true) {
|
|
2960
|
+
doNext();
|
|
2961
|
+
} else {
|
|
2962
|
+
// Only promise should be async
|
|
2963
|
+
Promise.resolve(result).then(doNext);
|
|
2964
|
+
}
|
|
2965
|
+
});
|
|
2966
|
+
}
|
|
2967
|
+
}
|
|
2968
|
+
}, [status, step]);
|
|
2969
|
+
React__namespace.useEffect(() => () => {
|
|
2970
|
+
cancelNextFrame();
|
|
2971
|
+
}, []);
|
|
2972
|
+
return [startQueue, step];
|
|
2973
|
+
});
|
|
2974
|
+
|
|
2975
|
+
function useStatus(supportMotion, visible, getElement, {
|
|
2976
|
+
motionEnter = true,
|
|
2977
|
+
motionAppear = true,
|
|
2978
|
+
motionLeave = true,
|
|
2979
|
+
motionDeadline,
|
|
2980
|
+
motionLeaveImmediately,
|
|
2981
|
+
onAppearPrepare,
|
|
2982
|
+
onEnterPrepare,
|
|
2983
|
+
onLeavePrepare,
|
|
2984
|
+
onAppearStart,
|
|
2985
|
+
onEnterStart,
|
|
2986
|
+
onLeaveStart,
|
|
2987
|
+
onAppearActive,
|
|
2988
|
+
onEnterActive,
|
|
2989
|
+
onLeaveActive,
|
|
2990
|
+
onAppearEnd,
|
|
2991
|
+
onEnterEnd,
|
|
2992
|
+
onLeaveEnd,
|
|
2993
|
+
onVisibleChanged
|
|
2994
|
+
}) {
|
|
2995
|
+
// Used for outer render usage to avoid `visible: false & status: none` to render nothing
|
|
2996
|
+
const [asyncVisible, setAsyncVisible] = React__namespace.useState();
|
|
2997
|
+
const [getStatus, setStatus] = useSyncState(STATUS_NONE);
|
|
2998
|
+
const [style, setStyle] = React__namespace.useState([null, null]);
|
|
2999
|
+
const currentStatus = getStatus();
|
|
3000
|
+
const mountedRef = React.useRef(false);
|
|
3001
|
+
const deadlineRef = React.useRef(null);
|
|
3002
|
+
|
|
3003
|
+
// =========================== Dom Node ===========================
|
|
3004
|
+
function getDomElement() {
|
|
3005
|
+
return getElement();
|
|
3006
|
+
}
|
|
3007
|
+
|
|
3008
|
+
// ========================== Motion End ==========================
|
|
3009
|
+
const activeRef = React.useRef(false);
|
|
3010
|
+
|
|
3011
|
+
/**
|
|
3012
|
+
* Clean up status & style
|
|
3013
|
+
*/
|
|
3014
|
+
function updateMotionEndStatus() {
|
|
3015
|
+
setStatus(STATUS_NONE);
|
|
3016
|
+
setStyle([null, null]);
|
|
3017
|
+
}
|
|
3018
|
+
const onInternalMotionEnd = useEvent(event => {
|
|
3019
|
+
const status = getStatus();
|
|
3020
|
+
// Do nothing since not in any transition status.
|
|
3021
|
+
// This may happen when `motionDeadline` trigger.
|
|
3022
|
+
if (status === STATUS_NONE) {
|
|
3023
|
+
return;
|
|
3024
|
+
}
|
|
3025
|
+
const element = getDomElement();
|
|
3026
|
+
if (event && !event.deadline && event.target !== element) {
|
|
3027
|
+
// event exists
|
|
3028
|
+
// not initiated by deadline
|
|
3029
|
+
// transitionEnd not fired by inner elements
|
|
3030
|
+
return;
|
|
3031
|
+
}
|
|
3032
|
+
const currentActive = activeRef.current;
|
|
3033
|
+
let canEnd;
|
|
3034
|
+
if (status === STATUS_APPEAR && currentActive) {
|
|
3035
|
+
canEnd = onAppearEnd?.(element, event);
|
|
3036
|
+
} else if (status === STATUS_ENTER && currentActive) {
|
|
3037
|
+
canEnd = onEnterEnd?.(element, event);
|
|
3038
|
+
} else if (status === STATUS_LEAVE && currentActive) {
|
|
3039
|
+
canEnd = onLeaveEnd?.(element, event);
|
|
3040
|
+
}
|
|
3041
|
+
|
|
3042
|
+
// Only update status when `canEnd` and not destroyed
|
|
3043
|
+
if (currentActive && canEnd !== false) {
|
|
3044
|
+
updateMotionEndStatus();
|
|
3045
|
+
}
|
|
3046
|
+
});
|
|
3047
|
+
const [patchMotionEvents] = useDomMotionEvents(onInternalMotionEnd);
|
|
3048
|
+
|
|
3049
|
+
// ============================= Step =============================
|
|
3050
|
+
const getEventHandlers = targetStatus => {
|
|
3051
|
+
switch (targetStatus) {
|
|
3052
|
+
case STATUS_APPEAR:
|
|
3053
|
+
return {
|
|
3054
|
+
[STEP_PREPARE]: onAppearPrepare,
|
|
3055
|
+
[STEP_START]: onAppearStart,
|
|
3056
|
+
[STEP_ACTIVE]: onAppearActive
|
|
3057
|
+
};
|
|
3058
|
+
case STATUS_ENTER:
|
|
3059
|
+
return {
|
|
3060
|
+
[STEP_PREPARE]: onEnterPrepare,
|
|
3061
|
+
[STEP_START]: onEnterStart,
|
|
3062
|
+
[STEP_ACTIVE]: onEnterActive
|
|
3063
|
+
};
|
|
3064
|
+
case STATUS_LEAVE:
|
|
3065
|
+
return {
|
|
3066
|
+
[STEP_PREPARE]: onLeavePrepare,
|
|
3067
|
+
[STEP_START]: onLeaveStart,
|
|
3068
|
+
[STEP_ACTIVE]: onLeaveActive
|
|
3069
|
+
};
|
|
3070
|
+
default:
|
|
3071
|
+
return {};
|
|
3072
|
+
}
|
|
3073
|
+
};
|
|
3074
|
+
const eventHandlers = React__namespace.useMemo(() => getEventHandlers(currentStatus), [currentStatus]);
|
|
3075
|
+
const [startStep, step] = useStepQueue(currentStatus, !supportMotion, newStep => {
|
|
3076
|
+
// Only prepare step can be skip
|
|
3077
|
+
if (newStep === STEP_PREPARE) {
|
|
3078
|
+
const onPrepare = eventHandlers[STEP_PREPARE];
|
|
3079
|
+
if (!onPrepare) {
|
|
3080
|
+
return SkipStep;
|
|
3081
|
+
}
|
|
3082
|
+
return onPrepare(getDomElement());
|
|
3083
|
+
}
|
|
3084
|
+
|
|
3085
|
+
// Rest step is sync update
|
|
3086
|
+
if (newStep in eventHandlers) {
|
|
3087
|
+
setStyle([eventHandlers[newStep]?.(getDomElement(), null) || null, newStep]);
|
|
3088
|
+
}
|
|
3089
|
+
if (newStep === STEP_ACTIVE && currentStatus !== STATUS_NONE) {
|
|
3090
|
+
// Patch events when motion needed
|
|
3091
|
+
patchMotionEvents(getDomElement());
|
|
3092
|
+
if (motionDeadline > 0) {
|
|
3093
|
+
clearTimeout(deadlineRef.current);
|
|
3094
|
+
deadlineRef.current = setTimeout(() => {
|
|
3095
|
+
onInternalMotionEnd({
|
|
3096
|
+
deadline: true
|
|
3097
|
+
});
|
|
3098
|
+
}, motionDeadline);
|
|
3099
|
+
}
|
|
3100
|
+
}
|
|
3101
|
+
if (newStep === STEP_PREPARED) {
|
|
3102
|
+
updateMotionEndStatus();
|
|
3103
|
+
}
|
|
3104
|
+
return DoStep;
|
|
3105
|
+
});
|
|
3106
|
+
const active = isActive(step);
|
|
3107
|
+
activeRef.current = active;
|
|
3108
|
+
|
|
3109
|
+
// ============================ Status ============================
|
|
3110
|
+
const visibleRef = React.useRef(null);
|
|
3111
|
+
|
|
3112
|
+
// Update with new status
|
|
3113
|
+
useIsomorphicLayoutEffect(() => {
|
|
3114
|
+
// When use Suspense, the `visible` will repeat trigger,
|
|
3115
|
+
// But not real change of the `visible`, we need to skip it.
|
|
3116
|
+
// https://github.com/ant-design/ant-design/issues/44379
|
|
3117
|
+
if (mountedRef.current && visibleRef.current === visible) {
|
|
3118
|
+
return;
|
|
3119
|
+
}
|
|
3120
|
+
setAsyncVisible(visible);
|
|
3121
|
+
const isMounted = mountedRef.current;
|
|
3122
|
+
mountedRef.current = true;
|
|
3123
|
+
|
|
3124
|
+
// if (!supportMotion) {
|
|
3125
|
+
// return;
|
|
3126
|
+
// }
|
|
3127
|
+
|
|
3128
|
+
let nextStatus;
|
|
3129
|
+
|
|
3130
|
+
// Appear
|
|
3131
|
+
if (!isMounted && visible && motionAppear) {
|
|
3132
|
+
nextStatus = STATUS_APPEAR;
|
|
3133
|
+
}
|
|
3134
|
+
|
|
3135
|
+
// Enter
|
|
3136
|
+
if (isMounted && visible && motionEnter) {
|
|
3137
|
+
nextStatus = STATUS_ENTER;
|
|
3138
|
+
}
|
|
3139
|
+
|
|
3140
|
+
// Leave
|
|
3141
|
+
if (isMounted && !visible && motionLeave || !isMounted && motionLeaveImmediately && !visible && motionLeave) {
|
|
3142
|
+
nextStatus = STATUS_LEAVE;
|
|
3143
|
+
}
|
|
3144
|
+
const nextEventHandlers = getEventHandlers(nextStatus);
|
|
3145
|
+
|
|
3146
|
+
// Update to next status
|
|
3147
|
+
if (nextStatus && (supportMotion || nextEventHandlers[STEP_PREPARE])) {
|
|
3148
|
+
setStatus(nextStatus);
|
|
3149
|
+
startStep();
|
|
3150
|
+
} else {
|
|
3151
|
+
// Set back in case no motion but prev status has prepare step
|
|
3152
|
+
setStatus(STATUS_NONE);
|
|
3153
|
+
}
|
|
3154
|
+
visibleRef.current = visible;
|
|
3155
|
+
}, [visible]);
|
|
3156
|
+
|
|
3157
|
+
// ============================ Effect ============================
|
|
3158
|
+
// Reset when motion changed
|
|
3159
|
+
React.useEffect(() => {
|
|
3160
|
+
if (
|
|
3161
|
+
// Cancel appear
|
|
3162
|
+
currentStatus === STATUS_APPEAR && !motionAppear ||
|
|
3163
|
+
// Cancel enter
|
|
3164
|
+
currentStatus === STATUS_ENTER && !motionEnter ||
|
|
3165
|
+
// Cancel leave
|
|
3166
|
+
currentStatus === STATUS_LEAVE && !motionLeave) {
|
|
3167
|
+
setStatus(STATUS_NONE);
|
|
3168
|
+
}
|
|
3169
|
+
}, [motionAppear, motionEnter, motionLeave]);
|
|
3170
|
+
React.useEffect(() => () => {
|
|
3171
|
+
mountedRef.current = false;
|
|
3172
|
+
clearTimeout(deadlineRef.current);
|
|
3173
|
+
}, []);
|
|
3174
|
+
|
|
3175
|
+
// Trigger `onVisibleChanged`
|
|
3176
|
+
const firstMountChangeRef = React__namespace.useRef(false);
|
|
3177
|
+
React.useEffect(() => {
|
|
3178
|
+
// [visible & motion not end] => [!visible & motion end] still need trigger onVisibleChanged
|
|
3179
|
+
if (asyncVisible) {
|
|
3180
|
+
firstMountChangeRef.current = true;
|
|
3181
|
+
}
|
|
3182
|
+
if (asyncVisible !== undefined && currentStatus === STATUS_NONE) {
|
|
3183
|
+
// Skip first render is invisible since it's nothing changed
|
|
3184
|
+
if (firstMountChangeRef.current || asyncVisible) {
|
|
3185
|
+
onVisibleChanged?.(asyncVisible);
|
|
3186
|
+
}
|
|
3187
|
+
firstMountChangeRef.current = true;
|
|
3188
|
+
}
|
|
3189
|
+
}, [asyncVisible, currentStatus]);
|
|
3190
|
+
|
|
3191
|
+
// ============================ Styles ============================
|
|
3192
|
+
let mergedStyle = style[0];
|
|
3193
|
+
if (eventHandlers[STEP_PREPARE] && step === STEP_START) {
|
|
3194
|
+
mergedStyle = {
|
|
3195
|
+
transition: 'none',
|
|
3196
|
+
...mergedStyle
|
|
3197
|
+
};
|
|
3198
|
+
}
|
|
3199
|
+
const styleStep = style[1];
|
|
3200
|
+
return [getStatus, step, mergedStyle, asyncVisible ?? visible,
|
|
3201
|
+
// Appear Check
|
|
3202
|
+
!mountedRef.current && currentStatus === STATUS_NONE && supportMotion && motionAppear ? 'NONE' :
|
|
3203
|
+
// Enter or Leave check
|
|
3204
|
+
step === STEP_START || step === STEP_ACTIVE ? styleStep === step : true];
|
|
3205
|
+
}
|
|
3206
|
+
|
|
3207
|
+
/* eslint-disable react/default-props-match-prop-types, react/no-multi-comp, react/prop-types */
|
|
3208
|
+
/**
|
|
3209
|
+
* `transitionSupport` is used for none transition test case.
|
|
3210
|
+
* Default we use browser transition event support check.
|
|
3211
|
+
*/
|
|
3212
|
+
function genCSSMotion(config) {
|
|
3213
|
+
let transitionSupport = config;
|
|
3214
|
+
if (typeof config === 'object') {
|
|
3215
|
+
({
|
|
3216
|
+
transitionSupport
|
|
3217
|
+
} = config);
|
|
3218
|
+
}
|
|
3219
|
+
function isSupportTransition(props, contextMotion) {
|
|
3220
|
+
return !!(props.motionName && transitionSupport && contextMotion !== false);
|
|
3221
|
+
}
|
|
3222
|
+
const CSSMotion = /*#__PURE__*/React__namespace.forwardRef((props, ref) => {
|
|
3223
|
+
const {
|
|
3224
|
+
// Default config
|
|
3225
|
+
visible = true,
|
|
3226
|
+
removeOnLeave = true,
|
|
3227
|
+
forceRender,
|
|
3228
|
+
children,
|
|
3229
|
+
motionName,
|
|
3230
|
+
leavedClassName,
|
|
3231
|
+
eventProps
|
|
3232
|
+
} = props;
|
|
3233
|
+
const {
|
|
3234
|
+
motion: contextMotion
|
|
3235
|
+
} = React__namespace.useContext(Context$1);
|
|
3236
|
+
const supportMotion = isSupportTransition(props, contextMotion);
|
|
3237
|
+
|
|
3238
|
+
// Ref to the react node, it may be a HTMLElement
|
|
3239
|
+
const nodeRef = React.useRef();
|
|
3240
|
+
function getDomElement() {
|
|
3241
|
+
return getDOM(nodeRef.current);
|
|
3242
|
+
}
|
|
3243
|
+
const [getStatus, statusStep, statusStyle, mergedVisible, styleReady] = useStatus(supportMotion, visible, getDomElement, props);
|
|
3244
|
+
const status = getStatus();
|
|
3245
|
+
|
|
3246
|
+
// Record whether content has rendered
|
|
3247
|
+
// Will return null for un-rendered even when `removeOnLeave={false}`
|
|
3248
|
+
const renderedRef = React__namespace.useRef(mergedVisible);
|
|
3249
|
+
if (mergedVisible) {
|
|
3250
|
+
renderedRef.current = true;
|
|
3251
|
+
}
|
|
3252
|
+
|
|
3253
|
+
// ====================== Refs ======================
|
|
3254
|
+
const refObj = React__namespace.useMemo(() => {
|
|
3255
|
+
const obj = {};
|
|
3256
|
+
Object.defineProperties(obj, {
|
|
3257
|
+
nativeElement: {
|
|
3258
|
+
enumerable: true,
|
|
3259
|
+
get: getDomElement
|
|
3260
|
+
},
|
|
3261
|
+
inMotion: {
|
|
3262
|
+
enumerable: true,
|
|
3263
|
+
get: () => () => getStatus() !== STATUS_NONE
|
|
3264
|
+
},
|
|
3265
|
+
enableMotion: {
|
|
3266
|
+
enumerable: true,
|
|
3267
|
+
get: () => () => supportMotion
|
|
3268
|
+
}
|
|
3269
|
+
});
|
|
3270
|
+
return obj;
|
|
3271
|
+
}, []);
|
|
3272
|
+
|
|
3273
|
+
// We lock `deps` here since function return object
|
|
3274
|
+
// will repeat trigger ref from `refConfig` -> `null` -> `refConfig`
|
|
3275
|
+
React__namespace.useImperativeHandle(ref, () => refObj, []);
|
|
3276
|
+
|
|
3277
|
+
// ===================== Render =====================
|
|
3278
|
+
// return motionChildren as React.ReactElement;
|
|
3279
|
+
const idRef = React__namespace.useRef(0);
|
|
3280
|
+
if (styleReady) {
|
|
3281
|
+
idRef.current += 1;
|
|
3282
|
+
}
|
|
3283
|
+
|
|
3284
|
+
// We should render children when motionStyle is sync with stepStatus
|
|
3285
|
+
return React__namespace.useMemo(() => {
|
|
3286
|
+
if (styleReady === 'NONE') {
|
|
3287
|
+
return null;
|
|
3288
|
+
}
|
|
3289
|
+
let motionChildren;
|
|
3290
|
+
const mergedProps = {
|
|
3291
|
+
...eventProps,
|
|
3292
|
+
visible
|
|
3293
|
+
};
|
|
3294
|
+
if (!children) {
|
|
3295
|
+
// No children
|
|
3296
|
+
motionChildren = null;
|
|
3297
|
+
} else if (status === STATUS_NONE) {
|
|
3298
|
+
// Stable children
|
|
3299
|
+
if (mergedVisible) {
|
|
3300
|
+
motionChildren = children({
|
|
3301
|
+
...mergedProps
|
|
3302
|
+
}, nodeRef);
|
|
3303
|
+
} else if (!removeOnLeave && renderedRef.current && leavedClassName) {
|
|
3304
|
+
motionChildren = children({
|
|
3305
|
+
...mergedProps,
|
|
3306
|
+
className: leavedClassName
|
|
3307
|
+
}, nodeRef);
|
|
3308
|
+
} else if (forceRender || !removeOnLeave && !leavedClassName) {
|
|
3309
|
+
motionChildren = children({
|
|
3310
|
+
...mergedProps,
|
|
3311
|
+
style: {
|
|
3312
|
+
display: 'none'
|
|
3313
|
+
}
|
|
3314
|
+
}, nodeRef);
|
|
3315
|
+
} else {
|
|
3316
|
+
motionChildren = null;
|
|
3317
|
+
}
|
|
3318
|
+
} else {
|
|
3319
|
+
// In motion
|
|
3320
|
+
let statusSuffix;
|
|
3321
|
+
if (statusStep === STEP_PREPARE) {
|
|
3322
|
+
statusSuffix = 'prepare';
|
|
3323
|
+
} else if (isActive(statusStep)) {
|
|
3324
|
+
statusSuffix = 'active';
|
|
3325
|
+
} else if (statusStep === STEP_START) {
|
|
3326
|
+
statusSuffix = 'start';
|
|
3327
|
+
}
|
|
3328
|
+
const motionCls = getTransitionName(motionName, `${status}-${statusSuffix}`);
|
|
3329
|
+
motionChildren = children({
|
|
3330
|
+
...mergedProps,
|
|
3331
|
+
className: clsx(getTransitionName(motionName, status), {
|
|
3332
|
+
[motionCls]: motionCls && statusSuffix,
|
|
3333
|
+
[motionName]: typeof motionName === 'string'
|
|
3334
|
+
}),
|
|
3335
|
+
style: statusStyle
|
|
3336
|
+
}, nodeRef);
|
|
3337
|
+
}
|
|
3338
|
+
|
|
3339
|
+
// Auto inject ref if child node not have `ref` props
|
|
3340
|
+
if ( /*#__PURE__*/React__namespace.isValidElement(motionChildren) && supportRef(motionChildren)) {
|
|
3341
|
+
const originNodeRef = getNodeRef(motionChildren);
|
|
3342
|
+
if (!originNodeRef) {
|
|
3343
|
+
motionChildren = /*#__PURE__*/React__namespace.cloneElement(motionChildren, {
|
|
3344
|
+
ref: nodeRef
|
|
3345
|
+
});
|
|
3346
|
+
}
|
|
3347
|
+
}
|
|
3348
|
+
return motionChildren;
|
|
3349
|
+
}, [idRef.current]);
|
|
3350
|
+
});
|
|
3351
|
+
CSSMotion.displayName = 'CSSMotion';
|
|
3352
|
+
return CSSMotion;
|
|
3353
|
+
}
|
|
3354
|
+
var CSSMotion = genCSSMotion(supportTransition);
|
|
3355
|
+
|
|
3356
|
+
function Arrow(props) {
|
|
3357
|
+
const {
|
|
3358
|
+
prefixCls,
|
|
3359
|
+
align,
|
|
3360
|
+
arrow,
|
|
3361
|
+
arrowPos
|
|
3362
|
+
} = props;
|
|
3363
|
+
const {
|
|
3364
|
+
className,
|
|
3365
|
+
content,
|
|
3366
|
+
style
|
|
3367
|
+
} = arrow || {};
|
|
3368
|
+
const {
|
|
3369
|
+
x = 0,
|
|
3370
|
+
y = 0
|
|
3371
|
+
} = arrowPos;
|
|
3372
|
+
const arrowRef = React__namespace.useRef(null);
|
|
3373
|
+
|
|
3374
|
+
// Skip if no align
|
|
3375
|
+
if (!align || !align.points) {
|
|
3376
|
+
return null;
|
|
3377
|
+
}
|
|
3378
|
+
const alignStyle = {
|
|
3379
|
+
position: 'absolute'
|
|
3380
|
+
};
|
|
3381
|
+
|
|
3382
|
+
// Skip if no need to align
|
|
3383
|
+
if (align.autoArrow !== false) {
|
|
3384
|
+
const popupPoints = align.points[0];
|
|
3385
|
+
const targetPoints = align.points[1];
|
|
3386
|
+
const popupTB = popupPoints[0];
|
|
3387
|
+
const popupLR = popupPoints[1];
|
|
3388
|
+
const targetTB = targetPoints[0];
|
|
3389
|
+
const targetLR = targetPoints[1];
|
|
3390
|
+
|
|
3391
|
+
// Top & Bottom
|
|
3392
|
+
if (popupTB === targetTB || !['t', 'b'].includes(popupTB)) {
|
|
3393
|
+
alignStyle.top = y;
|
|
3394
|
+
} else if (popupTB === 't') {
|
|
3395
|
+
alignStyle.top = 0;
|
|
3396
|
+
} else {
|
|
3397
|
+
alignStyle.bottom = 0;
|
|
3398
|
+
}
|
|
3399
|
+
|
|
3400
|
+
// Left & Right
|
|
3401
|
+
if (popupLR === targetLR || !['l', 'r'].includes(popupLR)) {
|
|
3402
|
+
alignStyle.left = x;
|
|
3403
|
+
} else if (popupLR === 'l') {
|
|
3404
|
+
alignStyle.left = 0;
|
|
3405
|
+
} else {
|
|
3406
|
+
alignStyle.right = 0;
|
|
3407
|
+
}
|
|
3408
|
+
}
|
|
3409
|
+
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
3410
|
+
ref: arrowRef,
|
|
3411
|
+
className: clsx(`${prefixCls}-arrow`, className),
|
|
3412
|
+
style: {
|
|
3413
|
+
...alignStyle,
|
|
3414
|
+
...style
|
|
3415
|
+
}
|
|
3416
|
+
}, content);
|
|
3417
|
+
}
|
|
3418
|
+
|
|
3419
|
+
function _extends$1() { _extends$1 = 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$1.apply(this, arguments); }
|
|
3420
|
+
function Mask(props) {
|
|
3421
|
+
const {
|
|
3422
|
+
prefixCls,
|
|
3423
|
+
open,
|
|
3424
|
+
zIndex,
|
|
3425
|
+
mask,
|
|
3426
|
+
motion,
|
|
3427
|
+
mobile
|
|
3428
|
+
} = props;
|
|
3429
|
+
if (!mask) {
|
|
3430
|
+
return null;
|
|
3431
|
+
}
|
|
3432
|
+
return /*#__PURE__*/React__namespace.createElement(CSSMotion, _extends$1({}, motion, {
|
|
3433
|
+
motionAppear: true,
|
|
3434
|
+
visible: open,
|
|
3435
|
+
removeOnLeave: true
|
|
3436
|
+
}), ({
|
|
3437
|
+
className
|
|
3438
|
+
}) => /*#__PURE__*/React__namespace.createElement("div", {
|
|
3439
|
+
style: {
|
|
3440
|
+
zIndex
|
|
3441
|
+
},
|
|
3442
|
+
className: clsx(`${prefixCls}-mask`, mobile && `${prefixCls}-mobile-mask`, className)
|
|
3443
|
+
}));
|
|
3444
|
+
}
|
|
3445
|
+
|
|
3446
|
+
const PopupContent = /*#__PURE__*/React__namespace.memo(({
|
|
3447
|
+
children
|
|
3448
|
+
}) => children, (_, next) => next.cache);
|
|
3449
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
3450
|
+
PopupContent.displayName = 'PopupContent';
|
|
3451
|
+
}
|
|
3452
|
+
|
|
3453
|
+
function useOffsetStyle(isMobile, ready, open, align, offsetR, offsetB, offsetX, offsetY) {
|
|
3454
|
+
// >>>>> Offset
|
|
3455
|
+
const AUTO = 'auto';
|
|
3456
|
+
const offsetStyle = isMobile ? {} : {
|
|
3457
|
+
left: '-1000vw',
|
|
3458
|
+
top: '-1000vh',
|
|
3459
|
+
right: AUTO,
|
|
3460
|
+
bottom: AUTO
|
|
3461
|
+
};
|
|
3462
|
+
|
|
3463
|
+
// Set align style
|
|
3464
|
+
if (!isMobile && (ready || !open)) {
|
|
3465
|
+
const {
|
|
3466
|
+
points
|
|
3467
|
+
} = align;
|
|
3468
|
+
const dynamicInset = align.dynamicInset || align._experimental?.dynamicInset;
|
|
3469
|
+
const alignRight = dynamicInset && points[0][1] === 'r';
|
|
3470
|
+
const alignBottom = dynamicInset && points[0][0] === 'b';
|
|
3471
|
+
if (alignRight) {
|
|
3472
|
+
offsetStyle.right = offsetR;
|
|
3473
|
+
offsetStyle.left = AUTO;
|
|
3474
|
+
} else {
|
|
3475
|
+
offsetStyle.left = offsetX;
|
|
3476
|
+
offsetStyle.right = AUTO;
|
|
3477
|
+
}
|
|
3478
|
+
if (alignBottom) {
|
|
3479
|
+
offsetStyle.bottom = offsetB;
|
|
3480
|
+
offsetStyle.top = AUTO;
|
|
3481
|
+
} else {
|
|
3482
|
+
offsetStyle.top = offsetY;
|
|
3483
|
+
offsetStyle.bottom = AUTO;
|
|
3484
|
+
}
|
|
3485
|
+
}
|
|
3486
|
+
return offsetStyle;
|
|
3487
|
+
}
|
|
3488
|
+
|
|
3489
|
+
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); }
|
|
3490
|
+
const Popup = /*#__PURE__*/React__namespace.forwardRef((props, ref) => {
|
|
3491
|
+
const {
|
|
3492
|
+
onEsc,
|
|
3493
|
+
popup,
|
|
3494
|
+
className,
|
|
3495
|
+
prefixCls,
|
|
3496
|
+
style,
|
|
3497
|
+
target,
|
|
3498
|
+
onVisibleChanged,
|
|
3499
|
+
// Open
|
|
3500
|
+
open,
|
|
3501
|
+
keepDom,
|
|
3502
|
+
fresh,
|
|
3503
|
+
// Click
|
|
3504
|
+
onClick,
|
|
3505
|
+
// Mask
|
|
3506
|
+
mask,
|
|
3507
|
+
// Arrow
|
|
3508
|
+
arrow,
|
|
3509
|
+
arrowPos,
|
|
3510
|
+
align,
|
|
3511
|
+
// Motion
|
|
3512
|
+
motion,
|
|
3513
|
+
maskMotion,
|
|
3514
|
+
// Mobile
|
|
3515
|
+
mobile,
|
|
3516
|
+
// Portal
|
|
3517
|
+
forceRender,
|
|
3518
|
+
getPopupContainer,
|
|
3519
|
+
autoDestroy,
|
|
3520
|
+
portal: Portal,
|
|
3521
|
+
children,
|
|
3522
|
+
zIndex,
|
|
3523
|
+
onMouseEnter,
|
|
3524
|
+
onMouseLeave,
|
|
3525
|
+
onPointerEnter,
|
|
3526
|
+
onPointerDownCapture,
|
|
3527
|
+
ready,
|
|
3528
|
+
offsetX,
|
|
3529
|
+
offsetY,
|
|
3530
|
+
offsetR,
|
|
3531
|
+
offsetB,
|
|
3532
|
+
onAlign,
|
|
3533
|
+
onPrepare,
|
|
3534
|
+
// Resize
|
|
3535
|
+
onResize,
|
|
3536
|
+
stretch,
|
|
3537
|
+
targetWidth,
|
|
3538
|
+
targetHeight
|
|
3539
|
+
} = props;
|
|
3540
|
+
const popupContent = typeof popup === 'function' ? popup() : popup;
|
|
3541
|
+
|
|
3542
|
+
// We can not remove holder only when motion finished.
|
|
3543
|
+
const isNodeVisible = open || keepDom;
|
|
3544
|
+
|
|
3545
|
+
// ========================= Mobile =========================
|
|
3546
|
+
const isMobile = !!mobile;
|
|
3547
|
+
|
|
3548
|
+
// ========================== Mask ==========================
|
|
3549
|
+
const [mergedMask, mergedMaskMotion, mergedPopupMotion] = React__namespace.useMemo(() => {
|
|
3550
|
+
if (mobile) {
|
|
3551
|
+
return [mobile.mask, mobile.maskMotion, mobile.motion];
|
|
3552
|
+
}
|
|
3553
|
+
return [mask, maskMotion, motion];
|
|
3554
|
+
}, [mobile, mask, maskMotion, motion]);
|
|
3555
|
+
|
|
3556
|
+
// ======================= Container ========================
|
|
3557
|
+
const getPopupContainerNeedParams = getPopupContainer?.length > 0;
|
|
3558
|
+
const [show, setShow] = React__namespace.useState(!getPopupContainer || !getPopupContainerNeedParams);
|
|
3559
|
+
|
|
3560
|
+
// Delay to show since `getPopupContainer` need target element
|
|
3561
|
+
useLayoutEffect(() => {
|
|
3562
|
+
if (!show && getPopupContainerNeedParams && target) {
|
|
3563
|
+
setShow(true);
|
|
3564
|
+
}
|
|
3565
|
+
}, [show, getPopupContainerNeedParams, target]);
|
|
3566
|
+
|
|
3567
|
+
// ========================= Resize =========================
|
|
3568
|
+
const onInternalResize = useEvent((size, ele) => {
|
|
3569
|
+
onResize?.(size, ele);
|
|
3570
|
+
onAlign();
|
|
3571
|
+
});
|
|
3572
|
+
|
|
3573
|
+
// ========================= Styles =========================
|
|
3574
|
+
const offsetStyle = useOffsetStyle(isMobile, ready, open, align, offsetR, offsetB, offsetX, offsetY);
|
|
3575
|
+
|
|
3576
|
+
// ========================= Render =========================
|
|
3577
|
+
if (!show) {
|
|
3578
|
+
return null;
|
|
3579
|
+
}
|
|
3580
|
+
|
|
3581
|
+
// >>>>> Misc
|
|
3582
|
+
const miscStyle = {};
|
|
3583
|
+
if (stretch) {
|
|
3584
|
+
if (stretch.includes('height') && targetHeight) {
|
|
3585
|
+
miscStyle.height = targetHeight;
|
|
3586
|
+
} else if (stretch.includes('minHeight') && targetHeight) {
|
|
3587
|
+
miscStyle.minHeight = targetHeight;
|
|
3588
|
+
}
|
|
3589
|
+
if (stretch.includes('width') && targetWidth) {
|
|
3590
|
+
miscStyle.width = targetWidth;
|
|
3591
|
+
} else if (stretch.includes('minWidth') && targetWidth) {
|
|
3592
|
+
miscStyle.minWidth = targetWidth;
|
|
3593
|
+
}
|
|
3594
|
+
}
|
|
3595
|
+
if (!open) {
|
|
3596
|
+
miscStyle.pointerEvents = 'none';
|
|
3597
|
+
}
|
|
3598
|
+
return /*#__PURE__*/React__namespace.createElement(Portal, {
|
|
3599
|
+
open: forceRender || isNodeVisible,
|
|
3600
|
+
getContainer: getPopupContainer && (() => getPopupContainer(target)),
|
|
3601
|
+
autoDestroy: autoDestroy,
|
|
3602
|
+
onEsc: onEsc
|
|
3603
|
+
}, /*#__PURE__*/React__namespace.createElement(Mask, {
|
|
3604
|
+
prefixCls: prefixCls,
|
|
3605
|
+
open: open,
|
|
3606
|
+
zIndex: zIndex,
|
|
3607
|
+
mask: mergedMask,
|
|
3608
|
+
motion: mergedMaskMotion,
|
|
3609
|
+
mobile: isMobile
|
|
3610
|
+
}), /*#__PURE__*/React__namespace.createElement(RefResizeObserver, {
|
|
3611
|
+
onResize: onInternalResize,
|
|
3612
|
+
disabled: !open
|
|
3613
|
+
}, resizeObserverRef => {
|
|
3614
|
+
return /*#__PURE__*/React__namespace.createElement(CSSMotion, _extends({
|
|
3615
|
+
motionAppear: true,
|
|
3616
|
+
motionEnter: true,
|
|
3617
|
+
motionLeave: true,
|
|
3618
|
+
removeOnLeave: false,
|
|
3619
|
+
forceRender: forceRender,
|
|
3620
|
+
leavedClassName: `${prefixCls}-hidden`
|
|
3621
|
+
}, mergedPopupMotion, {
|
|
3622
|
+
onAppearPrepare: onPrepare,
|
|
3623
|
+
onEnterPrepare: onPrepare,
|
|
3624
|
+
visible: open,
|
|
3625
|
+
onVisibleChanged: nextVisible => {
|
|
3626
|
+
motion?.onVisibleChanged?.(nextVisible);
|
|
3627
|
+
onVisibleChanged(nextVisible);
|
|
3628
|
+
}
|
|
3629
|
+
}), ({
|
|
3630
|
+
className: motionClassName,
|
|
3631
|
+
style: motionStyle
|
|
3632
|
+
}, motionRef) => {
|
|
3633
|
+
const cls = clsx(prefixCls, motionClassName, className, {
|
|
3634
|
+
[`${prefixCls}-mobile`]: isMobile
|
|
3635
|
+
});
|
|
3636
|
+
return /*#__PURE__*/React__namespace.createElement("div", {
|
|
3637
|
+
ref: composeRef(resizeObserverRef, ref, motionRef),
|
|
3638
|
+
className: cls,
|
|
3639
|
+
style: {
|
|
3640
|
+
'--arrow-x': `${arrowPos.x || 0}px`,
|
|
3641
|
+
'--arrow-y': `${arrowPos.y || 0}px`,
|
|
3642
|
+
...offsetStyle,
|
|
3643
|
+
...miscStyle,
|
|
3644
|
+
...motionStyle,
|
|
3645
|
+
boxSizing: 'border-box',
|
|
3646
|
+
zIndex,
|
|
3647
|
+
...style
|
|
3648
|
+
},
|
|
3649
|
+
onMouseEnter: onMouseEnter,
|
|
3650
|
+
onMouseLeave: onMouseLeave,
|
|
3651
|
+
onPointerEnter: onPointerEnter,
|
|
3652
|
+
onClick: onClick,
|
|
3653
|
+
onPointerDownCapture: onPointerDownCapture
|
|
3654
|
+
}, arrow && /*#__PURE__*/React__namespace.createElement(Arrow, {
|
|
3655
|
+
prefixCls: prefixCls,
|
|
3656
|
+
arrow: arrow,
|
|
3657
|
+
arrowPos: arrowPos,
|
|
3658
|
+
align: align
|
|
3659
|
+
}), /*#__PURE__*/React__namespace.createElement(PopupContent, {
|
|
3660
|
+
cache: !open && !fresh
|
|
3661
|
+
}, popupContent));
|
|
3662
|
+
});
|
|
3663
|
+
}), children);
|
|
3664
|
+
});
|
|
3665
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
3666
|
+
Popup.displayName = 'Popup';
|
|
3667
|
+
}
|
|
3668
|
+
|
|
3669
|
+
// ===================== Nest =====================
|
|
3670
|
+
|
|
3671
|
+
const TriggerContext = /*#__PURE__*/React__namespace.createContext(null);
|
|
3672
|
+
|
|
3673
|
+
// ==================== Unique ====================
|
|
3674
|
+
|
|
3675
|
+
const UniqueContext = /*#__PURE__*/React__namespace.createContext(null);
|
|
3676
|
+
|
|
3677
|
+
function toArray(val) {
|
|
3678
|
+
return val ? Array.isArray(val) ? val : [val] : [];
|
|
3679
|
+
}
|
|
3680
|
+
function useAction(action, showAction, hideAction) {
|
|
3681
|
+
return React__namespace.useMemo(() => {
|
|
3682
|
+
const mergedShowAction = toArray(showAction ?? action);
|
|
3683
|
+
const mergedHideAction = toArray(hideAction ?? action);
|
|
3684
|
+
const showActionSet = new Set(mergedShowAction);
|
|
3685
|
+
const hideActionSet = new Set(mergedHideAction);
|
|
3686
|
+
if (showActionSet.has('hover') && !showActionSet.has('click')) {
|
|
3687
|
+
showActionSet.add('touch');
|
|
3688
|
+
}
|
|
3689
|
+
if (hideActionSet.has('hover') && !hideActionSet.has('click')) {
|
|
3690
|
+
hideActionSet.add('touch');
|
|
3691
|
+
}
|
|
3692
|
+
return [showActionSet, hideActionSet];
|
|
3693
|
+
}, [action, showAction, hideAction]);
|
|
3694
|
+
}
|
|
3695
|
+
|
|
3696
|
+
var isVisible = (element => {
|
|
3697
|
+
if (!element) {
|
|
3698
|
+
return false;
|
|
3699
|
+
}
|
|
3700
|
+
if (element instanceof Element) {
|
|
3701
|
+
if (element.offsetParent) {
|
|
3702
|
+
return true;
|
|
3703
|
+
}
|
|
3704
|
+
if (element.getBBox) {
|
|
3705
|
+
const {
|
|
3706
|
+
width,
|
|
3707
|
+
height
|
|
3708
|
+
} = element.getBBox();
|
|
3709
|
+
if (width || height) {
|
|
3710
|
+
return true;
|
|
3711
|
+
}
|
|
3712
|
+
}
|
|
3713
|
+
if (element.getBoundingClientRect) {
|
|
3714
|
+
const {
|
|
3715
|
+
width,
|
|
3716
|
+
height
|
|
3717
|
+
} = element.getBoundingClientRect();
|
|
3718
|
+
if (width || height) {
|
|
3719
|
+
return true;
|
|
3720
|
+
}
|
|
3721
|
+
}
|
|
3722
|
+
}
|
|
3723
|
+
return false;
|
|
3724
|
+
});
|
|
3725
|
+
|
|
3726
|
+
function isPointsEq(a1 = [], a2 = [], isAlignPoint) {
|
|
3727
|
+
const getVal = (a, index) => a[index] || '';
|
|
3728
|
+
if (isAlignPoint) {
|
|
3729
|
+
return getVal(a1, 0) === getVal(a2, 0);
|
|
3730
|
+
}
|
|
3731
|
+
return getVal(a1, 0) === getVal(a2, 0) && getVal(a1, 1) === getVal(a2, 1);
|
|
3732
|
+
}
|
|
3733
|
+
function getAlignPopupClassName(builtinPlacements, prefixCls, align, isAlignPoint) {
|
|
3734
|
+
const {
|
|
3735
|
+
points
|
|
3736
|
+
} = align;
|
|
3737
|
+
const placements = Object.keys(builtinPlacements);
|
|
3738
|
+
for (let i = 0; i < placements.length; i += 1) {
|
|
3739
|
+
const placement = placements[i];
|
|
3740
|
+
if (isPointsEq(builtinPlacements[placement]?.points, points, isAlignPoint)) {
|
|
3741
|
+
return `${prefixCls}-placement-${placement}`;
|
|
3742
|
+
}
|
|
3743
|
+
}
|
|
3744
|
+
return '';
|
|
3745
|
+
}
|
|
3746
|
+
function getWin(ele) {
|
|
3747
|
+
return ele.ownerDocument.defaultView;
|
|
3748
|
+
}
|
|
3749
|
+
|
|
3750
|
+
/**
|
|
3751
|
+
* Get all the scrollable parent elements of the element
|
|
3752
|
+
* @param ele The element to be detected
|
|
3753
|
+
* @param areaOnly Only return the parent which will cut visible area
|
|
3754
|
+
*/
|
|
3755
|
+
function collectScroller(ele) {
|
|
3756
|
+
const scrollerList = [];
|
|
3757
|
+
let current = ele?.parentElement;
|
|
3758
|
+
const scrollStyle = ['hidden', 'scroll', 'clip', 'auto'];
|
|
3759
|
+
while (current) {
|
|
3760
|
+
const {
|
|
3761
|
+
overflowX,
|
|
3762
|
+
overflowY,
|
|
3763
|
+
overflow
|
|
3764
|
+
} = getWin(current).getComputedStyle(current);
|
|
3765
|
+
if ([overflowX, overflowY, overflow].some(o => scrollStyle.includes(o))) {
|
|
3766
|
+
scrollerList.push(current);
|
|
3767
|
+
}
|
|
3768
|
+
current = current.parentElement;
|
|
3769
|
+
}
|
|
3770
|
+
return scrollerList;
|
|
3771
|
+
}
|
|
3772
|
+
function toNum(num, defaultValue = 1) {
|
|
3773
|
+
return Number.isNaN(num) ? defaultValue : num;
|
|
3774
|
+
}
|
|
3775
|
+
function getPxValue(val) {
|
|
3776
|
+
return toNum(parseFloat(val), 0);
|
|
3777
|
+
}
|
|
3778
|
+
/**
|
|
3779
|
+
*
|
|
3780
|
+
*
|
|
3781
|
+
* **************************************
|
|
3782
|
+
* * Border *
|
|
3783
|
+
* * ************************** *
|
|
3784
|
+
* * * * * *
|
|
3785
|
+
* * B * * S * B *
|
|
3786
|
+
* * o * * c * o *
|
|
3787
|
+
* * r * Content * r * r *
|
|
3788
|
+
* * d * * o * d *
|
|
3789
|
+
* * e * * l * e *
|
|
3790
|
+
* * r ******************** l * r *
|
|
3791
|
+
* * * Scroll * *
|
|
3792
|
+
* * ************************** *
|
|
3793
|
+
* * Border *
|
|
3794
|
+
* **************************************
|
|
3795
|
+
*
|
|
3796
|
+
*/
|
|
3797
|
+
/**
|
|
3798
|
+
* Get visible area of element
|
|
3799
|
+
*/
|
|
3800
|
+
function getVisibleArea(initArea, scrollerList) {
|
|
3801
|
+
const visibleArea = {
|
|
3802
|
+
...initArea
|
|
3803
|
+
};
|
|
3804
|
+
(scrollerList || []).forEach(ele => {
|
|
3805
|
+
if (ele instanceof HTMLBodyElement || ele instanceof HTMLHtmlElement) {
|
|
3806
|
+
return;
|
|
3807
|
+
}
|
|
3808
|
+
|
|
3809
|
+
// Skip if static position which will not affect visible area
|
|
3810
|
+
const {
|
|
3811
|
+
overflow,
|
|
3812
|
+
overflowClipMargin,
|
|
3813
|
+
borderTopWidth,
|
|
3814
|
+
borderBottomWidth,
|
|
3815
|
+
borderLeftWidth,
|
|
3816
|
+
borderRightWidth
|
|
3817
|
+
} = getWin(ele).getComputedStyle(ele);
|
|
3818
|
+
const eleRect = ele.getBoundingClientRect();
|
|
3819
|
+
const {
|
|
3820
|
+
offsetHeight: eleOutHeight,
|
|
3821
|
+
clientHeight: eleInnerHeight,
|
|
3822
|
+
offsetWidth: eleOutWidth,
|
|
3823
|
+
clientWidth: eleInnerWidth
|
|
3824
|
+
} = ele;
|
|
3825
|
+
const borderTopNum = getPxValue(borderTopWidth);
|
|
3826
|
+
const borderBottomNum = getPxValue(borderBottomWidth);
|
|
3827
|
+
const borderLeftNum = getPxValue(borderLeftWidth);
|
|
3828
|
+
const borderRightNum = getPxValue(borderRightWidth);
|
|
3829
|
+
const scaleX = toNum(Math.round(eleRect.width / eleOutWidth * 1000) / 1000);
|
|
3830
|
+
const scaleY = toNum(Math.round(eleRect.height / eleOutHeight * 1000) / 1000);
|
|
3831
|
+
|
|
3832
|
+
// Original visible area
|
|
3833
|
+
const eleScrollWidth = (eleOutWidth - eleInnerWidth - borderLeftNum - borderRightNum) * scaleX;
|
|
3834
|
+
const eleScrollHeight = (eleOutHeight - eleInnerHeight - borderTopNum - borderBottomNum) * scaleY;
|
|
3835
|
+
|
|
3836
|
+
// Cut border size
|
|
3837
|
+
const scaledBorderTopWidth = borderTopNum * scaleY;
|
|
3838
|
+
const scaledBorderBottomWidth = borderBottomNum * scaleY;
|
|
3839
|
+
const scaledBorderLeftWidth = borderLeftNum * scaleX;
|
|
3840
|
+
const scaledBorderRightWidth = borderRightNum * scaleX;
|
|
3841
|
+
|
|
3842
|
+
// Clip margin
|
|
3843
|
+
let clipMarginWidth = 0;
|
|
3844
|
+
let clipMarginHeight = 0;
|
|
3845
|
+
if (overflow === 'clip') {
|
|
3846
|
+
const clipNum = getPxValue(overflowClipMargin);
|
|
3847
|
+
clipMarginWidth = clipNum * scaleX;
|
|
3848
|
+
clipMarginHeight = clipNum * scaleY;
|
|
3849
|
+
}
|
|
3850
|
+
|
|
3851
|
+
// Region
|
|
3852
|
+
const eleLeft = eleRect.x + scaledBorderLeftWidth - clipMarginWidth;
|
|
3853
|
+
const eleTop = eleRect.y + scaledBorderTopWidth - clipMarginHeight;
|
|
3854
|
+
const eleRight = eleLeft + eleRect.width + 2 * clipMarginWidth - scaledBorderLeftWidth - scaledBorderRightWidth - eleScrollWidth;
|
|
3855
|
+
const eleBottom = eleTop + eleRect.height + 2 * clipMarginHeight - scaledBorderTopWidth - scaledBorderBottomWidth - eleScrollHeight;
|
|
3856
|
+
visibleArea.left = Math.max(visibleArea.left, eleLeft);
|
|
3857
|
+
visibleArea.top = Math.max(visibleArea.top, eleTop);
|
|
3858
|
+
visibleArea.right = Math.min(visibleArea.right, eleRight);
|
|
3859
|
+
visibleArea.bottom = Math.min(visibleArea.bottom, eleBottom);
|
|
3860
|
+
});
|
|
3861
|
+
return visibleArea;
|
|
3862
|
+
}
|
|
3863
|
+
|
|
3864
|
+
function getUnitOffset(size, offset = 0) {
|
|
3865
|
+
const offsetStr = `${offset}`;
|
|
3866
|
+
const cells = offsetStr.match(/^(.*)\%$/);
|
|
3867
|
+
if (cells) {
|
|
3868
|
+
return size * (parseFloat(cells[1]) / 100);
|
|
3869
|
+
}
|
|
3870
|
+
return parseFloat(offsetStr);
|
|
3871
|
+
}
|
|
3872
|
+
function getNumberOffset(rect, offset) {
|
|
3873
|
+
const [offsetX, offsetY] = offset || [];
|
|
3874
|
+
return [getUnitOffset(rect.width, offsetX), getUnitOffset(rect.height, offsetY)];
|
|
3875
|
+
}
|
|
3876
|
+
function splitPoints(points = '') {
|
|
3877
|
+
return [points[0], points[1]];
|
|
3878
|
+
}
|
|
3879
|
+
function getAlignPoint(rect, points) {
|
|
3880
|
+
const topBottom = points[0];
|
|
3881
|
+
const leftRight = points[1];
|
|
3882
|
+
let x;
|
|
3883
|
+
let y;
|
|
3884
|
+
|
|
3885
|
+
// Top & Bottom
|
|
3886
|
+
if (topBottom === 't') {
|
|
3887
|
+
y = rect.y;
|
|
3888
|
+
} else if (topBottom === 'b') {
|
|
3889
|
+
y = rect.y + rect.height;
|
|
3890
|
+
} else {
|
|
3891
|
+
y = rect.y + rect.height / 2;
|
|
3892
|
+
}
|
|
3893
|
+
|
|
3894
|
+
// Left & Right
|
|
3895
|
+
if (leftRight === 'l') {
|
|
3896
|
+
x = rect.x;
|
|
3897
|
+
} else if (leftRight === 'r') {
|
|
3898
|
+
x = rect.x + rect.width;
|
|
3899
|
+
} else {
|
|
3900
|
+
x = rect.x + rect.width / 2;
|
|
3901
|
+
}
|
|
3902
|
+
return {
|
|
3903
|
+
x,
|
|
3904
|
+
y
|
|
3905
|
+
};
|
|
3906
|
+
}
|
|
3907
|
+
function reversePoints(points, index) {
|
|
3908
|
+
const reverseMap = {
|
|
3909
|
+
t: 'b',
|
|
3910
|
+
b: 't',
|
|
3911
|
+
l: 'r',
|
|
3912
|
+
r: 'l'
|
|
3913
|
+
};
|
|
3914
|
+
const clone = [...points];
|
|
3915
|
+
clone[index] = reverseMap[points[index]] || 'c';
|
|
3916
|
+
return clone;
|
|
3917
|
+
}
|
|
3918
|
+
function flatPoints(points) {
|
|
3919
|
+
return points.join('');
|
|
3920
|
+
}
|
|
3921
|
+
function useAlign(open, popupEle, target, placement, builtinPlacements, popupAlign, onPopupAlign, mobile) {
|
|
3922
|
+
const [offsetInfo, setOffsetInfo] = React__namespace.useState({
|
|
3923
|
+
ready: false,
|
|
3924
|
+
offsetX: 0,
|
|
3925
|
+
offsetY: 0,
|
|
3926
|
+
offsetR: 0,
|
|
3927
|
+
offsetB: 0,
|
|
3928
|
+
arrowX: 0,
|
|
3929
|
+
arrowY: 0,
|
|
3930
|
+
scaleX: 1,
|
|
3931
|
+
scaleY: 1,
|
|
3932
|
+
align: builtinPlacements[placement] || {}
|
|
3933
|
+
});
|
|
3934
|
+
const alignCountRef = React__namespace.useRef(0);
|
|
3935
|
+
const scrollerList = React__namespace.useMemo(() => {
|
|
3936
|
+
if (!popupEle || mobile) {
|
|
3937
|
+
return [];
|
|
3938
|
+
}
|
|
3939
|
+
return collectScroller(popupEle);
|
|
3940
|
+
}, [popupEle]);
|
|
3941
|
+
|
|
3942
|
+
// ========================= Flip ==========================
|
|
3943
|
+
// We will memo flip info.
|
|
3944
|
+
// If size change to make flip, it will memo the flip info and use it in next align.
|
|
3945
|
+
const prevFlipRef = React__namespace.useRef({});
|
|
3946
|
+
const resetFlipCache = () => {
|
|
3947
|
+
prevFlipRef.current = {};
|
|
3948
|
+
};
|
|
3949
|
+
if (!open) {
|
|
3950
|
+
resetFlipCache();
|
|
3951
|
+
}
|
|
3952
|
+
|
|
3953
|
+
// ========================= Align =========================
|
|
3954
|
+
const onAlign = useEvent(() => {
|
|
3955
|
+
if (popupEle && target && open && !mobile) {
|
|
3956
|
+
const popupElement = popupEle;
|
|
3957
|
+
const doc = popupElement.ownerDocument;
|
|
3958
|
+
const win = getWin(popupElement);
|
|
3959
|
+
const {
|
|
3960
|
+
position: popupPosition
|
|
3961
|
+
} = win.getComputedStyle(popupElement);
|
|
3962
|
+
const originLeft = popupElement.style.left;
|
|
3963
|
+
const originTop = popupElement.style.top;
|
|
3964
|
+
const originRight = popupElement.style.right;
|
|
3965
|
+
const originBottom = popupElement.style.bottom;
|
|
3966
|
+
const originOverflow = popupElement.style.overflow;
|
|
3967
|
+
|
|
3968
|
+
// Placement
|
|
3969
|
+
const placementInfo = {
|
|
3970
|
+
...builtinPlacements[placement],
|
|
3971
|
+
...popupAlign
|
|
3972
|
+
};
|
|
3973
|
+
|
|
3974
|
+
// placeholder element
|
|
3975
|
+
const placeholderElement = doc.createElement('div');
|
|
3976
|
+
popupElement.parentElement?.appendChild(placeholderElement);
|
|
3977
|
+
placeholderElement.style.left = `${popupElement.offsetLeft}px`;
|
|
3978
|
+
placeholderElement.style.top = `${popupElement.offsetTop}px`;
|
|
3979
|
+
placeholderElement.style.position = popupPosition;
|
|
3980
|
+
placeholderElement.style.height = `${popupElement.offsetHeight}px`;
|
|
3981
|
+
placeholderElement.style.width = `${popupElement.offsetWidth}px`;
|
|
3982
|
+
|
|
3983
|
+
// Reset first
|
|
3984
|
+
popupElement.style.left = '0';
|
|
3985
|
+
popupElement.style.top = '0';
|
|
3986
|
+
popupElement.style.right = 'auto';
|
|
3987
|
+
popupElement.style.bottom = 'auto';
|
|
3988
|
+
popupElement.style.overflow = 'hidden';
|
|
3989
|
+
|
|
3990
|
+
// Calculate align style, we should consider `transform` case
|
|
3991
|
+
let targetRect;
|
|
3992
|
+
if (Array.isArray(target)) {
|
|
3993
|
+
targetRect = {
|
|
3994
|
+
x: target[0],
|
|
3995
|
+
y: target[1],
|
|
3996
|
+
width: 0,
|
|
3997
|
+
height: 0
|
|
3998
|
+
};
|
|
3999
|
+
} else {
|
|
4000
|
+
const rect = target.getBoundingClientRect();
|
|
4001
|
+
rect.x = rect.x ?? rect.left;
|
|
4002
|
+
rect.y = rect.y ?? rect.top;
|
|
4003
|
+
targetRect = {
|
|
4004
|
+
x: rect.x,
|
|
4005
|
+
y: rect.y,
|
|
4006
|
+
width: rect.width,
|
|
4007
|
+
height: rect.height
|
|
4008
|
+
};
|
|
4009
|
+
}
|
|
4010
|
+
const popupRect = popupElement.getBoundingClientRect();
|
|
4011
|
+
const {
|
|
4012
|
+
height,
|
|
4013
|
+
width
|
|
4014
|
+
} = win.getComputedStyle(popupElement);
|
|
4015
|
+
popupRect.x = popupRect.x ?? popupRect.left;
|
|
4016
|
+
popupRect.y = popupRect.y ?? popupRect.top;
|
|
4017
|
+
const {
|
|
4018
|
+
clientWidth,
|
|
4019
|
+
clientHeight,
|
|
4020
|
+
scrollWidth,
|
|
4021
|
+
scrollHeight,
|
|
4022
|
+
scrollTop,
|
|
4023
|
+
scrollLeft
|
|
4024
|
+
} = doc.documentElement;
|
|
4025
|
+
const popupHeight = popupRect.height;
|
|
4026
|
+
const popupWidth = popupRect.width;
|
|
4027
|
+
const targetHeight = targetRect.height;
|
|
4028
|
+
const targetWidth = targetRect.width;
|
|
4029
|
+
|
|
4030
|
+
// Get bounding of visible area
|
|
4031
|
+
const visibleRegion = {
|
|
4032
|
+
left: 0,
|
|
4033
|
+
top: 0,
|
|
4034
|
+
right: clientWidth,
|
|
4035
|
+
bottom: clientHeight
|
|
4036
|
+
};
|
|
4037
|
+
const scrollRegion = {
|
|
4038
|
+
left: -scrollLeft,
|
|
4039
|
+
top: -scrollTop,
|
|
4040
|
+
right: scrollWidth - scrollLeft,
|
|
4041
|
+
bottom: scrollHeight - scrollTop
|
|
4042
|
+
};
|
|
4043
|
+
let {
|
|
4044
|
+
htmlRegion
|
|
4045
|
+
} = placementInfo;
|
|
4046
|
+
const VISIBLE = 'visible';
|
|
4047
|
+
const VISIBLE_FIRST = 'visibleFirst';
|
|
4048
|
+
if (htmlRegion !== 'scroll' && htmlRegion !== VISIBLE_FIRST) {
|
|
4049
|
+
htmlRegion = VISIBLE;
|
|
4050
|
+
}
|
|
4051
|
+
const isVisibleFirst = htmlRegion === VISIBLE_FIRST;
|
|
4052
|
+
const scrollRegionArea = getVisibleArea(scrollRegion, scrollerList);
|
|
4053
|
+
const visibleRegionArea = getVisibleArea(visibleRegion, scrollerList);
|
|
4054
|
+
const visibleArea = htmlRegion === VISIBLE ? visibleRegionArea : scrollRegionArea;
|
|
4055
|
+
|
|
4056
|
+
// When set to `visibleFirst`,
|
|
4057
|
+
// the check `adjust` logic will use `visibleRegion` for check first.
|
|
4058
|
+
const adjustCheckVisibleArea = isVisibleFirst ? visibleRegionArea : visibleArea;
|
|
4059
|
+
|
|
4060
|
+
// Record right & bottom align data
|
|
4061
|
+
popupElement.style.left = 'auto';
|
|
4062
|
+
popupElement.style.top = 'auto';
|
|
4063
|
+
popupElement.style.right = '0';
|
|
4064
|
+
popupElement.style.bottom = '0';
|
|
4065
|
+
const popupMirrorRect = popupElement.getBoundingClientRect();
|
|
4066
|
+
|
|
4067
|
+
// Reset back
|
|
4068
|
+
popupElement.style.left = originLeft;
|
|
4069
|
+
popupElement.style.top = originTop;
|
|
4070
|
+
popupElement.style.right = originRight;
|
|
4071
|
+
popupElement.style.bottom = originBottom;
|
|
4072
|
+
popupElement.style.overflow = originOverflow;
|
|
4073
|
+
popupElement.parentElement?.removeChild(placeholderElement);
|
|
4074
|
+
|
|
4075
|
+
// Calculate scale
|
|
4076
|
+
const scaleX = toNum(Math.round(popupWidth / parseFloat(width) * 1000) / 1000);
|
|
4077
|
+
const scaleY = toNum(Math.round(popupHeight / parseFloat(height) * 1000) / 1000);
|
|
4078
|
+
|
|
4079
|
+
// No need to align since it's not visible in view
|
|
4080
|
+
if (scaleX === 0 || scaleY === 0 || isDOM(target) && !isVisible(target)) {
|
|
4081
|
+
return;
|
|
4082
|
+
}
|
|
4083
|
+
|
|
4084
|
+
// Offset
|
|
4085
|
+
const {
|
|
4086
|
+
offset,
|
|
4087
|
+
targetOffset
|
|
4088
|
+
} = placementInfo;
|
|
4089
|
+
let [popupOffsetX, popupOffsetY] = getNumberOffset(popupRect, offset);
|
|
4090
|
+
const [targetOffsetX, targetOffsetY] = getNumberOffset(targetRect, targetOffset);
|
|
4091
|
+
targetRect.x -= targetOffsetX;
|
|
4092
|
+
targetRect.y -= targetOffsetY;
|
|
4093
|
+
|
|
4094
|
+
// Points
|
|
4095
|
+
const [popupPoint, targetPoint] = placementInfo.points || [];
|
|
4096
|
+
const targetPoints = splitPoints(targetPoint);
|
|
4097
|
+
const popupPoints = splitPoints(popupPoint);
|
|
4098
|
+
const targetAlignPoint = getAlignPoint(targetRect, targetPoints);
|
|
4099
|
+
const popupAlignPoint = getAlignPoint(popupRect, popupPoints);
|
|
4100
|
+
|
|
4101
|
+
// Real align info may not same as origin one
|
|
4102
|
+
const nextAlignInfo = {
|
|
4103
|
+
...placementInfo
|
|
4104
|
+
};
|
|
4105
|
+
let nextPoints = [popupPoints, targetPoints];
|
|
4106
|
+
|
|
4107
|
+
// Next Offset
|
|
4108
|
+
let nextOffsetX = targetAlignPoint.x - popupAlignPoint.x + popupOffsetX;
|
|
4109
|
+
let nextOffsetY = targetAlignPoint.y - popupAlignPoint.y + popupOffsetY;
|
|
4110
|
+
|
|
4111
|
+
// ============== Intersection ===============
|
|
4112
|
+
// Get area by position. Used for check if flip area is better
|
|
4113
|
+
function getIntersectionVisibleArea(offsetX, offsetY, area = visibleArea) {
|
|
4114
|
+
const l = popupRect.x + offsetX;
|
|
4115
|
+
const t = popupRect.y + offsetY;
|
|
4116
|
+
const r = l + popupWidth;
|
|
4117
|
+
const b = t + popupHeight;
|
|
4118
|
+
const visibleL = Math.max(l, area.left);
|
|
4119
|
+
const visibleT = Math.max(t, area.top);
|
|
4120
|
+
const visibleR = Math.min(r, area.right);
|
|
4121
|
+
const visibleB = Math.min(b, area.bottom);
|
|
4122
|
+
return Math.max(0, (visibleR - visibleL) * (visibleB - visibleT));
|
|
4123
|
+
}
|
|
4124
|
+
const originIntersectionVisibleArea = getIntersectionVisibleArea(nextOffsetX, nextOffsetY);
|
|
4125
|
+
|
|
4126
|
+
// As `visibleFirst`, we prepare this for check
|
|
4127
|
+
const originIntersectionRecommendArea = getIntersectionVisibleArea(nextOffsetX, nextOffsetY, visibleRegionArea);
|
|
4128
|
+
|
|
4129
|
+
// ========================== Overflow ===========================
|
|
4130
|
+
const targetAlignPointTL = getAlignPoint(targetRect, ['t', 'l']);
|
|
4131
|
+
const popupAlignPointTL = getAlignPoint(popupRect, ['t', 'l']);
|
|
4132
|
+
const targetAlignPointBR = getAlignPoint(targetRect, ['b', 'r']);
|
|
4133
|
+
const popupAlignPointBR = getAlignPoint(popupRect, ['b', 'r']);
|
|
4134
|
+
const overflow = placementInfo.overflow || {};
|
|
4135
|
+
const {
|
|
4136
|
+
adjustX,
|
|
4137
|
+
adjustY,
|
|
4138
|
+
shiftX,
|
|
4139
|
+
shiftY
|
|
4140
|
+
} = overflow;
|
|
4141
|
+
const supportAdjust = val => {
|
|
4142
|
+
if (typeof val === 'boolean') {
|
|
4143
|
+
return val;
|
|
4144
|
+
}
|
|
4145
|
+
return val >= 0;
|
|
4146
|
+
};
|
|
4147
|
+
|
|
4148
|
+
// Prepare position
|
|
4149
|
+
let nextPopupY;
|
|
4150
|
+
let nextPopupBottom;
|
|
4151
|
+
let nextPopupX;
|
|
4152
|
+
let nextPopupRight;
|
|
4153
|
+
function syncNextPopupPosition() {
|
|
4154
|
+
nextPopupY = popupRect.y + nextOffsetY;
|
|
4155
|
+
nextPopupBottom = nextPopupY + popupHeight;
|
|
4156
|
+
nextPopupX = popupRect.x + nextOffsetX;
|
|
4157
|
+
nextPopupRight = nextPopupX + popupWidth;
|
|
4158
|
+
}
|
|
4159
|
+
syncNextPopupPosition();
|
|
4160
|
+
|
|
4161
|
+
// >>>>>>>>>> Top & Bottom
|
|
4162
|
+
const needAdjustY = supportAdjust(adjustY);
|
|
4163
|
+
const sameTB = popupPoints[0] === targetPoints[0];
|
|
4164
|
+
|
|
4165
|
+
// Bottom to Top
|
|
4166
|
+
if (needAdjustY && popupPoints[0] === 't' && (nextPopupBottom > adjustCheckVisibleArea.bottom || prevFlipRef.current.bt)) {
|
|
4167
|
+
let tmpNextOffsetY = nextOffsetY;
|
|
4168
|
+
if (sameTB) {
|
|
4169
|
+
tmpNextOffsetY -= popupHeight - targetHeight;
|
|
4170
|
+
} else {
|
|
4171
|
+
tmpNextOffsetY = targetAlignPointTL.y - popupAlignPointBR.y - popupOffsetY;
|
|
4172
|
+
}
|
|
4173
|
+
const newVisibleArea = getIntersectionVisibleArea(nextOffsetX, tmpNextOffsetY);
|
|
4174
|
+
const newVisibleRecommendArea = getIntersectionVisibleArea(nextOffsetX, tmpNextOffsetY, visibleRegionArea);
|
|
4175
|
+
if (
|
|
4176
|
+
// Of course use larger one
|
|
4177
|
+
newVisibleArea > originIntersectionVisibleArea || newVisibleArea === originIntersectionVisibleArea && (!isVisibleFirst ||
|
|
4178
|
+
// Choose recommend one
|
|
4179
|
+
newVisibleRecommendArea >= originIntersectionRecommendArea)) {
|
|
4180
|
+
prevFlipRef.current.bt = true;
|
|
4181
|
+
nextOffsetY = tmpNextOffsetY;
|
|
4182
|
+
popupOffsetY = -popupOffsetY;
|
|
4183
|
+
nextPoints = [reversePoints(nextPoints[0], 0), reversePoints(nextPoints[1], 0)];
|
|
4184
|
+
} else {
|
|
4185
|
+
prevFlipRef.current.bt = false;
|
|
4186
|
+
}
|
|
4187
|
+
}
|
|
4188
|
+
|
|
4189
|
+
// Top to Bottom
|
|
4190
|
+
if (needAdjustY && popupPoints[0] === 'b' && (nextPopupY < adjustCheckVisibleArea.top || prevFlipRef.current.tb)) {
|
|
4191
|
+
let tmpNextOffsetY = nextOffsetY;
|
|
4192
|
+
if (sameTB) {
|
|
4193
|
+
tmpNextOffsetY += popupHeight - targetHeight;
|
|
4194
|
+
} else {
|
|
4195
|
+
tmpNextOffsetY = targetAlignPointBR.y - popupAlignPointTL.y - popupOffsetY;
|
|
4196
|
+
}
|
|
4197
|
+
const newVisibleArea = getIntersectionVisibleArea(nextOffsetX, tmpNextOffsetY);
|
|
4198
|
+
const newVisibleRecommendArea = getIntersectionVisibleArea(nextOffsetX, tmpNextOffsetY, visibleRegionArea);
|
|
4199
|
+
if (
|
|
4200
|
+
// Of course use larger one
|
|
4201
|
+
newVisibleArea > originIntersectionVisibleArea || newVisibleArea === originIntersectionVisibleArea && (!isVisibleFirst ||
|
|
4202
|
+
// Choose recommend one
|
|
4203
|
+
newVisibleRecommendArea >= originIntersectionRecommendArea)) {
|
|
4204
|
+
prevFlipRef.current.tb = true;
|
|
4205
|
+
nextOffsetY = tmpNextOffsetY;
|
|
4206
|
+
popupOffsetY = -popupOffsetY;
|
|
4207
|
+
nextPoints = [reversePoints(nextPoints[0], 0), reversePoints(nextPoints[1], 0)];
|
|
4208
|
+
} else {
|
|
4209
|
+
prevFlipRef.current.tb = false;
|
|
4210
|
+
}
|
|
4211
|
+
}
|
|
4212
|
+
|
|
4213
|
+
// >>>>>>>>>> Left & Right
|
|
4214
|
+
const needAdjustX = supportAdjust(adjustX);
|
|
4215
|
+
|
|
4216
|
+
// >>>>> Flip
|
|
4217
|
+
const sameLR = popupPoints[1] === targetPoints[1];
|
|
4218
|
+
|
|
4219
|
+
// Right to Left
|
|
4220
|
+
if (needAdjustX && popupPoints[1] === 'l' && (nextPopupRight > adjustCheckVisibleArea.right || prevFlipRef.current.rl)) {
|
|
4221
|
+
let tmpNextOffsetX = nextOffsetX;
|
|
4222
|
+
if (sameLR) {
|
|
4223
|
+
tmpNextOffsetX -= popupWidth - targetWidth;
|
|
4224
|
+
} else {
|
|
4225
|
+
tmpNextOffsetX = targetAlignPointTL.x - popupAlignPointBR.x - popupOffsetX;
|
|
4226
|
+
}
|
|
4227
|
+
const newVisibleArea = getIntersectionVisibleArea(tmpNextOffsetX, nextOffsetY);
|
|
4228
|
+
const newVisibleRecommendArea = getIntersectionVisibleArea(tmpNextOffsetX, nextOffsetY, visibleRegionArea);
|
|
4229
|
+
if (
|
|
4230
|
+
// Of course use larger one
|
|
4231
|
+
newVisibleArea > originIntersectionVisibleArea || newVisibleArea === originIntersectionVisibleArea && (!isVisibleFirst ||
|
|
4232
|
+
// Choose recommend one
|
|
4233
|
+
newVisibleRecommendArea >= originIntersectionRecommendArea)) {
|
|
4234
|
+
prevFlipRef.current.rl = true;
|
|
4235
|
+
nextOffsetX = tmpNextOffsetX;
|
|
4236
|
+
popupOffsetX = -popupOffsetX;
|
|
4237
|
+
nextPoints = [reversePoints(nextPoints[0], 1), reversePoints(nextPoints[1], 1)];
|
|
4238
|
+
} else {
|
|
4239
|
+
prevFlipRef.current.rl = false;
|
|
4240
|
+
}
|
|
4241
|
+
}
|
|
4242
|
+
|
|
4243
|
+
// Left to Right
|
|
4244
|
+
if (needAdjustX && popupPoints[1] === 'r' && (nextPopupX < adjustCheckVisibleArea.left || prevFlipRef.current.lr)) {
|
|
4245
|
+
let tmpNextOffsetX = nextOffsetX;
|
|
4246
|
+
if (sameLR) {
|
|
4247
|
+
tmpNextOffsetX += popupWidth - targetWidth;
|
|
4248
|
+
} else {
|
|
4249
|
+
tmpNextOffsetX = targetAlignPointBR.x - popupAlignPointTL.x - popupOffsetX;
|
|
4250
|
+
}
|
|
4251
|
+
const newVisibleArea = getIntersectionVisibleArea(tmpNextOffsetX, nextOffsetY);
|
|
4252
|
+
const newVisibleRecommendArea = getIntersectionVisibleArea(tmpNextOffsetX, nextOffsetY, visibleRegionArea);
|
|
4253
|
+
if (
|
|
4254
|
+
// Of course use larger one
|
|
4255
|
+
newVisibleArea > originIntersectionVisibleArea || newVisibleArea === originIntersectionVisibleArea && (!isVisibleFirst ||
|
|
4256
|
+
// Choose recommend one
|
|
4257
|
+
newVisibleRecommendArea >= originIntersectionRecommendArea)) {
|
|
4258
|
+
prevFlipRef.current.lr = true;
|
|
4259
|
+
nextOffsetX = tmpNextOffsetX;
|
|
4260
|
+
popupOffsetX = -popupOffsetX;
|
|
4261
|
+
nextPoints = [reversePoints(nextPoints[0], 1), reversePoints(nextPoints[1], 1)];
|
|
4262
|
+
} else {
|
|
4263
|
+
prevFlipRef.current.lr = false;
|
|
4264
|
+
}
|
|
4265
|
+
}
|
|
4266
|
+
nextAlignInfo.points = [flatPoints(nextPoints[0]), flatPoints(nextPoints[1])];
|
|
4267
|
+
|
|
4268
|
+
// ============================ Shift ============================
|
|
4269
|
+
syncNextPopupPosition();
|
|
4270
|
+
const numShiftX = shiftX === true ? 0 : shiftX;
|
|
4271
|
+
if (typeof numShiftX === 'number') {
|
|
4272
|
+
// Left
|
|
4273
|
+
if (nextPopupX < visibleRegionArea.left) {
|
|
4274
|
+
nextOffsetX -= nextPopupX - visibleRegionArea.left - popupOffsetX;
|
|
4275
|
+
if (targetRect.x + targetWidth < visibleRegionArea.left + numShiftX) {
|
|
4276
|
+
nextOffsetX += targetRect.x - visibleRegionArea.left + targetWidth - numShiftX;
|
|
4277
|
+
}
|
|
4278
|
+
}
|
|
4279
|
+
|
|
4280
|
+
// Right
|
|
4281
|
+
if (nextPopupRight > visibleRegionArea.right) {
|
|
4282
|
+
nextOffsetX -= nextPopupRight - visibleRegionArea.right - popupOffsetX;
|
|
4283
|
+
if (targetRect.x > visibleRegionArea.right - numShiftX) {
|
|
4284
|
+
nextOffsetX += targetRect.x - visibleRegionArea.right + numShiftX;
|
|
4285
|
+
}
|
|
4286
|
+
}
|
|
4287
|
+
}
|
|
4288
|
+
const numShiftY = shiftY === true ? 0 : shiftY;
|
|
4289
|
+
if (typeof numShiftY === 'number') {
|
|
4290
|
+
// Top
|
|
4291
|
+
if (nextPopupY < visibleRegionArea.top) {
|
|
4292
|
+
nextOffsetY -= nextPopupY - visibleRegionArea.top - popupOffsetY;
|
|
4293
|
+
|
|
4294
|
+
// When target if far away from visible area
|
|
4295
|
+
// Stop shift
|
|
4296
|
+
if (targetRect.y + targetHeight < visibleRegionArea.top + numShiftY) {
|
|
4297
|
+
nextOffsetY += targetRect.y - visibleRegionArea.top + targetHeight - numShiftY;
|
|
4298
|
+
}
|
|
4299
|
+
}
|
|
4300
|
+
|
|
4301
|
+
// Bottom
|
|
4302
|
+
if (nextPopupBottom > visibleRegionArea.bottom) {
|
|
4303
|
+
nextOffsetY -= nextPopupBottom - visibleRegionArea.bottom - popupOffsetY;
|
|
4304
|
+
if (targetRect.y > visibleRegionArea.bottom - numShiftY) {
|
|
4305
|
+
nextOffsetY += targetRect.y - visibleRegionArea.bottom + numShiftY;
|
|
4306
|
+
}
|
|
4307
|
+
}
|
|
4308
|
+
}
|
|
4309
|
+
|
|
4310
|
+
// ============================ Arrow ============================
|
|
4311
|
+
// Arrow center align
|
|
4312
|
+
const popupLeft = popupRect.x + nextOffsetX;
|
|
4313
|
+
const popupRight = popupLeft + popupWidth;
|
|
4314
|
+
const popupTop = popupRect.y + nextOffsetY;
|
|
4315
|
+
const popupBottom = popupTop + popupHeight;
|
|
4316
|
+
const targetLeft = targetRect.x;
|
|
4317
|
+
const targetRight = targetLeft + targetWidth;
|
|
4318
|
+
const targetTop = targetRect.y;
|
|
4319
|
+
const targetBottom = targetTop + targetHeight;
|
|
4320
|
+
|
|
4321
|
+
/** Max left of the popup and target element */
|
|
4322
|
+
const maxLeft = Math.max(popupLeft, targetLeft);
|
|
4323
|
+
/** Min right of the popup and target element */
|
|
4324
|
+
const minRight = Math.min(popupRight, targetRight);
|
|
4325
|
+
|
|
4326
|
+
/** The center X of popup & target cross area */
|
|
4327
|
+
const xCenter = (maxLeft + minRight) / 2;
|
|
4328
|
+
/** Arrow X of popup offset */
|
|
4329
|
+
const nextArrowX = xCenter - popupLeft;
|
|
4330
|
+
const maxTop = Math.max(popupTop, targetTop);
|
|
4331
|
+
const minBottom = Math.min(popupBottom, targetBottom);
|
|
4332
|
+
const yCenter = (maxTop + minBottom) / 2;
|
|
4333
|
+
const nextArrowY = yCenter - popupTop;
|
|
4334
|
+
onPopupAlign?.(popupEle, nextAlignInfo);
|
|
4335
|
+
|
|
4336
|
+
// Additional calculate right & bottom position
|
|
4337
|
+
let offsetX4Right = popupMirrorRect.right - popupRect.x - (nextOffsetX + popupRect.width);
|
|
4338
|
+
let offsetY4Bottom = popupMirrorRect.bottom - popupRect.y - (nextOffsetY + popupRect.height);
|
|
4339
|
+
if (scaleX === 1) {
|
|
4340
|
+
nextOffsetX = Math.floor(nextOffsetX);
|
|
4341
|
+
offsetX4Right = Math.floor(offsetX4Right);
|
|
4342
|
+
}
|
|
4343
|
+
if (scaleY === 1) {
|
|
4344
|
+
nextOffsetY = Math.floor(nextOffsetY);
|
|
4345
|
+
offsetY4Bottom = Math.floor(offsetY4Bottom);
|
|
4346
|
+
}
|
|
4347
|
+
const nextOffsetInfo = {
|
|
4348
|
+
ready: true,
|
|
4349
|
+
offsetX: nextOffsetX / scaleX,
|
|
4350
|
+
offsetY: nextOffsetY / scaleY,
|
|
4351
|
+
offsetR: offsetX4Right / scaleX,
|
|
4352
|
+
offsetB: offsetY4Bottom / scaleY,
|
|
4353
|
+
arrowX: nextArrowX / scaleX,
|
|
4354
|
+
arrowY: nextArrowY / scaleY,
|
|
4355
|
+
scaleX,
|
|
4356
|
+
scaleY,
|
|
4357
|
+
align: nextAlignInfo
|
|
4358
|
+
};
|
|
4359
|
+
setOffsetInfo(nextOffsetInfo);
|
|
4360
|
+
}
|
|
4361
|
+
});
|
|
4362
|
+
const triggerAlign = () => {
|
|
4363
|
+
alignCountRef.current += 1;
|
|
4364
|
+
const id = alignCountRef.current;
|
|
4365
|
+
|
|
4366
|
+
// Merge all align requirement into one frame
|
|
4367
|
+
Promise.resolve().then(() => {
|
|
4368
|
+
if (alignCountRef.current === id) {
|
|
4369
|
+
onAlign();
|
|
4370
|
+
}
|
|
4371
|
+
});
|
|
4372
|
+
};
|
|
4373
|
+
|
|
4374
|
+
// Reset ready status when placement & open changed
|
|
4375
|
+
const resetReady = () => {
|
|
4376
|
+
setOffsetInfo(ori => ({
|
|
4377
|
+
...ori,
|
|
4378
|
+
ready: false
|
|
4379
|
+
}));
|
|
4380
|
+
};
|
|
4381
|
+
useLayoutEffect(resetReady, [placement]);
|
|
4382
|
+
useLayoutEffect(() => {
|
|
4383
|
+
if (!open) {
|
|
4384
|
+
resetReady();
|
|
4385
|
+
}
|
|
4386
|
+
}, [open]);
|
|
4387
|
+
return [offsetInfo.ready, offsetInfo.offsetX, offsetInfo.offsetY, offsetInfo.offsetR, offsetInfo.offsetB, offsetInfo.arrowX, offsetInfo.arrowY, offsetInfo.scaleX, offsetInfo.scaleY, offsetInfo.align, triggerAlign];
|
|
4388
|
+
}
|
|
4389
|
+
|
|
4390
|
+
function useDelay() {
|
|
4391
|
+
const delayRef = React__namespace.useRef(null);
|
|
4392
|
+
const clearDelay = () => {
|
|
4393
|
+
if (delayRef.current) {
|
|
4394
|
+
clearTimeout(delayRef.current);
|
|
4395
|
+
delayRef.current = null;
|
|
4396
|
+
}
|
|
4397
|
+
};
|
|
4398
|
+
const delayInvoke = (callback, delay) => {
|
|
4399
|
+
clearDelay();
|
|
4400
|
+
if (delay === 0) {
|
|
4401
|
+
callback();
|
|
4402
|
+
} else {
|
|
4403
|
+
delayRef.current = setTimeout(() => {
|
|
4404
|
+
callback();
|
|
4405
|
+
}, delay * 1000);
|
|
4406
|
+
}
|
|
4407
|
+
};
|
|
4408
|
+
|
|
4409
|
+
// Clean up on unmount
|
|
4410
|
+
React__namespace.useEffect(() => {
|
|
4411
|
+
return () => {
|
|
4412
|
+
clearDelay();
|
|
4413
|
+
};
|
|
4414
|
+
}, []);
|
|
4415
|
+
return delayInvoke;
|
|
4416
|
+
}
|
|
4417
|
+
|
|
4418
|
+
function useWatch(open, target, popup, onAlign, onScroll) {
|
|
4419
|
+
useLayoutEffect(() => {
|
|
4420
|
+
if (open && target && popup) {
|
|
4421
|
+
const targetElement = target;
|
|
4422
|
+
const popupElement = popup;
|
|
4423
|
+
const targetScrollList = collectScroller(targetElement);
|
|
4424
|
+
const popupScrollList = collectScroller(popupElement);
|
|
4425
|
+
const win = getWin(popupElement);
|
|
4426
|
+
const mergedList = new Set([win, ...targetScrollList, ...popupScrollList]);
|
|
4427
|
+
function notifyScroll() {
|
|
4428
|
+
onAlign();
|
|
4429
|
+
onScroll();
|
|
4430
|
+
}
|
|
4431
|
+
mergedList.forEach(scroller => {
|
|
4432
|
+
scroller.addEventListener('scroll', notifyScroll, {
|
|
4433
|
+
passive: true
|
|
4434
|
+
});
|
|
4435
|
+
});
|
|
4436
|
+
win.addEventListener('resize', notifyScroll, {
|
|
4437
|
+
passive: true
|
|
4438
|
+
});
|
|
4439
|
+
|
|
4440
|
+
// First time always do align
|
|
4441
|
+
onAlign();
|
|
4442
|
+
return () => {
|
|
4443
|
+
mergedList.forEach(scroller => {
|
|
4444
|
+
scroller.removeEventListener('scroll', notifyScroll);
|
|
4445
|
+
win.removeEventListener('resize', notifyScroll);
|
|
4446
|
+
});
|
|
4447
|
+
};
|
|
4448
|
+
}
|
|
4449
|
+
}, [open, target, popup]);
|
|
4450
|
+
}
|
|
4451
|
+
|
|
4452
|
+
/**
|
|
4453
|
+
* Close if click on the window.
|
|
4454
|
+
* Return the function that click on the Popup element.
|
|
4455
|
+
*/
|
|
4456
|
+
function useWinClick(open, clickToHide, targetEle, popupEle, mask, maskClosable, inPopupOrChild, triggerOpen) {
|
|
4457
|
+
const openRef = React__namespace.useRef(open);
|
|
4458
|
+
openRef.current = open;
|
|
4459
|
+
const popupPointerDownRef = React__namespace.useRef(false);
|
|
4460
|
+
|
|
4461
|
+
// Click to hide is special action since click popup element should not hide
|
|
4462
|
+
React__namespace.useEffect(() => {
|
|
4463
|
+
if (clickToHide && popupEle && (!mask || maskClosable)) {
|
|
4464
|
+
const onPointerDown = () => {
|
|
4465
|
+
popupPointerDownRef.current = false;
|
|
4466
|
+
};
|
|
4467
|
+
const onTriggerClose = e => {
|
|
4468
|
+
if (openRef.current && !inPopupOrChild(e.composedPath?.()?.[0] || e.target) && !popupPointerDownRef.current) {
|
|
4469
|
+
triggerOpen(false);
|
|
4470
|
+
}
|
|
4471
|
+
};
|
|
4472
|
+
const win = getWin(popupEle);
|
|
4473
|
+
win.addEventListener('pointerdown', onPointerDown, true);
|
|
4474
|
+
win.addEventListener('mousedown', onTriggerClose, true);
|
|
4475
|
+
win.addEventListener('contextmenu', onTriggerClose, true);
|
|
4476
|
+
|
|
4477
|
+
// shadow root
|
|
4478
|
+
const targetShadowRoot = getShadowRoot(targetEle);
|
|
4479
|
+
if (targetShadowRoot) {
|
|
4480
|
+
targetShadowRoot.addEventListener('mousedown', onTriggerClose, true);
|
|
4481
|
+
targetShadowRoot.addEventListener('contextmenu', onTriggerClose, true);
|
|
4482
|
+
}
|
|
4483
|
+
|
|
4484
|
+
// Warning if target and popup not in same root
|
|
4485
|
+
if (process.env.NODE_ENV !== 'production' && targetEle) {
|
|
4486
|
+
const targetRoot = targetEle.getRootNode?.();
|
|
4487
|
+
const popupRoot = popupEle.getRootNode?.();
|
|
4488
|
+
warning(targetRoot === popupRoot, `trigger element and popup element should in same shadow root.`);
|
|
4489
|
+
}
|
|
4490
|
+
return () => {
|
|
4491
|
+
win.removeEventListener('pointerdown', onPointerDown, true);
|
|
4492
|
+
win.removeEventListener('mousedown', onTriggerClose, true);
|
|
4493
|
+
win.removeEventListener('contextmenu', onTriggerClose, true);
|
|
4494
|
+
if (targetShadowRoot) {
|
|
4495
|
+
targetShadowRoot.removeEventListener('mousedown', onTriggerClose, true);
|
|
4496
|
+
targetShadowRoot.removeEventListener('contextmenu', onTriggerClose, true);
|
|
4497
|
+
}
|
|
4498
|
+
};
|
|
4499
|
+
}
|
|
4500
|
+
}, [clickToHide, targetEle, popupEle, mask, maskClosable]);
|
|
4501
|
+
function onPopupPointerDown() {
|
|
4502
|
+
popupPointerDownRef.current = true;
|
|
4503
|
+
}
|
|
4504
|
+
return onPopupPointerDown;
|
|
4505
|
+
}
|
|
4506
|
+
|
|
4507
|
+
// Removed Props List
|
|
4508
|
+
// Seems this can be auto
|
|
4509
|
+
// getDocument?: (element?: HTMLElement) => Document;
|
|
4510
|
+
|
|
4511
|
+
// New version will not wrap popup with `rc-trigger-popup-content` when multiple children
|
|
4512
|
+
|
|
4513
|
+
function generateTrigger(PortalComponent = Portal) {
|
|
4514
|
+
const Trigger = /*#__PURE__*/React__namespace.forwardRef((props, ref) => {
|
|
4515
|
+
const {
|
|
4516
|
+
prefixCls = 'rc-trigger-popup',
|
|
4517
|
+
children,
|
|
4518
|
+
// Action
|
|
4519
|
+
action = 'hover',
|
|
4520
|
+
showAction,
|
|
4521
|
+
hideAction,
|
|
4522
|
+
// Open
|
|
4523
|
+
popupVisible,
|
|
4524
|
+
defaultPopupVisible,
|
|
4525
|
+
onOpenChange,
|
|
4526
|
+
afterOpenChange,
|
|
4527
|
+
onPopupVisibleChange,
|
|
4528
|
+
afterPopupVisibleChange,
|
|
4529
|
+
// Delay
|
|
4530
|
+
mouseEnterDelay,
|
|
4531
|
+
mouseLeaveDelay = 0.1,
|
|
4532
|
+
focusDelay,
|
|
4533
|
+
blurDelay,
|
|
4534
|
+
// Mask
|
|
4535
|
+
mask,
|
|
4536
|
+
maskClosable = true,
|
|
4537
|
+
// Portal
|
|
4538
|
+
getPopupContainer,
|
|
4539
|
+
forceRender,
|
|
4540
|
+
autoDestroy,
|
|
4541
|
+
// Popup
|
|
4542
|
+
popup,
|
|
4543
|
+
popupClassName,
|
|
4544
|
+
uniqueContainerClassName,
|
|
4545
|
+
uniqueContainerStyle,
|
|
4546
|
+
popupStyle,
|
|
4547
|
+
popupPlacement,
|
|
4548
|
+
builtinPlacements = {},
|
|
4549
|
+
popupAlign,
|
|
4550
|
+
zIndex,
|
|
4551
|
+
stretch,
|
|
4552
|
+
getPopupClassNameFromAlign,
|
|
4553
|
+
fresh,
|
|
4554
|
+
unique,
|
|
4555
|
+
alignPoint,
|
|
4556
|
+
onPopupClick,
|
|
4557
|
+
onPopupAlign,
|
|
4558
|
+
// Arrow
|
|
4559
|
+
arrow,
|
|
4560
|
+
// Motion
|
|
4561
|
+
popupMotion,
|
|
4562
|
+
maskMotion,
|
|
4563
|
+
// Private
|
|
4564
|
+
mobile,
|
|
4565
|
+
...restProps
|
|
4566
|
+
} = props;
|
|
4567
|
+
const mergedAutoDestroy = autoDestroy || false;
|
|
4568
|
+
const openUncontrolled = popupVisible === undefined;
|
|
4569
|
+
|
|
4570
|
+
// =========================== Mobile ===========================
|
|
4571
|
+
const isMobile = !!mobile;
|
|
4572
|
+
|
|
4573
|
+
// ========================== Context ===========================
|
|
4574
|
+
const subPopupElements = React__namespace.useRef({});
|
|
4575
|
+
const parentContext = React__namespace.useContext(TriggerContext);
|
|
4576
|
+
const context = React__namespace.useMemo(() => {
|
|
4577
|
+
return {
|
|
4578
|
+
registerSubPopup: (id, subPopupEle) => {
|
|
4579
|
+
subPopupElements.current[id] = subPopupEle;
|
|
4580
|
+
parentContext?.registerSubPopup(id, subPopupEle);
|
|
4581
|
+
}
|
|
4582
|
+
};
|
|
4583
|
+
}, [parentContext]);
|
|
4584
|
+
|
|
4585
|
+
// ======================== UniqueContext =========================
|
|
4586
|
+
const uniqueContext = React__namespace.useContext(UniqueContext);
|
|
4587
|
+
|
|
4588
|
+
// =========================== Popup ============================
|
|
4589
|
+
const id = useId();
|
|
4590
|
+
const [popupEle, setPopupEle] = React__namespace.useState(null);
|
|
4591
|
+
|
|
4592
|
+
// Used for forwardRef popup. Not use internal
|
|
4593
|
+
const externalPopupRef = React__namespace.useRef(null);
|
|
4594
|
+
const setPopupRef = useEvent(node => {
|
|
4595
|
+
externalPopupRef.current = node;
|
|
4596
|
+
if (isDOM(node) && popupEle !== node) {
|
|
4597
|
+
setPopupEle(node);
|
|
4598
|
+
}
|
|
4599
|
+
parentContext?.registerSubPopup(id, node);
|
|
4600
|
+
});
|
|
4601
|
+
|
|
4602
|
+
// =========================== Target ===========================
|
|
4603
|
+
// Use state to control here since `useRef` update not trigger render
|
|
4604
|
+
const [targetEle, setTargetEle] = React__namespace.useState(null);
|
|
4605
|
+
|
|
4606
|
+
// Used for forwardRef target. Not use internal
|
|
4607
|
+
const externalForwardRef = React__namespace.useRef(null);
|
|
4608
|
+
const setTargetRef = useEvent(node => {
|
|
4609
|
+
const domNode = getDOM(node);
|
|
4610
|
+
if (isDOM(domNode) && targetEle !== domNode) {
|
|
4611
|
+
setTargetEle(domNode);
|
|
4612
|
+
externalForwardRef.current = domNode;
|
|
4613
|
+
}
|
|
4614
|
+
});
|
|
4615
|
+
const cloneProps = {};
|
|
4616
|
+
const inPopupOrChild = useEvent(ele => {
|
|
4617
|
+
const childDOM = targetEle;
|
|
4618
|
+
return childDOM?.contains(ele) || getShadowRoot(childDOM)?.host === ele || ele === childDOM || popupEle?.contains(ele) || getShadowRoot(popupEle)?.host === ele || ele === popupEle || Object.values(subPopupElements.current).some(subPopupEle => subPopupEle?.contains(ele) || ele === subPopupEle);
|
|
4619
|
+
});
|
|
4620
|
+
|
|
4621
|
+
// =========================== Arrow ============================
|
|
4622
|
+
const innerArrow = arrow ? {
|
|
4623
|
+
// true and Object likely
|
|
4624
|
+
...(arrow !== true ? arrow : {})
|
|
4625
|
+
} : null;
|
|
4626
|
+
|
|
4627
|
+
// ============================ Open ============================
|
|
4628
|
+
const [internalOpen, setInternalOpen] = useControlledState(defaultPopupVisible || false, popupVisible);
|
|
4629
|
+
const mergedOpen = internalOpen || false;
|
|
4630
|
+
|
|
4631
|
+
// ========================== Children ==========================
|
|
4632
|
+
const child = React__namespace.useMemo(() => {
|
|
4633
|
+
const nextChild = typeof children === 'function' ? children({
|
|
4634
|
+
open: mergedOpen
|
|
4635
|
+
}) : children;
|
|
4636
|
+
return React__namespace.Children.only(nextChild);
|
|
4637
|
+
}, [children, mergedOpen]);
|
|
4638
|
+
const originChildProps = child?.props || {};
|
|
4639
|
+
|
|
4640
|
+
// Support ref
|
|
4641
|
+
const isOpen = useEvent(() => mergedOpen);
|
|
4642
|
+
|
|
4643
|
+
// Extract common options for UniqueProvider
|
|
4644
|
+
const getUniqueOptions = useEvent((delay = 0) => ({
|
|
4645
|
+
popup,
|
|
4646
|
+
target: targetEle,
|
|
4647
|
+
delay,
|
|
4648
|
+
prefixCls,
|
|
4649
|
+
popupClassName,
|
|
4650
|
+
uniqueContainerClassName,
|
|
4651
|
+
uniqueContainerStyle,
|
|
4652
|
+
popupStyle,
|
|
4653
|
+
popupPlacement,
|
|
4654
|
+
builtinPlacements,
|
|
4655
|
+
popupAlign,
|
|
4656
|
+
zIndex,
|
|
4657
|
+
mask,
|
|
4658
|
+
maskClosable,
|
|
4659
|
+
popupMotion,
|
|
4660
|
+
maskMotion,
|
|
4661
|
+
arrow: innerArrow,
|
|
4662
|
+
getPopupContainer,
|
|
4663
|
+
getPopupClassNameFromAlign,
|
|
4664
|
+
id,
|
|
4665
|
+
onEsc
|
|
4666
|
+
}));
|
|
4667
|
+
|
|
4668
|
+
// Handle controlled state changes for UniqueProvider
|
|
4669
|
+
// Only sync to UniqueProvider when it's controlled mode
|
|
4670
|
+
// If there is a parentContext, don't call uniqueContext methods
|
|
4671
|
+
useLayoutEffect(() => {
|
|
4672
|
+
if (uniqueContext && unique && targetEle && !openUncontrolled && !parentContext) {
|
|
4673
|
+
if (mergedOpen) {
|
|
4674
|
+
uniqueContext.show(getUniqueOptions(mouseEnterDelay), isOpen);
|
|
4675
|
+
} else {
|
|
4676
|
+
uniqueContext.hide(mouseLeaveDelay);
|
|
4677
|
+
}
|
|
4678
|
+
}
|
|
4679
|
+
}, [mergedOpen, targetEle]);
|
|
4680
|
+
const openRef = React__namespace.useRef(mergedOpen);
|
|
4681
|
+
openRef.current = mergedOpen;
|
|
4682
|
+
const internalTriggerOpen = useEvent(nextOpen => {
|
|
4683
|
+
reactDom.flushSync(() => {
|
|
4684
|
+
if (mergedOpen !== nextOpen) {
|
|
4685
|
+
setInternalOpen(nextOpen);
|
|
4686
|
+
onOpenChange?.(nextOpen);
|
|
4687
|
+
onPopupVisibleChange?.(nextOpen);
|
|
4688
|
+
}
|
|
4689
|
+
});
|
|
4690
|
+
});
|
|
4691
|
+
|
|
4692
|
+
// Trigger for delay
|
|
4693
|
+
const delayInvoke = useDelay();
|
|
4694
|
+
const triggerOpen = (nextOpen, delay = 0) => {
|
|
4695
|
+
// If it's controlled mode, always use internal trigger logic
|
|
4696
|
+
// UniqueProvider will be synced through useLayoutEffect
|
|
4697
|
+
if (popupVisible !== undefined) {
|
|
4698
|
+
delayInvoke(() => {
|
|
4699
|
+
internalTriggerOpen(nextOpen);
|
|
4700
|
+
}, delay);
|
|
4701
|
+
return;
|
|
4702
|
+
}
|
|
4703
|
+
|
|
4704
|
+
// If UniqueContext exists and not controlled, pass delay to Provider instead of handling it internally
|
|
4705
|
+
// If there is a parentContext, don't call uniqueContext methods
|
|
4706
|
+
if (uniqueContext && unique && openUncontrolled && !parentContext) {
|
|
4707
|
+
if (nextOpen) {
|
|
4708
|
+
uniqueContext.show(getUniqueOptions(delay), isOpen);
|
|
4709
|
+
} else {
|
|
4710
|
+
uniqueContext.hide(delay);
|
|
4711
|
+
}
|
|
4712
|
+
return;
|
|
4713
|
+
}
|
|
4714
|
+
delayInvoke(() => {
|
|
4715
|
+
internalTriggerOpen(nextOpen);
|
|
4716
|
+
}, delay);
|
|
4717
|
+
};
|
|
4718
|
+
function onEsc({
|
|
4719
|
+
top
|
|
4720
|
+
}) {
|
|
4721
|
+
if (top) {
|
|
4722
|
+
triggerOpen(false);
|
|
4723
|
+
}
|
|
4724
|
+
}
|
|
4725
|
+
|
|
4726
|
+
// ========================== Motion ============================
|
|
4727
|
+
const [inMotion, setInMotion] = React__namespace.useState(false);
|
|
4728
|
+
useLayoutEffect(firstMount => {
|
|
4729
|
+
if (!firstMount || mergedOpen) {
|
|
4730
|
+
setInMotion(true);
|
|
4731
|
+
}
|
|
4732
|
+
}, [mergedOpen]);
|
|
4733
|
+
const [motionPrepareResolve, setMotionPrepareResolve] = React__namespace.useState(null);
|
|
4734
|
+
|
|
4735
|
+
// =========================== Align ============================
|
|
4736
|
+
const [mousePos, setMousePos] = React__namespace.useState(null);
|
|
4737
|
+
const setMousePosByEvent = event => {
|
|
4738
|
+
setMousePos([event.clientX, event.clientY]);
|
|
4739
|
+
};
|
|
4740
|
+
const [ready, offsetX, offsetY, offsetR, offsetB, arrowX, arrowY, scaleX, scaleY, alignInfo, onAlign] = useAlign(mergedOpen, popupEle, alignPoint && mousePos !== null ? mousePos : targetEle, popupPlacement, builtinPlacements, popupAlign, onPopupAlign, isMobile);
|
|
4741
|
+
const [showActions, hideActions] = useAction(action, showAction, hideAction);
|
|
4742
|
+
const clickToShow = showActions.has('click');
|
|
4743
|
+
const clickToHide = hideActions.has('click') || hideActions.has('contextMenu');
|
|
4744
|
+
const triggerAlign = useEvent(() => {
|
|
4745
|
+
if (!inMotion) {
|
|
4746
|
+
onAlign();
|
|
4747
|
+
}
|
|
4748
|
+
});
|
|
4749
|
+
const onScroll = () => {
|
|
4750
|
+
if (openRef.current && alignPoint && clickToHide) {
|
|
4751
|
+
triggerOpen(false);
|
|
4752
|
+
}
|
|
4753
|
+
};
|
|
4754
|
+
useWatch(mergedOpen, targetEle, popupEle, triggerAlign, onScroll);
|
|
4755
|
+
useLayoutEffect(() => {
|
|
4756
|
+
triggerAlign();
|
|
4757
|
+
}, [mousePos, popupPlacement]);
|
|
4758
|
+
|
|
4759
|
+
// When no builtinPlacements and popupAlign changed
|
|
4760
|
+
useLayoutEffect(() => {
|
|
4761
|
+
if (mergedOpen && !builtinPlacements?.[popupPlacement]) {
|
|
4762
|
+
triggerAlign();
|
|
4763
|
+
}
|
|
4764
|
+
}, [JSON.stringify(popupAlign)]);
|
|
4765
|
+
const alignedClassName = React__namespace.useMemo(() => {
|
|
4766
|
+
const baseClassName = getAlignPopupClassName(builtinPlacements, prefixCls, alignInfo, alignPoint);
|
|
4767
|
+
return clsx(baseClassName, getPopupClassNameFromAlign?.(alignInfo));
|
|
4768
|
+
}, [alignInfo, getPopupClassNameFromAlign, builtinPlacements, prefixCls, alignPoint]);
|
|
4769
|
+
|
|
4770
|
+
// ============================ Refs ============================
|
|
4771
|
+
React__namespace.useImperativeHandle(ref, () => ({
|
|
4772
|
+
nativeElement: externalForwardRef.current,
|
|
4773
|
+
popupElement: externalPopupRef.current,
|
|
4774
|
+
forceAlign: triggerAlign
|
|
4775
|
+
}));
|
|
4776
|
+
|
|
4777
|
+
// ========================== Stretch ===========================
|
|
4778
|
+
const [targetWidth, setTargetWidth] = React__namespace.useState(0);
|
|
4779
|
+
const [targetHeight, setTargetHeight] = React__namespace.useState(0);
|
|
4780
|
+
const syncTargetSize = () => {
|
|
4781
|
+
if (stretch && targetEle) {
|
|
4782
|
+
const rect = targetEle.getBoundingClientRect();
|
|
4783
|
+
setTargetWidth(rect.width);
|
|
4784
|
+
setTargetHeight(rect.height);
|
|
4785
|
+
}
|
|
4786
|
+
};
|
|
4787
|
+
const onTargetResize = () => {
|
|
4788
|
+
syncTargetSize();
|
|
4789
|
+
triggerAlign();
|
|
4790
|
+
};
|
|
4791
|
+
|
|
4792
|
+
// ========================== Motion ============================
|
|
4793
|
+
const onVisibleChanged = visible => {
|
|
4794
|
+
setInMotion(false);
|
|
4795
|
+
onAlign();
|
|
4796
|
+
afterOpenChange?.(visible);
|
|
4797
|
+
afterPopupVisibleChange?.(visible);
|
|
4798
|
+
};
|
|
4799
|
+
|
|
4800
|
+
// We will trigger align when motion is in prepare
|
|
4801
|
+
const onPrepare = () => new Promise(resolve => {
|
|
4802
|
+
syncTargetSize();
|
|
4803
|
+
setMotionPrepareResolve(() => resolve);
|
|
4804
|
+
});
|
|
4805
|
+
useLayoutEffect(() => {
|
|
4806
|
+
if (motionPrepareResolve) {
|
|
4807
|
+
onAlign();
|
|
4808
|
+
motionPrepareResolve();
|
|
4809
|
+
setMotionPrepareResolve(null);
|
|
4810
|
+
}
|
|
4811
|
+
}, [motionPrepareResolve]);
|
|
4812
|
+
|
|
4813
|
+
// =========================== Action ===========================
|
|
4814
|
+
/**
|
|
4815
|
+
* Util wrapper for trigger action
|
|
4816
|
+
* @param eventName Listen event name
|
|
4817
|
+
* @param nextOpen Next open state after trigger
|
|
4818
|
+
* @param delay Delay to trigger open change
|
|
4819
|
+
* @param callback Callback if current event need additional action
|
|
4820
|
+
* @param ignoreCheck Ignore current event if check return true
|
|
4821
|
+
*/
|
|
4822
|
+
function wrapperAction(eventName, nextOpen, delay, callback, ignoreCheck) {
|
|
4823
|
+
cloneProps[eventName] = (event, ...args) => {
|
|
4824
|
+
if (!ignoreCheck || !ignoreCheck()) {
|
|
4825
|
+
callback?.(event);
|
|
4826
|
+
triggerOpen(nextOpen, delay);
|
|
4827
|
+
}
|
|
4828
|
+
|
|
4829
|
+
// Pass to origin
|
|
4830
|
+
originChildProps[eventName]?.(event, ...args);
|
|
4831
|
+
};
|
|
4832
|
+
}
|
|
4833
|
+
|
|
4834
|
+
// ======================= Action: Touch ========================
|
|
4835
|
+
const touchToShow = showActions.has('touch');
|
|
4836
|
+
const touchToHide = hideActions.has('touch');
|
|
4837
|
+
|
|
4838
|
+
/** Used for prevent `hover` event conflict with mobile env */
|
|
4839
|
+
const touchedRef = React__namespace.useRef(false);
|
|
4840
|
+
if (touchToShow || touchToHide) {
|
|
4841
|
+
cloneProps.onTouchStart = (...args) => {
|
|
4842
|
+
touchedRef.current = true;
|
|
4843
|
+
if (openRef.current && touchToHide) {
|
|
4844
|
+
triggerOpen(false);
|
|
4845
|
+
} else if (!openRef.current && touchToShow) {
|
|
4846
|
+
triggerOpen(true);
|
|
4847
|
+
}
|
|
4848
|
+
|
|
4849
|
+
// Pass to origin
|
|
4850
|
+
originChildProps.onTouchStart?.(...args);
|
|
4851
|
+
};
|
|
4852
|
+
}
|
|
4853
|
+
|
|
4854
|
+
// ======================= Action: Click ========================
|
|
4855
|
+
if (clickToShow || clickToHide) {
|
|
4856
|
+
cloneProps.onClick = (event, ...args) => {
|
|
4857
|
+
if (openRef.current && clickToHide) {
|
|
4858
|
+
triggerOpen(false);
|
|
4859
|
+
} else if (!openRef.current && clickToShow) {
|
|
4860
|
+
setMousePosByEvent(event);
|
|
4861
|
+
triggerOpen(true);
|
|
4862
|
+
}
|
|
4863
|
+
|
|
4864
|
+
// Pass to origin
|
|
4865
|
+
originChildProps.onClick?.(event, ...args);
|
|
4866
|
+
touchedRef.current = false;
|
|
4867
|
+
};
|
|
4868
|
+
}
|
|
4869
|
+
|
|
4870
|
+
// Click to hide is special action since click popup element should not hide
|
|
4871
|
+
const onPopupPointerDown = useWinClick(mergedOpen, clickToHide || touchToHide, targetEle, popupEle, mask, maskClosable, inPopupOrChild, triggerOpen);
|
|
4872
|
+
|
|
4873
|
+
// ======================= Action: Hover ========================
|
|
4874
|
+
const hoverToShow = showActions.has('hover');
|
|
4875
|
+
const hoverToHide = hideActions.has('hover');
|
|
4876
|
+
let onPopupMouseEnter;
|
|
4877
|
+
let onPopupMouseLeave;
|
|
4878
|
+
const ignoreMouseTrigger = () => {
|
|
4879
|
+
return touchedRef.current;
|
|
4880
|
+
};
|
|
4881
|
+
if (hoverToShow) {
|
|
4882
|
+
const onMouseEnterCallback = event => {
|
|
4883
|
+
setMousePosByEvent(event);
|
|
4884
|
+
};
|
|
4885
|
+
|
|
4886
|
+
// Compatible with old browser which not support pointer event
|
|
4887
|
+
wrapperAction('onMouseEnter', true, mouseEnterDelay, onMouseEnterCallback, ignoreMouseTrigger);
|
|
4888
|
+
wrapperAction('onPointerEnter', true, mouseEnterDelay, onMouseEnterCallback, ignoreMouseTrigger);
|
|
4889
|
+
onPopupMouseEnter = event => {
|
|
4890
|
+
// Only trigger re-open when popup is visible
|
|
4891
|
+
if ((mergedOpen || inMotion) && popupEle?.contains(event.target)) {
|
|
4892
|
+
triggerOpen(true, mouseEnterDelay);
|
|
4893
|
+
}
|
|
4894
|
+
};
|
|
4895
|
+
|
|
4896
|
+
// Align Point
|
|
4897
|
+
if (alignPoint) {
|
|
4898
|
+
cloneProps.onMouseMove = event => {
|
|
4899
|
+
originChildProps.onMouseMove?.(event);
|
|
4900
|
+
};
|
|
4901
|
+
}
|
|
4902
|
+
}
|
|
4903
|
+
if (hoverToHide) {
|
|
4904
|
+
wrapperAction('onMouseLeave', false, mouseLeaveDelay, undefined, ignoreMouseTrigger);
|
|
4905
|
+
wrapperAction('onPointerLeave', false, mouseLeaveDelay, undefined, ignoreMouseTrigger);
|
|
4906
|
+
onPopupMouseLeave = () => {
|
|
4907
|
+
triggerOpen(false, mouseLeaveDelay);
|
|
4908
|
+
};
|
|
4909
|
+
}
|
|
4910
|
+
|
|
4911
|
+
// ======================= Action: Focus ========================
|
|
4912
|
+
if (showActions.has('focus')) {
|
|
4913
|
+
wrapperAction('onFocus', true, focusDelay);
|
|
4914
|
+
}
|
|
4915
|
+
if (hideActions.has('focus')) {
|
|
4916
|
+
wrapperAction('onBlur', false, blurDelay);
|
|
4917
|
+
}
|
|
4918
|
+
|
|
4919
|
+
// ==================== Action: ContextMenu =====================
|
|
4920
|
+
if (showActions.has('contextMenu')) {
|
|
4921
|
+
cloneProps.onContextMenu = (event, ...args) => {
|
|
4922
|
+
if (openRef.current && hideActions.has('contextMenu')) {
|
|
4923
|
+
triggerOpen(false);
|
|
4924
|
+
} else {
|
|
4925
|
+
setMousePosByEvent(event);
|
|
4926
|
+
triggerOpen(true);
|
|
4927
|
+
}
|
|
4928
|
+
event.preventDefault();
|
|
4929
|
+
|
|
4930
|
+
// Pass to origin
|
|
4931
|
+
originChildProps.onContextMenu?.(event, ...args);
|
|
4932
|
+
};
|
|
4933
|
+
}
|
|
4934
|
+
|
|
4935
|
+
// ============================ Perf ============================
|
|
4936
|
+
const rendedRef = React__namespace.useRef(false);
|
|
4937
|
+
rendedRef.current ||= forceRender || mergedOpen || inMotion;
|
|
4938
|
+
|
|
4939
|
+
// =========================== Render ===========================
|
|
4940
|
+
const mergedChildrenProps = {
|
|
4941
|
+
...originChildProps,
|
|
4942
|
+
...cloneProps
|
|
4943
|
+
};
|
|
4944
|
+
|
|
4945
|
+
// Pass props into cloneProps for nest usage
|
|
4946
|
+
const passedProps = {};
|
|
4947
|
+
const passedEventList = ['onContextMenu', 'onClick', 'onMouseDown', 'onTouchStart', 'onMouseEnter', 'onMouseLeave', 'onFocus', 'onBlur'];
|
|
4948
|
+
passedEventList.forEach(eventName => {
|
|
4949
|
+
if (restProps[eventName]) {
|
|
4950
|
+
passedProps[eventName] = (...args) => {
|
|
4951
|
+
mergedChildrenProps[eventName]?.(...args);
|
|
4952
|
+
restProps[eventName](...args);
|
|
4953
|
+
};
|
|
4954
|
+
}
|
|
4955
|
+
});
|
|
4956
|
+
const arrowPos = {
|
|
4957
|
+
x: arrowX,
|
|
4958
|
+
y: arrowY
|
|
4959
|
+
};
|
|
4960
|
+
|
|
4961
|
+
// =================== Resize Observer ===================
|
|
4962
|
+
// Use hook to observe target element resize
|
|
4963
|
+
// Pass targetEle directly instead of a function so the hook will re-observe when target changes
|
|
4964
|
+
useResizeObserver(mergedOpen, targetEle, onTargetResize);
|
|
4965
|
+
|
|
4966
|
+
// Compose refs
|
|
4967
|
+
const mergedRef = useComposeRef(setTargetRef, getNodeRef(child));
|
|
4968
|
+
|
|
4969
|
+
// Child Node
|
|
4970
|
+
const triggerNode = /*#__PURE__*/React__namespace.cloneElement(child, {
|
|
4971
|
+
...mergedChildrenProps,
|
|
4972
|
+
...passedProps,
|
|
4973
|
+
ref: mergedRef
|
|
4974
|
+
});
|
|
4975
|
+
|
|
4976
|
+
// Render
|
|
4977
|
+
return /*#__PURE__*/React__namespace.createElement(React__namespace.Fragment, null, triggerNode, rendedRef.current && (!uniqueContext || !unique) && /*#__PURE__*/React__namespace.createElement(TriggerContext.Provider, {
|
|
4978
|
+
value: context
|
|
4979
|
+
}, /*#__PURE__*/React__namespace.createElement(Popup, {
|
|
4980
|
+
portal: PortalComponent,
|
|
4981
|
+
ref: setPopupRef,
|
|
4982
|
+
prefixCls: prefixCls,
|
|
4983
|
+
popup: popup,
|
|
4984
|
+
className: clsx(popupClassName, !isMobile && alignedClassName),
|
|
4985
|
+
style: popupStyle,
|
|
4986
|
+
target: targetEle,
|
|
4987
|
+
onMouseEnter: onPopupMouseEnter,
|
|
4988
|
+
onMouseLeave: onPopupMouseLeave
|
|
4989
|
+
// https://github.com/ant-design/ant-design/issues/43924
|
|
4990
|
+
,
|
|
4991
|
+
onPointerEnter: onPopupMouseEnter,
|
|
4992
|
+
zIndex: zIndex
|
|
4993
|
+
// Open
|
|
4994
|
+
,
|
|
4995
|
+
open: mergedOpen,
|
|
4996
|
+
keepDom: inMotion,
|
|
4997
|
+
fresh: fresh
|
|
4998
|
+
// Click
|
|
4999
|
+
,
|
|
5000
|
+
onClick: onPopupClick,
|
|
5001
|
+
onPointerDownCapture: onPopupPointerDown
|
|
5002
|
+
// Mask
|
|
5003
|
+
,
|
|
5004
|
+
mask: mask
|
|
5005
|
+
// Motion
|
|
5006
|
+
,
|
|
5007
|
+
motion: popupMotion,
|
|
5008
|
+
maskMotion: maskMotion,
|
|
5009
|
+
onVisibleChanged: onVisibleChanged,
|
|
5010
|
+
onPrepare: onPrepare
|
|
5011
|
+
// Portal
|
|
5012
|
+
,
|
|
5013
|
+
forceRender: forceRender,
|
|
5014
|
+
autoDestroy: mergedAutoDestroy,
|
|
5015
|
+
getPopupContainer: getPopupContainer,
|
|
5016
|
+
onEsc: onEsc
|
|
5017
|
+
// Arrow
|
|
5018
|
+
,
|
|
5019
|
+
align: alignInfo,
|
|
5020
|
+
arrow: innerArrow,
|
|
5021
|
+
arrowPos: arrowPos
|
|
5022
|
+
// Align
|
|
5023
|
+
,
|
|
5024
|
+
ready: ready,
|
|
5025
|
+
offsetX: offsetX,
|
|
5026
|
+
offsetY: offsetY,
|
|
5027
|
+
offsetR: offsetR,
|
|
5028
|
+
offsetB: offsetB,
|
|
5029
|
+
onAlign: triggerAlign
|
|
5030
|
+
// Stretch
|
|
5031
|
+
,
|
|
5032
|
+
stretch: stretch,
|
|
5033
|
+
targetWidth: targetWidth / scaleX,
|
|
5034
|
+
targetHeight: targetHeight / scaleY
|
|
5035
|
+
// Mobile
|
|
5036
|
+
,
|
|
5037
|
+
mobile: mobile
|
|
5038
|
+
})));
|
|
5039
|
+
});
|
|
5040
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
5041
|
+
Trigger.displayName = 'Trigger';
|
|
5042
|
+
}
|
|
5043
|
+
return Trigger;
|
|
5044
|
+
}
|
|
5045
|
+
generateTrigger(Portal);
|
|
5046
|
+
|
|
1398
5047
|
const byteToHex = [];
|
|
1399
5048
|
for (let i = 0; i < 256; ++i) {
|
|
1400
5049
|
byteToHex.push((i + 0x100).toString(16).slice(1));
|
|
@@ -4778,7 +8427,7 @@ var styleAttributes = [
|
|
|
4778
8427
|
*/
|
|
4779
8428
|
'backdropFilter',
|
|
4780
8429
|
/**
|
|
4781
|
-
*
|
|
8430
|
+
* Transition
|
|
4782
8431
|
*/
|
|
4783
8432
|
'transition',
|
|
4784
8433
|
'transitionBehavior',
|
|
@@ -4786,6 +8435,10 @@ var styleAttributes = [
|
|
|
4786
8435
|
'transitionDuration',
|
|
4787
8436
|
'transitionProperty',
|
|
4788
8437
|
'transitionTimingFunction',
|
|
8438
|
+
/**
|
|
8439
|
+
* Control
|
|
8440
|
+
*/
|
|
8441
|
+
'pointerEvents',
|
|
4789
8442
|
];
|
|
4790
8443
|
|
|
4791
8444
|
function useDevicePropsGenerator(componentProps, appearanceConfig) {
|
|
@@ -5665,8 +9318,8 @@ const tooltipAppearanceError = {
|
|
|
5665
9318
|
errorPrimary: {
|
|
5666
9319
|
fill: 'errorPrimary',
|
|
5667
9320
|
fillHover: 'errorHoverPrimary',
|
|
5668
|
-
borderColor: 'errorBorderPrimary',
|
|
5669
9321
|
titleColor: 'errorTextPrimary',
|
|
9322
|
+
borderColor: 'errorBorderPrimary',
|
|
5670
9323
|
textColor: 'errorTextPrimary',
|
|
5671
9324
|
},
|
|
5672
9325
|
};
|
|
@@ -5675,8 +9328,8 @@ const tooltipAppearanceRequire = {
|
|
|
5675
9328
|
requirePrimary: {
|
|
5676
9329
|
fill: 'warningPrimary',
|
|
5677
9330
|
fillHover: 'warningHoverPrimary',
|
|
5678
|
-
borderColor: 'warningBorderPrimary',
|
|
5679
9331
|
titleColor: 'warningTextPrimary',
|
|
9332
|
+
borderColor: 'warningBorderPrimary',
|
|
5680
9333
|
textColor: 'warningTextPrimary',
|
|
5681
9334
|
},
|
|
5682
9335
|
};
|
|
@@ -5742,8 +9395,8 @@ const tooltipAppearanceSuccess = {
|
|
|
5742
9395
|
successPrimary: {
|
|
5743
9396
|
fill: 'successPrimary',
|
|
5744
9397
|
fillHover: 'successHoverPrimary',
|
|
5745
|
-
borderColor: 'successBorderPrimary',
|
|
5746
9398
|
titleColor: 'successTextPrimary',
|
|
9399
|
+
borderColor: 'successBorderPrimary',
|
|
5747
9400
|
textColor: 'successTextPrimary',
|
|
5748
9401
|
},
|
|
5749
9402
|
};
|
|
@@ -5762,7 +9415,7 @@ const tooltipAppearance = {
|
|
|
5762
9415
|
const tooltipConfig = {
|
|
5763
9416
|
appearance: tooltipAppearance};
|
|
5764
9417
|
const Tooltip = React.forwardRef(function Tooltip(props, ref) {
|
|
5765
|
-
const { appearance, className, dataTestId, dataTour, initialIsVisible, title, text, before, after, openTimeoutDelay = 500, closeTimeoutDelay = 250, isSkeleton,
|
|
9418
|
+
const { appearance, className, dataTestId, dataTour, initialIsVisible, title, text, before, after, openTimeoutDelay = 500, closeTimeoutDelay = 250, isSkeleton, children, } = props;
|
|
5766
9419
|
const tooltipElementRef = React.useRef(null);
|
|
5767
9420
|
const tooltipTimeoutHideRef = React.useRef(null);
|
|
5768
9421
|
const tooltipTimeoutShowRef = React.useRef(null);
|
|
@@ -5805,13 +9458,9 @@ const Tooltip = React.forwardRef(function Tooltip(props, ref) {
|
|
|
5805
9458
|
}), [isTooltipVisible, openTooltip, closeTooltip]);
|
|
5806
9459
|
const appearanceConfig = useAppearanceConfig(appearance, tooltipConfig);
|
|
5807
9460
|
const propsGenerator = useDevicePropsGenerator(props, appearanceConfig);
|
|
5808
|
-
const { alignClass, alignDirectionClass, alignmentClass, alignPosition, fillClass, titleColor, titleSize, titleWeight, borderColorClass, borderTypeClass, borderWidthClass, textColor, textSize, textWeight, arrowPosition,
|
|
9461
|
+
const { alignClass, alignDirectionClass, alignmentClass, alignPosition, fillClass, titleColor, titleSize, titleWeight, borderColorClass, borderTypeClass, borderWidthClass, textColor, textSize, textWeight, arrowPosition, elevationClass, shapeClass, shapeStrengthClass, sizeClass, widthClass, } = propsGenerator;
|
|
5809
9462
|
const { styles: tooltipStyles } = useStyles(props);
|
|
5810
|
-
return (jsxRuntimeExports.jsxs("div", { className: clsx(className, 'tooltip',
|
|
5811
|
-
? isTooltipVisible
|
|
5812
|
-
? 'tooltip_state_open'
|
|
5813
|
-
: 'tooltip_state_close'
|
|
5814
|
-
: null, alignPosition && `tooltip_align-position_${alignPosition}`, alignDirectionClass && `align_${alignDirectionClass}`, alignClass && `align_${alignClass}`, elevationClass && `elevation_${elevationClass}`, centeringClass && `centering_${centeringClass}`, alignmentClass && `alignment_${alignmentClass}`, sizeClass && `tooltip_size_${sizeClass}`, isSkeleton && 'tooltip_skeleton', widthClass && `width_${widthClass}`), ref: tooltipElementRef, "data-testid": dataTestId, "data-tour": dataTour, style: tooltipStyles, onAnimationEnd: onAnimationEnd, children: [arrowPosition && (jsxRuntimeExports.jsx("div", { className: clsx('tooltip__arrow', arrowPosition && `tooltip__arrow_position_${arrowPosition}`, fillClass && `fill_${fillClass}`), children: "\u00A0" })), before, jsxRuntimeExports.jsxs("div", { className: clsx('tooltip__inner', borderWidthClass && `border-width_${borderWidthClass}`, borderColorClass && `border-color_${borderColorClass}`, borderTypeClass && `border_type_${borderTypeClass}`, fillClass && `fill_${fillClass}`, shapeClass && `shape_${shapeClass}`, shapeStrengthClass && `shape-strength_${shapeStrengthClass}`), children: [title && (jsxRuntimeExports.jsx(Title, { className: "tooltip__title text", size: titleSize, textColor: titleColor, textWeight: titleWeight, children: title })), text && (jsxRuntimeExports.jsx(Text, { className: "tooltip__text", size: textSize, textColor: textColor, textWeight: textWeight, children: text })), children] }), after] }));
|
|
9463
|
+
return (jsxRuntimeExports.jsxs("div", { className: clsx(className, 'tooltip', alignPosition && `tooltip_align-position_${alignPosition}`, alignDirectionClass && `align_${alignDirectionClass}`, alignClass && `align_${alignClass}`, elevationClass && `elevation_${elevationClass}`, alignmentClass && `alignment_${alignmentClass}`, sizeClass && `tooltip_size_${sizeClass}`, isSkeleton && 'tooltip_skeleton', widthClass && `width_${widthClass}`), ref: tooltipElementRef, "data-testid": dataTestId, "data-tour": dataTour, style: tooltipStyles, onAnimationEnd: onAnimationEnd, children: [arrowPosition && (jsxRuntimeExports.jsx("div", { className: clsx('tooltip__arrow', arrowPosition && `tooltip__arrow_position_${arrowPosition}`, fillClass && `fill_${fillClass}`), children: "\u00A0" })), before, jsxRuntimeExports.jsxs("div", { className: clsx('tooltip__inner', borderWidthClass && `border-width_${borderWidthClass}`, borderColorClass && `border-color_${borderColorClass}`, borderTypeClass && `border_type_${borderTypeClass}`, fillClass && `fill_${fillClass}`, shapeClass && `shape_${shapeClass}`, shapeStrengthClass && `shape-strength_${shapeStrengthClass}`), children: [title && (jsxRuntimeExports.jsx(Title, { className: "tooltip__title text", size: titleSize, textColor: titleColor, textWeight: titleWeight, children: title })), text && (jsxRuntimeExports.jsx(Text, { className: "tooltip__text", size: textSize, textColor: textColor, textWeight: textWeight, children: text })), children] }), after] }));
|
|
5815
9464
|
});
|
|
5816
9465
|
|
|
5817
9466
|
const UrlAssetPrefixContext = React.createContext({
|