Skip to content

Commit

Permalink
enhancement for grid layout
Browse files Browse the repository at this point in the history
  • Loading branch information
imanjra committed Jul 18, 2024
1 parent 5726176 commit 9dcd204
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 27 deletions.
43 changes: 38 additions & 5 deletions app/packages/core/src/plugins/SchemaIO/components/GridView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export default function GridView(props: ViewPropsType) {
const { schema, path, data } = props;
const { properties, view = {} } = schema as ObjectSchemaType;
const { alignX, alignY, align_x, align_y, gap = 1, orientation } = view;
const direction = orientation === "vertical" ? "row" : "column";
const direction = orientation === "horizontal" ? "row" : "column";

const propertiesAsArray = [];

Expand All @@ -25,14 +25,20 @@ export default function GridView(props: ViewPropsType) {
}

const layoutHeight = props?.layout?.height;
const parsedGap = parseGap(gap);
const adjustedLayoutWidth = getAdjustedLayoutWidth(
props?.layout?.width,
parsedGap
);

const baseGridProps: BoxProps = {
sx: {
display: "grid",
gap,
display: "flex",
flexWrap: "wrap",
gap: parsedGap,
justifyContent: alignX || align_x || "start",
alignItems: alignY || align_y || "start",
gridAutoFlow: direction,
flexDirection: direction,
...getPaddingSx(view),
...getMarginSx(view),
},
Expand All @@ -54,14 +60,19 @@ export default function GridView(props: ViewPropsType) {
orientation === "vertical"
? spaceToHeight(space, layoutHeight)
: undefined,
overflow: "hidden",
},
key: id,
};
return (
<Box
key={id}
{...getProps(
{ ...props, schema: property },
{
...props,
schema: property,
layout: { width: adjustedLayoutWidth, height: layoutHeight },
},
"item",
baseItemProps
)}
Expand All @@ -81,3 +92,25 @@ export default function GridView(props: ViewPropsType) {
</Box>
);
}

function parseGap(gap: number | string) {
if (typeof gap === "string") {
const gapStr = gap.trim().replace("px", "");
if (isNaN(gapStr)) {
console.warn("Ignored invalid gap value " + gap);
return 0;
}
const gapInt = parseInt(gapStr);
return gap.includes("px") ? gapInt / 8 : gapInt;
} else if (typeof gap === "number") {
return gap;
}
return 0;
}

function getAdjustedLayoutWidth(layoutWidth?: number, gap?: number) {
if (typeof gap === "number" && typeof layoutWidth === "number") {
return layoutWidth - gap * 8;
}
return layoutWidth;
}
32 changes: 24 additions & 8 deletions app/packages/operators/src/CustomPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { PANEL_LOAD_TIMEOUT } from "./constants";
import { Property } from "./types";

import { CustomPanelProps, useCustomPanelHooks } from "./useCustomPanelHooks";
import { useEffect } from "react";

export function CustomPanel(props: CustomPanelProps) {
const { panelId, dimensions, panelName, panelLabel } = props;
Expand Down Expand Up @@ -48,18 +49,33 @@ export function CustomPanel(props: CustomPanelProps) {
const schema = Property.fromJSON(panelSchema);

return (
<Box sx={{ height: "100%", width: "100%", position: "relative" }}>
<OperatorIO
schema={schema}
onChange={handlePanelStateChange}
data={data}
layout={{ height, width }}
onPathChange={handlePanelStatePathChange}
/>
<Box
sx={{ height: "100%", width: "100%", position: "relative" }}
ref={dimensions.widthRef}
>
<DimensionRefresher dimensions={dimensions}>
<OperatorIO
schema={schema}
onChange={handlePanelStateChange}
data={data}
layout={{ height, width }}
onPathChange={handlePanelStatePathChange}
/>
</DimensionRefresher>
</Box>
);
}

function DimensionRefresher(props) {
const { dimensions, children } = props;

useEffect(() => {
dimensions?.refresh();
}, []);

return children;
}

export function defineCustomPanel({
on_load,
on_change,
Expand Down
1 change: 1 addition & 0 deletions app/packages/operators/src/useCustomPanelHooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ export interface CustomPanelProps {
height?: number;
width?: number;
};
widthRef: React.MutableRefObject<HTMLDivElement | null>;
} | null;
panelName?: string;
panelLabel?: string;
Expand Down
9 changes: 7 additions & 2 deletions app/packages/spaces/src/components/Panel.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { CenteredStack } from "@fiftyone/components";
import { CenteredStack, scrollable } from "@fiftyone/components";
import * as fos from "@fiftyone/state";
import React from "react";
import { PANEL_LOADING_TIMEOUT } from "../constants";
Expand Down Expand Up @@ -35,7 +35,12 @@ function Panel(props: PanelProps) {
const { component: Component } = panel;

return (
<StyledPanel id={node.id} ref={dimensions.ref} data-cy={panelContentTestId}>
<StyledPanel
id={node.id}
data-cy={panelContentTestId}
className={scrollable}
ref={dimensions.ref}
>
<PanelContext.Provider value={{ node }}>
<Component panelNode={node} dimensions={dimensions} />
</PanelContext.Provider>
Expand Down
2 changes: 0 additions & 2 deletions app/packages/spaces/src/components/StyledElements.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { scrollbarStyles } from "@fiftyone/utilities";
import styled from "styled-components";

export const SpaceContainer = styled.div`
Expand All @@ -24,7 +23,6 @@ export const StyledPanel = styled.div`
height: calc(100% - 28px);
overflow: auto;
background: var(--fo-palette-background-mediaSpace);
${scrollbarStyles}
`;

export const AddPanelButtonContainer = styled.div`
Expand Down
40 changes: 30 additions & 10 deletions app/packages/state/src/hooks/useDimensions.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,48 @@
import { useState, useRef, useLayoutEffect, DOMElement } from "react";
import { throttle } from "lodash";
import { useLayoutEffect, useMemo, useRef, useState } from "react";

type Dimensions = {
width: number;
height: number;
};
const DIMENSION_REFRESH_THROTTLE = 250;

type Dimensions = { width: number; height: number };

export default function useDimensions() {
const [bounds, update] = useState<Dimensions>(null);
const ref = useRef<HTMLElement>();
const widthRef = useRef<HTMLElement>();
const heightRef = useRef<HTMLElement>();

function refresh() {
if (!ref.current) return;
const { width, height } = ref.current.getBoundingClientRect();
if (!ref.current && !widthRef.current && !heightRef.current) return;
let height, width;
if ((!widthRef.current || !heightRef.current) && ref.current) {
height = ref.current.getBoundingClientRect().height;
width = ref.current.getBoundingClientRect().width;
}
if (widthRef.current) {
width = widthRef.current.getBoundingClientRect().width;
}
if (heightRef.current) {
height = heightRef.current.getBoundingClientRect().height;
}
update({ width, height });
}

const ro = new ResizeObserver(refresh);
const throttledRefresh = useMemo(() => {
return throttle(() => {
refresh();
}, DIMENSION_REFRESH_THROTTLE);
}, []);

const ro = useMemo(() => {
return new ResizeObserver(throttledRefresh);
}, [throttledRefresh]);

useLayoutEffect(() => {
if (ref.current) {
refresh();
ro.observe(ref.current);
}
}, [ref.current]);
}, [ro, ref.current]); // eslint-disable-line

return { bounds, ref, update, refresh };
return { bounds, ref, heightRef, widthRef, update, refresh };
}

0 comments on commit 9dcd204

Please sign in to comment.