Skip to content

Commit

Permalink
Return a more suitable ref (#5)
Browse files Browse the repository at this point in the history
Previously, the ref will always return an SVGGElement when the element's type is one of `path`, `circle`, `line`, `rect`, `ellipse`, `polygon`, `polyline`. Because we wrap these types of elements in an SVGGElement and return the SVGGElement as the ref.

https://github.com/Bowen7/react-rough-fiber/blob/70f91aa7588ec8375dd53225d8ca74445a716f72/packages/react-rough-fiber/src/renderer.ts#L26-L32

Now, I have changed it to return the first path element of the SVGGElement. 

It's just a better, not a perfect way to handle the ref. Because `roughjs` renders all shapes to SVGPathElement, we can't get the original ref.
  • Loading branch information
Bowen7 authored May 3, 2024
1 parent 70f91aa commit ae27e2c
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 6 deletions.
2 changes: 1 addition & 1 deletion packages/react-rough-fiber/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-rough-fiber",
"version": "0.0.4",
"version": "0.0.5",
"description": "A React renderer for rendering hand-drawn SVGs.",
"keywords": [
"react",
Expand Down
45 changes: 45 additions & 0 deletions packages/react-rough-fiber/src/__tests__/ref.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { cleanup, render, screen } from '@testing-library/react';
import { RoughSVG } from '../index';

afterEach(() => {
cleanup();
jest.clearAllMocks();
});

describe('return correct ref', () => {
it('render g', () => {
let ref: SVGElement | null = null;
render(
<RoughSVG>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
>
<path d="M0 0 L 10 10" data-testid="path" />
<g ref={_ref => ref = _ref}/>
</svg>
</RoughSVG>
);
expect(ref!.tagName).toBe('g');
});

it('render path', () => {
let ref: SVGElement | null = null;
render(
<RoughSVG>
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
>
<path d="M0 0 L 10 10" data-testid="path" ref={_ref => ref = _ref} />
<g/>
</svg>
</RoughSVG>
);
expect(ref!.tagName).toBe('path');
});
});
2 changes: 2 additions & 0 deletions packages/react-rough-fiber/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,5 @@ export const SVG_SHAPE_MAP: { [key in SVGShape['type']]: SVGShape } = {

export const FILL_CSS_VARIABLE = '--rrf-fill-color';
export const FILL_OPACITY_CSS_VARIABLE = '--rrf-fill-opacity';

export const DATA_RRF_GROUP = 'data-rrf-group';
19 changes: 14 additions & 5 deletions packages/react-rough-fiber/src/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,9 @@ import {
HostContext,
HostConfig,
InstanceWithListeners,
SVGShape,
Options,
} from './types';
import { SVG_NAMESPACE, HTML_NAMESPACE, SVG_SHAPE_MAP } from './constants';
import { SVG_NAMESPACE, HTML_NAMESPACE, SVG_SHAPE_MAP, DATA_RRF_GROUP } from './constants';
import { isFun } from './utils';
import { diffProps } from './props';

Expand All @@ -27,9 +26,11 @@ const createInstance = (
// roughjs renders a shape as a fill path(if fill is not none) and a stroke path(if stroke is not none)
// so we need to wrap the shape in a g element
if (!inDefs && type in SVG_SHAPE_MAP) {
type = 'g';
domElement = ownerDocument.createElementNS(SVG_NAMESPACE, 'g');
domElement.setAttribute(DATA_RRF_GROUP, '');
} else {
domElement = ownerDocument.createElementNS(SVG_NAMESPACE, type);
}
domElement = ownerDocument.createElementNS(SVG_NAMESPACE, type);
} else {
domElement = ownerDocument.createElement(type);
}
Expand Down Expand Up @@ -137,7 +138,15 @@ export const createReconciler = (
(<any>textInstance).nodeValue = newText;
},
commitMount() {},
getPublicInstance: (instance) => instance!,
getPublicInstance: (instance) => {
if(instance?.hasAttribute(DATA_RRF_GROUP)) {
const firstChild = instance.children[0];
if(firstChild?.tagName === 'path') {
return firstChild as SVGElement;
}
}
return instance!
},
prepareForCommit: () => null,
preparePortalMount: () => {},
resetAfterCommit: () => {},
Expand Down

0 comments on commit ae27e2c

Please sign in to comment.