Skip to content

Commit

Permalink
extract resizableheaderpanel
Browse files Browse the repository at this point in the history
  • Loading branch information
pomahtri committed Dec 8, 2024
1 parent 80581d6 commit 3e50556
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 89 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion */
import { resizeObserverSingleton } from '@ts/core/m_resize_observer';
import { getBoundingRect } from '@ts/core/utils/m_position';
import type { Column } from '@ts/grids/new/grid_core/columns_controller/types';
import { Component, createRef } from 'inferno';
import type { RefObject } from 'inferno';
import { Component } from 'inferno';

import { Sortable } from '../../grid_core/inferno_wrappers/sortable';
import { DropDownButton } from './drop_down_button';
Expand All @@ -15,38 +14,32 @@ export const CLASSES = {
export interface HeaderPanelProps {
columns: Column[];

onReorder?: (fromIndex: number, toIndex: number) => void;
onReorder: (fromIndex: number, toIndex: number) => void;

onAdd?: (fromIndex: number, toIndex: number) => void;
onAdd: (fromIndex: number, toIndex: number) => void;

onRemove?: (name: string) => void;
onRemove: (name: string) => void;

shownColumnCount: number;

elementRef: RefObject<HTMLDivElement>;
}

interface HeaderPanelState {
shownColumnCount: number;
}

export class HeaderPanel extends Component<HeaderPanelProps, HeaderPanelState> {
private status: 'initial' | 'shrinking' | 'normal' = 'initial';

private normalHeight = 0;

private readonly ref = createRef<HTMLDivElement>();

state = {
shownColumnCount: 1,
};

public render(): JSX.Element {
const visibleColumns = this.props.columns.filter(
(_, index) => index < this.state.shownColumnCount,
(_, index) => index < this.props.shownColumnCount,
);
const nonVisibleColumns = this.props.columns.filter(
(_, index) => index >= this.state.shownColumnCount,
(_, index) => index >= this.props.shownColumnCount,
);

return (
<div className={CLASSES.headers} ref={this.ref}>
<div className={CLASSES.headers} ref={this.props.elementRef}>
<Sortable
itemOrientation='horizontal'
dropFeedbackMode='indicate'
Expand All @@ -72,72 +65,4 @@ export class HeaderPanel extends Component<HeaderPanelProps, HeaderPanelState> {
</div>
);
}

private getHeight(): number {
return getBoundingRect(this.ref.current!).height as number;
}

private updateShownColumns(): void {
// eslint-disable-next-line no-undef-init
let stateToApply: undefined | HeaderPanelState = undefined;

switch (this.status) {
case 'initial': {
if (this.state.shownColumnCount !== 1) {
throw new Error();
}

if (!this.props.columns.length) {
return;
}

this.normalHeight = this.getHeight();
this.status = 'shrinking';
stateToApply = {
shownColumnCount: this.props.columns.length,
};
break;
}

case 'shrinking': {
if (this.getHeight() > this.normalHeight) {
stateToApply = {
shownColumnCount: this.state.shownColumnCount - 1,
};
} else {
this.status = 'normal';
}
break;
}

case 'normal': {
this.status = 'shrinking';
stateToApply = {
shownColumnCount: this.props.columns.length,
};
break;
}

default: {
// eslint-disable-next-line max-len
// eslint-disable-next-line @typescript-eslint/naming-convention, @typescript-eslint/no-unused-vars
const _: never = this.status;
}
}

if (stateToApply) {
this.setState(stateToApply);
}
}

componentDidMount(): void {
resizeObserverSingleton.observe(
this.ref.current!,
() => this.updateShownColumns(),
);
}

componentDidUpdate(): void {
this.updateShownColumns();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/* eslint-disable @typescript-eslint/no-non-null-assertion */
import { resizeObserverSingleton } from '@ts/core/m_resize_observer';
import { getBoundingRect } from '@ts/core/utils/m_position';
import { Component, createRef } from 'inferno';

import type { HeaderPanelProps } from './header_panel';
import { HeaderPanel } from './header_panel';

export type Props = Omit<HeaderPanelProps, 'shownColumnCount' | 'elementRef'>;

interface State {
shownColumnCount: number;
}

export class ResizableHeaderPanel extends Component<Props, State> {
private status: 'initial' | 'shrinking' | 'normal' = 'initial';

private normalHeight = 0;

private readonly ref = createRef<HTMLDivElement>();

state = {
shownColumnCount: 1,
};

public render(): JSX.Element {
return (
<HeaderPanel
{...this.props}
elementRef={this.ref}
shownColumnCount={this.state.shownColumnCount}
/>
);
}

private getHeight(): number {
return getBoundingRect(this.ref.current!).height as number;
}

private updateShownColumns(): void {
// eslint-disable-next-line no-undef-init
let stateToApply: undefined | State = undefined;

switch (this.status) {
case 'initial': {
if (this.state.shownColumnCount !== 1) {
throw new Error();
}

if (!this.props.columns.length) {
return;
}

this.normalHeight = this.getHeight();
this.status = 'shrinking';
stateToApply = {
shownColumnCount: this.props.columns.length,
};
break;
}

case 'shrinking': {
if (this.getHeight() > this.normalHeight) {
stateToApply = {
shownColumnCount: this.state.shownColumnCount - 1,
};
} else {
this.status = 'normal';
}
break;
}

case 'normal': {
this.status = 'shrinking';
stateToApply = {
shownColumnCount: this.props.columns.length,
};
break;
}

default: {
// eslint-disable-next-line max-len
// eslint-disable-next-line @typescript-eslint/naming-convention, @typescript-eslint/no-unused-vars
const _: never = this.status;
}
}

if (stateToApply) {
this.setState(stateToApply);
}
}

componentDidMount(): void {
resizeObserverSingleton.observe(
this.ref.current!,
() => this.updateShownColumns(),
);
}

componentDidUpdate(): void {
this.updateShownColumns();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import { computed } from '@ts/core/reactive/index';
import { ColumnsController } from '@ts/grids/new/grid_core/columns_controller/columns_controller';
import { View } from '@ts/grids/new/grid_core/core/view_old';

import { HeaderPanel } from './header_panel';
import { ResizableHeaderPanel } from './resizable_header_panel';

export class HeaderPanelView extends View {
public vdom = computed(
(columns) => (
<HeaderPanel
<ResizableHeaderPanel
columns={columns}
onReorder={this.onReorder.bind(this)}
onAdd={this.onAdd.bind(this)}
Expand Down

0 comments on commit 3e50556

Please sign in to comment.