Merge pull request #749 from Recursing/playground-state-in-url
Store playground state in url, for easy sharing
This commit is contained in:
commit
fabb916cff
|
@ -1,4 +1,4 @@
|
||||||
import React, { FC, Fragment, useState } from "react";
|
import React, { FC, Fragment, useState, useEffect } from "react";
|
||||||
import ReactDOM from "react-dom";
|
import ReactDOM from "react-dom";
|
||||||
import { Path, useForm, UseFormRegister, useWatch } from "react-hook-form";
|
import { Path, useForm, UseFormRegister, useWatch } from "react-hook-form";
|
||||||
import * as yup from "yup";
|
import * as yup from "yup";
|
||||||
|
@ -35,6 +35,7 @@ interface PlaygroundProps {
|
||||||
/** If code is set, component becomes controlled */
|
/** If code is set, component becomes controlled */
|
||||||
code?: string;
|
code?: string;
|
||||||
onCodeChange?(expr: string): void;
|
onCodeChange?(expr: string): void;
|
||||||
|
onSettingsChange?(settings: any): void;
|
||||||
/** Should we show the editor? */
|
/** Should we show the editor? */
|
||||||
showEditor?: boolean;
|
showEditor?: boolean;
|
||||||
}
|
}
|
||||||
|
@ -205,6 +206,7 @@ export const SquigglePlayground: FC<PlaygroundProps> = ({
|
||||||
showSummary = false,
|
showSummary = false,
|
||||||
code: controlledCode,
|
code: controlledCode,
|
||||||
onCodeChange,
|
onCodeChange,
|
||||||
|
onSettingsChange,
|
||||||
showEditor = true,
|
showEditor = true,
|
||||||
}) => {
|
}) => {
|
||||||
const [uncontrolledCode, setUncontrolledCode] = useState(
|
const [uncontrolledCode, setUncontrolledCode] = useState(
|
||||||
|
@ -233,6 +235,11 @@ export const SquigglePlayground: FC<PlaygroundProps> = ({
|
||||||
const vars = useWatch({
|
const vars = useWatch({
|
||||||
control,
|
control,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
onSettingsChange?.(vars);
|
||||||
|
}, [vars, onSettingsChange]);
|
||||||
|
|
||||||
const chartSettings = {
|
const chartSettings = {
|
||||||
start: Number(vars.diagramStart),
|
start: Number(vars.diagramStart),
|
||||||
stop: Number(vars.diagramStop),
|
stop: Number(vars.diagramStop),
|
||||||
|
|
|
@ -6,11 +6,13 @@ This website is built using [Docusaurus 2](https://docusaurus.io/), a modern sta
|
||||||
|
|
||||||
We assume you ran `yarn` at monorepo level.
|
We assume you ran `yarn` at monorepo level.
|
||||||
|
|
||||||
The website depends on `squiggle-lang`, which you have to build manually.
|
The website depends on `squiggle-lang` and `components`, which you have to build manually.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cd ../squiggle-lang
|
cd ../squiggle-lang
|
||||||
yarn build
|
yarn build
|
||||||
|
cd ../components
|
||||||
|
yarn build
|
||||||
```
|
```
|
||||||
|
|
||||||
Generate static content, to the `build` directory.
|
Generate static content, to the `build` directory.
|
||||||
|
|
|
@ -15,8 +15,10 @@
|
||||||
"@docusaurus/core": "2.0.0-beta.21",
|
"@docusaurus/core": "2.0.0-beta.21",
|
||||||
"@docusaurus/preset-classic": "2.0.0-beta.21",
|
"@docusaurus/preset-classic": "2.0.0-beta.21",
|
||||||
"@quri/squiggle-components": "^0.2.20",
|
"@quri/squiggle-components": "^0.2.20",
|
||||||
|
"base64-js": "^1.5.1",
|
||||||
"clsx": "^1.1.1",
|
"clsx": "^1.1.1",
|
||||||
"hast-util-is-element": "2.1.2",
|
"hast-util-is-element": "2.1.2",
|
||||||
|
"pako": "^2.0.4",
|
||||||
"prism-react-renderer": "^1.3.3",
|
"prism-react-renderer": "^1.3.3",
|
||||||
"react": "^18.1.0",
|
"react": "^18.1.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
|
|
|
@ -1,8 +1,52 @@
|
||||||
|
import { deflate, inflate } from "pako";
|
||||||
|
import { toByteArray, fromByteArray } from "base64-js";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import Layout from "@theme/Layout";
|
import Layout from "@theme/Layout";
|
||||||
import { SquigglePlayground } from "../components/SquigglePlayground";
|
import { SquigglePlayground } from "../components/SquigglePlayground";
|
||||||
|
|
||||||
|
const HASH_PREFIX = "#code=";
|
||||||
|
function getHashData() {
|
||||||
|
if (typeof window === "undefined") {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const hash = window.location.hash;
|
||||||
|
if (!hash.startsWith(HASH_PREFIX)) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const compressed = toByteArray(
|
||||||
|
decodeURIComponent(hash.slice(HASH_PREFIX.length))
|
||||||
|
);
|
||||||
|
const text = inflate(compressed, { to: "string" });
|
||||||
|
return JSON.parse(text);
|
||||||
|
} catch (err) {
|
||||||
|
console.error(err);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setHashData(data) {
|
||||||
|
const text = JSON.stringify({ ...getHashData(), ...data });
|
||||||
|
const compressed = deflate(text, { level: 9 });
|
||||||
|
window.history.replaceState(
|
||||||
|
undefined,
|
||||||
|
"",
|
||||||
|
HASH_PREFIX + encodeURIComponent(fromByteArray(compressed))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export default function PlaygroundPage() {
|
export default function PlaygroundPage() {
|
||||||
|
const playgroundProps = {
|
||||||
|
initialSquiggleString: "normal(0,1)",
|
||||||
|
height: 700,
|
||||||
|
showTypes: true,
|
||||||
|
...getHashData(),
|
||||||
|
onCodeChange: (code) => setHashData({ initialSquiggleString: code }),
|
||||||
|
onSettingsChange: (settings) => {
|
||||||
|
const { showTypes, showControls, showSummary, showEditor } = settings;
|
||||||
|
setHashData({ showTypes, showControls, showSummary, showEditor });
|
||||||
|
},
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<Layout title="Playground" description="Squiggle Playground">
|
<Layout title="Playground" description="Squiggle Playground">
|
||||||
<div
|
<div
|
||||||
|
@ -10,11 +54,7 @@ export default function PlaygroundPage() {
|
||||||
maxWidth: 2000,
|
maxWidth: 2000,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<SquigglePlayground
|
<SquigglePlayground {...playgroundProps} />
|
||||||
initialSquiggleString="normal(0,1)"
|
|
||||||
height={700}
|
|
||||||
showTypes={true}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</Layout>
|
</Layout>
|
||||||
);
|
);
|
||||||
|
|
11
yarn.lock
11
yarn.lock
|
@ -4344,7 +4344,7 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/react" "*"
|
"@types/react" "*"
|
||||||
|
|
||||||
"@types/react@*", "@types/react@^18.0.1", "@types/react@^18.0.9":
|
"@types/react@*", "@types/react@^18.0.9":
|
||||||
version "18.0.14"
|
version "18.0.14"
|
||||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.14.tgz#e016616ffff51dba01b04945610fe3671fdbe06d"
|
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.14.tgz#e016616ffff51dba01b04945610fe3671fdbe06d"
|
||||||
integrity sha512-x4gGuASSiWmo0xjDLpm5mPb52syZHJx02VKbqUKdLmKtAwIh63XClGsiTI1K6DO5q7ox4xAsQrU+Gl3+gGXF9Q==
|
integrity sha512-x4gGuASSiWmo0xjDLpm5mPb52syZHJx02VKbqUKdLmKtAwIh63XClGsiTI1K6DO5q7ox4xAsQrU+Gl3+gGXF9Q==
|
||||||
|
@ -5853,7 +5853,7 @@ base16@^1.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/base16/-/base16-1.0.0.tgz#e297f60d7ec1014a7a971a39ebc8a98c0b681e70"
|
resolved "https://registry.yarnpkg.com/base16/-/base16-1.0.0.tgz#e297f60d7ec1014a7a971a39ebc8a98c0b681e70"
|
||||||
integrity sha512-pNdYkNPiJUnEhnfXV56+sQy8+AaPcG3POZAUnwr4EeqCUZFz4u2PePbo3e5Gj4ziYPCWGUZT9RHisvJKnwFuBQ==
|
integrity sha512-pNdYkNPiJUnEhnfXV56+sQy8+AaPcG3POZAUnwr4EeqCUZFz4u2PePbo3e5Gj4ziYPCWGUZT9RHisvJKnwFuBQ==
|
||||||
|
|
||||||
base64-js@^1.0.2:
|
base64-js@^1.0.2, base64-js@^1.5.1:
|
||||||
version "1.5.1"
|
version "1.5.1"
|
||||||
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
|
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
|
||||||
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
|
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
|
||||||
|
@ -13082,6 +13082,11 @@ package-json@^6.3.0:
|
||||||
registry-url "^5.0.0"
|
registry-url "^5.0.0"
|
||||||
semver "^6.2.0"
|
semver "^6.2.0"
|
||||||
|
|
||||||
|
pako@^2.0.4:
|
||||||
|
version "2.0.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/pako/-/pako-2.0.4.tgz#6cebc4bbb0b6c73b0d5b8d7e8476e2b2fbea576d"
|
||||||
|
integrity sha512-v8tweI900AUkZN6heMU/4Uy4cXRc2AYNRggVmTR+dEncawDJgCdLMximOVA2p4qO57WMynangsfGRb5WD6L1Bg==
|
||||||
|
|
||||||
pako@~1.0.5:
|
pako@~1.0.5:
|
||||||
version "1.0.11"
|
version "1.0.11"
|
||||||
resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf"
|
resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf"
|
||||||
|
@ -14791,7 +14796,7 @@ react-vega@^7.5.1:
|
||||||
prop-types "^15.8.1"
|
prop-types "^15.8.1"
|
||||||
vega-embed "^6.5.1"
|
vega-embed "^6.5.1"
|
||||||
|
|
||||||
react@^18.0.0, react@^18.1.0:
|
react@^18.1.0:
|
||||||
version "18.2.0"
|
version "18.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
|
resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
|
||||||
integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
|
integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
|
||||||
|
|
Loading…
Reference in New Issue
Block a user