Skip to content

Commit

Permalink
feat(web): url-saver
Browse files Browse the repository at this point in the history
  • Loading branch information
astahmer committed Aug 26, 2023
1 parent ed630fc commit a098a71
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 2 deletions.
1 change: 1 addition & 0 deletions packages/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"@pandacss/shared": "^0.7.0",
"@xstate/react": "^3.2.2",
"esbuild-wasm": "^0.18.14",
"lz-string": "^1.5.0",
"monaco-editor": "0.40.0",
"pastable": "^2.2.0",
"react": "^18.2.0",
Expand Down
11 changes: 9 additions & 2 deletions packages/web/src/Playground/Playground.machine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { initialInputList, initialOutputList } from "../../../../demo-code-sampl
import { createMergeCss } from "@pandacss/shared";

import { createPandaContext, createTailwindContext, rewriteTwFileContentToPanda, type TwResultItem } from "tw2panda";
import { UrlSaver } from "./url-saver";

type PlaygroundContext = {
monaco: Monaco | null;
Expand All @@ -33,13 +34,16 @@ type PlaygroundEvent =
| { type: "Select output tab"; name: string }
| { type: "Update input"; value: string };

const urlSaver = new UrlSaver();
const initialAppInput = urlSaver.getValue("input") || initialInputList["tw-App.tsx"];

const initialContext: PlaygroundContext = {
monaco: null,
inputEditor: null,
outputEditor: null,
sourceFile: null,
resultList: [],
inputList: initialInputList,
inputList: { ...initialInputList, "tw-App.tsx": initialAppInput },
selectedInput: "tw-App.tsx",
outputList: initialOutputList,
selectedOutput: "App.tsx",
Expand Down Expand Up @@ -115,10 +119,13 @@ export const playgroundMachine = createMachine(
}
return { ...ctx, inputList };
}),
updateUrl(context) {
urlSaver.setValue("input", context.inputList[context.selectedInput] ?? "");
},
updateInput: choose([
{
cond: "isAppFile",
actions: ["updateSelectedInput", "extractClassList"],
actions: ["updateSelectedInput", "updateUrl", "extractClassList"],
},
{ actions: ["updateSelectedInput"] },
]),
Expand Down
1 change: 1 addition & 0 deletions packages/web/src/Playground/Playground.machine.typegen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export interface Typegen0 {
selectOutputTab: "Select output tab";
updateInput: "Editor Loaded" | "Select input tab" | "Update input";
updateSelectedInput: "Editor Loaded" | "Select input tab" | "Update input";
updateUrl: "Editor Loaded" | "Select input tab" | "Update input";
};
eventsCausingDelays: {};
eventsCausingGuards: {
Expand Down
67 changes: 67 additions & 0 deletions packages/web/src/Playground/url-saver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import { compressToEncodedURIComponent, decompressFromEncodedURIComponent } from 'lz-string'

// adapted from https://github.dev/dsherret/ts-ast-viewer/blob/c71e238123d972bae889b3829e23b44f39d8d5c2/site/src/utils/UrlSaver.ts#L1-L29
function getDecompressedStringFromUrl(name: string) {
if (typeof window === 'undefined') return

const search = new URLSearchParams(window.location.search)
const code = (search.get(name) ?? '').trim()
return decompressFromEncodedURIComponent(code) ?? '' // will be null on error
}

function updateUrlWithCompressedString(name: string, value: string) {
if (value.length === 0) {
updateUrlWithParam(name, '')
} else {
const compressed = compressToEncodedURIComponent(value)
const url = new URL(window.location.href)
url.searchParams.set(name, compressed)

// completely arbitrary limit of characters, but it appears to not work anymore around that
if (url.toString().length >= 14_500) {
throw new Error('The compressed string is too large to be stored in the URL.')
} else {
updateUrlWithParam(name, compressed)
}
}
}

function updateUrlWithParam(name: string, value: string | number) {
if (typeof window === 'undefined') return

const url = new URL(window.location.href)
url.searchParams.set(name, String(value))
window.history.replaceState(undefined, '', url)
}

const resetUrl = () => {
if (typeof window === 'undefined') return

window.history.replaceState(undefined, '', window.location.origin + window.location.pathname)
}

const deletingParamInUrl = (name: string) => {
if (typeof window === 'undefined') return

const url = new URL(window.location.href)
url.searchParams.delete(name)
window.history.replaceState(undefined, '', url)
}

export class UrlSaver {
getValue(name: string) {
return getDecompressedStringFromUrl(name)
}

setValue(name: string, value: string) {
updateUrlWithCompressedString(name, value)
}

reset(name: string) {
deletingParamInUrl(name)
}

resetAll() {
resetUrl()
}
}
8 changes: 8 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit a098a71

Please sign in to comment.