Skip to content

Commit

Permalink
Changes from CR
Browse files Browse the repository at this point in the history
  • Loading branch information
ghsolomon committed Nov 7, 2023
1 parent dd36844 commit c012963
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 37 deletions.
21 changes: 11 additions & 10 deletions cmp/grid/Grid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
import composeRefs from '@seznam/compose-react-refs';
import {agGrid, AgGrid} from '@xh/hoist/cmp/ag-grid';
import {getTreeStyleClasses} from '@xh/hoist/cmp/grid';
import {gridScrollbar} from '@xh/hoist/cmp/grid/impl/GridScrollbar';
import {gridHScrollbar} from '@xh/hoist/cmp/grid/impl/GridHScrollbar';
import {getAgGridMenuItems} from '@xh/hoist/cmp/grid/impl/MenuSupport';
import {div, frame, vframe} from '@xh/hoist/cmp/layout';
import {div, fragment, frame, vframe} from '@xh/hoist/cmp/layout';
import {
hoistCmp,
HoistModel,
Expand Down Expand Up @@ -107,20 +107,21 @@ export const [Grid, grid] = hoistCmp.withFactory<GridProps>({
highlightRowOnClick ? 'xh-grid--highlight-row-on-click' : null
);

const container = model.experimental['enableFullWidthScroll'] ? vframe : frame;
const {enableFullWidthScroll} = model.experimental,
container = enableFullWidthScroll ? vframe : frame;

return container(
frame({
return fragment(
container({
className,
items: [
agGrid({
model: model.agGridModel,
...getLayoutProps(props),
...impl.agOptions
}),
gridScrollbar({
omit: !model.experimental['enableFullWidthScroll'],
viewRef: impl.viewRef
gridHScrollbar({
omit: !enableFullWidthScroll,
gridLocalModel: impl
})
],
testId,
Expand All @@ -138,7 +139,7 @@ export const [Grid, grid] = hoistCmp.withFactory<GridProps>({
//------------------------
// Implementation
//------------------------
class GridLocalModel extends HoistModel {
export class GridLocalModel extends HoistModel {
override xhImpl = true;

@lookup(GridModel)
Expand Down Expand Up @@ -281,7 +282,7 @@ class GridLocalModel extends HoistModel {
}

// Support for FullWidthScroll
if (model.experimental['enableFullWidthScroll']) {
if (model.experimental.enableFullWidthScroll) {
ret.suppressHorizontalScroll = true;
}

Expand Down
75 changes: 48 additions & 27 deletions cmp/grid/impl/GridScrollbar.ts → cmp/grid/impl/GridHScrollbar.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {GridModel} from '@xh/hoist/cmp/grid';
import {GridLocalModel, GridModel} from '@xh/hoist/cmp/grid';
import {div} from '@xh/hoist/cmp/layout';
import {hoistCmp, HoistModel, HoistProps, useLocalModel} from '@xh/hoist/core';
import {makeObservable} from '@xh/hoist/mobx';
Expand All @@ -7,19 +7,25 @@ import {sumBy} from 'lodash';
import {action, observable} from 'mobx';
import {createRef, RefObject} from 'react';

export interface GridScrollbarProps extends HoistProps<GridModel> {
viewRef: RefObject<HTMLElement>;
/**
* Implementation for Grid's full-width horizontal scrollbar, to span pinned columns
* @internal
*/

export interface GridHScrollbarProps extends HoistProps<GridModel> {
gridLocalModel: GridLocalModel;
}

export const gridScrollbar = hoistCmp.factory<GridScrollbarProps>({
className: 'xh-grid__grid-scrollbar',
export const gridHScrollbar = hoistCmp.factory<GridHScrollbarProps>({
className: 'xh-grid__grid-hscrollbar',
render({className}) {
const impl = useLocalModel(GridScrollbarModel),
{scrollerRef, viewportWidth, visibleColumnWidth, SCROLLBAR_SIZE} = impl;
const impl = useLocalModel(GridHScrollbarModel),
{scrollerRef, viewWidth, visibleColumnWidth, SCROLLBAR_SIZE} = impl;

if (viewWidth > visibleColumnWidth) return null;

return div({
className,
omit: viewportWidth > visibleColumnWidth,
item: div({
className: `${className}__filler`,
style: {
Expand All @@ -32,29 +38,35 @@ export const gridScrollbar = hoistCmp.factory<GridScrollbarProps>({
},
ref: scrollerRef,
style: {
height: SCROLLBAR_SIZE,
height: SCROLLBAR_SIZE, // TODO: make this a property on GridModel to apply to both scrollbars
overflowX: 'auto',
overflowY: 'hidden'
}
});
}
});

class GridScrollbarModel extends HoistModel {
class GridHScrollbarModel extends HoistModel {
readonly SCROLLBAR_SIZE = 10;
readonly scrollerRef = createRef<HTMLDivElement>();

@observable viewportWidth: number;
@observable viewWidth: number;
@observable private isVerticalScrollbarVisible = false;

private viewportResizeObserver: ResizeObserver;
/** Observe AG's viewport to detect when vertical scrollbar visibility changes */
private agViewportResizeObserver: ResizeObserver;
/** Observe overall view to detect when horizontal scrollbar is needed */
private viewResizeObserver: ResizeObserver;

get visibleColumnWidth(): number {
const {model, SCROLLBAR_SIZE} = this;
const {gridModel, SCROLLBAR_SIZE} = this;
return (
sumBy(model.columnState, it =>
it.hidden ? 0 : it.width ?? model.getColumn(it.colId).minWidth ?? 0
) + (this.isVerticalScrollbarVisible ? SCROLLBAR_SIZE : 0)
sumBy(gridModel.columnState, ({colId, hidden, width}) => {
if (hidden) return 0;
const minWidth = gridModel.getColumn(colId).minWidth ?? 0;
if (width) return Math.max(width, minWidth);
return minWidth;
}) + (this.isVerticalScrollbarVisible ? SCROLLBAR_SIZE : 0)
);
}

Expand All @@ -66,12 +78,12 @@ class GridScrollbarModel extends HoistModel {
return this.viewRef.current.querySelector('.ag-body-vertical-scroll-container');
}

private get model(): GridModel {
private get gridModel(): GridModel {
return this.componentProps.model as GridModel;
}

private get viewRef(): RefObject<HTMLElement> {
return this.componentProps.viewRef;
return this.componentProps.gridLocalModel.viewRef;
}

constructor() {
Expand All @@ -89,31 +101,40 @@ class GridScrollbarModel extends HoistModel {

override afterLinked() {
this.addReaction({
when: () => !!this.viewRef.current && this.model.isReady,
when: () => this.viewRef.current && this.gridModel.isReady,
run: () => {
const {agViewport, viewportResizeObserver} = this;
this.viewportWidth = agViewport.clientWidth;
const {agViewport, viewRef} = this;
this.viewWidth = viewRef.current.clientWidth;
agViewport.addEventListener('scroll', e =>
this.scrollScroller((e.target as HTMLDivElement).scrollLeft)
);
viewportResizeObserver?.disconnect();
this.viewportResizeObserver = observeResize(
rect => this.onViewResized(rect),
this.agViewportResizeObserver = observeResize(
() => this.onAgViewportResized(),
agViewport,
{debounce: 100}
);
this.viewResizeObserver = observeResize(
rect => this.onViewResized(rect),
viewRef.current,
{debounce: 100}
);
}
});
}

override destroy() {
super.destroy();
this.viewportResizeObserver?.disconnect();
this.agViewportResizeObserver?.disconnect();
this.viewResizeObserver?.disconnect();
}

@action
private onViewResized({width}: DOMRect) {
this.viewportWidth = width;
private onAgViewportResized() {
this.isVerticalScrollbarVisible = !!this.agVerticalScrollContainer.clientHeight;
}

@action
private onViewResized({width}: DOMRect) {
this.viewWidth = width;
}
}

0 comments on commit c012963

Please sign in to comment.