react-use#useScroll TypeScript Examples
The following examples show how to use
react-use#useScroll.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: page-container.tsx From erda-ui with GNU Affero General Public License v3.0 | 4 votes |
PageContainer = ({ route }: IProps) => {
const [noAuth, notFound] = userStore.useStore((s: any) => [s.noAuth, s.notFound]);
const currentOrg = orgStore.useStore((s) => s.currentOrg);
const [showMessage, customMain] = layoutStore.useStore((s) => [s.showMessage, s.customMain]);
const [currentRoute, prevRouteInfo] = routeInfoStore.useStore((s) => [s.currentRoute, s.prevRouteInfo]);
const [state, updater] = useUpdate({
startInit: false,
});
const mainEle = React.useRef<HTMLDivElement>(null);
const { y } = useScroll(mainEle);
useEffectOnce(() => {
const skeleton = document.querySelector('#erda-skeleton');
const content = document.querySelector('#erda-content');
if (skeleton && content) {
skeleton.className += ' fade';
content.classList.remove('hidden');
setTimeout(() => {
skeleton.remove();
}, 500);
}
emit('layout/mount');
if (process.env.NODE_ENV === 'production') {
checkVersion();
}
const checkLoginStatus = () => {
agent.get('/api/users/me').catch((error: any) => {
const { statusCode } = error.response;
if ([401].includes(statusCode)) {
userStore.effects.login();
}
});
};
// 注册并监听登录状态的变化
LSObserver.watch('diceLoginState', (val: any) => {
if (val.toString() === 'false' && currentOrg.id) {
setTimeout(() => {
checkLoginStatus();
}, 0);
}
});
// wait for layout complete
setTimeout(() => {
updater.startInit(true);
}, 0);
});
React.useEffect(() => {
if (prevRouteInfo?.currentRoute.path !== currentRoute.path) {
if (mainEle && mainEle.current) {
mainEle.current.scrollTop = 0;
}
}
}, [currentRoute, prevRouteInfo, mainEle]);
const { layout } = currentRoute;
const hideHeader = showMessage || layout?.hideHeader;
const layoutCls = [];
let showSidebar = !noAuth && !notFound;
let CustomLayout;
let noWrapper = false;
if (typeof layout === 'object') {
const { className, use, hideSidebar } = layout;
if (hideSidebar) showSidebar = false;
className && layoutCls.push(className);
layoutMap[use] && (CustomLayout = layoutMap[use]);
noWrapper = layout.noWrapper;
}
const layoutClass = classnames(layoutCls);
if (CustomLayout) {
return <CustomLayout layoutClass={layoutClass}>{renderRoutes(route.routes)}</CustomLayout>;
}
let MainContent = null;
if (noAuth) {
MainContent = <NoAuth />;
} else if (notFound) {
MainContent = <NotFound />;
} else if (state.startInit) {
MainContent = <RenderMainContent noWrapper={noWrapper} customMain={customMain} route={route} layout={layout} />;
}
return (
<Shell
className={layoutClass}
navigation={<Navigation />}
sidebar={showSidebar ? <SideBar /> : undefined}
breadcrumb={!hideHeader ? <Breadcrumb /> : undefined}
announcement={!hideHeader ? <Announcement /> : undefined}
mainClassName={classnames({ 'mt-0': hideHeader })}
>
{!hideHeader && (
<>
<Header layout={layout} />
<div className={`main-scroll-tip ${y > 2 ? 'show' : ''}`} aria-hidden="true" />
</>
)}
<div id="main" ref={mainEle} style={{ opacity: showMessage ? 0 : undefined }} className={hideHeader ? 'p-0' : ''}>
{MainContent}
</div>
<MessageCenter show={showMessage} />
</Shell>
);
}
Example #2
Source File: issue-drawer.tsx From erda-ui with GNU Affero General Public License v3.0 | 4 votes |
IssueDrawer = (props: IProps) => {
const {
className = '',
canCreate = false,
canDelete = false,
children,
editMode,
shareLink,
loading = false,
visible,
onClose,
onDelete,
confirmCloseTip,
handleCopy,
maskClosable,
data,
issueType,
projectId,
setData,
header = IssueDrawer.Empty,
footer = IssueDrawer.Empty,
extraHeaderOp = null,
detailTitle,
...rest
} = props;
const [
formField = IssueDrawer.Empty,
descField = IssueDrawer.Empty,
workflowField = IssueDrawer.Empty,
inclusionField = IssueDrawer.Empty,
relationField = IssueDrawer.Empty,
logField = IssueDrawer.Empty,
] = React.Children.toArray(children);
const customFieldDetail = issueStore.useStore((s) => s.customFieldDetail);
const escStack = layoutStore.useStore((s) => s.escStack);
const [copyTitle, setCopyTitle] = React.useState('');
const [isChanged, setIsChanged] = React.useState(false);
const [showCopy, setShowCopy] = React.useState(false);
const [showAnchor, setShowAnchor] = React.useState(false);
const preDataRef = React.useRef(data);
const preData = preDataRef.current;
const escClose = React.useCallback(
(e) => {
if (e.key === 'Escape') {
if (escStack.length) {
return;
}
if (isChanged && confirmCloseTip) {
Modal.confirm({
title: confirmCloseTip,
onOk() {
onClose(e);
},
});
} else {
onClose(e);
}
}
},
[confirmCloseTip, escStack, isChanged, onClose],
);
useEvent('keydown', escClose);
React.useEffect(() => {
const isIssueDrawerChanged = (initData: CreateDrawerData, currentData: CreateDrawerData) => {
setIsChanged(false);
Object.keys(currentData).forEach((key) => {
if (key in initData) {
if (!isEqual(initData[key], currentData[key])) {
setIsChanged(true);
}
} else {
const defaultValue = find(customFieldDetail?.property, { propertyName: key })?.values;
// Determine whether the field has changed. When the value is the following conditions, the field has not changed
const notChange =
isEqual(defaultValue, currentData[key]) ||
currentData[key] === undefined ||
currentData[key] === '' ||
isEqual(currentData[key], []) ||
isEqual(currentData[key], { estimateTime: 0, remainingTime: 0 });
if (!notChange) {
setIsChanged(true);
}
}
});
};
isIssueDrawerChanged(preData, data);
}, [customFieldDetail?.property, data, preData]);
const mainEle = React.useRef<HTMLDivElement>(null);
const { y } = useScroll(mainEle);
React.useLayoutEffect(() => {
let timer: NodeJS.Timeout;
if (mainEle.current) {
// wait for layout stable
timer = setTimeout(() => {
setShowAnchor(true);
}, 1000);
}
return () => timer && clearTimeout(timer);
}, []);
return (
<Modal
wrapClassName="issue-drawer-modal"
className={`task-drawer ${className}`}
width="calc(100% - 80px)"
closable={false}
visible={visible}
onCancel={onClose}
footer={null}
maskClosable={maskClosable || !isChanged}
keyboard={false}
forceRender // useScroll will not take effect if mainRel is lazy mounted
{...rest}
>
<Spin spinning={loading}>
<div className="relative flex flex-col" style={{ height: 'calc(100vh - 80px)' }}>
<If condition={header !== IssueDrawer.Empty}>
<div className={`task-drawer-header ${y > 2 ? 'shadow-card' : ''}`}>
<div className="flex justify-between items-center">
<div className="flex-1 nowrap">{typeof header === 'function' ? header(y) : header}</div>
<div className="task-drawer-op flex items-center">
{extraHeaderOp}
<SubscribersSelector
subscribers={data.subscribers}
issueID={customFieldDetail?.issueID}
issueType={issueType}
projectId={projectId}
setData={setData}
data={data}
/>
<If condition={editMode && shareLink}>
<Copy selector=".copy-share-link" tipName={i18n.t('dop:link-share')} />
<ErdaIcon
type="lianjie"
className="cursor-copy hover-active copy-share-link ml-4 text-default-6"
size="20"
data-clipboard-text={shareLink}
/>
</If>
<If condition={editMode}>
<WithAuth pass={canCreate}>
<Popover
title={i18n.t('dop:Copy issue')}
visible={showCopy}
onVisibleChange={(v) => setShowCopy(v)}
content={
<>
<Input
placeholder={i18n.t('dop:Please enter the issue title')}
style={{ width: 400 }}
value={copyTitle}
onChange={(e) => setCopyTitle(e.target.value)}
/>
<div className="flex items-center flex-wrap justify-end mt-2">
<Button
className="mr-2"
onClick={() => {
setCopyTitle('');
setShowCopy(false);
}}
>
{i18n.t('Cancel')}
</Button>
<Button
onClick={() => {
if (copyTitle === '') {
message.error(i18n.t('dop:The title can not be empty'));
return;
}
handleCopy && handleCopy(true, copyTitle);
setCopyTitle('');
setShowCopy(false);
}}
type="primary"
>
{i18n.t('Copy')}
</Button>
</div>
</>
}
placement="leftTop"
trigger="click"
>
<ErdaIcon type="fuzhi" className="hover-active ml-4 text-default-6" size="20" />
</Popover>
</WithAuth>
</If>
{onDelete ? (
<WithAuth pass={canDelete}>
<Popconfirm
title={`${i18n.t('common:confirm to delete')}?`}
placement="bottomRight"
onConfirm={onDelete}
>
<ErdaIcon type="shanchu-4d7l02mb" className="hover-active ml-4 text-default-6" size="20" />
</Popconfirm>
</WithAuth>
) : null}
{isChanged && confirmCloseTip ? (
<Popconfirm title={confirmCloseTip} placement="bottomRight" onConfirm={onClose}>
<ErdaIcon type="guanbi" className="ml-4 hover-active text-default-6" size="20" />
</Popconfirm>
) : (
<ErdaIcon type="guanbi" className="ml-4 hover-active text-default-6" size="20" onClick={onClose} />
)}
</div>
</div>
</div>
</If>
<div
ref={mainEle}
className="relative flex-1 overflow-x-hidden overflow-y-auto"
style={footer !== IssueDrawer.Empty ? { padding: '0 12% 60px' } : { padding: '0 12%' }}
>
<If condition={editMode && showAnchor}>
<div className="absolute">
<Anchor offsetTop={16} getContainer={() => mainEle.current || document.body}>
{formField !== IssueDrawer.Empty && <Anchor.Link href="#field" title={i18n.t('dop:Basic')} />}
{descField !== IssueDrawer.Empty && <Anchor.Link href="#desc" title={i18n.t('dop:Content')} />}
{workflowField !== IssueDrawer.Empty && (
<Anchor.Link href="#workflow" title={i18n.t('dop:workflow')} />
)}
{inclusionField !== IssueDrawer.Empty && (
<Anchor.Link href="#inclusion" title={i18n.t('dop:Contain')} />
)}
{relationField !== IssueDrawer.Empty && (
<Anchor.Link href="#relation" title={i18n.t('dop:Reference')} />
)}
{logField !== IssueDrawer.Empty && <Anchor.Link href="#log" title={i18n.t('dop:Log')} />}
</Anchor>
</div>
</If>
<If condition={formField !== IssueDrawer.Empty}>
<div id="field">{formField}</div>
</If>
<If condition={descField !== IssueDrawer.Empty}>
<div id="desc" className="h-px bg-default-08 my-4" />
{descField}
</If>
<If condition={workflowField !== IssueDrawer.Empty}>
<div id="workflow" className="mt-6">
{workflowField}
</div>
</If>
<If condition={inclusionField !== IssueDrawer.Empty}>
<div id="inclusion" className="mt-6">
{inclusionField}
</div>
</If>
<If condition={relationField !== IssueDrawer.Empty}>
<div id="relation" className="mt-6">
{relationField}
</div>
</If>
<If condition={logField !== IssueDrawer.Empty}>
<div id="log" className="mt-6">
{logField}
</div>
</If>
</div>
<If condition={footer !== IssueDrawer.Empty}>
<div className="task-drawer-footer">
{typeof footer === 'function' ? footer(isChanged, confirmCloseTip) : footer}
</div>
</If>
</div>
</Spin>
</Modal>
);
}
Example #3
Source File: HorizontalScrollable.tsx From oxen-website with GNU General Public License v3.0 | 4 votes |
function HorizontalScrollableInner(props: Props) {
const { onItemClick, children } = props;
const scrollRef = useRef(null);
const innerContentRef = useRef(null);
const { x } = useScroll(scrollRef);
const pageWidth = useWindowSize().width;
const scrollDistance = pageWidth > 1400 ? 450 : pageWidth / 3;
const [rightScrollHidden, setRightScrollHidden] = useState(false);
const { isDesktop } = useContext(ScreenContext);
const handleLeftScroll = () => {
scrollRef.current.scrollBy({
left: -scrollDistance,
behavior: 'smooth',
});
};
const handleRightScroll = () => {
scrollRef.current.scrollBy({
left: scrollDistance,
behavior: 'smooth',
});
};
function handleItemClick() {
if (onItemClick) {
onItemClick();
}
}
useEffect(() => {
const isFullRight =
scrollRef.current.scrollWidth - scrollRef.current.clientWidth ===
scrollRef.current.scrollLeft;
const tooSmallToScroll =
innerContentRef.current.clientWidth < scrollRef.current.clientWidth;
setRightScrollHidden(tooSmallToScroll || isFullRight);
}, [x, children]);
return (
<div className="relative flex w-full">
<div
className={classNames(
'absolute left-0 flex items-center justify-between h-full w-full',
!isDesktop && 'hidden',
)}
>
<div
className={classNames(
'flex flex-col justify-center h-full z-50 duration-300 -ml-8',
x <= 1 && 'opacity-0',
)}
>
<LeftOutlined
onClick={handleLeftScroll}
className={classNames('h-20 mt-1 cursor-pointer')}
/>
</div>
<div
className={classNames(
'flex flex-col justify-center h-full z-50 duration-300 -mr-8',
rightScrollHidden && 'opacity-0',
)}
>
<RightOutlined
onClick={handleRightScroll}
className="h-20 mt-1 cursor-pointer"
/>
</div>
</div>
<div
ref={scrollRef}
className={classNames(
'relative',
'w-full',
'hide_scroll',
'scrolling-touch hide-scroll',
isDesktop ? 'overflow-x-scroll' : 'overflow-x-scroll',
)}
>
<div
ref={innerContentRef}
className={classNames('flex space-x-8 overflow-y-visible')}
style={{
width: 'min-content',
marginLeft: `${!isDesktop ? UI.PAGE_CONTAINED_PADDING_VW : 0}vw`,
paddingRight: `${!isDesktop ? UI.PAGE_CONTAINED_PADDING_VW : 0}vw`,
}}
>
{children}
</div>
</div>
</div>
);
}