mirror of https://github.com/mastodon/mastodon
Refactor `<Column>` to TypeScript (#33081)
parent
752d49eefe
commit
346a27b6fc
@ -1,72 +0,0 @@
|
|||||||
import PropTypes from 'prop-types';
|
|
||||||
import { PureComponent } from 'react';
|
|
||||||
|
|
||||||
import { supportsPassiveEvents } from 'detect-passive-events';
|
|
||||||
|
|
||||||
import { scrollTop } from '../scroll';
|
|
||||||
|
|
||||||
const listenerOptions = supportsPassiveEvents ? { passive: true } : false;
|
|
||||||
|
|
||||||
export default class Column extends PureComponent {
|
|
||||||
|
|
||||||
static propTypes = {
|
|
||||||
children: PropTypes.node,
|
|
||||||
label: PropTypes.string,
|
|
||||||
bindToDocument: PropTypes.bool,
|
|
||||||
};
|
|
||||||
|
|
||||||
scrollTop () {
|
|
||||||
let scrollable = null;
|
|
||||||
|
|
||||||
if (this.props.bindToDocument) {
|
|
||||||
scrollable = document.scrollingElement;
|
|
||||||
} else {
|
|
||||||
scrollable = this.node.querySelector('.scrollable');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!scrollable) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._interruptScrollAnimation = scrollTop(scrollable);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleWheel = () => {
|
|
||||||
if (typeof this._interruptScrollAnimation !== 'function') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._interruptScrollAnimation();
|
|
||||||
};
|
|
||||||
|
|
||||||
setRef = c => {
|
|
||||||
this.node = c;
|
|
||||||
};
|
|
||||||
|
|
||||||
componentDidMount () {
|
|
||||||
if (this.props.bindToDocument) {
|
|
||||||
document.addEventListener('wheel', this.handleWheel, listenerOptions);
|
|
||||||
} else {
|
|
||||||
this.node.addEventListener('wheel', this.handleWheel, listenerOptions);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillUnmount () {
|
|
||||||
if (this.props.bindToDocument) {
|
|
||||||
document.removeEventListener('wheel', this.handleWheel, listenerOptions);
|
|
||||||
} else {
|
|
||||||
this.node.removeEventListener('wheel', this.handleWheel, listenerOptions);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render () {
|
|
||||||
const { label, children } = this.props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div role='region' aria-label={label} className='column' ref={this.setRef}>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -0,0 +1,52 @@
|
|||||||
|
import { forwardRef, useRef, useImperativeHandle } from 'react';
|
||||||
|
import type { Ref } from 'react';
|
||||||
|
|
||||||
|
import { scrollTop } from 'mastodon/scroll';
|
||||||
|
|
||||||
|
export interface ColumnRef {
|
||||||
|
scrollTop: () => void;
|
||||||
|
node: HTMLDivElement | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ColumnProps {
|
||||||
|
children?: React.ReactNode;
|
||||||
|
label?: string;
|
||||||
|
bindToDocument?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Column = forwardRef<ColumnRef, ColumnProps>(
|
||||||
|
({ children, label, bindToDocument }, ref: Ref<ColumnRef>) => {
|
||||||
|
const nodeRef = useRef<HTMLDivElement>(null);
|
||||||
|
|
||||||
|
useImperativeHandle(ref, () => ({
|
||||||
|
node: nodeRef.current,
|
||||||
|
|
||||||
|
scrollTop() {
|
||||||
|
let scrollable = null;
|
||||||
|
|
||||||
|
if (bindToDocument) {
|
||||||
|
scrollable = document.scrollingElement;
|
||||||
|
} else {
|
||||||
|
scrollable = nodeRef.current?.querySelector('.scrollable');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!scrollable) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
scrollTop(scrollable);
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div role='region' aria-label={label} className='column' ref={nodeRef}>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
Column.displayName = 'Column';
|
||||||
|
|
||||||
|
// eslint-disable-next-line import/no-default-export
|
||||||
|
export default Column;
|
Loading…
Reference in New Issue