@kne/system-layout 0.2.0-alpha.22 → 0.2.0-alpha.24
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/README.md +593 -18
- package/dist/{index-677f911f.js → index-ce544506.js} +1 -1
- package/dist/{index-677f911f.js.map → index-ce544506.js.map} +1 -1
- package/dist/index.css +464 -83
- package/dist/index.css.map +1 -1
- package/dist/index.js +125 -45
- package/dist/index.js.map +1 -1
- package/dist/index.modern.js +126 -45
- package/dist/index.modern.js.map +1 -1
- package/package.json +3 -1
package/dist/index.modern.js
CHANGED
|
@@ -10,7 +10,7 @@ import Icon from '@kne/react-icon';
|
|
|
10
10
|
import ensureSlash from '@kne/ensure-slash';
|
|
11
11
|
import isPlainObject from 'lodash/isPlainObject';
|
|
12
12
|
import VirtualList from 'rc-virtual-list';
|
|
13
|
-
import { useScrollElement, usePopupContainer, useResponsiveContext, useIsMobile, RESPONSIVE_BOUNDARY_CLASS, RESPONSIVE_CONTAINER_CLASS, RESPONSIVE_SCROLL_CLASS, findResponsiveScroll, getDefaultScrollElement, ResponsiveProvider,
|
|
13
|
+
import { useScrollElement, usePopupContainer, useResponsiveContext, useIsMobile, RESPONSIVE_BOUNDARY_CLASS, RESPONSIVE_CONTAINER_CLASS, RESPONSIVE_SCROLL_CLASS, findResponsiveScroll, findScrollParent, getDefaultScrollElement, ResponsiveProvider, IS_MOBILE_QUERY } from '@kne/responsive-utils';
|
|
14
14
|
export { MOBILE_BREAKPOINT, RESPONSIVE_BOUNDARY_CLASS, RESPONSIVE_CONTAINER_CLASS, RESPONSIVE_SCROLL_CLASS, ResponsiveProvider, MOBILE_BREAKPOINT as mobileBreakpoint, useBreakpoint, useIsMobile, useMediaQuery, usePopupContainer, useResponsiveContext, useScrollElement } from '@kne/responsive-utils';
|
|
15
15
|
import defaultLogo from './defaultLogo~beHinxEU.svg';
|
|
16
16
|
import { ReactComponent } from './expand~bdCTnjYJ.svg';
|
|
@@ -535,16 +535,19 @@ const ErrorBoundary = props => {
|
|
|
535
535
|
}));
|
|
536
536
|
};
|
|
537
537
|
|
|
538
|
-
const hasParentResponsiveProvider = parent => {
|
|
539
|
-
return parent.getBoundaryElement !== defaultResponsiveContextValue.getBoundaryElement || parent.getScrollElement !== defaultResponsiveContextValue.getScrollElement;
|
|
540
|
-
};
|
|
541
538
|
const resolvePageScrollElement = (pageScrollRef, openScrollbar, deviceIsMobile) => {
|
|
542
539
|
if (deviceIsMobile && !openScrollbar) {
|
|
543
540
|
const _anchor = pageScrollRef.current;
|
|
544
|
-
if (_anchor
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
541
|
+
if (_anchor) {
|
|
542
|
+
// example 手机外框:滚动在 SimpleBar wrapper 上;class 可能晚于首帧挂上,
|
|
543
|
+
// findScrollParent 不依赖 kne-responsive-scroll,避免 is-scrolled 监听绑错。
|
|
544
|
+
const marked = findResponsiveScroll(_anchor.parentElement || _anchor);
|
|
545
|
+
if (marked) {
|
|
546
|
+
return marked;
|
|
547
|
+
}
|
|
548
|
+
const scrollParent = findScrollParent(_anchor);
|
|
549
|
+
if (scrollParent) {
|
|
550
|
+
return scrollParent;
|
|
548
551
|
}
|
|
549
552
|
}
|
|
550
553
|
return getDefaultScrollElement();
|
|
@@ -561,6 +564,10 @@ const resolvePageScrollElement = (pageScrollRef, openScrollbar, deviceIsMobile)
|
|
|
561
564
|
}
|
|
562
565
|
return findResponsiveScroll(anchor) || getDefaultScrollElement();
|
|
563
566
|
};
|
|
567
|
+
|
|
568
|
+
// 始终覆盖本页 scroller(否则嵌套在 Global 下 sticky 会绑到 body)。
|
|
569
|
+
// container 模式(example 手机外框)保留外层 boundary,toolbar/menu 才能 portal 到
|
|
570
|
+
// .example-driver-device-scroll(非滚动内容区),absolute/fixed 相对手机视口生效。
|
|
564
571
|
const LayoutResponsiveScope = ({
|
|
565
572
|
boundaryRef,
|
|
566
573
|
scrollRef,
|
|
@@ -568,13 +575,17 @@ const LayoutResponsiveScope = ({
|
|
|
568
575
|
children
|
|
569
576
|
}) => {
|
|
570
577
|
const parent = useResponsiveContext();
|
|
571
|
-
|
|
572
|
-
return children;
|
|
573
|
-
}
|
|
578
|
+
const inheritBoundary = parent.mode === 'container';
|
|
574
579
|
return /*#__PURE__*/jsx(ResponsiveProvider, {
|
|
580
|
+
mode: parent.mode,
|
|
581
|
+
containerWidth: parent.containerWidth,
|
|
575
582
|
boundaryRef: boundaryRef,
|
|
576
583
|
scrollRef: scrollRef,
|
|
577
584
|
getScrollElement: getScrollElement,
|
|
585
|
+
getBoundaryElement: inheritBoundary ? () => {
|
|
586
|
+
const fromParent = typeof parent.getBoundaryElement === 'function' ? parent.getBoundaryElement() : null;
|
|
587
|
+
return fromParent || null;
|
|
588
|
+
} : undefined,
|
|
578
589
|
children: children
|
|
579
590
|
});
|
|
580
591
|
};
|
|
@@ -957,7 +968,7 @@ const Layout = ({
|
|
|
957
968
|
});
|
|
958
969
|
};
|
|
959
970
|
|
|
960
|
-
var style = {"page":"kne-system-layout_c1kXt","page-header":"kne-system-layout_h-YXH","is-
|
|
971
|
+
var style = {"page":"kne-system-layout_c1kXt","page-header":"kne-system-layout_h-YXH","is-viewport":"kne-system-layout_XjOj5","is-boundary":"kne-system-layout_Q-5NT","page-title-outer":"kne-system-layout_jhcGo","page-title":"kne-system-layout_IOVGr","page-title-extra":"kne-system-layout_mKsLu","page-title-actions":"kne-system-layout_XTAI-","is-scrolled":"kne-system-layout_dEXMy","capsule-click":"kne-system-layout_Ps1FA","back-icon":"kne-system-layout_07Mna","has-float":"kne-system-layout_SD6-j","page-top":"kne-system-layout_Y1y7o","page-inner":"kne-system-layout_wHWje","no-padding":"kne-system-layout_tBnAD","is-mobile":"kne-system-layout_yRZMx","page-header-boundary-overlay":"kne-system-layout_4pjtx","page-loading":"kne-system-layout_vcf3J","page-bottom":"kne-system-layout_vXk1s"};
|
|
961
972
|
|
|
962
973
|
const PageLoading = () => {
|
|
963
974
|
return /*#__PURE__*/jsx(Flex, {
|
|
@@ -991,8 +1002,15 @@ const Page = ({
|
|
|
991
1002
|
} = useContext();
|
|
992
1003
|
const navigate = useNavigate();
|
|
993
1004
|
const getScrollElement = useScrollElement();
|
|
1005
|
+
const getBoundaryElement = usePopupContainer();
|
|
1006
|
+
const {
|
|
1007
|
+
mode
|
|
1008
|
+
} = useResponsiveContext();
|
|
994
1009
|
const navbarRef = useRef(null);
|
|
995
1010
|
const [isScrolled, setIsScrolled] = useState(false);
|
|
1011
|
+
const useBoundaryMount = deviceIsMobile && mode === 'container';
|
|
1012
|
+
const useViewportFixed = deviceIsMobile && mode !== 'container';
|
|
1013
|
+
const boundaryTarget = useBoundaryMount ? getBoundaryElement() : null;
|
|
996
1014
|
useEffect(() => {
|
|
997
1015
|
setToolbarShow && setToolbarShow(!!_toolbar);
|
|
998
1016
|
setNavbarShow && setNavbarShow(!!_navbar);
|
|
@@ -1001,35 +1019,103 @@ const Page = ({
|
|
|
1001
1019
|
if (!deviceIsMobile || !_navbar) {
|
|
1002
1020
|
return;
|
|
1003
1021
|
}
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1022
|
+
let boundEl = null;
|
|
1023
|
+
let remove = null;
|
|
1024
|
+
const bind = () => {
|
|
1025
|
+
const scrollEl = getScrollElement();
|
|
1026
|
+
if (!scrollEl || typeof scrollEl.addEventListener !== 'function' || scrollEl === boundEl) {
|
|
1027
|
+
return;
|
|
1028
|
+
}
|
|
1029
|
+
if (typeof remove === 'function') {
|
|
1030
|
+
remove();
|
|
1031
|
+
}
|
|
1032
|
+
boundEl = scrollEl;
|
|
1033
|
+
const handleScroll = () => {
|
|
1034
|
+
const threshold = navbarRef.current ? navbarRef.current.offsetHeight : 48;
|
|
1035
|
+
setIsScrolled(scrollEl.scrollTop > threshold);
|
|
1036
|
+
};
|
|
1037
|
+
handleScroll();
|
|
1038
|
+
scrollEl.addEventListener('scroll', handleScroll, {
|
|
1039
|
+
passive: true
|
|
1040
|
+
});
|
|
1041
|
+
remove = () => scrollEl.removeEventListener('scroll', handleScroll);
|
|
1042
|
+
};
|
|
1043
|
+
bind();
|
|
1044
|
+
// SimpleBar / kne-responsive-scroll 可能在下一帧才就绪,补一次绑定
|
|
1045
|
+
const raf = requestAnimationFrame(bind);
|
|
1046
|
+
return () => {
|
|
1047
|
+
cancelAnimationFrame(raf);
|
|
1048
|
+
if (typeof remove === 'function') {
|
|
1049
|
+
remove();
|
|
1050
|
+
}
|
|
1011
1051
|
};
|
|
1012
|
-
handleScroll();
|
|
1013
|
-
scrollEl.addEventListener('scroll', handleScroll, {
|
|
1014
|
-
passive: true
|
|
1015
|
-
});
|
|
1016
|
-
return () => scrollEl.removeEventListener('scroll', handleScroll);
|
|
1017
1052
|
}, [deviceIsMobile, _navbar, getScrollElement, scrollReady]);
|
|
1018
|
-
const
|
|
1053
|
+
const titleExtraContent = (() => {
|
|
1054
|
+
if (_extra) {
|
|
1055
|
+
if (deviceIsMobile && userAvatar) {
|
|
1056
|
+
return /*#__PURE__*/jsxs(Flex, {
|
|
1057
|
+
gap: 4,
|
|
1058
|
+
align: "center",
|
|
1059
|
+
children: [_extra, /*#__PURE__*/jsx(Image.Avatar, {
|
|
1060
|
+
id: userAvatar,
|
|
1061
|
+
src: userAvatar,
|
|
1062
|
+
shape: "circle",
|
|
1063
|
+
size: 30,
|
|
1064
|
+
alt: "avatar"
|
|
1065
|
+
})]
|
|
1066
|
+
});
|
|
1067
|
+
}
|
|
1068
|
+
return _extra;
|
|
1069
|
+
}
|
|
1070
|
+
if (deviceIsMobile && (buttonProps || userAvatar)) {
|
|
1071
|
+
const actions = buttonProps ? /*#__PURE__*/jsx("div", {
|
|
1072
|
+
className: classnames('page-title-actions', style['page-title-actions']),
|
|
1073
|
+
children: /*#__PURE__*/jsx(ButtonGroup, _extends({}, Object.assign({}, buttonProps, {
|
|
1074
|
+
showLength: 0,
|
|
1075
|
+
moreType: 'link'
|
|
1076
|
+
})))
|
|
1077
|
+
}) : null;
|
|
1078
|
+
const avatar = userAvatar ? /*#__PURE__*/jsx(Image.Avatar, {
|
|
1079
|
+
id: userAvatar,
|
|
1080
|
+
src: userAvatar,
|
|
1081
|
+
shape: "circle",
|
|
1082
|
+
size: 30,
|
|
1083
|
+
alt: "avatar"
|
|
1084
|
+
}) : null;
|
|
1085
|
+
// 仅更多按钮时不要套带 gap 的 Flex,否则 ButtonGroup 测宽空节点也会吃 gap,导致不居中
|
|
1086
|
+
if (actions && avatar) {
|
|
1087
|
+
return /*#__PURE__*/jsxs(Flex, {
|
|
1088
|
+
gap: 4,
|
|
1089
|
+
align: "center",
|
|
1090
|
+
children: [actions, avatar]
|
|
1091
|
+
});
|
|
1092
|
+
}
|
|
1093
|
+
return actions || avatar;
|
|
1094
|
+
}
|
|
1095
|
+
if (buttonProps) {
|
|
1096
|
+
return /*#__PURE__*/jsx(ButtonGroup, _extends({}, buttonProps));
|
|
1097
|
+
}
|
|
1098
|
+
return null;
|
|
1099
|
+
})();
|
|
1100
|
+
const navbarInner = _navbar ? /*#__PURE__*/jsxs(Flex, {
|
|
1019
1101
|
ref: navbarRef,
|
|
1020
1102
|
justify: "space-between",
|
|
1021
1103
|
align: "center",
|
|
1022
1104
|
gap: 20,
|
|
1023
1105
|
className: classnames('page-header', style['page-header'], {
|
|
1106
|
+
['is-mobile']: deviceIsMobile,
|
|
1107
|
+
[style['is-mobile']]: deviceIsMobile,
|
|
1024
1108
|
['is-scrolled']: isScrolled,
|
|
1025
|
-
[style['is-scrolled']]: isScrolled
|
|
1109
|
+
[style['is-scrolled']]: isScrolled,
|
|
1110
|
+
[style['is-boundary']]: useBoundaryMount && !!boundaryTarget,
|
|
1111
|
+
[style['is-viewport']]: useViewportFixed || useBoundaryMount && !boundaryTarget
|
|
1026
1112
|
}),
|
|
1027
1113
|
children: [/*#__PURE__*/jsxs(Flex, {
|
|
1028
1114
|
className: classnames('page-title-outer', style['page-title-outer']),
|
|
1029
1115
|
align: "center",
|
|
1030
1116
|
gap: 4,
|
|
1031
1117
|
children: [back && /*#__PURE__*/jsx(Button, {
|
|
1032
|
-
type: "
|
|
1118
|
+
type: "link",
|
|
1033
1119
|
icon: /*#__PURE__*/jsx(Icon, {
|
|
1034
1120
|
className: style['back-icon'],
|
|
1035
1121
|
type: "a-Typearrow_forward_ios",
|
|
@@ -1052,24 +1138,19 @@ const Page = ({
|
|
|
1052
1138
|
className: classnames('page-title', style['page-title']),
|
|
1053
1139
|
children: title
|
|
1054
1140
|
})]
|
|
1055
|
-
}), /*#__PURE__*/jsx("div", {
|
|
1056
|
-
className: classnames('page-title-extra', style['page-title-extra']),
|
|
1057
|
-
children:
|
|
1058
|
-
|
|
1059
|
-
align: "center",
|
|
1060
|
-
children: [buttonProps && /*#__PURE__*/jsx(ButtonGroup, _extends({}, Object.assign({}, buttonProps, deviceIsMobile ? {
|
|
1061
|
-
showLength: 0,
|
|
1062
|
-
moreType: 'link'
|
|
1063
|
-
} : {}))), /*#__PURE__*/jsx(Image.Avatar, {
|
|
1064
|
-
id: userAvatar,
|
|
1065
|
-
src: userAvatar,
|
|
1066
|
-
shape: "circle",
|
|
1067
|
-
size: 30,
|
|
1068
|
-
alt: "avatar"
|
|
1069
|
-
})]
|
|
1070
|
-
}) : buttonProps && /*#__PURE__*/jsx(ButtonGroup, _extends({}, buttonProps))
|
|
1071
|
-
})]
|
|
1141
|
+
}), titleExtraContent ? /*#__PURE__*/jsx("div", {
|
|
1142
|
+
className: classnames('page-title-extra', style['page-title-extra'], style['has-float']),
|
|
1143
|
+
children: titleExtraContent
|
|
1144
|
+
}) : null]
|
|
1072
1145
|
}) : null;
|
|
1146
|
+
const navbarEl = navbarInner && useBoundaryMount && boundaryTarget ? /*#__PURE__*/createPortal(/*#__PURE__*/jsx("div", {
|
|
1147
|
+
className: classnames('page-header-boundary-overlay', style['page-header-boundary-overlay']),
|
|
1148
|
+
style: {
|
|
1149
|
+
'--safe-area-inset-top': 'env(safe-area-inset-top)',
|
|
1150
|
+
'--safe-area-inset-bottom': 'env(safe-area-inset-bottom)'
|
|
1151
|
+
},
|
|
1152
|
+
children: navbarInner
|
|
1153
|
+
}), boundaryTarget) : navbarInner;
|
|
1073
1154
|
const pageInnerClassNameOrigin = classnames('page-inner', style['page-inner']);
|
|
1074
1155
|
const pageInnerClassName = classnames(pageInnerClassNameOrigin, {
|
|
1075
1156
|
['no-padding']: noPadding,
|
|
@@ -1127,7 +1208,7 @@ const isMobile = () => {
|
|
|
1127
1208
|
const transparentBgContainer = {
|
|
1128
1209
|
colorBgContainer: 'transparent'
|
|
1129
1210
|
};
|
|
1130
|
-
const transparentBgContainerComponents = ['Input', 'InputNumber', 'Card', 'Tree', 'Select', 'DatePicker'];
|
|
1211
|
+
const transparentBgContainerComponents = ['Input', 'InputNumber', 'Card', 'Tree', 'Select', 'DatePicker', 'Tabs'];
|
|
1131
1212
|
const themeToken = {
|
|
1132
1213
|
components: merge({}, transform(transparentBgContainerComponents, (result, component) => {
|
|
1133
1214
|
result[component] = transparentBgContainer;
|