-
-
Notifications
You must be signed in to change notification settings - Fork 89
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #491 from live-codes/jsx-runtime
Render JSX/TSX default export as a React component
- Loading branch information
Showing
28 changed files
with
1,049 additions
and
151 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,233 @@ | ||
# JSX | ||
|
||
TODO... | ||
import LiveCodes from '../../src/components/LiveCodes.tsx'; | ||
import RunInLiveCodes from '../../src/components/RunInLiveCodes.tsx'; | ||
|
||
[JSX](https://react.dev/learn/writing-markup-with-jsx) is a syntax extension for JavaScript that allows writing HTML-like markup inside JavaScript. | ||
It has been popularized by [React](https://react.dev/), and then adopted by many other libraries/frameworks. | ||
|
||
By default, when running JSX in LiveCodes, [React](https://react.dev/) runtime is used. | ||
However, other libraries like [Preact](https://preactjs.com/), [nano JSX](https://nanojsx.io/) and others can be used as well (see [Custom JSX Runtimes](#custom-jsx-runtimes)). | ||
|
||
Please note that TSX is also supported in LiveCodes and is [documented here](./tsx.md). | ||
|
||
## Demo: | ||
|
||
<LiveCodes template="react" height="400px"></LiveCodes> | ||
|
||
## Usage | ||
|
||
The easiest way is to [auto-render](#auto-rendering) a component by exporting it as the [default export](https://developer.mozilla.org/en-US/docs/web/javascript/reference/statements/export#using_the_default_export): | ||
|
||
export const basicJsxDemo = { jsx: `export default function App() {\n return <h1>Hello World!</h1>;\n}`} | ||
|
||
<RunInLiveCodes params={basicJsxDemo} code={basicJsxDemo.jsx} language="jsx" formatCode={false}></RunInLiveCodes> | ||
|
||
You may, however, be more explicit and render the component yourself using [React DOM](https://react.dev/reference/react-dom/client): | ||
|
||
export const reactDomDemo = { jsx: `import { createRoot } from "react-dom/client";\n\nfunction App() {\n return <h1>Hello World!</h1>;\n}\n\nconst root = createRoot(document.querySelector("#root"));\nroot.render(<App />);`, html: `<div id="root"></div>`} | ||
|
||
<RunInLiveCodes params={reactDomDemo} code={reactDomDemo.jsx} language="jsx" formatCode={false}></RunInLiveCodes> | ||
|
||
:::info note | ||
|
||
React's [new JSX transform](https://legacy.reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html) is utilized. So there is no need to import React. | ||
|
||
```jsx | ||
// this is not needed: | ||
// import React from 'react'; | ||
|
||
export default function App() { | ||
return <h1>Hello World!</h1>; | ||
} | ||
``` | ||
|
||
::: | ||
|
||
### Auto-rendering | ||
|
||
A component is rendered automatically as a React component (without having to manually use React Dom to render it) if the following conditions are met: | ||
|
||
- The component is exported as the default export. | ||
- No custom JSX runtime is used (see [Custom JSX Runtimes](#custom-jsx-runtimes)). | ||
- No [imports from `"./script"`](#exports) in markup editor. | ||
- Auto-rendering is not [disabled](#disabling-auto-rendering). | ||
|
||
#### Root Element | ||
|
||
To render the React components to a specific [root](https://react.dev/reference/react-dom/client/createRoot) DOM element use `"livecodes-app"` as the element `id`. Otherwise, if that element is not found, a new `div` element is added to `document.body` and is used as the root. | ||
|
||
Example: | ||
|
||
export const rootDemo = { html: `<div id="livecodes-app">Loading...</div>`, jsx: `export default function App() {\n return <h1>Hello World!</h1>;\n}`} | ||
|
||
<RunInLiveCodes params={rootDemo} code={rootDemo.html} language="html" formatCode={false}></RunInLiveCodes> | ||
|
||
#### Disabling Auto-rendering | ||
|
||
To disable auto-rendering, set the [custom settings](#custom-settings) `disableAutoRender` property to `true`. | ||
|
||
export const disableAutoRenderDemo = {markup: {language: "html", content: `JSX auto-rendering is disabled. Set from app menu → Custom Settings.`}, script: {language: "jsx", content: `export default function App() {\n return <h1>Hello World!</h1>;\n}`}, customSettings: {"jsx": {"disableAutoRender": true}}} | ||
|
||
<RunInLiveCodes config={disableAutoRenderDemo} code={JSON.stringify(disableAutoRenderDemo.customSettings, null, 2)} language="json" codeTitle="Custom Settings" formatCode={false}></RunInLiveCodes> | ||
|
||
### Importing Modules | ||
|
||
npm modules can be imported as described in the section about [module resolution](../features/module-resolution.md), including bare module imports and importing from different CDNs. Stylesheet imports are added as `<link rel="stylesheet">` tags in the page `head`. | ||
|
||
Example: | ||
|
||
export const importsDemo = { jsx: `import { useState, useEffect } from "react";\nimport confetti from "canvas-confetti";\nimport "bootstrap/dist/css/bootstrap.css";\n\nexport default function App() {\n const [count, setCount] = useState(0);\n\n useEffect(() => {\n if (count > 0) {\n confetti();\n }\n }, [count]);\n\n return (\n <div className="m-5 text-center">\n <p>You clicked {count} times.</p>\n <button onClick={() => setCount(count + 1)}>Click me</button>\n </div>\n );\n}\n` } | ||
|
||
<RunInLiveCodes params={importsDemo} code={importsDemo.jsx} language="jsx" formatCode={false}></RunInLiveCodes> | ||
|
||
Module imports can be customized using import maps as described in [module resolution](../features/module-resolution.md#custom-module-resolution) documentations. | ||
|
||
#### Types for Imported Modules | ||
|
||
Types for imported modules are loaded automatically (if available) to provide [Intellisense](../features/intellisense.md), auto-completion and type information. | ||
|
||
![LiveCodes Intellisense](../../static/img/screenshots/intellisense1.jpg) | ||
|
||
![LiveCodes Intellisense](../../static/img/screenshots/intellisense2.jpg) | ||
|
||
Moreover, you can provide custom type definitions for modules that do not have types available on npm. See [Custom Types](../features/intellisense.md#custom-types) for details. | ||
|
||
### Exports | ||
|
||
Values exported from script editor (default or named) can be imported in the markup editor by importing from `"./script"` (with no extension). | ||
|
||
This can be useful, for example, when using [MDX](./mdx.md) to import components exported form JSX. | ||
|
||
Demo: | ||
|
||
export const exportsDemo = { mdx: `import Greeting from "./script";\n\n<Greeting name="MDX" />\n`, jsx: `export default function(props) {\n return <h1>Greeting from {props.name}!</h1>;\n}\n` } | ||
|
||
<LiveCodes params={exportsDemo}></LiveCodes> | ||
|
||
:::info note | ||
|
||
When values are imported from `"./script"`, [auto-rendering](#auto-rendering) is disabled, because it is assumed that you want to take control over component rendering. | ||
|
||
::: | ||
|
||
### Styles | ||
|
||
CSS can be applied to the component using various ways: | ||
|
||
#### Style Editor | ||
|
||
Styles added in the style editor is applied globally to the [result page](../features/result.md). This can use different **languages/processors** supported in LiveCodes including CSS, SCSS, Less, Stylus, ..etc. See [style documentation](../features/css.md) for more details. | ||
|
||
And of course, styles and stylesheets added in markup editor are also applied globally. | ||
|
||
#### Importing Stylesheets | ||
|
||
Stylesheets imported in script editor are added as `<link rel="stylesheet">` tags in the page `head`. | ||
The stylesheet URL can be an absolute URL or a path in the npm package. The URL has to end with `".css"`. | ||
|
||
example: | ||
|
||
export const stylesDemo = { jsx: `import "bootstrap/dist/css/bootstrap.css";\n\nexport default () => <h1 className="m-5 text-center">Hello World!</h1>;\n` } | ||
|
||
<RunInLiveCodes params={stylesDemo} code={stylesDemo.jsx} language="jsx" formatCode={false}></RunInLiveCodes> | ||
|
||
#### CSS Modules | ||
|
||
CSS modules are supported and are [documented separately](./cssmodules.md). Make sure to enable CSS modules (from style editor menu or in [`processors`](../configuration/configuration-object.md#processors) property of [configuration object](../configuration/configuration-object.md)). | ||
|
||
Demo: | ||
|
||
export const cssModulesDemo = { activeEditor: 'script' , style: {language: 'css', content: `.title {\n color: green;\n font-family: sans-serif;\n}\n`}, script: {language: 'jsx', content: `import classes from './style.module.css';\n\nexport default function() {\n return <h1 className={classes.title}>Hello, CSS Modules!</h1>;\n}\n`}, processors: ['cssmodules'] } | ||
|
||
<LiveCodes config={cssModulesDemo}></LiveCodes> | ||
|
||
#### CSS Frameworks | ||
|
||
[CSS Frameworks](../features/css.md#css-processors) supported in LiveCodes (e.g. [Tailwind CSS](./tailwindcss.md), [UnoCSS](./unocss.md), [WindiCSS](./windicss.md)) can detect class names added in JSX. Make sure that the required utility is enabled (from style editor menu or in [`processors`](../configuration/configuration-object.md#processors) property of [configuration object](../configuration/configuration-object.md)) and that required [directives](https://tailwindcss.com/docs/functions-and-directives#tailwind) are added to the style editor. | ||
|
||
Demo: | ||
|
||
export const tailwindcssDemo = { activeEditor: 'script' , style: {language: 'css', content: `@tailwind base;\n@tailwind components;\n@tailwind utilities;\n`}, script: {language: 'jsx', content: `export default function() {\n return <h1 className="text-3xl font-bold text-gray-500 text-center m-4">Hello, Tailwind CSS!</h1>;\n}\n`}, processors: ['tailwindcss'] } | ||
|
||
<LiveCodes config={tailwindcssDemo}></LiveCodes> | ||
|
||
#### CSS-in-JS | ||
|
||
CSS-in-JS libraries can be imported and used as usual. | ||
|
||
Demo: | ||
|
||
export const styledComponentsDemo = { jsx: `import styled from 'styled-components';\n\nconst Title = styled.h1\`\n text-align: center;\n font-family: sans-serif;\n color: palevioletred;\n\`;\n\nexport default function () {\n return <Title>Hello, styled-components!</Title>;\n}\n` } | ||
|
||
<LiveCodes params={styledComponentsDemo}></LiveCodes> | ||
|
||
### Custom JSX Runtimes | ||
|
||
LiveCodes allows using other libraries (like [Preact](https://preactjs.com/) and [nano JSX](https://nanojsx.io/)) as the JSX runtime. | ||
|
||
JSX is compiled to JavaScript using the TypeScript compiler, which allows multiple configuration options for JSX, including [`jsx`](https://www.typescriptlang.org/tsconfig#jsx), [`jsxFactory`](https://www.typescriptlang.org/tsconfig#jsxFactory), [`jsxFragmentFactory`](https://www.typescriptlang.org/tsconfig#jsxFragmentFactory) and [`jsxImportSource`](https://www.typescriptlang.org/tsconfig#jsxImportSource). | ||
|
||
These can be configured using in-code pragmas or in [custom settings](#custom-settings). | ||
|
||
Example for using Preact: | ||
|
||
export const preactDemo = { jsx: `/** @jsx h */\nimport { h, render } from 'preact';\n\nconst App = (props) => <h1>Hello, {props.name}</h1>;\n\nrender(<App name="Preact" />, document.body);\n` } | ||
|
||
<RunInLiveCodes params={preactDemo} code={'//highlight-next-line\n' + preactDemo.jsx} language="jsx" formatCode={false} showLineNumbers={true}></RunInLiveCodes> | ||
|
||
:::info note | ||
|
||
[Auto-rendering](#auto-rendering) is disabled for custom JSX runtimes. | ||
|
||
::: | ||
|
||
## Language Info | ||
|
||
### Name | ||
|
||
`jsx` | ||
|
||
### Extension | ||
|
||
`.jsx` | ||
|
||
### Editor | ||
|
||
`script` | ||
|
||
## Compiler | ||
|
||
[TypeScript compiler](./typescript.md) | ||
|
||
## Code Formatting | ||
|
||
Using [Prettier](https://prettier.io/). | ||
|
||
## Custom Settings | ||
|
||
[Custom settings](../advanced/custom-settings.md) added to the property `jsx` are passed to the TypeScript compiler as [compiler options](https://www.typescriptlang.org/tsconfig#compilerOptions) while compiling JSX. | ||
In addition, the option `disableAutoRender` can be set to `true` to disable [auto-rendering](#auto-rendering). | ||
|
||
Please note that custom settings should be valid JSON (i.e. functions are not allowed). | ||
|
||
**Example:** | ||
|
||
```json title="Custom Settings" | ||
{ | ||
"jsx": { | ||
"disableAutoRender": true, | ||
"jsxFactory": "h", | ||
"jsxFragmentFactory": "Fragment" | ||
} | ||
} | ||
``` | ||
|
||
## Starter Template | ||
|
||
https://livecodes.io/?template=react | ||
|
||
## Links | ||
|
||
- [React](https://react.dev/) | ||
- [JSX](https://react.dev/learn/writing-markup-with-jsx) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,64 @@ | ||
# React Native (TSX) | ||
|
||
TODO... | ||
import LiveCodes from '../../src/components/LiveCodes.tsx'; | ||
|
||
[React Native](https://reactnative.dev/) is a framework for building mobile apps using React and React Native. React Native support in LiveCodes is achieved by using [React Native for Web](https://necolas.github.io/react-native-web/) (an accessible implementation of React Native's Components and APIs that is interoperable with React DOM). | ||
|
||
## Demo | ||
|
||
<LiveCodes template="react-native" height="400px"></LiveCodes> | ||
|
||
## Usage | ||
|
||
For usage and examples, see documentation for [JSX](./jsx.md). | ||
|
||
## Language Info | ||
|
||
### Name | ||
|
||
`react-native-tsx` | ||
|
||
### Extension | ||
|
||
`.react-native.tsx` | ||
|
||
### Editor | ||
|
||
`script` | ||
|
||
## Compiler | ||
|
||
[TypeScript compiler](./typescript.md) and [React Native for Web](https://necolas.github.io/react-native-web/) | ||
|
||
## Code Formatting | ||
|
||
Using [Prettier](https://prettier.io/). | ||
|
||
## Custom Settings | ||
|
||
[Custom settings](../advanced/custom-settings.md) added to the property `react-native-tsx` are passed to the TypeScript compiler as [compiler options](https://www.typescriptlang.org/tsconfig#compilerOptions) while compiling TSX. | ||
In addition, the option `disableAutoRender` can be set to `true` to disable [auto-rendering](./jsx#auto-rendering). | ||
|
||
Please note that custom settings should be valid JSON (i.e. functions are not allowed). | ||
|
||
**Example:** | ||
|
||
```json title="Custom Settings" | ||
{ | ||
"react-native-tsx": { | ||
"disableAutoRender": true | ||
} | ||
} | ||
``` | ||
|
||
## Starter Template | ||
|
||
https://livecodes.io/?template=react-native (uses JSX) | ||
|
||
## Links | ||
|
||
- [React Native](https://reactnative.dev/) | ||
- [React Native for Web](https://necolas.github.io/react-native-web/) | ||
- [React](https://react.dev/) | ||
- [JSX](https://react.dev/learn/writing-markup-with-jsx) | ||
- [TypeScript](https://www.typescriptlang.org/) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,66 @@ | ||
# React Native | ||
|
||
TODO... | ||
import LiveCodes from '../../src/components/LiveCodes.tsx'; | ||
|
||
[React Native](https://reactnative.dev/) is a framework for building mobile apps using React and React Native. React Native support in LiveCodes is achieved by using [React Native for Web](https://necolas.github.io/react-native-web/) (an accessible implementation of React Native's Components and APIs that is interoperable with React DOM). | ||
|
||
TypeScript is also supported in React Native (TSX) and is [documented here](./react-native-tsx.md). | ||
|
||
## Demo | ||
|
||
<LiveCodes template="react-native" height="400px"></LiveCodes> | ||
|
||
## Usage | ||
|
||
For usage and examples, see documentation for [JSX](./jsx.md). | ||
|
||
## Language Info | ||
|
||
### Name | ||
|
||
`react-native` | ||
|
||
### Extension | ||
|
||
`.react-native.jsx` | ||
|
||
### Editor | ||
|
||
`script` | ||
|
||
## Compiler | ||
|
||
[TypeScript compiler](./typescript.md) and [React Native for Web](https://necolas.github.io/react-native-web/) | ||
|
||
## Code Formatting | ||
|
||
Using [Prettier](https://prettier.io/). | ||
|
||
## Custom Settings | ||
|
||
[Custom settings](../advanced/custom-settings.md) added to the property `react-native` are passed to the TypeScript compiler as [compiler options](https://www.typescriptlang.org/tsconfig#compilerOptions) while compiling JSX. | ||
In addition, the option `disableAutoRender` can be set to `true` to disable [auto-rendering](./jsx#auto-rendering). | ||
|
||
Please note that custom settings should be valid JSON (i.e. functions are not allowed). | ||
|
||
**Example:** | ||
|
||
```json title="Custom Settings" | ||
{ | ||
"react-native": { | ||
"disableAutoRender": true | ||
} | ||
} | ||
``` | ||
|
||
## Starter Template | ||
|
||
https://livecodes.io/?template=react-native | ||
|
||
## Links | ||
|
||
- [React Native](https://reactnative.dev/) | ||
- [React Native for Web](https://necolas.github.io/react-native-web/) | ||
- [React](https://react.dev/) | ||
- [JSX](https://react.dev/learn/writing-markup-with-jsx) | ||
- [TypeScript](https://www.typescriptlang.org/) |
Oops, something went wrong.