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

Implementing react-native-svg compatible api #154

Open
ilyalesik opened this issue Nov 14, 2019 · 8 comments · May be fixed by #285
Open

Implementing react-native-svg compatible api #154

ilyalesik opened this issue Nov 14, 2019 · 8 comments · May be fixed by #285
Labels
complexity: hard Hard task priority: minor Minor task topic: primitives support Compatibility with react-native, react-sketchapp, react-primitives type: feature or enhancement New feature or request

Comments

@ilyalesik
Copy link
Member

ilyalesik commented Nov 14, 2019

react-sketchapp:

import sketch from 'sketch';
import { Svg, render } from 'react-sketchapp';

export default () => {
  render(
    <Svg xmlns="http://www.w3.org/2000/svg" width="494" height="447" viewBox="0 0 494 447">
      <Svg.G fill="none" fillRule="evenodd">
        <Svg.Path fill="#FFAE00" d="M247 447L0 160 107 15 247 0l140 15 107 145" />
        <Svg.Path fill="#EC6C00" d="M247 447L0 160h494" />
        <Svg.Path fill="#FFAE00" d="M247 447L100 160h294" />
        <Svg.Path fill="#FFEFB4" d="M247 0L100 160h294" />
        <Svg.Path fill="#FFAE00" d="M107 15L52 88 0 160h101M387 15l55 73 52 72H393" />
        <Svg.Path fill="#FED305" d="M107 15l-7 145L247 0m140 15l7 145L247 0" />
      </Svg.G>
    </Svg>,
    sketch.getSelectedDocument().selectedPage,
  );
};
@ilyalesik ilyalesik added complexity: hard Hard task type: idea priority: minor Minor task topic: primitives support Compatibility with react-native, react-sketchapp, react-primitives type: feature or enhancement New feature or request and removed type: idea labels Nov 14, 2019
@macintoshhelper
Copy link
Contributor

macintoshhelper commented Apr 1, 2020

I'm working on a cross-platform vx fork and am looking into integrating react-figma with vx, to allow for generating Figma components/designs from d3 code.

I've created a proof-of-concept solution for rendering JSX to svg in react-figma, would there be any drawbacks that I'm missing though, of doing this?

import { renderToStaticMarkup } from 'react-dom/server';

const svgString = ({ size }) => renderToStaticMarkup((
  <svg height={`${size}`} width={`${size}`}>
    <circle cx="50" cy="50" r="40" stroke="red" stroke-width="3" fill="green" />
  </svg>
))

render((
  <Svg
    style={{ width: 100, height: 100 }}
    source={svgString({ size: 100 })}
  />
), figma.root);

and for the react-native-svg compatibility layer, we could do this in the Svg export (pseudo-code):

import { Svg as SvgXml } from 'react-figma';
import { renderToStaticMarkup } from 'react-dom/server';


const Svg = ({ children, ...props }) => {
  const source = renderToStaticMarkup(children)// TODO: memoize this for performance, as we're escaping the virtual DOM :
    .replace('<figma_', '<');

  // Using `<figma_svg>` instead of `<svg>`, as this is an internal/private API that can break in the future

  return <SvgXml source={source} {...props} />;
};

Svg.Svg = (props) => <figma_svg {...props} />;
Svg.G = (props) => <figma_g {...props} />;
Svg.Rect = (props) => <figma_rect {...props} />;
// TODO: other SVG components here...

render((
  <Svg>
    <Rect ...(attributes_here) />
  </Svg>
));

And a rendering from d3 to Figma with a hacked together setup (render string with @vx/primitives, and copy/paste it into Figma) 🙂:

image

Seems simpler than #182 I think, should I open a PR with a demo? (I don't really want to create a conflicting PR though, so maybe best to just do a fork) 😄

@ilyalesik
Copy link
Member Author

Open PR with a demo, please. 🙏
#182 is a draft and probably will not be developed further.

@macintoshhelper
Copy link
Contributor

I had a go, but found jsx-to-string doesn't actually render down the tree, it just stringifies the literal jsx, which is no use. ReactDOMServer.renderToStaticMarkup would work in theory, but it seems to have some import statement which is not allowed in the Figma Node.js runtime. So I think working on top of your draft PR is probably the best bet, integrating it into the react-reconciler renderer.

macintoshhelper added a commit to macintoshhelper/react-figma that referenced this issue Apr 6, 2020
@macintoshhelper macintoshhelper linked a pull request Apr 6, 2020 that will close this issue
@ilyalesik
Copy link
Member Author

A simple work around, just using string template literals:

import * as React from 'react';
import {Page, Svg} from 'react-figma';

const svg = `
    <svg width="14" height="16" viewBox="0 0 14 16" fill="none" xmlns="http://www.w3.org/2000/svg">
        <path fill-rule="evenodd" clip-rule="evenodd" d="M5 3H6V4H5V3ZM3 3H4V4H3V3ZM1 3H2V4H1V3ZM13 13H1V5H13V13ZM13 4H7V3H13V4ZM14 3C14 2.45 13.55 2 13 2H1C0.45 2 0 2.45 0 3V13C0 13.55 0.45 14 1 14H13C13.55 14 14 13.55 14 13V3Z" fill="#1B1F23"/>
    </svg>
`

export const App = () => {
    return (
        <Page name="New page" isCurrent>
            <Svg source={svg} />
        </Page>
    );
};

@thierryc
Copy link
Contributor

thierryc commented Mar 19, 2021

I would like to try this : renderToStaticMarkup from 'react-dom/server'

You test it already? It is a good way or not?
@macintoshhelper you try it, what is your feedback?

// [fake code]
import { renderToStaticMarkup } from 'react-dom/server';
import { SvgComp } from './SvgComp';

export const App = () => {
    return (
        <Page name="New page" isCurrent>
            <Svg source={renderToStaticMarkup(<SvgComp />)} />
        </Page>
    );
};

@ilyalesik
Copy link
Member Author

@thierryc Also, there are an unfinished PR where I tried to start to implement SVG.<...> API

@thierryc
Copy link
Contributor

thierryc commented Mar 20, 2021

image


import * as React from 'react';
import { Page, Rectangle, Text, View, Svg } from 'react-figma';
import { Circle } from './react-figma-svg';
import { renderToStaticMarkup } from 'react-dom/server';


export const App = () => {
    return (
        <Page isCurrent name="Page X">
            <Text characters="Hello, react-figma!"/>
            <Rectangle style={{ width: 200, height: 100, backgroundColor: '#0ddd25' }} />
            <Rectangle style={{ width: 200, height: 100, backgroundColor: '#a6dd00' }} />
            <View>
                <View style={{ width: 200, height: 100, backgroundColor: '#dd55aa' }} />
                <Text style={{ color: '#ffffff' }}>text</Text>
            </View>
            <Svg source={
                renderToStaticMarkup(
                <Circle cx="50" cy="50" r="40" stroke="red" stroke-width="3" fill="green"/>
                )}>
            </Svg>
        </Page>
    );
};



Now I need to write SVG as un function to make the bride ...

@thierryc
Copy link
Contributor

This option work and I will work around.
For the moment, it generates 3 times the same SVG.

image

import * as React from 'react';
import { Page, Rectangle, Text, View, Svg } from 'react-figma';
import { Circle, G } from './react-figma-svg';
import { renderToStaticMarkup } from 'react-dom/server';

export const App = () => {
    console.log('render cycle');
    return (
        <Page isCurrent name="Page X">
            <Svg name="svg-test-1" source={
                renderToStaticMarkup(
                    <G name="circles"> 
                        <Circle cx={10} cy="100" r="10" stroke="lime" strokeWidth="3" fill="teal"/> 
                        <Circle cx={40} cy="100" r="10" stroke="lime" strokeWidth="3" fill="pink"/> 
                        <Circle cx={70} cy="100" r="10" stroke="lime" strokeWidth="3" fill="green"/> 
                    </G>
                )}>
            </Svg>
        </Page>
    );
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
complexity: hard Hard task priority: minor Minor task topic: primitives support Compatibility with react-native, react-sketchapp, react-primitives type: feature or enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants