diff --git a/package.json b/package.json index 300ffb4d..46a56d76 100644 --- a/package.json +++ b/package.json @@ -14,13 +14,14 @@ "./packages/*" ], "devDependencies": { - "@changesets/cli": "2.26.2", - "prettier": "^3.0.3", - "prettier-plugin-tailwindcss": "^0.5.4" + "@changesets/cli": "2.27.11", + "prettier": "^3.4.2", + "prettier-plugin-tailwindcss": "^0.6.10" }, "pnpm": { "patchedDependencies": { - "monaco-editor@0.43.0": "patches/monaco-editor@0.43.0.patch" + "monaco-editor": "patches/monaco-editor.patch" } - } + }, + "packageManager": "pnpm@9.15.4" } diff --git a/packages/playground/package.json b/packages/playground/package.json index 2c15a64b..698c667d 100644 --- a/packages/playground/package.json +++ b/packages/playground/package.json @@ -4,36 +4,39 @@ "scripts": { "build": "vite build", "start": "vite preview", - "dev": "vite" + "dev": "vite", + "tsc": "tsc" }, + "type": "module", "dependencies": { - "@solid-primitives/scheduled": "^1.4.1", - "@solidjs/router": "^0.8.3", - "dedent": "^1.5.1", + "@solid-primitives/scheduled": "^1.5.0", + "@solidjs/router": "^0.15.3", + "@unocss/preset-wind3": "66.1.0-beta.3", + "dedent": "^1.5.3", "onigasm": "^2.2.5", - "solid-dismiss": "^1.7.121", + "solid-dismiss": "^1.8.2", "solid-heroicons": "^3.2.4", - "solid-js": "1.7.11", + "solid-js": "1.9.5", "solid-repl": "workspace:*" }, "devDependencies": { "@amoutonbrady/lz-string": "^0.1.0", - "@babel/core": "^7.22.19", - "@babel/plugin-syntax-jsx": "^7.22.5", - "@babel/preset-typescript": "^7.22.15", - "@babel/types": "^7.22.19", - "@solidjs/router": "^0.8.3", - "@types/babel__standalone": "^7.1.5", - "@types/dedent": "^0.7.0", - "@unocss/preset-wind": "^0.55.7", + "@babel/core": "^7.26.9", + "@babel/plugin-syntax-jsx": "^7.25.9", + "@babel/preset-typescript": "^7.26.0", + "@babel/types": "^7.26.9", + "@solidjs/router": "^0.15.3", + "@types/babel__standalone": "^7.1.9", + "@types/dedent": "^0.7.2", "assert": "^2.1.0", - "csstype": "^3.1.2", + "csstype": "^3.1.3", "jszip": "^3.10.1", - "monaco-editor": "^0.43.0", + "monaco-editor": "^0.52.2", "register-service-worker": "^1.7.2", - "typescript": "^5.2.2", - "unocss": "^0.55.7", - "vite": "^4.4.9", - "vite-plugin-solid": "^2.7.0" + "solid-devtools": "^0.33.0", + "typescript": "^5.8.2", + "unocss": "^66.0.0", + "vite": "^6.2.0", + "vite-plugin-solid": "^2.11.6" } } diff --git a/packages/playground/public/sw.js b/packages/playground/public/sw.js index 9d3a4283..f54881cf 100644 --- a/packages/playground/public/sw.js +++ b/packages/playground/public/sw.js @@ -1,19 +1,22 @@ const cacheName = 'my-cache'; -async function fetchAndCacheIfOk(event, stale) { +async function revalidate(event) { + const client = await clients.get(event.clientId); + client.postMessage({ type: 'cache' }); +} + +async function fetchAndCacheIfOk(cache, event) { try { const response = await fetch(event.request); if (response.ok) { - const responseClone = response.clone(); - const cache = await caches.open(cacheName); - await cache.put(event.request, responseClone); - if (stale) self.postMessage({ type: 'cache' }); + await cache.put(event.request, response.clone()); } return response; } catch (e) { - const cache = await caches.open(cacheName); + console.error(e); + return await cache.match('/index.html'); } } @@ -21,9 +24,49 @@ async function fetchAndCacheIfOk(event, stale) { async function fetchWithCache(event) { const cache = await caches.open(cacheName); const response = await cache.match(event.request); - const result = fetchAndCacheIfOk(event, !!response); + const result = fetchAndCacheIfOk(cache, event); if (!!response) { - return response; + result.then(async (response2) => { + const reader1 = response.body.getReader(); + const reader2 = response2.body.getReader(); + + let i = 0; + let j = 0; + + let oldChunk1 = null; + let oldChunk2 = null; + if (!oldChunk1) { + oldChunk1 = await reader1.read(); + } + if (!oldChunk2) { + oldChunk2 = await reader2.read(); + } + while (!oldChunk1.done && !oldChunk2.done) { + if (oldChunk1.value[i] !== oldChunk2.value[j]) { + revalidate(event); + return; + } + i++; + j++; + if (i === oldChunk1.value.length) { + oldChunk1 = await reader1.read(); + i = 0; + } + if (j === oldChunk2.value.length) { + oldChunk2 = await reader2.read(); + j = 0; + } + } + + if (oldChunk1.done && oldChunk2.done) { + return; + } else { + revalidate(event); + return; + } + }); + + return response.clone(); } else { return result; } diff --git a/packages/playground/src/app.tsx b/packages/playground/src/app.tsx index 3bc035f7..3d6ca5c5 100644 --- a/packages/playground/src/app.tsx +++ b/packages/playground/src/app.tsx @@ -1,5 +1,5 @@ import { Show, JSX } from 'solid-js'; -import { Routes, Route, useSearchParams } from '@solidjs/router'; +import { Route, Router } from '@solidjs/router'; import { eventBus, setEventBus } from './utils/serviceWorker'; import { Update } from './components/update'; import { useZoom } from 'solid-repl/src/hooks/useZoom'; @@ -28,20 +28,14 @@ export const App = (): JSX.Element => { } }); - const [searchParams] = useSearchParams(); - return ( -
- - } - /> - } /> - } /> - } /> - - +
+ + + + + + setEventBus(false)} />} />
); diff --git a/packages/playground/src/components/header.tsx b/packages/playground/src/components/header.tsx index 115012f0..c5806015 100644 --- a/packages/playground/src/components/header.tsx +++ b/packages/playground/src/components/header.tsx @@ -2,14 +2,61 @@ import Dismiss from 'solid-dismiss'; import { A } from '@solidjs/router'; import { Icon } from 'solid-heroicons'; import { unwrap } from 'solid-js/store'; -import { onCleanup, createSignal, Show, ParentComponent } from 'solid-js'; -import { share, link, arrowDownTray, xCircle, bars_3, moon, sun } from 'solid-heroicons/outline'; +import { onCleanup, createSignal, Show, ParentComponent, JSX } from 'solid-js'; +import { share, link, arrowDownTray, bars_3, moon, sun } from 'solid-heroicons/outline'; import { exportToZip } from '../utils/exportFiles'; import { ZoomDropdown } from './zoomDropdown'; import { API, useAppContext } from '../context'; import logo from '../assets/logo.svg?url'; +export const HeaderButton = (props: { + ref?: HTMLButtonElement; + onClick?: () => void; + title: string; + classList?: Record; + children: JSX.Element; +}) => { + return ( + + ); +}; + +export const HeaderIcon = (props: { + ref?: HTMLButtonElement; + menu: boolean; + onClick?: () => void; + title: string; + classList?: Record; + + path: { path: JSX.Element; outline: boolean; mini: boolean }; + text: string; +}) => { + return ( + + + {props.text} + + ); +}; export const Header: ParentComponent<{ compiler?: Worker; fork?: () => void; @@ -41,120 +88,75 @@ export const Header: ParentComponent<{ } return ( -
+
- solid-js logo + solid-js logo {props.children || ( -

+

SolidJS Playground

)} - menuBtnEl} - open={showMenu} - setOpen={setShowMenu} - show - > +
- - - + /> - + - - - - ), - outline: false, - mini: false, + - Github - - - -
+ +
+
@@ -162,17 +164,17 @@ export const Header: ParentComponent<{ } > - - profileBtn} open={showProfile} setOpen={setShowProfile}> -
- + +
+ {context.user()?.display} diff --git a/packages/playground/src/components/zoomDropdown.tsx b/packages/playground/src/components/zoomDropdown.tsx index 2c2a122e..468d5a3a 100644 --- a/packages/playground/src/components/zoomDropdown.tsx +++ b/packages/playground/src/components/zoomDropdown.tsx @@ -1,8 +1,8 @@ -import { Icon } from 'solid-heroicons'; import { magnifyingGlassPlus } from 'solid-heroicons/outline'; import Dismiss from 'solid-dismiss'; import { Component, createSignal, createEffect } from 'solid-js'; import { useZoom } from 'solid-repl/src/hooks/useZoom'; +import { HeaderIcon } from './header'; export const ZoomDropdown: Component<{ showMenu: boolean }> = (props) => { const [open, setOpen] = createSignal(false); @@ -85,22 +85,16 @@ export const ZoomDropdown: Component<{ showMenu: boolean }> = (props) => { ref={containerEl} tabindex="-1" > - + path={magnifyingGlassPlus} + text="Scale Editor" + title="Scale editor to make text larger or smaller" + />
= (props) => { >
-
+
{zoomState.zoom}%
-
- - -
+ + +
diff --git a/packages/playground/src/index.tsx b/packages/playground/src/index.tsx index 7f728220..4ace6978 100644 --- a/packages/playground/src/index.tsx +++ b/packages/playground/src/index.tsx @@ -1,18 +1,16 @@ -import { Router } from '@solidjs/router'; import { render } from 'solid-js/web'; import { App } from './app'; import { AppContextProvider } from './context'; import { registerServiceWorker } from './utils/serviceWorker'; +import 'solid-devtools' import 'virtual:uno.css'; import 'solid-repl/repl/main.css'; render( () => ( - - - - - + + + ), document.querySelector('#app')!, ); diff --git a/packages/playground/src/pages/edit.tsx b/packages/playground/src/pages/edit.tsx index 8b86d8eb..f931bcff 100644 --- a/packages/playground/src/pages/edit.tsx +++ b/packages/playground/src/pages/edit.tsx @@ -7,13 +7,15 @@ import FormatterWorker from 'solid-repl/repl/formatter?worker'; import LinterWorker from 'solid-repl/repl/linter?worker'; import onigasm from 'onigasm/lib/onigasm.wasm?url'; import { batch, createResource, createSignal, lazy, onCleanup, Show, Suspense } from 'solid-js'; -import { useMatch, useNavigate, useParams } from '@solidjs/router'; +import { useMatch, useNavigate, useParams, useSearchParams } from '@solidjs/router'; import { API, useAppContext } from '../context'; import { debounce } from '@solid-primitives/scheduled'; import { defaultTabs } from 'solid-repl/src'; import type { Tab } from 'solid-repl'; import type { APIRepl } from './home'; -import { Header } from '../components/header'; +import { Header, HeaderButton } from '../components/header'; +import { Icon } from 'solid-heroicons'; +import { folder, inboxStack } from 'solid-heroicons/outline'; const Repl = lazy(() => import('../components/setupSolid')); @@ -38,7 +40,9 @@ interface InternalTab extends Tab { _source: string; _name: string; } -export const Edit = (props: { horizontal: boolean }) => { +export const Edit = () => { + const [searchParams] = useSearchParams(); + const scratchpad = useMatch(() => '/scratchpad'); const compiler = new CompilerWorker(); const formatter = new FormatterWorker(); @@ -145,7 +149,9 @@ export const Edit = (props: { horizontal: boolean }) => { const repl = resource.latest; if (!repl) return; - if ((context.token && context.user()?.display == params.user) || localStorage.getItem(params.repl)) { + const loggedIn = context.token && params.user && context.user()?.display == params.user; + + if (loggedIn || localStorage.getItem(params.repl)) { fetch(`${API}/repl/${params.repl}`, { method: 'PUT', headers: { @@ -166,8 +172,10 @@ export const Edit = (props: { horizontal: boolean }) => { !!scratchpad() ? 10 : 1000, ); + let toggleVisible: () => void; + return ( - <> +
{}} @@ -231,39 +239,73 @@ export const Edit = (props: { horizontal: boolean }) => { /> )}
- + + + + + + } + > + + (toggleVisible = tv)} + id="repl" + /> + + +
+
); }; diff --git a/packages/playground/src/pages/home.tsx b/packages/playground/src/pages/home.tsx index fcbd4bdd..82288f2d 100644 --- a/packages/playground/src/pages/home.tsx +++ b/packages/playground/src/pages/home.tsx @@ -97,7 +97,7 @@ export const Home = () => { {`${params.user}'s`} Repls}>
{ if (e.target !== e.currentTarget) return; setOpen(undefined); @@ -229,13 +229,13 @@ export const Home = () => { role="presentation" >