Skip to content

Commit ae27e2c

Browse files
authored
Return a more suitable ref (#5)
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.
1 parent 70f91aa commit ae27e2c

File tree

4 files changed

+62
-6
lines changed

4 files changed

+62
-6
lines changed

packages/react-rough-fiber/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-rough-fiber",
3-
"version": "0.0.4",
3+
"version": "0.0.5",
44
"description": "A React renderer for rendering hand-drawn SVGs.",
55
"keywords": [
66
"react",
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { cleanup, render, screen } from '@testing-library/react';
2+
import { RoughSVG } from '../index';
3+
4+
afterEach(() => {
5+
cleanup();
6+
jest.clearAllMocks();
7+
});
8+
9+
describe('return correct ref', () => {
10+
it('render g', () => {
11+
let ref: SVGElement | null = null;
12+
render(
13+
<RoughSVG>
14+
<svg
15+
xmlns="http://www.w3.org/2000/svg"
16+
width="24"
17+
height="24"
18+
viewBox="0 0 24 24"
19+
>
20+
<path d="M0 0 L 10 10" data-testid="path" />
21+
<g ref={_ref => ref = _ref}/>
22+
</svg>
23+
</RoughSVG>
24+
);
25+
expect(ref!.tagName).toBe('g');
26+
});
27+
28+
it('render path', () => {
29+
let ref: SVGElement | null = null;
30+
render(
31+
<RoughSVG>
32+
<svg
33+
xmlns="http://www.w3.org/2000/svg"
34+
width="24"
35+
height="24"
36+
viewBox="0 0 24 24"
37+
>
38+
<path d="M0 0 L 10 10" data-testid="path" ref={_ref => ref = _ref} />
39+
<g/>
40+
</svg>
41+
</RoughSVG>
42+
);
43+
expect(ref!.tagName).toBe('path');
44+
});
45+
});

packages/react-rough-fiber/src/constants.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,5 @@ export const SVG_SHAPE_MAP: { [key in SVGShape['type']]: SVGShape } = {
6161

6262
export const FILL_CSS_VARIABLE = '--rrf-fill-color';
6363
export const FILL_OPACITY_CSS_VARIABLE = '--rrf-fill-opacity';
64+
65+
export const DATA_RRF_GROUP = 'data-rrf-group';

packages/react-rough-fiber/src/renderer.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,9 @@ import {
77
HostContext,
88
HostConfig,
99
InstanceWithListeners,
10-
SVGShape,
1110
Options,
1211
} from './types';
13-
import { SVG_NAMESPACE, HTML_NAMESPACE, SVG_SHAPE_MAP } from './constants';
12+
import { SVG_NAMESPACE, HTML_NAMESPACE, SVG_SHAPE_MAP, DATA_RRF_GROUP } from './constants';
1413
import { isFun } from './utils';
1514
import { diffProps } from './props';
1615

@@ -27,9 +26,11 @@ const createInstance = (
2726
// roughjs renders a shape as a fill path(if fill is not none) and a stroke path(if stroke is not none)
2827
// so we need to wrap the shape in a g element
2928
if (!inDefs && type in SVG_SHAPE_MAP) {
30-
type = 'g';
29+
domElement = ownerDocument.createElementNS(SVG_NAMESPACE, 'g');
30+
domElement.setAttribute(DATA_RRF_GROUP, '');
31+
} else {
32+
domElement = ownerDocument.createElementNS(SVG_NAMESPACE, type);
3133
}
32-
domElement = ownerDocument.createElementNS(SVG_NAMESPACE, type);
3334
} else {
3435
domElement = ownerDocument.createElement(type);
3536
}
@@ -137,7 +138,15 @@ export const createReconciler = (
137138
(<any>textInstance).nodeValue = newText;
138139
},
139140
commitMount() {},
140-
getPublicInstance: (instance) => instance!,
141+
getPublicInstance: (instance) => {
142+
if(instance?.hasAttribute(DATA_RRF_GROUP)) {
143+
const firstChild = instance.children[0];
144+
if(firstChild?.tagName === 'path') {
145+
return firstChild as SVGElement;
146+
}
147+
}
148+
return instance!
149+
},
141150
prepareForCommit: () => null,
142151
preparePortalMount: () => {},
143152
resetAfterCommit: () => {},

0 commit comments

Comments
 (0)