FormidableLabs / react-live

A flexible playground for live editing React components
https://commerce.nearform.com/open-source/react-live/
MIT License
4.31k stars 241 forks source link

Next: Plan future API #89

Closed kitten closed 5 years ago

kitten commented 6 years ago

Perfect-world-wishful-thinking-optimal-API:

// Live is the default export and should render
// a nice output with minimal props

<Live
  code=""
  scope={{ SomeComponent }}
  renderEditor={Live.Editor}
  {...defaultProps}

  /* defaultProps: */
  transform={bubleTransform}
  transformOutput={bubleOutput}
  transformError={bubleErrors}
/>

//////////////

<LiveProvider code="">
  <Live.DefaultLayout>
    <Live.Editor />
    <Live.Preview />
    <Live.Error />
  </Live.DefaultLayout>
</LiveProvider>

// LiveProvider is an export and all "broken out"
// bits of react-live are exported

// Live.Editor is context wrapped
// but import { Editor } is also present

//////////////////

// The normal editor doesn't come with any defaults?
<Editor code="" language="jsx" Prism={...} theme={...} padding={...} />
alejandrogarciasalas commented 6 years ago

@kitten @sofiapoh This looks great! A few questions and comments though:

  1. do we want to necessarily stick with bublé? I think having the option to use Babel would be nice since you can have custom presets that match your company best practices, this would also allow us to support superscripts of JS like TypeScript (not sure what the TS support is for bublé). Sadly babel is not as lightweight but IMO it's not that much of a compromise specially if we support this as an alternate option.
  2. is transformOutput the same as transformCode from the current API?
  3. does transformError passes the error message down as a string? does this mean any sort of manipulation has to happen by using regex? I believe this is the current behavior and can be suboptimal.. is having an object representation of the error possible? 🤔
  4. how easy would overriding a theme be? specially if you want the option to toggle between multiple themes and want to avoid loading multiple stylesheets with css selectors that might conflict (currently one needs to override the .prism-code class. For now the only workaround I found was doing something similar to what react-live using dangerouslySetInnerHTML.
  5. I don't see noInline as a prop, are we getting rid of this? If we are not can we change this to be called inline or some other prop name? I think generally speaking avoiding boolean values that are negative by default is cleaner since then you don't have to negate a false boolean value. Would this prop still involve wrapping the components to be rendered by a render(<Component />) function?
  6. what would Live.DefaultLayout do and how is this different than just wrapping Live.Editor, Live.Preview and Live.Error by different divs with flexbox etc. and creating a custom layout from that. What's the benefit? Is it just cleaner?
  7. are we still exposingwithLive as an HoC?
  8. If Editor takes a language prop what languages would we support? js, ts(we need buble for this)? js already works with jsx so is this neccesary? specially since this is a react playground, meaning most people will be using jsx already? does this just change the prism language highlight?
  9. how would additional prism features like line numbers and line highlighting work? this would be great when using react-live for examples.
  10. nice to have: is this component accesible? Can I navigate it with a screen reader etc.
  11. If we have something like noInline it could be interesting to have fake import statements for all components in scope to replicate a more editor like experience and pinpoint what components are being used e.g from what library etc.

These are some things that first come to mind (I'll let you know if I can think of anything else). I know this is a draft but think it might be nice to clarify what the PropType of each prop is and go into more detail on what the behavior of each of this prop is, similar to the table in the react-live README.

I am very excited for this, let me know if there's any other way I can help, happy to help writing code and/or docs 😄

kitten commented 6 years ago

@alejandrogarciasalas These are some great questions :) Let me try to go through them one by one

  1. The transformer should become configurable and some built-in error inline-output might be supported. This is obviously quite a complex piece of API work, so it might not land in the next version immediately.
  2. Maybe, maybe not, based on the above
  3. This would be taking a thrown error and returning a formatted output based on our API to show inline-errors (See 1)
  4. It'd still be possible to use prism CSS-based themes but react-live will switch its editor to react-simple-code-editor, which has been made for this purpose/library, and prism-react-renderer. Check out its theming: https://github.com/FormidableLabs/prism-react-renderer#theming
  5. This'd probably stay or might become part of the custom transpilation; we'll see what works
  6. Default layout is an idea to simplify using react-live immediately. We'd regard Live as a new render prop-based component that can be customised, but the core would still be broken out into separate components; This enables customisation at every single point and it's make it easy to get started easily
  7. Yes, there'd likely still be an HOC with a new internal API, but it won't be very necessary I'd say
  8. It'd support all languages that prism-react-renderer supports, but it'd default to js which is probably initially the only one we're still interested in
  9. Custom UI features are implementable in prism-react-renderer, with pure React code, so Prism plugins stay unsupported. This "side-kick" project and react-simple-code-editor are built to accommodate that as a solid alternative. It's pretty easy to build line numbering with prism-react-renderer. Its CodeSandbox example shows some
  10. Yes, accessibility in the Editor is now being prioritised and react-simple-code-editor is taking care of that part
  11. Fake import statements are likely still out of scope, but may become possible to be implemented when custom transpilation is a thing (See 1)

Hope this answers everything :)

tl;dr Take a look at prism-react-renderer and react-simple-code-editor to get an idea of the future Editor component, which are both published and ready for prod use today individually :)

https://github.com/FormidableLabs/prism-react-renderer https://github.com/satya164/react-simple-code-editor

jimthedev commented 6 years ago

Regarding Bable/Babel. If Buble isn't swapped out then it probably makes sense to contribute back to it on a few key tickets that follow some pretty commonly used features in the react/babel community that don't currently work in react-live:

https://github.com/Rich-Harris/buble/issues/123 https://github.com/Rich-Harris/buble/pull/125

satya164 commented 6 years ago

One feedback regarding the API, renderEditor={Live.Editor} should probably be editor={Live.Editor} or editorComponent={Live.Editor} to distinguish it from a render callback, or renderEditor={props => <Live.Editor {...props} />}

philholden commented 6 years ago

I would like to be able have editors not map 1:1 onto previews. E.g. have one editor and multiple previews. The editor shows the code for the most recently clicked preview. That way code can be shown in another pane (e.g. storybook) without needing loads of providers . The code in the code pane may change depending on scroll position, focus or button press.

function ThreePreviewsOneEditor() {
  const [activeId, setActive] = useState("a")
  return <LiveProvider>
    <Live.Code id="a" code="<div>A</div>" /> /* render null*/
    <Live.Code id="b" code="<div>B</div>" />
    <Live.Code id="c" code="<div>C</div>" />
    <Live.Editor fileName={activeId} />
    <Live.Preview activeId="a" onFocus={() => setActive("a")} />
    <Live.Preview activeId="b" onFocus={() => setActive("b")} />
    <Live.Preview activeId="c" onFocus={() => setActive("c")} />
  </LiveProvider>
}
aaronbeall commented 5 years ago

do we want to necessarily stick with bublé? I think having the option to use Babel would be nice since you can have custom presets that match your company best practices, this would also allow us to support superscripts of JS like TypeScript (not sure what the TS support is for bublé). Sadly babel is not as lightweight but IMO it's not that much of a compromise specially if we support this as an alternate option.

+1 for TypeScript support! I can't use this project currently but I so wish I could.