[Glitch] Refactor `<Column>` to TypeScript
Port 346a27b6fc
to glitch-soc
Signed-off-by: Claire <claire.github-309c@sitedethib.com>
pull/2921/head
parent
0aa69487a2
commit
14fe8c7d4b
|
@ -1,73 +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,
|
|
||||||
extraClasses: PropTypes.string,
|
|
||||||
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, extraClasses } = this.props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div role='region' aria-label={label} className={`column ${extraClasses || ''}`} ref={this.setRef}>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
import { forwardRef, useRef, useImperativeHandle } from 'react';
|
||||||
|
import type { Ref } from 'react';
|
||||||
|
|
||||||
|
import { scrollTop } from 'flavours/glitch/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;
|
|
@ -18,7 +18,8 @@ import {
|
||||||
fetchDirectory,
|
fetchDirectory,
|
||||||
expandDirectory,
|
expandDirectory,
|
||||||
} from 'flavours/glitch/actions/directory';
|
} from 'flavours/glitch/actions/directory';
|
||||||
import Column from 'flavours/glitch/components/column';
|
import { Column } from 'flavours/glitch/components/column';
|
||||||
|
import type { ColumnRef } from 'flavours/glitch/components/column';
|
||||||
import { ColumnHeader } from 'flavours/glitch/components/column_header';
|
import { ColumnHeader } from 'flavours/glitch/components/column_header';
|
||||||
import { LoadMore } from 'flavours/glitch/components/load_more';
|
import { LoadMore } from 'flavours/glitch/components/load_more';
|
||||||
import { LoadingIndicator } from 'flavours/glitch/components/loading_indicator';
|
import { LoadingIndicator } from 'flavours/glitch/components/loading_indicator';
|
||||||
|
@ -52,7 +53,7 @@ export const Directory: React.FC<{
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
const column = useRef<Column>(null);
|
const column = useRef<ColumnRef>(null);
|
||||||
|
|
||||||
const [orderParam, setOrderParam] = useSearchParam('order');
|
const [orderParam, setOrderParam] = useSearchParam('order');
|
||||||
const [localParam, setLocalParam] = useSearchParam('local');
|
const [localParam, setLocalParam] = useSearchParam('local');
|
||||||
|
|
|
@ -5,7 +5,8 @@ import { useParams } from 'react-router-dom';
|
||||||
|
|
||||||
import ExploreIcon from '@/material-icons/400-24px/explore.svg?react';
|
import ExploreIcon from '@/material-icons/400-24px/explore.svg?react';
|
||||||
import { expandLinkTimeline } from 'flavours/glitch/actions/timelines';
|
import { expandLinkTimeline } from 'flavours/glitch/actions/timelines';
|
||||||
import Column from 'flavours/glitch/components/column';
|
import { Column } from 'flavours/glitch/components/column';
|
||||||
|
import type { ColumnRef } from 'flavours/glitch/components/column';
|
||||||
import { ColumnHeader } from 'flavours/glitch/components/column_header';
|
import { ColumnHeader } from 'flavours/glitch/components/column_header';
|
||||||
import StatusListContainer from 'flavours/glitch/features/ui/containers/status_list_container';
|
import StatusListContainer from 'flavours/glitch/features/ui/containers/status_list_container';
|
||||||
import type { Card } from 'flavours/glitch/models/status';
|
import type { Card } from 'flavours/glitch/models/status';
|
||||||
|
@ -17,7 +18,7 @@ export const LinkTimeline: React.FC<{
|
||||||
const { url } = useParams<{ url: string }>();
|
const { url } = useParams<{ url: string }>();
|
||||||
const decodedUrl = url ? decodeURIComponent(url) : undefined;
|
const decodedUrl = url ? decodeURIComponent(url) : undefined;
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
const columnRef = useRef<Column>(null);
|
const columnRef = useRef<ColumnRef>(null);
|
||||||
const firstStatusId = useAppSelector((state) =>
|
const firstStatusId = useAppSelector((state) =>
|
||||||
decodedUrl
|
decodedUrl
|
||||||
? // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
|
? // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
|
||||||
|
|
|
@ -11,7 +11,7 @@ import MoreHorizIcon from '@/material-icons/400-24px/more_horiz.svg?react';
|
||||||
import SquigglyArrow from '@/svg-icons/squiggly_arrow.svg?react';
|
import SquigglyArrow from '@/svg-icons/squiggly_arrow.svg?react';
|
||||||
import { fetchLists } from 'flavours/glitch/actions/lists';
|
import { fetchLists } from 'flavours/glitch/actions/lists';
|
||||||
import { openModal } from 'flavours/glitch/actions/modal';
|
import { openModal } from 'flavours/glitch/actions/modal';
|
||||||
import Column from 'flavours/glitch/components/column';
|
import { Column } from 'flavours/glitch/components/column';
|
||||||
import { ColumnHeader } from 'flavours/glitch/components/column_header';
|
import { ColumnHeader } from 'flavours/glitch/components/column_header';
|
||||||
import { Icon } from 'flavours/glitch/components/icon';
|
import { Icon } from 'flavours/glitch/components/icon';
|
||||||
import ScrollableList from 'flavours/glitch/components/scrollable_list';
|
import ScrollableList from 'flavours/glitch/components/scrollable_list';
|
||||||
|
|
|
@ -20,7 +20,7 @@ import {
|
||||||
import type { ApiAccountJSON } from 'flavours/glitch/api_types/accounts';
|
import type { ApiAccountJSON } from 'flavours/glitch/api_types/accounts';
|
||||||
import { Avatar } from 'flavours/glitch/components/avatar';
|
import { Avatar } from 'flavours/glitch/components/avatar';
|
||||||
import { Button } from 'flavours/glitch/components/button';
|
import { Button } from 'flavours/glitch/components/button';
|
||||||
import Column from 'flavours/glitch/components/column';
|
import { Column } from 'flavours/glitch/components/column';
|
||||||
import { ColumnHeader } from 'flavours/glitch/components/column_header';
|
import { ColumnHeader } from 'flavours/glitch/components/column_header';
|
||||||
import { ColumnSearchHeader } from 'flavours/glitch/components/column_search_header';
|
import { ColumnSearchHeader } from 'flavours/glitch/components/column_search_header';
|
||||||
import { FollowersCounter } from 'flavours/glitch/components/counters';
|
import { FollowersCounter } from 'flavours/glitch/components/counters';
|
||||||
|
|
|
@ -14,7 +14,7 @@ import { fetchList } from 'flavours/glitch/actions/lists';
|
||||||
import { createList, updateList } from 'flavours/glitch/actions/lists_typed';
|
import { createList, updateList } from 'flavours/glitch/actions/lists_typed';
|
||||||
import { apiGetAccounts } from 'flavours/glitch/api/lists';
|
import { apiGetAccounts } from 'flavours/glitch/api/lists';
|
||||||
import type { RepliesPolicyType } from 'flavours/glitch/api_types/lists';
|
import type { RepliesPolicyType } from 'flavours/glitch/api_types/lists';
|
||||||
import Column from 'flavours/glitch/components/column';
|
import { Column } from 'flavours/glitch/components/column';
|
||||||
import { ColumnHeader } from 'flavours/glitch/components/column_header';
|
import { ColumnHeader } from 'flavours/glitch/components/column_header';
|
||||||
import { LoadingIndicator } from 'flavours/glitch/components/loading_indicator';
|
import { LoadingIndicator } from 'flavours/glitch/components/loading_indicator';
|
||||||
import { useAppDispatch, useAppSelector } from 'flavours/glitch/store';
|
import { useAppDispatch, useAppSelector } from 'flavours/glitch/store';
|
||||||
|
|
|
@ -36,7 +36,8 @@ import { useAppDispatch, useAppSelector } from 'flavours/glitch/store';
|
||||||
|
|
||||||
import { addColumn, removeColumn, moveColumn } from '../../actions/columns';
|
import { addColumn, removeColumn, moveColumn } from '../../actions/columns';
|
||||||
import { submitMarkers } from '../../actions/markers';
|
import { submitMarkers } from '../../actions/markers';
|
||||||
import Column from '../../components/column';
|
import { Column } from '../../components/column';
|
||||||
|
import type { ColumnRef } from '../../components/column';
|
||||||
import { ColumnHeader } from '../../components/column_header';
|
import { ColumnHeader } from '../../components/column_header';
|
||||||
import { LoadGap } from '../../components/load_gap';
|
import { LoadGap } from '../../components/load_gap';
|
||||||
import ScrollableList from '../../components/scrollable_list';
|
import ScrollableList from '../../components/scrollable_list';
|
||||||
|
@ -96,7 +97,7 @@ export const Notifications: React.FC<{
|
||||||
selectNeedsNotificationPermission,
|
selectNeedsNotificationPermission,
|
||||||
);
|
);
|
||||||
|
|
||||||
const columnRef = useRef<Column>(null);
|
const columnRef = useRef<ColumnRef>(null);
|
||||||
|
|
||||||
const selectChild = useCallback((index: number, alignTop: boolean) => {
|
const selectChild = useCallback((index: number, alignTop: boolean) => {
|
||||||
const container = columnRef.current?.node as HTMLElement | undefined;
|
const container = columnRef.current?.node as HTMLElement | undefined;
|
||||||
|
|
|
@ -14,7 +14,7 @@ import { fetchSuggestions } from 'flavours/glitch/actions/suggestions';
|
||||||
import { markAsPartial } from 'flavours/glitch/actions/timelines';
|
import { markAsPartial } from 'flavours/glitch/actions/timelines';
|
||||||
import { apiRequest } from 'flavours/glitch/api';
|
import { apiRequest } from 'flavours/glitch/api';
|
||||||
import type { ApiAccountJSON } from 'flavours/glitch/api_types/accounts';
|
import type { ApiAccountJSON } from 'flavours/glitch/api_types/accounts';
|
||||||
import Column from 'flavours/glitch/components/column';
|
import { Column } from 'flavours/glitch/components/column';
|
||||||
import { ColumnHeader } from 'flavours/glitch/components/column_header';
|
import { ColumnHeader } from 'flavours/glitch/components/column_header';
|
||||||
import { ColumnSearchHeader } from 'flavours/glitch/components/column_search_header';
|
import { ColumnSearchHeader } from 'flavours/glitch/components/column_search_header';
|
||||||
import ScrollableList from 'flavours/glitch/components/scrollable_list';
|
import ScrollableList from 'flavours/glitch/components/scrollable_list';
|
||||||
|
|
|
@ -13,7 +13,7 @@ import EditIcon from '@/material-icons/400-24px/edit.svg?react';
|
||||||
import PersonIcon from '@/material-icons/400-24px/person.svg?react';
|
import PersonIcon from '@/material-icons/400-24px/person.svg?react';
|
||||||
import { updateAccount } from 'flavours/glitch/actions/accounts';
|
import { updateAccount } from 'flavours/glitch/actions/accounts';
|
||||||
import { Button } from 'flavours/glitch/components/button';
|
import { Button } from 'flavours/glitch/components/button';
|
||||||
import Column from 'flavours/glitch/components/column';
|
import { Column } from 'flavours/glitch/components/column';
|
||||||
import { ColumnHeader } from 'flavours/glitch/components/column_header';
|
import { ColumnHeader } from 'flavours/glitch/components/column_header';
|
||||||
import { Icon } from 'flavours/glitch/components/icon';
|
import { Icon } from 'flavours/glitch/components/icon';
|
||||||
import { LoadingIndicator } from 'flavours/glitch/components/loading_indicator';
|
import { LoadingIndicator } from 'flavours/glitch/components/loading_indicator';
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import Column from 'flavours/glitch/components/column';
|
import { Column } from 'flavours/glitch/components/column';
|
||||||
import { ColumnHeader } from 'flavours/glitch/components/column_header';
|
import { ColumnHeader } from 'flavours/glitch/components/column_header';
|
||||||
import type { Props as ColumnHeaderProps } from 'flavours/glitch/components/column_header';
|
import type { Props as ColumnHeaderProps } from 'flavours/glitch/components/column_header';
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue