Skip to content

Commit

Permalink
refactor: Easer access to utlitites
Browse files Browse the repository at this point in the history
- Removed default export: update to `import preprocessReact to "svelte-preprocess/preprocessReact"`
- Direct export utilities
- Documented utlitites
- Removed useWritable and rename useReadable to useStore
  • Loading branch information
Bob Fanger committed Sep 17, 2022
1 parent 3662bba commit 548eb50
Show file tree
Hide file tree
Showing 14 changed files with 141 additions and 71 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Visit https://github.com/bfanger/svelte-preprocess-react/releases for the release notes.
6 changes: 3 additions & 3 deletions Readme.md → README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ npm install svelte-preprocess-react

```js
// svelte.config.js
import preprocessReact from "svelte-preprocess-react";
import preprocessReact from "svelte-preprocess-react/preprocessReact";

export default {
preprocess: preprocessReact(),
Expand All @@ -74,7 +74,7 @@ When using other processors like [svelte-preprocess]() use:
```js
// svelte.config.js
import preprocess from "svelte-preprocess";
import preprocessReact from "svelte-preprocess-react";
import preprocessReact from "svelte-preprocess-react/preprocessReact";

export default {
preprocess: preprocessReact({
Expand All @@ -93,7 +93,7 @@ The preprocessor that is passed as an option is applied before running the prepr
Once you've converted a React component to Svelte, you'd want delete that React component, but some if other React components depended on that component you can use `reactify` to use the new Svelte component as a React component.

```jsx
import reactify from "$lib/reactify";
import { reactify } from "resvelte-preprocess-react";
import ButtonSvelte from "../components/Button.svelte";

const Button = reactify(ButtonSvelte);
Expand Down
11 changes: 9 additions & 2 deletions docs/architecture.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# Architecture

This document describes design desicions and implementation details of the preprocessor.

## Context

```jsx
Expand All @@ -10,7 +14,7 @@
</App>
```

Both svelte and react have component trees, for context to work in both Svelte needs to act as if the tree is:
Both Svelte and React have component trees, for context to work in both, Svelte needs to act as if the tree is:

```jsx
<App>
Expand All @@ -28,7 +32,7 @@ and React needs to act as if the tree is:

### Client mode

sveltifyReact create a single React Root and based on the Hierachy of the ReactWrapper components we/re abel to built the react tree:
sveltifyReact creates a single React Root and based on the Hierachy of the ReactWrapper components we're able to built the React tree:

```jsx
<Bridge>
Expand All @@ -42,6 +46,9 @@ sveltifyReact create a single React Root and based on the Hierachy of the ReactW

The `<Bridge>`s use React Portals to render the components into the DOM of the ReactWrapper Svelte component.

This is why the childeren prop passed to your React is an array, even when you manually pass a children prop.
This array allows svelte-preprocess-react to inject the slotted content into the correct place in the React tree.

### Server mode

Based off on how the Svelte component is compiled we can detect SSR and utitilize the renderToString method th generate the html. (limited to leaf nodes a.t.m.)
Expand Down
64 changes: 64 additions & 0 deletions docs/utilities.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Utilities

svelte-preprocess-react comes with a utilities to make using Svelte primitives inside React components easier.
And to make using React primitives inside Svelte components easier.

## reactify

Convert a Svelte component into an React component.

### Usage:

```ts
import ButtonSvelte from "$lib/components/Button.svelte";
const Button = reactify(ButtonSvelte);

type Props = {
onClose: () => void;
};
const Dialog: React.FC<Props> = ({ onClose }) => (
<div className="dialog">
<h2>Thanks for subscribing!</h2>
<Button type="primary" onClick={() => onClose()}>
Close
</Button>
</div>
);
```

React only has props, we we asume that the props starting with "on" followed by a capital letter are event handlers.

## useStore

useStore is a React hook that allows using a Svelte Store in a React component.

### Usage:

```ts
import { useStore } from "svelte-preprocess-react";
const userStore = writable({ name: "John Doe" });

const UserGreet: React.FC = () => {
const $user = useStore(userStore);
return <h1>Hello, {$user.name}</h1>;
};
export default UserGreet;
```

When the Svelte Store is updated the component will rerender and receive the new value from the useStore hook.

### Writable stores

Inside a Svelte component `$user = { name:'Jane Doe' }` or `$user.name = 'Jane Doe'` will trigger an update.
In React and other regular javascript files this does _not_ work.
To update the value and trigger an update use the `set` or `update` methods:

```ts
// Instead of `$user = { name:'Jane Doe' }`
user.set({ name: "Jane Doe" });

// Instead of `$user.name = 'Jane Doe'`
user.update((user) => ({ ...user, name: "Jane Doe" }));
```

See https://svelte.dev/docs#run-time-svelte-store for more information.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"type": "git",
"url": "https://github.com/bfanger/svelte-preprocess-react.git"
},
"version": "0.9.0",
"version": "0.10.0",
"license": "MIT",
"type": "module",
"scripts": {
Expand Down
6 changes: 3 additions & 3 deletions src/lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
import preprocessReact from "./preprocess.js";

export default preprocessReact;
export { default as useStore } from "./useStore.js";
export { default as reactify } from "./reactify.js";
export { default as sveltify } from "./sveltify.js";
8 changes: 4 additions & 4 deletions src/lib/internal/Bridge.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type React from "react";
import { createElement } from "react";
import useReadable from "../useReadable.js";
import useStore from "../useStore.js";
import SvelteToReactContext from "./SvelteToReactContext.js";
import Child from "./Child.js";
import type { TreeNode } from "./types";
Expand All @@ -14,9 +14,9 @@ export type BridgeProps = {
node: TreeNode;
};
const Bridge: React.FC<BridgeProps> = ({ createPortal, node }) => {
const target = useReadable(node.target);
let props = useReadable(node.props);
const slot = useReadable(node.slot);
const target = useStore(node.target);
let props = useStore(node.props);
const slot = useStore(node.slot);

if (!target) {
return null;
Expand Down
File renamed without changes.
16 changes: 13 additions & 3 deletions src/lib/useReadable.ts → src/lib/useStore.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
import { useEffect as useLayoutEffect, useState } from "react";
import { useEffect, useState } from "react";
import { get, type Readable } from "svelte/store";

export default function useReadable<T>(store: Readable<T>): T {
/**
* Hook for using Svelte stores in React.
*
* Usage:
*
* const User: React.FC = () => {
* const $user = useStore(userStore);
* return <h1>Hello, {$user.name}</h1>;
* }
*/
export default function useStore<T>(store: Readable<T>): T {
const [value, setValue] = useState(() => get(store));
useLayoutEffect(() => {
useEffect(() => {
let first = true;
const cancel = store.subscribe((next) => {
if (first) {
Expand Down
18 changes: 0 additions & 18 deletions src/lib/useWritable.ts

This file was deleted.

3 changes: 1 addition & 2 deletions src/routes/context-svelte/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
<script lang="ts">
import reactify from "$lib/reactify";
import sveltify from "$lib/sveltify";
import { reactify, sveltify } from "$lib";
import { createPortal } from "react-dom";
import ReactDOM from "react-dom/client";
import { setContext } from "svelte";
Expand Down
2 changes: 1 addition & 1 deletion src/tests/preprocess.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { preprocess } from "svelte/compiler";
import sveltePreprocess from "svelte-preprocess";
import { readFile } from "fs/promises";
import { dirname, resolve } from "path";
import preprocessReact from "../lib/preprocess";
import preprocessReact from "../lib/preprocessReact";

describe("svelte-preprocess-react", () => {
it("should process <react:component> tags", async () => {
Expand Down
9 changes: 5 additions & 4 deletions svelte.config.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import preprocess from "svelte-preprocess";
import adapter from "@sveltejs/adapter-static";

const buildPackage = process.argv[2] === "package";
const skip =
process.argv[1].endsWith("svelte-package") || process.argv[2] === "sync";
let preprocessReact;
if (!buildPackage) {
preprocessReact = (await import("./package/preprocess.js")).default;
if (!skip) {
preprocessReact = (await import("./package/preprocessReact.js")).default;
}

/** @type {import('@sveltejs/kit').Config} */
export default {
preprocess: buildPackage
preprocess: skip
? preprocess({ sourceMap: true })
: preprocessReact({ preprocess: preprocess({ sourceMap: true }) }),

Expand Down
66 changes: 36 additions & 30 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -157,11 +157,12 @@
integrity sha512-PAgSp1GA8HkYE4p30/sBvJme2nefhcTBJafqQdMNoUksWZF2WzuL8OEO8wa9ndE6cghcGk3j6Ve0Oskg/wtTOw==

"@sveltejs/kit@next":
version "1.0.0-next.482"
resolved "https://registry.yarnpkg.com/@sveltejs/kit/-/kit-1.0.0-next.482.tgz#9bc5bea057e5e3968f4bc679f02b9b114f508564"
integrity sha512-ZPWVtY1ZBpVtqblZBuvVWyAEblV/89PXzlUKXPX5+4BpM3UbKNlXRXwNOC3MrcyniYuJQtU7uLvFZvQHcOKEcQ==
version "1.0.0-next.484"
resolved "https://registry.yarnpkg.com/@sveltejs/kit/-/kit-1.0.0-next.484.tgz#159d65be7d596ab9e49a59d52799e0983d6d6923"
integrity sha512-Y3l8OmlgmfJX3m081rMUZmmEQWHtiSsj3+YWYK/CQ4V99jqoztXPz/4cAxUt5mC45jVF5Ee9ykmh6GzkYjvfAQ==
dependencies:
"@sveltejs/vite-plugin-svelte" "^1.0.5"
"@types/cookie" "^0.5.1"
cookie "^0.5.0"
devalue "^3.1.2"
kleur "^4.1.4"
Expand Down Expand Up @@ -197,9 +198,9 @@
svelte-hmr "^0.14.12"

"@testing-library/dom@^8.1.0":
version "8.17.1"
resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-8.17.1.tgz#2d7af4ff6dad8d837630fecd08835aee08320ad7"
integrity sha512-KnH2MnJUzmFNPW6RIKfd+zf2Wue8mEKX0M3cpX6aKl5ZXrJM1/c/Pc8c2xDNYQCnJO48Sm5ITbMXgqTr3h4jxQ==
version "8.18.0"
resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-8.18.0.tgz#fe5903a456f2c2b64770d91e50237a031c382121"
integrity sha512-hP7v7Ifiq104Lb4dTuQzUtlkbX4sgsmxVwOTnVSDOU4ntApvPfp+eFLvasS8GpMP6pVfdbNRXNF/bSK7LTriEg==
dependencies:
"@babel/code-frame" "^7.10.4"
"@babel/runtime" "^7.12.5"
Expand Down Expand Up @@ -241,6 +242,11 @@
dependencies:
"@types/node" "*"

"@types/cookie@^0.5.1":
version "0.5.1"
resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.5.1.tgz#b29aa1f91a59f35e29ff8f7cb24faf1a3a750554"
integrity sha512-COUnqfB2+ckwXXSFInsFdOAWQzCCx+a5hq2ruyj+Vjund94RJQd4LG2u9hnvJrTgunKAaax7ancBYlDrNYxA0g==

"@types/[email protected]":
version "0.0.33"
resolved "https://registry.yarnpkg.com/@types/form-data/-/form-data-0.0.33.tgz#c9ac85b2a5fd18435b8c85d9ecb50e6d6c893ff8"
Expand Down Expand Up @@ -568,14 +574,14 @@ braces@^3.0.2, braces@~3.0.2:
fill-range "^7.0.1"

browserslist@^4.21.3:
version "4.21.3"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.3.tgz#5df277694eb3c48bc5c4b05af3e8b7e09c5a6d1a"
integrity sha512-898rgRXLAyRkM1GryrrBHGkqA5hlpkV5MhtZwg9QXeiyLUYs2k00Un05aX5l2/yJIOObYKOpS2JNo8nJDE7fWQ==
version "4.21.4"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.4.tgz#e7496bbc67b9e39dd0f98565feccdcb0d4ff6987"
integrity sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw==
dependencies:
caniuse-lite "^1.0.30001370"
electron-to-chromium "^1.4.202"
caniuse-lite "^1.0.30001400"
electron-to-chromium "^1.4.251"
node-releases "^2.0.6"
update-browserslist-db "^1.0.5"
update-browserslist-db "^1.0.9"

buffer-crc32@^0.2.5:
version "0.2.13"
Expand All @@ -600,10 +606,10 @@ callsites@^3.0.0:
resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==

caniuse-lite@^1.0.30001370, caniuse-lite@^1.0.30001399:
version "1.0.30001399"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001399.tgz#1bf994ca375d7f33f8d01ce03b7d5139e8587873"
integrity sha512-4vQ90tMKS+FkvuVWS5/QY1+d805ODxZiKFzsU8o/RsVJz49ZSRR8EjykLJbqhzdPgadbX6wB538wOzle3JniRA==
caniuse-lite@^1.0.30001399, caniuse-lite@^1.0.30001400:
version "1.0.30001402"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001402.tgz#aa29e1f47f5055b0d0c07696a67b8b08023d14c8"
integrity sha512-Mx4MlhXO5NwuvXGgVb+hg65HZ+bhUYsz8QtDGDo2QmaJS2GBX47Xfi2koL86lc8K+l+htXeTEB/Aeqvezoo6Ew==

caseless@^0.12.0, caseless@~0.12.0:
version "0.12.0"
Expand Down Expand Up @@ -914,10 +920,10 @@ eastasianwidth@^0.2.0:
resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb"
integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==

electron-to-chromium@^1.4.202:
version "1.4.249"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.249.tgz#49c34336c742ee65453dbddf4c84355e59b96e2c"
integrity sha512-GMCxR3p2HQvIw47A599crTKYZprqihoBL4lDSAUmr7IYekXFK5t/WgEBrGJDCa2HWIZFQEkGuMqPCi05ceYqPQ==
electron-to-chromium@^1.4.251:
version "1.4.254"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.254.tgz#c6203583890abf88dfc0be046cd72d3b48f8beb6"
integrity sha512-Sh/7YsHqQYkA6ZHuHMy24e6TE4eX6KZVsZb9E/DvU1nQRIrH4BflO/4k+83tfdYvDl+MObvlqHPRICzEdC9c6Q==

emoji-regex@^8.0.0:
version "8.0.0"
Expand Down Expand Up @@ -1782,9 +1788,9 @@ is-boolean-object@^1.1.0:
has-tostringtag "^1.0.0"

is-callable@^1.1.4, is-callable@^1.2.4:
version "1.2.5"
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.5.tgz#6123e0b1fef5d7591514b371bb018204892f1a2b"
integrity sha512-ZIWRujF6MvYGkEuHMYtFRkL2wAtFw89EHfKlXrkPkjQZZRWeh9L1q3SV13NIfHnqxugjLvAOkEHx9mb1zcMnEw==
version "1.2.6"
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.6.tgz#fd6170b0b8c7e2cc73de342ef8284a2202023c44"
integrity sha512-krO72EO2NptOGAX2KYyqbP9vYMlNAXdB53rq6f8LXY6RY7JdSR/3BD6wLUlPHSAesmY9vstNrjvqGaCiRK/91Q==

is-core-module@^2.10.0, is-core-module@^2.8.1, is-core-module@^2.9.0:
version "2.10.0"
Expand Down Expand Up @@ -2927,9 +2933,9 @@ svelte-preprocess@^4.0.0, svelte-preprocess@^4.10.7:
strip-indent "^3.0.0"

svelte2tsx@^0.5.13, svelte2tsx@~0.5.10:
version "0.5.17"
resolved "https://registry.yarnpkg.com/svelte2tsx/-/svelte2tsx-0.5.17.tgz#0ad2036f212742f681d9c48a7c12a7617c2d099b"
integrity sha512-4NAWuDhNu8AfBqivnbc9YZlWiHjLqoIPX6Fz2TwzzXM8a2qs3t6brAYa+C+vc2Gm5hNltDNJMmF0sC9D01PoCA==
version "0.5.18"
resolved "https://registry.yarnpkg.com/svelte2tsx/-/svelte2tsx-0.5.18.tgz#8ff3306c04f2dfd73a97ca6dc8cbb1dc3ece0630"
integrity sha512-yhfEv1xvTYJZR/6Abygw09IH7uhAprKbar6Vk/YsfJyNcz4PQc/EHlG0LJbsm+FW8Us6ihZ9KJC4u+FnNW99lg==
dependencies:
dedent-js "^1.0.1"
pascal-case "^3.1.1"
Expand Down Expand Up @@ -3123,7 +3129,7 @@ undici@^5.8.1:
resolved "https://registry.yarnpkg.com/undici/-/undici-5.10.0.tgz#dd9391087a90ccfbd007568db458674232ebf014"
integrity sha512-c8HsD3IbwmjjbLvoZuRI26TZic+TSEe8FPMLLOkN1AfYRhdjnKBU6yL+IwcSCbdZiX4e5t0lfMDLDCqj4Sq70g==

update-browserslist-db@^1.0.5:
update-browserslist-db@^1.0.9:
version "1.0.9"
resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.9.tgz#2924d3927367a38d5c555413a7ce138fc95fcb18"
integrity sha512-/xsqn21EGVdXI3EXSum1Yckj3ZVZugqyOZQ/CxYPBD/R+ko9NSUScf8tFF4dOKY+2pvSSJA/S+5B8s4Zr4kyvg==
Expand Down Expand Up @@ -3154,9 +3160,9 @@ vite-tsconfig-paths@^3.5.0:
tsconfig-paths "^4.0.0"

"vite@^2.9.12 || ^3.0.0-0", vite@^3.0.6:
version "3.1.0"
resolved "https://registry.yarnpkg.com/vite/-/vite-3.1.0.tgz#3138b279072941d57e76bcf7f66f272fc6a17fe2"
integrity sha512-YBg3dUicDpDWFCGttmvMbVyS9ydjntwEjwXRj2KBFwSB8SxmGcudo1yb8FW5+M/G86aS8x828ujnzUVdsLjs9g==
version "3.1.2"
resolved "https://registry.yarnpkg.com/vite/-/vite-3.1.2.tgz#6b080f928490b1a46465ed3cbb4815f31f1a5376"
integrity sha512-wTDKPkiVbeT+drTPdkuvjVIC/2vKKUc1w3qNOuwgpyvPCZF6fvdxB5v5WEcCsqaYea0zrwA4+XialJKCHM3oVQ==
dependencies:
esbuild "^0.15.6"
postcss "^8.4.16"
Expand Down

0 comments on commit 548eb50

Please sign in to comment.