Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Containers and portal refactor #2799

Merged
merged 43 commits into from
May 29, 2024
Merged
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
6c00505
Rewrite victory-container as a function component
KenanYusuf Feb 9, 2024
b6efcbe
victory-selection-container
KenanYusuf Feb 12, 2024
7609176
victory-zoom-container
KenanYusuf Feb 12, 2024
057c8bb
Merge branch 'main' into victory-container-rewrite
KenanYusuf Feb 12, 2024
995b740
Merge branch 'main' into victory-container-rewrite
KenanYusuf Feb 13, 2024
86f2ee4
working create-container function
KenanYusuf Feb 13, 2024
15e31eb
wip
KenanYusuf Feb 13, 2024
9ed6257
victory-voronoi-container
KenanYusuf Feb 13, 2024
d089573
victory-cursor-container
KenanYusuf Feb 13, 2024
9f9b9ee
victory-brush-container
KenanYusuf Feb 13, 2024
f791d36
Remove class files
KenanYusuf Feb 13, 2024
19cbc01
reset demos
KenanYusuf Feb 13, 2024
42b9225
remove class victory-container
KenanYusuf Feb 13, 2024
cd69e6b
fix victory-container name
KenanYusuf Feb 13, 2024
ec330d0
clean up
KenanYusuf Feb 13, 2024
920f373
type create-container function properly
KenanYusuf Feb 14, 2024
d2ebc2a
improve generic naming
KenanYusuf Feb 14, 2024
0a8a23c
rewrite victory-native/victory-container
KenanYusuf Feb 14, 2024
242279b
victory-native/victory-brush-container
KenanYusuf Feb 14, 2024
38a9b66
victory-native/victory-cursor-container
KenanYusuf Feb 14, 2024
b8efab2
victory-native/victory-selection-container
KenanYusuf Feb 14, 2024
623a699
victory-native/victory-voronoi-container
KenanYusuf Feb 14, 2024
c9bad96
victory-native/victory-zoom-container
KenanYusuf Feb 14, 2024
780371a
Improve create-container types
KenanYusuf Feb 15, 2024
bef9472
improve types
KenanYusuf Feb 16, 2024
a1ea866
refactor victory-portal and portal components
KenanYusuf Feb 16, 2024
03d3045
fix some tests
KenanYusuf Feb 16, 2024
f7bd26d
fix more tests
KenanYusuf Feb 16, 2024
ea71f7d
Merge branch 'main' into victory-container-rewrite
KenanYusuf Feb 16, 2024
8f90ab5
reset demo file
KenanYusuf Feb 16, 2024
65d0241
changeset
KenanYusuf Feb 19, 2024
06ac3f1
fix cursor label position
KenanYusuf Feb 19, 2024
d373b48
fixed cursor overflow
KenanYusuf Feb 19, 2024
708063b
Merge branch 'main' into victory-container-rewrite
KenanYusuf Feb 19, 2024
7488648
prevent scroll when zooming
KenanYusuf Feb 19, 2024
7e17603
remove comment
KenanYusuf Feb 19, 2024
69f5108
add comments to merge refs utility
KenanYusuf Feb 21, 2024
585d1eb
rename container components const
KenanYusuf Feb 21, 2024
f06b954
Merge branch 'main' into victory-container-rewrite
KenanYusuf Mar 20, 2024
f27716c
Merge branch 'main' into victory-container-rewrite
carbonrobot Mar 27, 2024
3a4b911
Merge branch 'main' into victory-container-rewrite
KenanYusuf May 16, 2024
ffc9841
refactor victory-portal to remove dependency on react-dom (#2870)
KenanYusuf May 17, 2024
b82bc5b
Add minor changeset
carbonrobot May 29, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .changeset/giant-carrots-own.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
"victory": patch
"victory-brush-container": patch
"victory-core": patch
"victory-create-container": patch
"victory-cursor-container": patch
"victory-native": patch
"victory-selection-container": patch
"victory-voronoi-container": patch
"victory-zoom-container": patch
---

Refactor containers and portal to function components
347 changes: 175 additions & 172 deletions packages/victory-brush-container/src/victory-brush-container.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import React from "react";
import {
VictoryContainer,
Selection,
Rect,
DomainTuple,
VictoryContainerProps,
VictoryContainer,
VictoryEventHandler,
} from "victory-core";
import { BrushHelpers } from "./brush-helpers";
import { defaults } from "lodash";
Expand Down Expand Up @@ -37,186 +38,188 @@ export interface VictoryBrushContainerProps extends VictoryContainerProps {
) => void;
}

type ComponentClass<TProps> = { new (props: TProps): React.Component<TProps> };
interface VictoryBrushContainerMutatedProps extends VictoryBrushContainerProps {
domain: { x: DomainTuple; y: DomainTuple };
currentDomain: { x: DomainTuple; y: DomainTuple } | undefined;
cachedBrushDomain: { x: DomainTuple; y: DomainTuple } | undefined;
}

export function brushContainerMixin<
TBase extends ComponentClass<TProps>,
TProps extends VictoryBrushContainerProps,
>(Base: TBase) {
// @ts-expect-error "TS2545: A mixin class must have a constructor with a single rest parameter of type 'any[]'."
return class VictoryBrushContainer extends Base {
static displayName = "VictoryBrushContainer";
static defaultProps = {
...VictoryContainer.defaultProps,
allowDrag: true,
allowDraw: true,
allowResize: true,
brushComponent: <Rect />,
brushStyle: {
stroke: "transparent",
fill: "black",
fillOpacity: 0.1,
},
handleComponent: <Rect />,
handleStyle: {
stroke: "transparent",
fill: "transparent",
},
handleWidth: 8,
mouseMoveThreshold: 0,
};
export const VICTORY_BRUSH_CONTAINER_DEFAULT_PROPS = {
allowDrag: true,
allowDraw: true,
allowResize: true,
brushComponent: <Rect />,
brushStyle: {
stroke: "transparent",
fill: "black",
fillOpacity: 0.1,
},
handleComponent: <Rect />,
handleStyle: {
stroke: "transparent",
fill: "transparent",
},
handleWidth: 8,
mouseMoveThreshold: 0,
};

static defaultEvents = (props) => {
return [
{
target: "parent",
eventHandlers: {
onMouseDown: (evt, targetProps) => {
return props.disable
? {}
: BrushHelpers.onMouseDown(evt, targetProps);
},
onTouchStart: (evt, targetProps) => {
return props.disable
? {}
: BrushHelpers.onMouseDown(evt, targetProps);
},
onGlobalMouseMove: (evt, targetProps) => {
return props.disable ||
(!targetProps.isPanning && !targetProps.isSelecting)
? {}
: BrushHelpers.onGlobalMouseMove(evt, targetProps);
},
onGlobalTouchMove: (evt, targetProps) => {
return props.disable ||
(!targetProps.isPanning && !targetProps.isSelecting)
? {}
: BrushHelpers.onGlobalMouseMove(evt, targetProps);
},
onGlobalMouseUp: (evt, targetProps) => {
return props.disable
? {}
: BrushHelpers.onGlobalMouseUp(evt, targetProps);
},
onGlobalTouchEnd: (evt, targetProps) => {
return props.disable
? {}
: BrushHelpers.onGlobalMouseUp(evt, targetProps);
},
onGlobalTouchCancel: (evt, targetProps) => {
return props.disable
? {}
: BrushHelpers.onGlobalMouseUp(evt, targetProps);
},
},
},
];
};
export const useVictoryBrushContainer = (
initialProps: VictoryBrushContainerProps,
) => {
const props = {
...VICTORY_BRUSH_CONTAINER_DEFAULT_PROPS,
...(initialProps as VictoryBrushContainerMutatedProps),
};
const { children } = props;

getSelectBox(props, coordinates) {
const { x, y } = coordinates;
const { brushStyle, brushComponent, name } = props;
const brushComponentStyle =
brushComponent.props && brushComponent.props.style;
const cursor = !props.allowDrag && !props.allowResize ? "auto" : "move";
return x[0] !== x[1] && y[0] !== y[1]
? React.cloneElement(brushComponent, {
key: `${name}-brush`,
width: Math.abs(x[1] - x[0]) || 1,
height: Math.abs(y[1] - y[0]) || 1,
x: Math.min(x[0], x[1]),
y: Math.min(y[0], y[1]),
cursor,
style: defaults({}, brushComponentStyle, brushStyle),
})
: null;
}
const getSelectBox = (coordinates) => {
const { x, y } = coordinates;
const { brushStyle, brushComponent, name } = props;
const brushComponentStyle =
brushComponent.props && brushComponent.props.style;
const cursor = !props.allowDrag && !props.allowResize ? "auto" : "move";
return x[0] !== x[1] && y[0] !== y[1]
? React.cloneElement(brushComponent, {
key: `${name}-brush`,
width: Math.abs(x[1] - x[0]) || 1,
height: Math.abs(y[1] - y[0]) || 1,
x: Math.min(x[0], x[1]),
y: Math.min(y[0], y[1]),
cursor,
style: defaults({}, brushComponentStyle, brushStyle),
})
: null;
};

getCursorPointers(props) {
const cursors = {
yProps: "ns-resize",
xProps: "ew-resize",
};
if (!props.allowResize && props.allowDrag) {
cursors.xProps = "move";
cursors.yProps = "move";
} else if (!props.allowResize && !props.allowDrag) {
cursors.xProps = "auto";
cursors.yProps = "auto";
}
return cursors;
const getCursorPointers = () => {
const cursors = {
yProps: "ns-resize",
xProps: "ew-resize",
};
if (!props.allowResize && props.allowDrag) {
cursors.xProps = "move";
cursors.yProps = "move";
} else if (!props.allowResize && !props.allowDrag) {
cursors.xProps = "auto";
cursors.yProps = "auto";
}
return cursors;
};

getHandles(props, domain) {
const { handleWidth, handleStyle, handleComponent, name } = props;
const domainBox = BrushHelpers.getDomainBox(props, domain);
const { x1, x2, y1, y2 } = domainBox;
const { top, bottom, left, right } = BrushHelpers.getHandles(
props,
domainBox,
);
const width = Math.abs(x2 - x1) || 1;
const height = Math.abs(y2 - y1) || 1;
const handleComponentStyle =
(handleComponent.props && handleComponent.props.style) || {};
const style = defaults({}, handleComponentStyle, handleStyle);
const getHandles = (domain) => {
const { handleWidth, handleStyle, handleComponent, name } = props;
const domainBox = BrushHelpers.getDomainBox(props, domain);
const { x1, x2, y1, y2 } = domainBox;
const { top, bottom, left, right } = BrushHelpers.getHandles(
props,
domainBox,
);
const width = Math.abs(x2 - x1) || 1;
const height = Math.abs(y2 - y1) || 1;
const handleComponentStyle =
(handleComponent.props && handleComponent.props.style) || {};
const style = defaults({}, handleComponentStyle, handleStyle);

const cursors = this.getCursorPointers(props);
const yProps = {
style,
width,
height: handleWidth,
cursor: cursors.yProps,
};
const xProps = {
style,
width: handleWidth,
height,
cursor: cursors.xProps,
};
const cursors = getCursorPointers();
const yProps = {
style,
width,
height: handleWidth,
cursor: cursors.yProps,
};
const xProps = {
style,
width: handleWidth,
height,
cursor: cursors.xProps,
};

const handleProps = {
top: top && Object.assign({ x: top.x1, y: top.y1 }, yProps),
bottom: bottom && Object.assign({ x: bottom.x1, y: bottom.y1 }, yProps),
left: left && Object.assign({ y: left.y1, x: left.x1 }, xProps),
right: right && Object.assign({ y: right.y1, x: right.x1 }, xProps),
};
const handles = ["top", "bottom", "left", "right"].reduce(
(memo, curr) =>
handleProps[curr]
? memo.concat(
React.cloneElement(
handleComponent,
Object.assign(
{ key: `${name}-handle-${curr}` },
handleProps[curr],
),
const handleProps = {
top: top && Object.assign({ x: top.x1, y: top.y1 }, yProps),
bottom: bottom && Object.assign({ x: bottom.x1, y: bottom.y1 }, yProps),
left: left && Object.assign({ y: left.y1, x: left.x1 }, xProps),
right: right && Object.assign({ y: right.y1, x: right.x1 }, xProps),
};
const handles = ["top", "bottom", "left", "right"].reduce(
(memo, curr) =>
handleProps[curr]
? memo.concat(
React.cloneElement(
handleComponent,
Object.assign(
{ key: `${name}-handle-${curr}` },
handleProps[curr],
),
)
: memo,
[] as React.ReactElement[],
);
return handles.length ? handles : null;
}
),
)
: memo,
[] as React.ReactElement[],
);
return handles.length ? handles : null;
};

getRect(props) {
const { currentDomain, cachedBrushDomain } = props;
const brushDomain = defaults({}, props.brushDomain, props.domain);
const domain = isEqual(brushDomain, cachedBrushDomain)
? defaults({}, currentDomain, brushDomain)
: brushDomain;
const coordinates = Selection.getDomainCoordinates(props, domain);
const selectBox = this.getSelectBox(props, coordinates);
return selectBox ? [selectBox, this.getHandles(props, domain)] : [];
}
const getRect = () => {
const { currentDomain, cachedBrushDomain } = props;
const brushDomain = defaults({}, props.brushDomain, props.domain);
const domain = isEqual(brushDomain, cachedBrushDomain)
? defaults({}, currentDomain, brushDomain)
: brushDomain;
const coordinates = Selection.getDomainCoordinates(props, domain);
const selectBox = getSelectBox(coordinates);
return selectBox ? [selectBox, getHandles(domain)] : [];
};

// Overrides method in VictoryContainer
getChildren(props) {
return [
...React.Children.toArray(props.children),
...this.getRect(props),
];
}
return {
props,
children: [
...React.Children.toArray(children),
...getRect(),
] as React.ReactElement[],
};
}
export const VictoryBrushContainer = brushContainerMixin(VictoryContainer);
};

export const VictoryBrushContainer = (
initialProps: VictoryBrushContainerProps,
) => {
const { props, children } = useVictoryBrushContainer(initialProps);
return <VictoryContainer {...props}>{children}</VictoryContainer>;
};

VictoryBrushContainer.role = "container";

VictoryBrushContainer.defaultEvents = (
initialProps: VictoryBrushContainerProps,
) => {
const props = { ...VICTORY_BRUSH_CONTAINER_DEFAULT_PROPS, ...initialProps };
const createEventHandler =
(
handler: VictoryEventHandler,
isDisabled?: (targetProps: any) => boolean,
): VictoryEventHandler =>
// eslint-disable-next-line max-params
(event, targetProps, eventKey, context) =>
props.disable || isDisabled?.(targetProps)
? {}
: handler(event, { ...props, ...targetProps }, eventKey, context);

return [
{
target: "parent",
eventHandlers: {
onMouseDown: createEventHandler(BrushHelpers.onMouseDown),
onTouchStart: createEventHandler(BrushHelpers.onMouseDown),
onGlobalMouseMove: createEventHandler(
BrushHelpers.onGlobalMouseMove,
(targetProps) => !targetProps.isPanning && !targetProps.isSelecting,
),
onGlobalTouchMove: createEventHandler(
BrushHelpers.onGlobalMouseMove,
(targetProps) => !targetProps.isPanning && !targetProps.isSelecting,
),
onGlobalMouseUp: createEventHandler(BrushHelpers.onGlobalMouseUp),
onGlobalTouchEnd: createEventHandler(BrushHelpers.onGlobalMouseUp),
onGlobalTouchCancel: createEventHandler(BrushHelpers.onGlobalMouseUp),
},
},
];
};
Loading