diff --git a/.changeset/chilly-rabbits-lie.md b/.changeset/chilly-rabbits-lie.md deleted file mode 100644 index 38d5e62ba..000000000 --- a/.changeset/chilly-rabbits-lie.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@solidjs/start": minor ---- - -add new dev toolbar diff --git a/apps/tests/src/routes/server-function-file.tsx b/apps/tests/src/routes/server-function-file.tsx deleted file mode 100644 index da0a369f0..000000000 --- a/apps/tests/src/routes/server-function-file.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { createEffect, createSignal } from "solid-js"; - -async function ping(file: File) { - "use server"; - return await file.text(); -} - -export default function App() { - const [output, setOutput] = createSignal<{ result?: boolean }>({}); - - createEffect(async () => { - const file = new File(['Hello, World!'], 'hello-world.txt'); - const result = await ping(file); - const value = await file.text(); - setOutput(prev => ({ ...prev, result: value === result })); - }); - - return ( -
- {JSON.stringify(output())} -
- ); -} diff --git a/apps/tests/src/routes/server-function-iterator.tsx b/apps/tests/src/routes/server-function-iterator.tsx deleted file mode 100644 index 9beb1a34d..000000000 --- a/apps/tests/src/routes/server-function-iterator.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import { createEffect, createSignal } from "solid-js"; - -async function ping(value: Date) { - "use server"; - - const current = [ - value, - { - name: 'example', - *[Symbol.iterator]() { - yield 'foo'; - yield 'bar'; - yield 'baz'; - } - } - ]; - - return current; -} - -export default function App() { - const [output, setOutput] = createSignal<{ result?: boolean }>({}); - - createEffect(async () => { - const value = new Date(); - const result = await ping(value); - setOutput((prev) => ({ ...prev, result: value.toString() === result[0].toString() })); - }); - - return ( -
- {JSON.stringify(output())} -
- ); -} diff --git a/apps/tests/src/routes/server-function-ping.tsx b/apps/tests/src/routes/server-function-ping.tsx index 677a35340..70f9d2617 100644 --- a/apps/tests/src/routes/server-function-ping.tsx +++ b/apps/tests/src/routes/server-function-ping.tsx @@ -1,38 +1,18 @@ import { createEffect, createSignal } from "solid-js"; -async function sleep(value: unknown, ms: number) { - return new Promise((res) => { - setTimeout(res, ms, value); - }) -} - -async function ping(value: Date) { +async function ping(value: string) { "use server"; - const current = [ - value, - { - name: 'example', - async *[Symbol.asyncIterator]() { - yield sleep('foo', 5000); - yield sleep('bar', 5000); - yield sleep('baz', 5000); - } - } - ]; - - return current; + return await Promise.resolve(value); } export default function App() { const [output, setOutput] = createSignal<{ result?: boolean }>({}); createEffect(async () => { - const value = new Date(); + const value = `${Math.random() * 1000}`; const result = await ping(value); - await ping(value); - console.log(result); - setOutput((prev) => ({ ...prev, result: value.toString() === result[0].toString() })); + setOutput(prev => ({ ...prev, result: value === result })); }); return ( diff --git a/apps/tests/src/routes/server-function-plugin.tsx b/apps/tests/src/routes/server-function-plugin.tsx deleted file mode 100644 index e9b8d4b2b..000000000 --- a/apps/tests/src/routes/server-function-plugin.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { createEffect, createSignal } from "solid-js"; - -async function sleep(value: unknown, ms: number) { - return new Promise((res) => { - setTimeout(res, ms, value); - }) -} - -async function ping(value: URLSearchParams, clone: URLSearchParams) { - "use server"; - - const current = [ - value.toString() === clone.toString(), - value, - clone, - ] as const; - - return current; -} - -export default function App() { - const [output, setOutput] = createSignal<{ result?: boolean }>({}); - - createEffect(async () => { - const value = new URLSearchParams([ - ['foo', 'bar'], - ['hello', 'world'], - ]); - const result = await ping(value, value); - setOutput((prev) => ({ ...prev, result: result[0] })); - }); - - return ( -
- {JSON.stringify(output())} -
- ); -} diff --git a/apps/tests/src/routes/server-function-readable-stream.tsx b/apps/tests/src/routes/server-function-readable-stream.tsx deleted file mode 100644 index 53d39dcf0..000000000 --- a/apps/tests/src/routes/server-function-readable-stream.tsx +++ /dev/null @@ -1,39 +0,0 @@ -import { createEffect, createSignal } from "solid-js"; - -async function sleep(value: T, ms: number) { - return new Promise((res) => { - setTimeout(res, ms, value); - }) -} - -async function ping(value: ReadableStream) { - "use server"; - return value; -} - -export default function App() { - const [output, setOutput] = createSignal<{ result?: boolean }>({}); - - createEffect(async () => { - const result = await ping( - new ReadableStream({ - async start(controller) { - controller.enqueue(await sleep('foo', 100)); - controller.enqueue(await sleep('bar', 100)); - controller.enqueue(await sleep('baz', 100)); - controller.close(); - }, - }) - ); - - const reader = result.getReader(); - const first = await reader.read(); - setOutput((prev) => ({ ...prev, result: first.value === 'foo' })); - }); - - return ( -
- {JSON.stringify(output())} -
- ); -} diff --git a/apps/tests/src/routes/treeshaking/(no-side-effects).tsx b/apps/tests/src/routes/treeshaking/(no-side-effects).tsx index be86a00a0..40cff9649 100644 --- a/apps/tests/src/routes/treeshaking/(no-side-effects).tsx +++ b/apps/tests/src/routes/treeshaking/(no-side-effects).tsx @@ -1,5 +1,4 @@ import { createAsync } from "@solidjs/router"; -import { createEffect } from "solid-js"; const a = "myTreeshakingTestUniqueString1"; diff --git a/packages/start/package.json b/packages/start/package.json index 2dfb74a44..715706853 100644 --- a/packages/start/package.json +++ b/packages/start/package.json @@ -76,7 +76,7 @@ "solid-js": "^1.9.11", "source-map-js": "^1.2.1", "srvx": "^0.12.0", - "terracotta": "^1.1.1", + "terracotta": "^1.1.0", "vite-plugin-solid": "^2.11.11" }, "engines": { diff --git a/packages/start/src/fns/client.ts b/packages/start/src/fns/client.ts index 690bc811d..c50fb21f9 100644 --- a/packages/start/src/fns/client.ts +++ b/packages/start/src/fns/client.ts @@ -1,15 +1,19 @@ import { type Component } from "solid-js"; -import { pushRequest, pushResponse } from "../shared/dev-toolbar/functions/tracker.ts"; import { // serializeToJSONStream, serializeToJSONString, } from "./serialization.ts"; -import { BODY_FORMAT_KEY, BodyFormat, extractBody, getHeadersAndBody } from "./shared.ts"; +import { + BODY_FORMAT_KEY, + BodyFormat, + extractBody, + getHeadersAndBody, +} from "./shared.ts"; let INSTANCE = 0; -async function createRequest(base: string, id: string, instance: string, options: RequestInit) { - const request = new Request(base, { +function createRequest(base: string, id: string, instance: string, options: RequestInit) { + return fetch(base, { method: "POST", ...options, headers: { @@ -18,15 +22,6 @@ async function createRequest(base: string, id: string, instance: string, options "X-Server-Instance": instance, }, }); - if (import.meta.env.DEV) { - console.log(pushRequest); - pushRequest(id, instance, request.clone()); - } - const response = await fetch(request); - if (import.meta.env.DEV) { - pushResponse(id, instance, response.clone()); - } - return response; } async function initializeResponse( diff --git a/packages/start/src/fns/handler.ts b/packages/start/src/fns/handler.ts index 2badc918f..302bb7349 100644 --- a/packages/start/src/fns/handler.ts +++ b/packages/start/src/fns/handler.ts @@ -124,6 +124,7 @@ export async function handleServerFunction(h3Event: H3Event) { h3Event.res.headers.set("content-type", "text/javascript"); return serializeToJSStream(instance, result); } + h3Event.res.headers.set("content-type", "text/plain"); return serializeToJSONStream(result); } catch (x) { if (x instanceof Response) { @@ -133,18 +134,14 @@ export async function handleServerFunction(h3Event: H3Event) { // forward headers if ((x as any).headers) mergeResponseHeaders(h3Event, (x as any).headers); // forward non-redirect statuses - if ( - (x as any).status && - (!instance || (x as any).status < 300 || (x as any).status >= 400) - ) + if ((x as any).status && (!instance || (x as any).status < 300 || (x as any).status >= 400)) h3Event.res.status = (x as any).status; if ((x as any).customBody) { x = await (x as any).customBody(); } else if ((x as any).body == null) x = null; h3Event.res.headers.set("X-Error", "true"); } else if (instance) { - const error = - x instanceof Error ? x.message : typeof x === "string" ? x : "true"; + const error = x instanceof Error ? x.message : typeof x === "string" ? x : "true"; h3Event.res.headers.set("X-Error", toHeaderValue(error)); } else { @@ -167,6 +164,7 @@ export async function handleServerFunction(h3Event: H3Event) { h3Event.res.headers.set("content-type", "text/javascript"); return serializeToJSStream(instance, x); } + h3Event.res.headers.set("content-type", "text/plain"); return serializeToJSONStream(x); } return x; @@ -194,10 +192,7 @@ function handleNoJS(result: any, request: Request, parsed: any[], thrown?: boole if (result.headers.has("Location")) { headers.set( `Location`, - new URL( - result.headers.get("Location")!, - url.origin + import.meta.env.BASE_URL, - ).toString(), + new URL(result.headers.get("Location")!, url.origin + import.meta.env.BASE_URL).toString(), ); statusCode = getExpectedRedirectStatus(result); } @@ -214,10 +209,7 @@ function handleNoJS(result: any, request: Request, parsed: any[], thrown?: boole result: isError ? result.message : result, thrown: thrown, error: isError, - input: [ - ...parsed.slice(0, -1), - [...parsed[parsed.length - 1].entries()], - ], + input: [...parsed.slice(0, -1), [...parsed[parsed.length - 1].entries()]], }), )}; Secure; HttpOnly;`, ); @@ -243,7 +235,7 @@ export function createSingleFlightHeaders(sourceEvent: FetchEvent) { // useH3Internals = true; // sourceEvent.nativeEvent.node.req.headers.cookie = ""; // } - SetCookies.forEach((cookie) => { + SetCookies.forEach(cookie => { if (!cookie) return; const { maxAge, expires, name, value } = parseSetCookie(cookie); if (maxAge != null && maxAge <= 0) { @@ -264,10 +256,7 @@ export function createSingleFlightHeaders(sourceEvent: FetchEvent) { return headers; } -async function handleSingleFlight( - sourceEvent: FetchEvent, - result: any, -): Promise { +async function handleSingleFlight(sourceEvent: FetchEvent, result: any): Promise { let revalidate: string[]; let url = new URL(sourceEvent.request.headers.get("referer")!).toString(); if (result instanceof Response) { diff --git a/packages/start/src/fns/serialization.ts b/packages/start/src/fns/serialization.ts index e09e1b004..b266eb027 100644 --- a/packages/start/src/fns/serialization.ts +++ b/packages/start/src/fns/serialization.ts @@ -109,7 +109,7 @@ export function serializeToJSONStream(value: any) { }); } -export class SerovalChunkReader { +class SerovalChunkReader { reader: ReadableStreamDefaultReader; buffer: Uint8Array; done: boolean; diff --git a/packages/start/src/shared/ErrorBoundary.tsx b/packages/start/src/shared/ErrorBoundary.tsx index 7aa8c0df8..6be12348e 100644 --- a/packages/start/src/shared/ErrorBoundary.tsx +++ b/packages/start/src/shared/ErrorBoundary.tsx @@ -1,12 +1,12 @@ // @refresh skip -import { catchError, ErrorBoundary as DefaultErrorBoundary, type ParentProps } from "solid-js"; +import { ErrorBoundary as DefaultErrorBoundary, catchError, type ParentProps } from "solid-js"; import { isServer } from "solid-js/web"; -import { DevToolbar } from "./dev-toolbar/index.tsx"; import { HttpStatusCode } from "./HttpStatusCode.ts"; +import { DevOverlay } from "./dev-overlay/index.tsx"; export const ErrorBoundary = import.meta.env.DEV && import.meta.env.START_DEV_OVERLAY - ? (props: ParentProps) => {props.children} + ? (props: ParentProps) => {props.children} : (props: ParentProps) => { const message = isServer ? "500 | Internal Server Error" diff --git a/packages/start/src/shared/dev-toolbar/error-viewer/CodeView.tsx b/packages/start/src/shared/dev-overlay/CodeView.tsx similarity index 93% rename from packages/start/src/shared/dev-toolbar/error-viewer/CodeView.tsx rename to packages/start/src/shared/dev-overlay/CodeView.tsx index 83673540e..45950197f 100644 --- a/packages/start/src/shared/dev-toolbar/error-viewer/CodeView.tsx +++ b/packages/start/src/shared/dev-overlay/CodeView.tsx @@ -72,7 +72,7 @@ export function CodeView(props: CodeViewProps): JSX.Element | null { for (let i = 0, len = lines.length; i < len; i++) { const el = lines[i] as HTMLElement; if (props.line - minLine() - 1 === i) { - el.dataset.startErrorViewerErrorLine = ''; + el.dataset.startDevOverlayErrorLine = ''; } } } @@ -81,9 +81,9 @@ export function CodeView(props: CodeViewProps): JSX.Element | null { return (
); diff --git a/packages/start/src/shared/dev-toolbar/error-viewer/index.tsx b/packages/start/src/shared/dev-overlay/DevOverlayDialog.tsx similarity index 57% rename from packages/start/src/shared/dev-toolbar/error-viewer/index.tsx rename to packages/start/src/shared/dev-overlay/DevOverlayDialog.tsx index d1d0bfea0..975e46507 100644 --- a/packages/start/src/shared/dev-toolbar/error-viewer/index.tsx +++ b/packages/start/src/shared/dev-overlay/DevOverlayDialog.tsx @@ -3,8 +3,13 @@ import ErrorStackParser from "error-stack-parser"; import * as htmlToImage from "html-to-image"; import type { JSX } from "solid-js"; import { createMemo, createSignal, ErrorBoundary, For, Show, Suspense } from "solid-js"; -import IconButton from "../../ui/IconButton.tsx"; -import { Select, SelectOption } from "../../ui/Select.tsx"; +import { Portal } from "solid-js/web"; +// @ts-ignore - terracotta module resolution issue with NodeNext +import { Dialog, DialogOverlay, DialogPanel, Select, SelectOption } from "terracotta"; +import info from "../../../package.json" with { type: "json" }; +import { CodeView } from "./CodeView.tsx"; +import { createStackFrame, type StackFrameSource } from "./createStackFrame.ts"; +import download from "./download.ts"; import { ArrowLeftIcon, ArrowRightIcon, @@ -12,12 +17,10 @@ import { DiscordIcon, GithubIcon, RefreshIcon, + SolidStartIcon, ViewCompiledIcon, ViewOriginalIcon, -} from "../icons.tsx"; -import { CodeView } from "./CodeView.tsx"; -import { createStackFrame, type StackFrameSource } from "./create-stack-frame.ts"; -import download from "./download.ts"; +} from "./icons.tsx"; import "./styles.css"; export function classNames(...classes: (string | boolean | undefined)[]): string { @@ -44,9 +47,9 @@ function ErrorInfo(props: ErrorInfoProps): JSX.Element { }); return ( - - {error().name} - {error().message} + + {error().name} + {error().message} ); } @@ -74,7 +77,7 @@ function getFilePath(source: StackFrameSource) { function CodeFallback(): JSX.Element { return ( -
+
Source not available.
); @@ -86,8 +89,8 @@ function StackFramesContent(props: StackFramesContentProps) { const [selectedFrame, setSelectedFrame] = createSignal(stackframes[0]!); return ( -
-
+
+
{(() => { const data = createStackFrame(selectedFrame(), () => props.isCompiled); @@ -96,8 +99,8 @@ function StackFramesContent(props: StackFramesContentProps) { }> {source => ( <> - {source.source} -
+ {source.source} +
- data-start-error-viewer-stack-frames + data-start-dev-overlay-stack-frames value={selectedFrame()} onChange={setSelectedFrame} > @@ -121,11 +124,11 @@ function StackFramesContent(props: StackFramesContentProps) { {current => ( - +
+ {current.functionName ?? ""} - + {getFilePath({ source: current.getFileName()!, content: "", @@ -134,7 +137,7 @@ function StackFramesContent(props: StackFramesContentProps) { name: current.getFunctionName(), })} - +
} > {(() => { @@ -143,13 +146,11 @@ function StackFramesContent(props: StackFramesContentProps) { {source => ( - - + + {source.name ?? ""} - - {getFilePath(source)} - + {getFilePath(source)} )} @@ -177,8 +178,7 @@ function StackFrames(props: StackFramesProps) { ); } -interface ErrorViewerProps { - show?: boolean; +interface DevOverlayDialogProps { errors: any[]; resetError: () => void; } @@ -186,7 +186,7 @@ interface ErrorViewerProps { const ISSUE_THREAD = "https://github.com/solidjs/solid-start/issues/new"; const DISCORD_INVITE = "https://discord.com/invite/solidjs"; -export default function ErrorViewer(props: ErrorViewerProps): JSX.Element { +export default function DevOverlayDialog(props: DevOverlayDialogProps): JSX.Element { const [currentPage, setCurrentPage] = createSignal(1); const [isCompiled, setIsCompiled] = createSignal(false); const length = createMemo(() => props.errors.length); @@ -248,58 +248,69 @@ export default function ErrorViewer(props: ErrorViewerProps): JSX.Element { } return ( - -
-
-
-
- 1}> -
- - - -
- {`${truncated()} of ${props.errors.length}`} + + +
+ + +
+
+
+
+
+ +
+ {info.version as string}
- - - + 1}> +
+ +
+ {`${truncated()} of ${props.errors.length}`} +
+ +
+
+
+
+ + + + +
+
+ + {current => ( +
+ + +
+ )}
-
- - - - - - - - - - - } - > - - - - - - -
-
- - {current => ( -
- - -
- )} -
+
-
-
+ + ); } diff --git a/packages/start/src/shared/dev-toolbar/error-viewer/create-stack-frame.ts b/packages/start/src/shared/dev-overlay/createStackFrame.ts similarity index 100% rename from packages/start/src/shared/dev-toolbar/error-viewer/create-stack-frame.ts rename to packages/start/src/shared/dev-overlay/createStackFrame.ts diff --git a/packages/start/src/shared/dev-toolbar/error-viewer/download.ts b/packages/start/src/shared/dev-overlay/download.ts similarity index 100% rename from packages/start/src/shared/dev-toolbar/error-viewer/download.ts rename to packages/start/src/shared/dev-overlay/download.ts diff --git a/packages/start/src/shared/dev-toolbar/error-viewer/env.d.ts b/packages/start/src/shared/dev-overlay/env.d.ts similarity index 100% rename from packages/start/src/shared/dev-toolbar/error-viewer/env.d.ts rename to packages/start/src/shared/dev-overlay/env.d.ts diff --git a/packages/start/src/shared/dev-toolbar/error-viewer/get-source-map.ts b/packages/start/src/shared/dev-overlay/get-source-map.ts similarity index 100% rename from packages/start/src/shared/dev-toolbar/error-viewer/get-source-map.ts rename to packages/start/src/shared/dev-overlay/get-source-map.ts diff --git a/packages/start/src/shared/dev-toolbar/icons.tsx b/packages/start/src/shared/dev-overlay/icons.tsx similarity index 88% rename from packages/start/src/shared/dev-toolbar/icons.tsx rename to packages/start/src/shared/dev-overlay/icons.tsx index f35312170..dd5598b3e 100644 --- a/packages/start/src/shared/dev-toolbar/icons.tsx +++ b/packages/start/src/shared/dev-overlay/icons.tsx @@ -169,25 +169,6 @@ export function GithubIcon(props: JSX.IntrinsicElements["svg"] & { title: string ); } -export function ErrorIcon(props: JSX.IntrinsicElements["svg"] & { title: string }): JSX.Element { - return ( - - {props.title} - - - ); -} - export function SolidStartIcon( props: JSX.IntrinsicElements["svg"] & { title: string }, ): JSX.Element { @@ -195,7 +176,7 @@ export function SolidStartIcon( {props.title} - + ); } - -export function FunctionIcon(props: JSX.IntrinsicElements["svg"] & { title: string }): JSX.Element { - return ( - - {props.title} - - - ); -} - -export function TrashIcon(props: JSX.IntrinsicElements["svg"] & { title: string }): JSX.Element { - return ( - - {props.title} - - - ); -} diff --git a/packages/start/src/shared/dev-overlay/index.tsx b/packages/start/src/shared/dev-overlay/index.tsx new file mode 100644 index 000000000..bb4dea670 --- /dev/null +++ b/packages/start/src/shared/dev-overlay/index.tsx @@ -0,0 +1,63 @@ +// @refresh skip +import { + createEffect, + createSignal, + ErrorBoundary, + type JSX, + onCleanup, + resetErrorBoundaries, + Show, +} from "solid-js"; +import clientOnly from "../clientOnly.ts"; +import { HttpStatusCode } from "../HttpStatusCode.ts"; + +export interface DevOverlayProps { + children?: JSX.Element; +} + +const DevOverlayDialog = import.meta.env.PROD + ? () => <> + : clientOnly(() => import("./DevOverlayDialog"), { lazy: true }); + +export function DevOverlay(props: DevOverlayProps): JSX.Element { + const [errors, setErrors] = createSignal([]); + + function resetError() { + setErrors([]); + resetErrorBoundaries(); + } + + function pushError(error: unknown) { + console.error(error); + setErrors(current => [error, ...current]); + } + + createEffect(() => { + const onErrorEvent = (error: ErrorEvent) => { + pushError(error.error ?? error); + }; + + window.addEventListener("error", onErrorEvent); + + onCleanup(() => { + window.removeEventListener("error", onErrorEvent); + }); + }); + + return ( + <> + { + pushError(error); + return ; + }} + > + {props.children} + + + + + + + ); +} diff --git a/packages/start/src/shared/dev-overlay/styles.css b/packages/start/src/shared/dev-overlay/styles.css new file mode 100644 index 000000000..ce51fdb95 --- /dev/null +++ b/packages/start/src/shared/dev-overlay/styles.css @@ -0,0 +1,292 @@ +[data-start-dev-overlay] { + position: fixed; + inset: 0px; + z-index: 50; + overflow-y: auto; +} + +[data-start-dev-overlay]>div { + position: relative; + display: flex; + align-items: center; + justify-content: center; + min-height: 100vh; +} + +[data-start-dev-overlay-background] { + position: absolute; + inset: 0px; + background-color: rgb(17 24 39 / 0.5); +} + +[data-start-dev-overlay-panel] { + display: flex; + flex-direction: column; + width: 75vw; + margin-top: 2rem; + margin-bottom: 2rem; + gap: 0.5rem; + color: rgb(17 24 39); + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; +} + +[data-start-dev-overlay-panel-container] { + margin: 2rem; + z-index: 10; +} + +[data-start-dev-overlay-navbar] { + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + gap: 0.5rem; +} + +[data-start-dev-overlay-pagination] { + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + gap: 0.5rem; + border-radius: 9999px; + background-color: rgb(249 250 251); + padding: 0.25rem; +} + +[data-start-dev-overlay-button] { + display: flex; + padding: 0.125rem; + border-radius: 9999px; + border-width: 0px; + align-items: center; + justify-content: center; + background-color: rgb(249 250 251); + color: rgb(17 24 39); + transition-property: color, background-color, border-color, box-shadow; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; +} + +[data-start-dev-overlay-button]:hover { + background-color: rgb(229 231 235); + color: rgb(55 65 81); +} + +[data-start-dev-overlay-button]:focus { + outline: 2px solid transparent; + outline-offset: 2px +} + +[data-start-dev-overlay-button]:focus-visible { + box-shadow: 0 0 0 calc(3px) rgb(17 24 39 / 0.75); +} + +[data-start-dev-overlay-button]:active { + background-color: rgb(243 244 246); + color: rgb(31 41 55); +} + +[data-start-dev-overlay-button]>svg { + height: 1.5rem; + width: 1.5rem; +} + +[data-start-dev-overlay-page-counter] { + font-size: 0.875rem; + line-height: 1.25rem; + font-weight: 600; +} + +[data-start-dev-overlay-navbar-left] { + display: flex; + flex-direction: row; + gap: 0.5rem; +} + + +[data-start-dev-overlay-controls] { + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + gap: 0.25rem; + border-radius: 9999px; + background-color: rgb(249 250 251); + padding: 0.25rem; +} + +[data-start-dev-overlay-version] { + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + gap: 0.25rem; + border-radius: 9999px; + background-color: rgb(249 250 251); + padding: 0.25rem 0.5rem; + font-size: 0.875rem; + line-height: 1.25rem; + font-weight: 600; +} + +[data-start-dev-overlay-version]>div { + height: 1.5rem; + width: 1.5rem; +} + +[data-start-dev-overlay-version]>div>svg { + height: 1.5rem; + width: 1.5rem; +} + +[data-start-dev-overlay-content] { + display: flex; + flex-direction: column; + gap: 0.75rem; + border-radius: 1.5rem; + background-color: rgb(249 250 251); + padding: 1rem; +} + +[data-start-dev-overlay-error-info] { + display: flex; + flex-direction: column; + gap: 0.25rem; +} + +[data-start-dev-overlay-error-info-name] { + font-weight: 700; +} + +[data-start-dev-overlay-error-info-message] { + font-size: 1.5rem; + line-height: 2rem; + color: rgb(239 68 68); + font-weight: 700; +} + +[data-start-dev-overlay-stack-frames-content] { + display: flex; + flex-direction: column; + gap: 0.75rem; +} + +[data-start-dev-overlay-stack-frames] { + flex: 1 1 0%; + display: flex; + flex-direction: column; + margin: 0; + margin-block: 0; + list-style-type: none; + padding-inline: 0; + max-height: 16rem; + overflow-y: auto; + border-radius: 0.5rem; +} + +[data-start-dev-overlay-stack-frame] { + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + gap: 1rem; + color: rgb(17 24 39); + cursor: default; + user-select: none; + padding-top: 0.5rem; + padding-bottom: 0.5rem; + padding-left: 1rem; + padding-right: 1rem; + font-size: 0.875rem; + line-height: 1.25rem; + outline: none; +} + +[data-start-dev-overlay-stack-frame][tc-active], +[data-start-dev-overlay-stack-frame][tc-selected], +[data-start-dev-overlay-stack-frame]:focus { + background-color: rgb(219 234 254); + color: rgb(30 58 138); +} + +[data-start-dev-overlay-stack-frame-function] { + font-weight: 700; +} + +[data-start-dev-overlay-stack-frame-file] { + white-space: nowrap; + font-size: 0.75rem; + /* 12px */ + line-height: 1rem; + /* 16px */ +} + +[data-start-dev-overlay-stack-frames-code] { + padding: 0.5rem 1rem; + gap: 0.25rem; + flex: 1 1 0%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + border-radius: 0.5rem; + background-color: rgb(17 24 39); +} + +[data-start-dev-overlay-stack-frames-code-fallback] { + display: flex; + align-items: center; + justify-content: center; + color: rgb(249 250 251); + min-height: 16rem; + font-size: 0.875rem; + line-height: 1.25rem; +} + +[data-start-dev-overlay-stack-frames-code-source] { + font-size: 0.875rem; + line-height: 1.25rem; + color: rgb(249 250 251); +} + +[data-start-dev-overlay-stack-frames-code-container] { + width: 100%; + overflow: hidden; + min-width: 100%; + min-height: 16rem; + border-top-width: 1px; + border-top-style: solid; + border-top-color: rgb(249 250 251); +} + +[data-start-dev-overlay-code-view] { + overflow: auto; + min-width: 100%; + min-height: 16rem; +} + +[data-start-dev-overlay-code-view]>.shiki { + float: left; + min-width: 100%; + overflow-x: auto; + font-size: 0.75rem; + line-height: 1rem; + counter-reset: step; + counter-increment: step calc(var(--dev-overlay-code-view-start, 1) - 1); + background-color: transparent !important; +} + +[data-start-dev-overlay-code-view]>.shiki .line::before { + content: counter(step); + counter-increment: step; + width: 1rem; + margin-right: 1.5rem; + display: inline-block; + text-align: right; + color: rgba(115, 138, 148, .4) +} + +[data-start-dev-overlay-error-line] { + background-color: rgba(239, 68, 68, .4); +} diff --git a/packages/start/src/shared/dev-toolbar/error-viewer/styles.css b/packages/start/src/shared/dev-toolbar/error-viewer/styles.css deleted file mode 100644 index 5a422cd8f..000000000 --- a/packages/start/src/shared/dev-toolbar/error-viewer/styles.css +++ /dev/null @@ -1,224 +0,0 @@ -[data-start-error-viewer] { - display: flex; - flex-direction: column; - - width: 100%; -} - -[data-start-error-viewer-navbar] { - display: flex; - flex-direction: row; - align-items: center; - justify-content: space-between; - gap: 0.5rem; -} - -[data-start-error-viewer-pagination] { - display: flex; - flex-direction: row; - align-items: center; - justify-content: center; - gap: 0.5rem; - border-radius: 9999px; - color: rgb(249 250 251); - background-color: rgb(17 24 39); - padding: 0.25rem; -} - -[data-start-error-viewer-button] { - /* empty */ -} - -[data-start-error-viewer-button]:hover { - color: rgb(229 231 235); - background-color: rgb(55 65 81); -} - -[data-start-error-viewer-button]:focus { - outline: 2px solid transparent; - outline-offset: 2px; - outline-color: rgb(229 231 235); -} - -[data-start-error-viewer-button]:focus-visible { - box-shadow: 0 0 0 calc(3px) rgb(17 24 39 / 0.75); -} - -[data-start-error-viewer-button]:active { - color: rgb(243 244 246); - background-color: rgb(31 41 55); -} - -[data-start-error-viewer-button] > svg { - height: 1.5rem; - width: 1.5rem; -} - -[data-start-error-viewer-page-counter] { - font-size: 0.875rem; - line-height: 1.25rem; - font-weight: 600; -} - -[data-start-error-viewer-navbar-left] { - display: flex; - flex-direction: row; - gap: 0.5rem; -} - -[data-start-error-viewer-controls] { - display: flex; - flex-direction: row; - align-items: center; - justify-content: center; - gap: 0.25rem; - border-radius: 9999px; - color: rgb(249 250 251); - padding: 0.25rem; -} - -[data-start-error-viewer-content] { - display: flex; - flex-direction: column; - gap: 0.75rem; - padding: 1rem; - - border-top-width: 1px; - border-top-style: solid; - border-top-color: oklch(87% 0.065 274.039); -} - -[data-start-error-viewer-error-info] { - display: flex; - flex-direction: column; - gap: 0.25rem; -} - -[data-start-error-viewer-error-info-name] { - font-weight: 700; - color: rgb(249 250 251); -} - -[data-start-error-viewer-error-info-message] { - font-size: 1.5rem; - line-height: 2rem; - color: rgb(239 68 68); - font-weight: 700; -} - -[data-start-error-viewer-stack-frames-content] { - display: flex; - flex-direction: column; - gap: 0.75rem; -} - -[data-start-error-viewer-stack-frames] { - flex: 1 1 0%; - max-height: 16rem; - overflow-y: auto; -} - -[data-start-error-viewer-stack-frame] { - display: flex; - flex-direction: row; - align-items: center; - justify-content: space-between; - gap: 1rem; - color: rgb(249 250 251); - cursor: default; - user-select: none; - padding-top: 0.5rem; - padding-bottom: 0.5rem; - padding-left: 1rem; - padding-right: 1rem; - font-size: 0.875rem; - line-height: 1.25rem; - outline: none; -} - -[data-start-error-viewer-stack-frame][tc-active], -[data-start-error-viewer-stack-frame][tc-selected], -[data-start-error-viewer-stack-frame]:focus { - color: rgb(219 234 254); - background-color: rgb(30 58 138); -} - -[data-start-error-viewer-stack-frame-function] { - font-weight: 700; -} - -[data-start-error-viewer-stack-frame-file] { - white-space: nowrap; - font-size: 0.75rem; - /* 12px */ - line-height: 1rem; - /* 16px */ -} - -[data-start-error-viewer-stack-frames-code] { - padding: 0.5rem 1rem; - gap: 0.25rem; - flex: 1 1 0%; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - border-radius: 0.5rem; - background-color: rgb(17 24 39); -} - -[data-start-error-viewer-stack-frames-code-fallback] { - display: flex; - align-items: center; - justify-content: center; - color: rgb(249 250 251); - min-height: 16rem; - font-size: 0.875rem; - line-height: 1.25rem; -} - -[data-start-error-viewer-stack-frames-code-source] { - font-size: 0.875rem; - line-height: 1.25rem; - color: rgb(249 250 251); -} - -[data-start-error-viewer-stack-frames-code-container] { - width: 100%; - overflow: hidden; - min-width: 100%; - max-height: 16rem; - border-top-width: 1px; - border-top-style: solid; - border-top-color: oklch(87% 0.065 274.039); -} - -[data-start-error-viewer-code-view] { - overflow: auto; - min-width: 100%; -} - -[data-start-error-viewer-code-view] > .shiki { - float: left; - min-width: 100%; - overflow-x: auto; - font-size: 0.75rem; - line-height: 1rem; - counter-reset: step; - counter-increment: step calc(var(--error-viewer-code-view-start, 1) - 1); - background-color: transparent !important; -} - -[data-start-error-viewer-code-view] > .shiki .line::before { - content: counter(step); - counter-increment: step; - width: 1rem; - margin-right: 1.5rem; - display: inline-block; - text-align: right; - color: rgba(115, 138, 148, 0.4); -} - -[data-start-error-viewer-error-line] { - background-color: rgba(239, 68, 68, 0.4); -} diff --git a/packages/start/src/shared/dev-toolbar/functions/BlobViewer.css b/packages/start/src/shared/dev-toolbar/functions/BlobViewer.css deleted file mode 100644 index b440887f3..000000000 --- a/packages/start/src/shared/dev-toolbar/functions/BlobViewer.css +++ /dev/null @@ -1,4 +0,0 @@ -[data-start-blob-viewer] svg { - width: 1rem; - height: 1rem; -} \ No newline at end of file diff --git a/packages/start/src/shared/dev-toolbar/functions/BlobViewer.tsx b/packages/start/src/shared/dev-toolbar/functions/BlobViewer.tsx deleted file mode 100644 index 890698a58..000000000 --- a/packages/start/src/shared/dev-toolbar/functions/BlobViewer.tsx +++ /dev/null @@ -1,78 +0,0 @@ -import { createMemo, createResource, type JSX, onCleanup, Show, Suspense } from 'solid-js'; - -import { Badge } from "../../ui/Badge.tsx"; -import Button from "../../ui/Button.tsx"; - -import './BlobViewer.css'; - - -function DocumentIcon( - props: JSX.IntrinsicElements["svg"] & { title: string }, -): JSX.Element { - return ( - - {props.title} - - - ); -} - -interface BlobViewerInnerProps { - source: File | Blob; -} - -function BlobViewerInner(props: BlobViewerInnerProps): JSX.Element { - const fileURL = createMemo(() => URL.createObjectURL(props.source)); - - onCleanup(() => { - URL.revokeObjectURL(fileURL()); - }); - - function openFileInNewTab() { - const link = document.createElement("a"); - link.href = fileURL(); - link.target = "_blank"; // Open in a new tab - link.style.display = "none"; // Hide the link - document.body.appendChild(link); - link.click(); - document.body.removeChild(link); - } - - return ( - - ) -} - - -export interface BlobViewerProps { - source: Blob | File | Promise; -} - - -export function BlobViewer(props: BlobViewerProps): JSX.Element { - const [data] = createResource(() => props.source); - - return ( - - - {(current) => } - - - ); -} diff --git a/packages/start/src/shared/dev-toolbar/functions/FormDataViewer.tsx b/packages/start/src/shared/dev-toolbar/functions/FormDataViewer.tsx deleted file mode 100644 index a896bbac7..000000000 --- a/packages/start/src/shared/dev-toolbar/functions/FormDataViewer.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import { createResource, For, type JSX, Show, Suspense } from 'solid-js'; -import { Section } from '../../ui/Section.tsx'; -import { BlobViewer } from './BlobViewer.tsx'; -import { PropertySeparator, SerovalValue } from './SerovalValue.tsx'; - -interface FormDataViewerInnerProps { - source: FormData; -} - -function FormDataViewerInner(props: FormDataViewerInnerProps): JSX.Element { - return ( -
-
- - {([key, value]) => ( -
- - - {typeof value === 'string' - ? - : } -
- )} -
-
- - ); -} - -export interface FormDataViewerProps { - source: FormData | Promise; -} - -export function FormDataViewer(props: FormDataViewerProps) { - const [data] = createResource(() => props.source); - - return ( - - - {(current) => } - - - ); -} \ No newline at end of file diff --git a/packages/start/src/shared/dev-toolbar/functions/HeadersViewer.css b/packages/start/src/shared/dev-toolbar/functions/HeadersViewer.css deleted file mode 100644 index e6b8c1c4d..000000000 --- a/packages/start/src/shared/dev-toolbar/functions/HeadersViewer.css +++ /dev/null @@ -1,8 +0,0 @@ -[data-start-headers-viewer] { - font-size: 0.75rem; - line-height: 1rem; -} - -[data-start-headers-viewer] > [data-start-property] > *:first-child { - text-transform: capitalize; -} diff --git a/packages/start/src/shared/dev-toolbar/functions/HeadersViewer.tsx b/packages/start/src/shared/dev-toolbar/functions/HeadersViewer.tsx deleted file mode 100644 index d0109b65d..000000000 --- a/packages/start/src/shared/dev-toolbar/functions/HeadersViewer.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { For } from "solid-js"; -import { PropertySeparator, SerovalValue } from "./SerovalValue.tsx"; - -import './HeadersViewer.css'; -import { Text } from "../../ui/Text.tsx"; - -interface HeadersViewerProps { - headers: Headers; -} - -export function HeadersViewer(props: HeadersViewerProps) { - return ( -
- - {([key, value]) => ( -
- {key} - - -
- )} -
-
- ); -} diff --git a/packages/start/src/shared/dev-toolbar/functions/HexViewer.css b/packages/start/src/shared/dev-toolbar/functions/HexViewer.css deleted file mode 100644 index 9e2a9f996..000000000 --- a/packages/start/src/shared/dev-toolbar/functions/HexViewer.css +++ /dev/null @@ -1,34 +0,0 @@ -[data-start-hex-viewer] { - display: flex; - border: 1px oklch(87% 0.065 274.039) solid; - overflow: auto; -} - -[data-start-hex-viewer-bytes] { - flex: 1; - display: flex; - flex-direction: column; - gap: 0.5rem; - padding: 0.5rem; -} - -[data-start-hex-viewer-text] { - flex: 1; - display: flex; - flex-direction: column; - gap: 0.5rem; - padding: 0.5rem; - border-left: 1px oklch(87% 0.065 274.039) solid; -} - -[data-start-hex-row] { - display: flex; - align-items: center; - gap: 1rem; -} - -[data-start-hex-text] { - display: flex; - align-items: center; - justify-content: start; -} diff --git a/packages/start/src/shared/dev-toolbar/functions/HexViewer.tsx b/packages/start/src/shared/dev-toolbar/functions/HexViewer.tsx deleted file mode 100644 index 29bf21f87..000000000 --- a/packages/start/src/shared/dev-toolbar/functions/HexViewer.tsx +++ /dev/null @@ -1,111 +0,0 @@ -import { createMemo, createResource, For, type JSX, Show, Suspense } from "solid-js"; -import { Text } from "../../ui/Text.tsx"; - -import './HexViewer.css'; - - -function toHex(num: number, digits = 2): string { - return num.toString(16).padStart(digits, '0').toUpperCase(); -} - -function HexChunk(props: HexViewerInnerProps) { - - const content = createMemo(() => { - const byte1 = props.bytes[0] || 0; - const byte2 = props.bytes[1] || 0; - const byte3 = props.bytes[2] || 0; - const byte4 = props.bytes[3] || 0; - - return `${toHex(byte1)} ${toHex(byte2)} ${toHex(byte3)} ${toHex(byte4)}` - }); - return ( - - {content()} - - ); -} - -function HexRow(props: HexViewerInnerProps) { - const chunk1 = createMemo(() => props.bytes.subarray(0, 4)); - const chunk2 = createMemo(() => props.bytes.subarray(4, 8)); - const chunk3 = createMemo(() => props.bytes.subarray(8, 12)); - const chunk4 = createMemo(() => props.bytes.subarray(12, 16)); - - return ( -
- - - - -
- ); -} - -function replaceString(string: string): string { - const result = string.codePointAt(0); - if (result == null) { - return string; - } - return String.fromCodePoint(result + 0x2400); -} - -function HexText(props: HexViewerInnerProps) { - const text = createMemo(() => { - const decoder = new TextDecoder(); - const result = decoder.decode(props.bytes).replaceAll(/[\x00-\x1F]/g, replaceString); - return result; - }); - - return ( -
- - {text()} - -
- ); -} - -interface HexViewerInnerProps { - bytes: Uint8Array; -} - -export function HexViewerInner(props: HexViewerInnerProps): JSX.Element { - const rows = createMemo(() => { - const arrays: Uint8Array[] = []; - for (let i = 0, len = props.bytes.length; i < len; i += 16) { - arrays.push(props.bytes.subarray(i, i + 16)); - } - return arrays; - }); - - return ( -
-
- - {(current) => } - -
-
- - {(current) => } - -
-
- ); -} - -export interface HexViewerProps { - bytes: Uint8Array | Promise; -} - -export function HexViewer(props: HexViewerProps): JSX.Element { - const [data] = createResource(() => props.bytes); - - return ( - - - {(current) => } - - - ); -} diff --git a/packages/start/src/shared/dev-toolbar/functions/SerovalValue.css b/packages/start/src/shared/dev-toolbar/functions/SerovalValue.css deleted file mode 100644 index b38afc019..000000000 --- a/packages/start/src/shared/dev-toolbar/functions/SerovalValue.css +++ /dev/null @@ -1,7 +0,0 @@ - - -[data-start-seroval-value] { - display: flex; - gap: 0.25rem; - align-items: center; -} diff --git a/packages/start/src/shared/dev-toolbar/functions/SerovalValue.tsx b/packages/start/src/shared/dev-toolbar/functions/SerovalValue.tsx deleted file mode 100644 index a8b420a92..000000000 --- a/packages/start/src/shared/dev-toolbar/functions/SerovalValue.tsx +++ /dev/null @@ -1,18 +0,0 @@ -import { Text } from "../../ui/Text.tsx"; -import './SerovalValue.css'; - -interface SerovalValueProps { - value: string | number | boolean | undefined | null; -} - -export function SerovalValue(props: SerovalValueProps) { - return ( - - {`${props.value}`} - - ); -} - -export function PropertySeparator() { - return :; -} diff --git a/packages/start/src/shared/dev-toolbar/functions/SerovalViewer.css b/packages/start/src/shared/dev-toolbar/functions/SerovalViewer.css deleted file mode 100644 index 2bcb7df04..000000000 --- a/packages/start/src/shared/dev-toolbar/functions/SerovalViewer.css +++ /dev/null @@ -1,71 +0,0 @@ -[data-start-seroval-viewer] { - display: grid; - grid-template-columns: 1fr 2fr; -} - -[data-start-seroval-promise] { - display: flex; - gap: 0.5rem; - align-items: center; -} - -[data-start-seroval-renderer] { - display: flex; - border-top: 1px oklch(87% 0.065 274.039) solid; - border-bottom: 1px oklch(87% 0.065 274.039) solid; -} - -[data-start-seroval-renderer] > * { - border-left: 1px oklch(87% 0.065 274.039) solid; -} - -[data-start-seroval-renderer]:last-child { - border-right: 1px oklch(87% 0.065 274.039) solid; -} - -[data-start-seroval-node] { - display: flex; - flex-direction: column; - gap: 0.25rem; - padding: 0.25rem; - - width: 100%; - max-width: 16rem; -} - -[data-start-seroval-node-header] { - position: sticky; - top: 0; - display: flex; - align-items: center; - justify-content: space-between; - color: rgb(249 250 251); -} - -[data-start-seroval-node-content] { - display: flex; - flex-direction: column; - gap: 0.25rem; -} - -[data-start-seroval-value] { - color: rgb(249 250 251); -} - -[data-start-seroval-value-wrapper] { - display: inline-flex; - gap: 0.25rem; - align-items: center; -} - -[data-start-seroval-link] { - display: inline-flex; - gap: 0.25rem; - align-items: center; -} - -[data-start-seroval-link] > svg { - width: 1rem; - height: 1rem; -} - diff --git a/packages/start/src/shared/dev-toolbar/functions/SerovalViewer.tsx b/packages/start/src/shared/dev-toolbar/functions/SerovalViewer.tsx deleted file mode 100644 index e6af11736..000000000 --- a/packages/start/src/shared/dev-toolbar/functions/SerovalViewer.tsx +++ /dev/null @@ -1,997 +0,0 @@ -import type { SerovalNode } from "seroval"; -import { createEffect, createSignal, For, type JSX, Show, splitProps } from "solid-js"; - -import { Badge } from "../../ui/Badge.tsx"; -import { Cascade, CascadeOption } from "../../ui/Cascade.tsx"; -import { Section } from "../../ui/Section.tsx"; -import { HexViewer } from "./HexViewer.tsx"; -import { PropertySeparator, SerovalValue } from "./SerovalValue.tsx"; - -import { SerovalChunkReader } from "../../../fns/serialization.ts"; -import "./SerovalViewer.css"; - -function LinkIcon(props: JSX.IntrinsicElements["svg"] & { title: string }): JSX.Element { - return ( - - {props.title} - - - ); -} - -export interface SerovalViewerProps { - stream: Request | Response; -} - -function getNodeType(node: SerovalNode) { - switch (node.t) { - // Number = 0, - case 0: - return "number"; - // String = 1, - case 1: - return "string"; - // Constant = 2, - case 2: - switch (node.s) { - case 0: - return "null"; - case 1: - return "undefined"; - case 2: - return "true"; - case 3: - return "false"; - case 4: - return "-0"; - case 5: - return "Infinity"; - case 6: - return "-Infinity"; - case 7: - return "NaN"; - } - break; - // BigInt = 3, - case 3: - return "bigint"; - // Date = 5, - case 5: - return "Date"; - // RegExp = 6, - case 6: - return "RegExp"; - // Set = 7, - case 7: - return "Set"; - // Map = 8, - case 8: - return "Map"; - // Array = 9, - case 9: - return "Array"; - // Object = 10, - case 10: - // NullConstructor = 11, - case 11: - return "Object"; - // Promise = 12, - case 12: - return "Promise"; - // Error = 13, - case 13: - switch (node.s) { - case 0: - return "Error"; - case 1: - return "EvalError"; - case 2: - return "RangeError"; - case 3: - return "ReferenceError"; - case 4: - return "SyntaxError"; - case 5: - return "TypeError"; - case 6: - return "URIError"; - } - return "Error"; - // AggregateError = 14, - case 14: - return "AggregateError"; - // TypedArray = 15, - case 15: - // BigIntTypedArray = 16, - case 16: - return node.c; - // WKSymbol = 17, - case 17: - return "symbol"; - // ArrayBuffer = 19, - case 19: - return "ArrayBuffer"; - // DataView = 20, - case 20: - return "DataView"; - // Boxed = 21, - case 21: - return "Boxed"; - // PromiseConstructor = 22, - case 22: - return "Promise"; - // Plugin = 25, - case 25: - // due to the nature of this node, we have to traverse it ourselves - return "Plugin"; - // IteratorFactoryInstance = 28, - case 28: - return "Iterator"; - // AsyncIteratorFactoryInstance = 30, - case 30: - return "AsyncIterator"; - // StreamConstructor = 31, - case 31: - return "Stream"; - case 35: - return "Sequence"; - } - throw new Error("unsupported node type"); -} - -function traverse(node: SerovalNode, handler: (node: SerovalNode) => void): void { - handler(node); - switch (node.t) { - // Number = 0, - case 0: - // String = 1, - case 1: - // Constant = 2, - case 2: - // BigInt = 3, - case 3: - // IndexedValue = 4, - case 4: - // Date = 5, - case 5: - // RegExp = 6, - case 6: - break; - // Set = 7, - case 7: - // Traverse items - for (const child of node.a) { - traverse(child, handler); - } - break; - // Map = 8, - case 8: - // Traverse keys - for (const key of node.e.k) { - traverse(key, handler); - } - for (const value of node.e.v) { - traverse(value, handler); - } - break; - // Array = 9, - case 9: - // Traverse items - for (const child of node.a) { - if (child) { - traverse(child, handler); - } - } - break; - // Object = 10, - case 10: - // NullConstructor = 11, - case 11: - for (const child of node.p.k) { - if (typeof child !== "string") { - traverse(child, handler); - } - } - for (const child of node.p.v) { - traverse(child, handler); - } - break; - // Promise = 12, - case 12: - traverse(node.f, handler); - break; - // Error = 13, - case 13: - // AggregateError = 14, - case 14: - if (node.p) { - for (const child of node.p.k) { - if (typeof child !== "string") { - traverse(child, handler); - } - } - for (const child of node.p.v) { - traverse(child, handler); - } - } - break; - // TypedArray = 15, - case 15: - // BigIntTypedArray = 16, - case 16: - traverse(node.f, handler); - break; - // WKSymbol = 17, - case 17: - // Reference = 18, - case 18: - break; - // ArrayBuffer = 19, - case 19: - // DataView = 20, - case 20: - // Boxed = 21, - case 21: - traverse(node.f, handler); - break; - // PromiseConstructor = 22, - case 22: - break; - // PromiseSuccess = 23, - case 23: - // PromiseFailure = 24, - case 24: - traverse(node.a[1], handler); - break; - // Plugin = 25, - case 25: - for (const key in node.s) { - const current = node.s[key]; - if (current) { - traverse(current, handler); - } - } - break; - // SpecialReference = 26, - case 26: - break; - // IteratorFactory = 27, - case 27: - traverse(node.f, handler); - break; - // IteratorFactoryInstance = 28, - case 28: - traverse(node.a[0], handler); - traverse(node.a[1], handler); - break; - // AsyncIteratorFactory = 29, - case 29: - traverse(node.a[1], handler); - break; - // AsyncIteratorFactoryInstance = 30, - case 30: - traverse(node.a[0], handler); - traverse(node.a[1], handler); - break; - // StreamConstructor = 31, - case 31: - // Traverse items - for (const child of node.a) { - traverse(child, handler); - } - break; - // StreamNext = 32, - case 32: - // StreamThrow = 33, - case 33: - // StreamReturn = 34 - case 34: - traverse(node.f, handler); - break; - case 35: - // Traverse items - for (const child of node.a) { - if (child) { - traverse(child, handler); - } - } - break; - } -} - -function getConstantValue(value: number) { - switch (value) { - case 0: - return "null"; - case 1: - return "undefined"; - case 2: - return "true"; - case 3: - return "false"; - case 4: - return "-0"; - case 5: - return "Infinity"; - case 6: - return "-Infinity"; - case 7: - return "NaN"; - } - return ""; -} - -function getSymbolValue(value: number) { - switch (value) { - case 0: - return "Symbol.asyncIterator"; - case 1: - return "Symbol.hasInstance"; - case 2: - return "Symbol.isConcatSpreadable"; - case 3: - return "Symbol.iterator"; - case 4: - return "Symbol.match"; - case 5: - return "Symbol.matchAll"; - case 6: - return "Symbol.replace"; - case 7: - return "Symbol.search"; - case 8: - return "Symbol.species"; - case 9: - return "Symbol.toPrimitive"; - case 10: - return "Symbol.toStringTag"; - case 11: - return "Symbol.unscopables"; - } - return ""; -} - -function getObjectFlag(value: number) { - switch (value) { - case 1: - return "non-extensible"; - case 2: - return "sealed"; - case 3: - return "frozen"; - default: - return "none"; - } -} - -function zip(keys: Key[], values: Value[]): [key: Key, value: Value][] { - const zipped: [key: Key, value: Value][] = []; - - for (let i = 0, len = keys.length; i < len; i++) { - zipped[i] = [keys[i]!, values[i]!]; - } - - return zipped; -} - -interface RenderContext { - getNode: (index: number) => SerovalNode | undefined; - getPromise: (index: number) => Extract | undefined; - getStream: (index: number) => Extract[] | undefined; -} - -function getStreamKeyword(t: 32 | 33 | 34): string { - switch (t) { - case 32: - return "next"; - case 33: - return "throw"; - case 34: - return "return"; - } -} - -function renderSerovalNode( - ctx: RenderContext, - node: SerovalNode, - onSelect: (index: number | undefined) => void, - inner?: boolean, -): JSX.Element { - if ( - node.t >= 4 && - (inner || node.t === 4) && - node.i != null && - !(node.t === 5 || node.t === 6 || node.t === 17) - ) { - const index = node.i; - const description = `id: ${index}`; - const lookup = ctx.getNode(index)!; - return ( - - - {getNodeType(lookup)} - {description} - - ); - } - switch (node.t) { - // Number = 0, - case 0: - return ; - // String = 1, - case 1: - return ; - // Constant = 2, - case 2: - return ; - // BigInt = 3, - case 3: - return ( -
- bigint - -
- ); - // Date = 5, - case 5: - return ( -
- Date - -
- ); - // RegExp = 6, - case 6: - return ( -
- RegExp - -
- ); - // Set = 7, - case 7: - return ( - <> -
-
- - - -
-
-
- - data-start-properties - defaultValue={undefined} - onChange={onSelect} - > - [index, node] as const)}> - {([key, value]) => ( -
- - - {renderSerovalNode(ctx, value, onSelect, true)} -
- )} -
- -
- - ); - // Map = 8, - case 8: - return ( - <> -
-
- - - -
-
-
- - data-start-properties - defaultValue={undefined} - onChange={onSelect} - > - }> - {([key, value]) => ( -
- {renderSerovalNode(ctx, key, onSelect, true)} - - {renderSerovalNode(ctx, value, onSelect, true)} -
- )} -
- -
- - ); - // Array = 9, - case 9: - return ( - <> -
-
- - - -
-
- - - {getObjectFlag(node.o)} -
-
-
- - data-start-properties - defaultValue={undefined} - onChange={onSelect} - > - [index, node] as const)} - fallback={} - > - {([key, value]) => ( -
- - - {value === 0 ? ( - - ) : ( - renderSerovalNode(ctx, value, onSelect, true) - )} -
- )} -
- -
- - ); - // Object = 10, - case 10: - // NullConstructor = 11, - case 11: - return ( - <> -
-
- - - -
-
- - - {getObjectFlag(node.o)} -
-
-
- - data-start-properties - defaultValue={undefined} - onChange={onSelect} - > - }> - {([key, value]) => ( -
- {typeof key === "string" ? ( - - ) : ( - renderSerovalNode(ctx, key, onSelect, true) - )} - - {renderSerovalNode(ctx, value, onSelect, true)} -
- )} -
- -
- - ); - // Promise = 12, - case 12: - return ( - - data-start-properties - defaultValue={undefined} - onChange={onSelect} - > - {renderSerovalNode(ctx, node.f, onSelect, true)} - - ); - // Error = 13, - case 13: - // AggregateError = 14, - case 14: - return ( - <> -
-
- - - -
-
- - {current => ( -
- - data-start-properties - defaultValue={undefined} - onChange={onSelect} - > - } - > - {([key, value]) => ( -
- {typeof key === "string" ? ( - - ) : ( - renderSerovalNode(ctx, key, onSelect, true) - )} - - {renderSerovalNode(ctx, value, onSelect, true)} -
- )} -
- -
- )} -
- - ); - // WKSymbol = 17, - case 17: - return ; - // Reference = 18, - case 18: - break; - // ArrayBuffer = 19, - case 19: { - const data = atob(node.s); - const result = new TextEncoder().encode(data); - return ; - } - // TypedArray = 15, - case 15: - // BigIntTypedArray = 16, - case 16: - // DataView = 20, - case 20: - return ( - <> -
-
- - - -
-
- - - -
-
-
- - data-start-properties - defaultValue={undefined} - onChange={onSelect} - > - {renderSerovalNode(ctx, node.f, onSelect, true)} - -
- - ); - // Boxed = 21, - case 21: - return ( - - data-start-properties - defaultValue={undefined} - onChange={onSelect} - > - {renderSerovalNode(ctx, node.f, onSelect, true)} - - ); - case 22: - return ( - <> - {(() => { - const result = ctx.getPromise(node.s); - if (result) { - const status = result.t === 23 ? "success" : ("failure" as const); - return ( - - data-start-properties - defaultValue={undefined} - onChange={onSelect} - > -
- - - {status} -
- - - - {renderSerovalNode(ctx, result.a[1], onSelect, true)} - - - ); - } - return pending; - })()} - - ); - // Plugin = 25 - case 25: - return ( - <> -
-
- - - -
-
-
- - data-start-properties - defaultValue={undefined} - onChange={onSelect} - > - }> - {([key, value]) => ( -
- - - {renderSerovalNode(ctx, value, onSelect, true)} -
- )} -
- -
- - ); - // IteratorFactory = 27, - case 27: - break; - // IteratorFactoryInstance = 28, - case 28: - return renderSerovalNode(ctx, node.a[1], onSelect, true); - // AsyncIteratorFactory = 29, - case 29: - break; - // AsyncIteratorFactoryInstance = 30, - case 30: - return renderSerovalNode(ctx, node.a[1], onSelect, true); - // StreamConstructor = 31, - case 31: - return ( - <> - {(() => { - const result = ctx.getStream(node.i) || []; - return ( - - data-start-properties - defaultValue={undefined} - onChange={onSelect} - > - }> - {current => ( -
- - - {renderSerovalNode(ctx, current.f, onSelect, true)} -
- )} -
- - ); - })()} - - ); - case 35: - return ( - - data-start-properties - defaultValue={undefined} - onChange={onSelect} - > - }> - {(current, index) => ( -
- - - {renderSerovalNode(ctx, current, onSelect, true)} -
- )} -
- - ); - } -} - -interface SerovalNodeRendererProps extends RenderContext { - node: SerovalNode; -} - -function SerovalNodeRenderer(props: SerovalNodeRendererProps): JSX.Element { - const [, rest] = splitProps(props, ["node"]); - const [next, setNext] = createSignal(); - - function onSelect(index: number | undefined) { - if (index == null) { - setNext(undefined); - } else { - setNext(props.getNode(index)); - } - } - - return ( - <> -
-
- {getNodeType(props.node)} - {props.node.i != null && {`id: ${props.node.i}`}} -
-
{renderSerovalNode(props, props.node, onSelect)}
-
- - {current => } - - - ); -} - -interface SerovalRendererProps extends Omit { - node?: SerovalNode; -} - -function SerovalRenderer(props: SerovalRendererProps): JSX.Element { - const [, rest] = splitProps(props, ["node"]); - return ( -
- {current => } -
- ); -} - -function createSimpleStore>(initial: T) { - const [state, setState] = createSignal(initial); - - return { - get(): T { - return state(); - }, - read(key: K): T[K] { - return state()[key]; - }, - write(key: K, value: T[K]): void { - setState(current => ({ - ...current, - [key]: value, - })); - }, - update(key: K, value: (current: T[K]) => T[K]): void { - setState(current => ({ - ...current, - [key]: value(current[key]), - })); - }, - }; -} - -export function SerovalViewer(props: SerovalViewerProps): JSX.Element { - const [selected, setSelected] = createSignal(); - - const references = createSimpleStore< - Record | undefined> - >({}); - const streams = createSimpleStore< - Record[] | undefined> - >({}); - const promises = createSimpleStore< - Record | undefined> - >({}); - - createEffect(async () => { - setSelected(undefined); - if (!props.stream.body) { - throw new Error("missing body"); - } - const reader = new SerovalChunkReader(props.stream.body); - const result = await reader.next(); - if (!result.done) { - function traverseNode(node: SerovalNode): void { - // Check for promises - switch (node.t) { - case 0: - case 1: - case 2: - case 3: - case 4: - break; - case 23: - case 24: - promises.write(node.i, node); - break; - case 32: - case 33: - case 34: - streams.update(node.i, current => { - if (current) { - return [...current, node]; - } - return [node]; - }); - break; - case 5: - case 6: - case 7: - case 8: - case 9: - case 10: - case 11: - case 12: - case 13: - case 14: - case 15: - case 16: - case 17: - case 18: - case 19: - case 20: - case 21: - case 25: - case 26: - case 27: - case 29: - case 31: - case 35: - references.write(node.i, node); - break; - } - } - - function interpretChunk(chunk: string): SerovalNode { - const result = JSON.parse(chunk) as SerovalNode; - traverse(result, traverseNode); - return result; - } - - void reader.drain(interpretChunk); - const root = interpretChunk(result.value); - setSelected(root); - } - }); - - return ( -
- references.read(index)} - getPromise={index => promises.read(index)} - getStream={index => streams.read(index)} - /> -
- ); -} diff --git a/packages/start/src/shared/dev-toolbar/functions/URLSearchParamsViewer.tsx b/packages/start/src/shared/dev-toolbar/functions/URLSearchParamsViewer.tsx deleted file mode 100644 index 6d45ce585..000000000 --- a/packages/start/src/shared/dev-toolbar/functions/URLSearchParamsViewer.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { createResource, For, type JSX, Show, Suspense } from 'solid-js'; -import { Section } from '../../ui/Section.tsx'; -import { PropertySeparator, SerovalValue } from './SerovalValue.tsx'; - -interface URLSearchParamsViewerInnerProps { - source: URLSearchParams; -} - -function URLSearchParamsViewerInner(props: URLSearchParamsViewerInnerProps): JSX.Element { - return ( -
-
- - {([key, value]) => ( -
- - - -
- )} -
-
-
- ); -} - -export interface URLSearchParamsViewerProps { - source: URLSearchParams | Promise; -} - -export function URLSearchParamsViewer(props: URLSearchParamsViewerProps) { - const [data] = createResource(() => props.source); - - return ( - - - {(current) => } - - - ); -} \ No newline at end of file diff --git a/packages/start/src/shared/dev-toolbar/functions/index.tsx b/packages/start/src/shared/dev-toolbar/functions/index.tsx deleted file mode 100644 index 4249f94fc..000000000 --- a/packages/start/src/shared/dev-toolbar/functions/index.tsx +++ /dev/null @@ -1,306 +0,0 @@ -import { createMemo, createSignal, For, type JSX, Show } from "solid-js"; -import { BODY_FORMAL_FILE, BODY_FORMAT_KEY, BodyFormat } from "../../../fns/shared.ts"; -import { Badge } from "../../ui/Badge.tsx"; -import IconButton from "../../ui/IconButton.tsx"; -import Placeholder from "../../ui/Placeholder.tsx"; -import { Section } from "../../ui/Section.tsx"; -import { Select, SelectOption } from "../../ui/Select.tsx"; -import { Tab, TabGroup, TabList, TabPanel } from "../../ui/Tabs.tsx"; -import { Text } from "../../ui/Text.tsx"; -import { ArrowLeftIcon, FunctionIcon, TrashIcon } from "../icons.tsx"; -import { BlobViewer } from "./BlobViewer.tsx"; -import { FormDataViewer } from "./FormDataViewer.tsx"; -import { HeadersViewer } from "./HeadersViewer.tsx"; -import { HexViewer } from "./HexViewer.tsx"; -import { PropertySeparator, SerovalValue } from "./SerovalValue.tsx"; -import { SerovalViewer } from "./SerovalViewer.tsx"; -import "./styles.css"; -import { type ServerFunctionRequest, type ServerFunctionResponse } from "./tracker.ts"; -import { URLSearchParamsViewer } from "./URLSearchParamsViewer.tsx"; - -async function getFile(source: Response | Request): Promise { - const formData = await source.formData(); - const file = formData.get(BODY_FORMAL_FILE); - if (!(file && file instanceof File)) { - throw new Error("invalid file input"); - } - return file; -} - -async function getURLSearchParams(source: Response | Request): Promise { - const text = await source.text(); - return new URLSearchParams(text); -} - -interface ContentViewerProps { - source: ServerFunctionRequest | ServerFunctionResponse; -} - -function ContentViewer(props: ContentViewerProps): JSX.Element { - return ( - <> -
- -
-
- {(() => { - const source = props.source.source.clone(); - const startType = source.headers.get(BODY_FORMAT_KEY); - const contentType = source.headers.get("Content-Type"); - switch (true) { - case startType === "true": - case startType === BodyFormat.Seroval: - return ; - case startType === BodyFormat.String: - return ; - case startType === BodyFormat.File: - return ; - case startType === BodyFormat.FormData: - case contentType?.startsWith("multipart/form-data"): - return ; - case startType === BodyFormat.URLSearchParams: - case contentType?.startsWith("application/x-www-form-urlencoded"): - return ; - case startType === BodyFormat.Blob: - return ; - case startType === BodyFormat.ArrayBuffer: - case startType === BodyFormat.Uint8Array: - return ; - } - })()} -
- - ); -} - -interface RequestViewerProps { - request: ServerFunctionRequest; -} - -function convertRequestToEntries(request: Request) { - return [ - ["Cache", request.cache], - ["Credentials", request.credentials], - ["Destination", request.destination], - ["Integrity", request.integrity], - ["Keep Alive", request.keepalive], - ["Mode", request.mode], - ["Redirect", request.redirect], - ["Referrer", request.referrer], - ["Referrer Policy", request.referrerPolicy], - ["URL", request.url], - ]; -} - -function RequestViewer(props: RequestViewerProps): JSX.Element { - return ( - -
- - {([key, value]) => ( -
- {key} - - -
- )} -
-
- -
- ); -} - -interface ResponseViewerProps { - request: ServerFunctionRequest; - response?: ServerFunctionResponse; -} - -function convertResponseToEntries(response: Response) { - return [ - ["OK", response.ok], - ["Redirected", response.redirected], - ["Status", response.status], - ["Status Text", response.statusText], - ["Type", response.type], - ["URL", response.url], - ]; -} - -function ResponseViewer(props: ResponseViewerProps): JSX.Element { - return ( - - - {instance => ( - <> -
- - {([key, value]) => ( -
- {key} - - -
- )} -
-
- Timing - - -
-
- - - )} -
-
- ); -} - -export interface ServerFunctionInstance { - request: ServerFunctionRequest; - response?: ServerFunctionResponse; -} - -interface ServerFunctionInstanceDetailProps { - id: string; - value: ServerFunctionInstance; -} - -function ServerFunctionInstanceDetail(props: ServerFunctionInstanceDetailProps) { - return ( - <> - - {props.value.request.source.method} - {props.id} - - - {response => { - if (response().source.ok) { - return {response().source.status}; - } - return {response().source.status}; - }} - - - ); -} - -interface ServerFunctionInstanceViewerProps { - id: string; - instance: ServerFunctionInstance; - onDelete: () => void; - onReturn: () => void; -} - -function ServerFunctionInstanceViewer(props: ServerFunctionInstanceViewerProps): JSX.Element { - const [tab, setTab] = createSignal<"request" | "response">("request"); - return ( -
-
-
- - - -
- -
-
-
- - - -
-
-
- setTab(value ?? "request")}> - - Request - Response - - - - -
-
- ); -} - -function EmptyServerFunctions(): JSX.Element { - return ( - - No server function calls detected. - - ); -} - -export interface ServerFunctionViewerProps { - instances: Record; - onDeleteInstance: (value: string) => void; - show?: boolean; -} - -export function ServerFunctionViewer(props: ServerFunctionViewerProps): JSX.Element { - const [currentInstance, setCurrentInstance] = createSignal(); - - const keys = createMemo(() => Object.keys(props.instances)); - - return ( - -
-
- {/* request/response viewer */} - - {value => ( - - {instance => ( - { - setCurrentInstance(undefined); - }} - onDelete={() => { - props.onDeleteInstance(value()); - }} - /> - )} - - )} - - - {/* list of calls */} -
- - Server functions -
-
- }> - - -
-
-
-
-
- ); -} diff --git a/packages/start/src/shared/dev-toolbar/functions/styles.css b/packages/start/src/shared/dev-toolbar/functions/styles.css deleted file mode 100644 index 854f9d1bc..000000000 --- a/packages/start/src/shared/dev-toolbar/functions/styles.css +++ /dev/null @@ -1,110 +0,0 @@ -[data-start-functions-instance-detail] { - display: flex; - align-items: center; - gap: 0.5rem; -} - -[data-start-functions-viewer] { - color: rgb(249 250 251); - - display: flex; - flex-direction: column; - - min-height: 100%; -} - -[data-start-functions-instances-container] { - color: rgb(249 250 251); - width: 100%; - min-height: 100%; - overflow: auto; -} - -[data-start-functions-instances] { - list-style: none; - display: flex; - flex-direction: column; - padding: 0px; -} - -[data-start-functions-instances] > [data-start-select-option] { - display: flex; - align-items: center; - justify-content: space-between; - padding: 0.5rem; - color: rgb(249 250 251); -} - -[data-start-headers] { - display: flex; - flex-direction: column; - gap: 0.5rem; -} - -[data-start-headers-title] { - font-weight: 500; -} - -[data-start-properties] { - display: flex; - flex-direction: column; - gap: 0.25rem; -} - -[data-start-property] { - display: flex; - flex-direction: row; - align-items: center; - flex-wrap: nowrap; - - gap: 0.25rem; -} - -[data-start-function-instance-viewer] { - display: flex; - flex-direction: column; - - width: 100%; -} - -[data-start-function-instance-viewer-nav], -[data-start-functions-nav] { - padding: 0.5rem; - display: flex; - align-items: center; - gap: 0.5rem; - - justify-content: space-between; - - position: sticky; - top: 0; - - border-bottom: oklch(87% 0.065 274.039) 1px solid; - - background: oklch(25.7% 0.09 281.288); -} - -[data-start-functions-nav] svg { - padding: 0.25rem; -} - -[data-start-function-instance-viewer-nav-left] { - display: flex; - align-items: center; - gap: 0.5rem; -} - -[data-start-function-instance-viewer-nav-left] > div { - display: flex; - align-items: center; - gap: 0.5rem; -} - -[data-start-function-instance-viewer-content] { - - height: 100%; -} - -[data-start-function-instance-viewer-content] > [tc-tab-group] { - height: 100%; -} diff --git a/packages/start/src/shared/dev-toolbar/functions/tracker.ts b/packages/start/src/shared/dev-toolbar/functions/tracker.ts deleted file mode 100644 index 2fd56f264..000000000 --- a/packages/start/src/shared/dev-toolbar/functions/tracker.ts +++ /dev/null @@ -1,61 +0,0 @@ -export type ServerFunctionRequest = { - type: "request"; - id: string; - instance: string; - source: Request; - time: number; -}; -export type ServerFunctionResponse = { - type: "response"; - id: string; - instance: string; - source: Response; - time: number; -}; - -export type ServerFunctionCall = ServerFunctionRequest | ServerFunctionResponse; - -export type ServerFunctionCallListener = (event: ServerFunctionCall) => void; - -const LISTENERS = new Set(); - -export function captureServerFunctionCall( - listener: ServerFunctionCallListener, -): () => void { - LISTENERS.add(listener); - return () => LISTENERS.delete(listener); -} - -export function pushRequest( - id: string, - instance: string, - source: Request, -): void { - const event: ServerFunctionCall = { - type: "request", - id, - instance, - source, - time: performance.now(), - }; - for (const listener of new Set(LISTENERS)) { - listener(event); - } -} - -export function pushResponse( - id: string, - instance: string, - source: Response, -): void { - const event: ServerFunctionCall = { - type: "response", - id, - instance, - source, - time: performance.now(), - }; - for (const listener of new Set(LISTENERS)) { - listener(event); - } -} diff --git a/packages/start/src/shared/dev-toolbar/index.css b/packages/start/src/shared/dev-toolbar/index.css deleted file mode 100644 index 5b69569dd..000000000 --- a/packages/start/src/shared/dev-toolbar/index.css +++ /dev/null @@ -1,88 +0,0 @@ -[data-start-dev-toolbar] { - position: fixed; - - bottom: 0px; - left: 0px; - - display: flex; - flex-direction: column-reverse; - align-items: flex-start; - - cursor: grab; -} - -[data-start-dev-toolbar]:active { - cursor: grabbing; -} - -[data-start-dev-toolbar] > [tc-toolbar] { - position: relative; - - background: oklch(25.7% 0.09 281.288); - margin: 1rem; - padding: 0.25rem 0.5rem; - - overflow: hidden; - border-radius: 9999px; - - display: flex; - flex-direction: row; - align-items: center; - - gap: 0.5rem; - - border: oklch(87% 0.065 274.039) 1px solid; -} - -[data-start-dev-toolbar] > [tc-toolbar] > div { - display: flex; - - flex-direction: row; - align-items: center; - justify-content: center; -} - -[data-start-dev-toolbar] > [tc-toolbar] > div:last-child { - border-left: rgb(249 250 251) 1px solid; - padding-left: 0.5rem; - - gap: 0.5rem; -} - -[data-start-dev-toolbar-version] { - border-radius: 9999px; - color: rgb(249 250 251); - padding: 0.125rem 0.5rem; - - font-size: 0.875rem; - line-height: 1.25rem; - font-weight: 600; - - border: oklch(87% 0.065 274.039) 1px solid; -} - -[data-start-dev-toolbar-version] > div { - height: 1.5rem; - width: 1.5rem; -} - -[data-start-dev-toolbar] svg { - height: 1.25rem; - width: 1.25rem; -} - -[data-start-dev-toolbar-panel] { - border: oklch(87% 0.065 274.039) 1px solid; - background: oklch(25.7% 0.09 281.288); - margin: 0rem 1rem; - - overflow: auto; - - width: 50rem; - height: 30rem; - - max-width: calc(100vw - 10rem); - max-height: calc(100vh - 2rem); - - border-radius: 1rem; -} diff --git a/packages/start/src/shared/dev-toolbar/index.tsx b/packages/start/src/shared/dev-toolbar/index.tsx deleted file mode 100644 index 7bfa72ef0..000000000 --- a/packages/start/src/shared/dev-toolbar/index.tsx +++ /dev/null @@ -1,242 +0,0 @@ -import { - createEffect, - createSignal, - ErrorBoundary, - onCleanup, - resetErrorBoundaries, - Show, - type JSX, -} from "solid-js"; -import { createStore } from "solid-js/store"; -import { Portal } from "solid-js/web"; -import { Toolbar } from "terracotta"; -import info from "../../../package.json" with { type: "json" }; -import clientOnly from "../clientOnly.ts"; -import { HttpStatusCode } from "../HttpStatusCode.ts"; -import IconButton from "../ui/IconButton.tsx"; -import { Text } from "../ui/Text.tsx"; -import { type ServerFunctionInstance, ServerFunctionViewer } from "./functions/index.tsx"; -import { captureServerFunctionCall } from "./functions/tracker.ts"; -import { ErrorIcon, FunctionIcon, SolidStartIcon } from "./icons.tsx"; -import "./index.css"; - -const ErrorViewer = import.meta.env.PROD - ? () => <> - : clientOnly(() => import("./error-viewer/index.tsx"), { lazy: true }); - -export interface DevToolbarProps { - children?: JSX.Element; -} - -export function DevToolbar(props: DevToolbarProps) { - const [ref, setRef] = createSignal(); - - createEffect(() => { - const current = ref(); - - if (current) { - let isDown = false; - - // Offsets of the mouse relatively to the element's position - let offsetX = 0; - let offsetY = 0; - - let currentX = 0; - let currentY = 0; - - let centerX = 0; - let centerY = 0; - - const resetPosition = () => { - current.style.top = "auto"; - current.style.left = "auto"; - current.style.bottom = "auto"; - current.style.right = "auto"; - }; - - let isDirty = false; - - const ac = new AbortController(); - - current.addEventListener( - "mousedown", - e => { - isDown = true; - - const rect = current.getBoundingClientRect(); - - currentX = rect.left; - currentY = rect.top; - - offsetX = e.clientX - currentX; - offsetY = e.clientY - currentY; - - centerX = rect.width / 2; - centerY = rect.height / 2; - - isDirty = true; - }, - { - signal: ac.signal, - }, - ); - - window.addEventListener( - "mouseup", - () => { - if (isDown && !isDirty) { - const preferredAnchorX = currentX + centerX < window.innerWidth / 2 ? "left" : "right"; - const preferredAnchorY = currentY + centerY < window.innerHeight / 2 ? "top" : "bottom"; - - resetPosition(); - - current.style[preferredAnchorX] = "0px"; - current.style[preferredAnchorY] = "0px"; - - current.style.flexDirection = - preferredAnchorY === "bottom" ? "column-reverse" : "column"; - current.style.alignItems = preferredAnchorX === "left" ? "flex-start" : "flex-end"; - } - isDown = false; - }, - { - signal: ac.signal, - }, - ); - - window.addEventListener( - "mousemove", - e => { - if (isDown) { - if (isDirty) { - resetPosition(); - isDirty = false; - } - currentX = e.clientX - offsetX; - currentY = e.clientY - offsetY; - - current.style.left = `${currentX}px`; - current.style.top = `${currentY}px`; - } - }, - { - signal: ac.signal, - passive: true, - }, - ); - - onCleanup(() => { - ac.abort(); - }); - } - }); - - const [content, setContent] = createSignal<"fn" | "err" | undefined>(undefined); - - function toggleContent(value: "fn" | "err") { - if (content() === value) { - setContent(undefined); - } else { - setContent(value); - } - } - - const [errors, setErrors] = createSignal([]); - - function resetError() { - setErrors([]); - resetErrorBoundaries(); - } - - function pushError(error: unknown) { - console.error(error); - setErrors(current => [error, ...current]); - - setContent("err"); - } - - createEffect(() => { - const onErrorEvent = (error: ErrorEvent) => { - pushError(error.error ?? error); - }; - - window.addEventListener("error", onErrorEvent); - - onCleanup(() => { - window.removeEventListener("error", onErrorEvent); - }); - }); - - const [store, setStore] = createStore({ - instances: {} as Record, - }); - - createEffect(() => { - onCleanup( - captureServerFunctionCall(call => { - console.log(call); - if (call.type === "request") { - setStore("instances", call.instance, value => { - return { - ...value, - request: call, - }; - }); - } else { - setStore("instances", call.instance, value => { - return { - ...value, - response: call, - }; - }); - } - }), - ); - }); - - return ( - <> - -
- -
- toggleContent("err")} disabled={errors().length === 0}> - - - toggleContent("fn")}> - - -
-
- -
- - {info.version as string} - -
-
-
- - { - setStore("instances", value, undefined); - }} - /> -
-
- { - pushError(error); - return ; - }} - > - {props.children} - - 0}> - - - - ); -} diff --git a/packages/start/src/shared/ui/Badge.css b/packages/start/src/shared/ui/Badge.css deleted file mode 100644 index cee81bcf5..000000000 --- a/packages/start/src/shared/ui/Badge.css +++ /dev/null @@ -1,34 +0,0 @@ -[data-start-badge] { - display: inline-flex; - align-items: center; - justify-content: center; - gap: 0.25rem; - - border-radius: 0.375rem; - padding: 0.125rem 0.25rem; - - background-color: var(--background); - border: 1px var(--foreground) solid; - color: var(--foreground); -} - -[data-start-badge="success"] { - --background: oklch(98.2% 0.018 155.826); - --foreground: oklch(52.7% 0.154 150.069); -} - -[data-start-badge="failure"] { - --background: oklch(97.1% 0.013 17.38); - --foreground: oklch(50.5% 0.213 27.518); -} - -[data-start-badge="warning"] { - --background: oklch(98.7% 0.026 102.212); - --foreground: oklch(47.6% 0.114 61.907); -} - - -[data-start-badge="info"] { - --background: oklch(97% 0.014 254.604); - --foreground: oklch(48.8% 0.243 264.376); -} diff --git a/packages/start/src/shared/ui/Badge.tsx b/packages/start/src/shared/ui/Badge.tsx deleted file mode 100644 index 5de35361e..000000000 --- a/packages/start/src/shared/ui/Badge.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import type { JSX } from 'solid-js'; -import './Badge.css'; -import { Text } from './Text.tsx'; - - -export interface BadgeProps { - type: 'info' | 'success' | 'failure' | 'warning'; - children: JSX.Element; -} - -export function Badge(props: BadgeProps): JSX.Element { - return ( - - {props.children} - - ); -} diff --git a/packages/start/src/shared/ui/Button.css b/packages/start/src/shared/ui/Button.css deleted file mode 100644 index e48c1c75c..000000000 --- a/packages/start/src/shared/ui/Button.css +++ /dev/null @@ -1,32 +0,0 @@ -[data-start-button] { - display: flex; - align-items: center; - justify-content: center; - - cursor: pointer; - - border-radius: 0.5rem; - - color: oklch(97% 0.014 254.604); - - background-color: rgb(17 24 39); - padding: 0.25rem 0.5rem; - font-size: 0.875rem; - line-height: 1.25rem; - border: none; - outline: none; - - transition-property: color, background-color, border-color, box-shadow; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; - - white-space: nowrap; -} - -[data-start-button][tc-active], -[data-start-button][tc-selected], -[data-start-button]:hover, -[data-start-button]:focus { - color: rgb(219 234 254); - background-color: rgb(30 58 138); -} diff --git a/packages/start/src/shared/ui/Button.tsx b/packages/start/src/shared/ui/Button.tsx deleted file mode 100644 index a32756439..000000000 --- a/packages/start/src/shared/ui/Button.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import { Button as BaseButton } from "terracotta"; -import "./Button.css"; - -const Button: typeof BaseButton = (props) => ( - -); - -export default Button; diff --git a/packages/start/src/shared/ui/Cascade.css b/packages/start/src/shared/ui/Cascade.css deleted file mode 100644 index db25b019d..000000000 --- a/packages/start/src/shared/ui/Cascade.css +++ /dev/null @@ -1,29 +0,0 @@ -[data-start-cascade] { - display: flex; - flex-direction: column; - margin: 0; - margin-block: 0; - list-style-type: none; - padding-inline: 0; -} - -[data-start-cascade-option] { - border-radius: 0.25rem; - font-size: 0.875rem; - line-height: 1.25rem; - outline: none; - cursor: pointer; - - transition-property: color, background-color, border-color, box-shadow; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; - - white-space: nowrap; -} - -[data-start-cascade-option][tc-active], -[data-start-cascade-option][tc-selected], -[data-start-cascade-option]:focus { - background-color: rgb(219 234 254); - color: rgb(30 58 138); -} diff --git a/packages/start/src/shared/ui/Cascade.tsx b/packages/start/src/shared/ui/Cascade.tsx deleted file mode 100644 index 459b2af25..000000000 --- a/packages/start/src/shared/ui/Cascade.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { - Select as BaseSelect, - SelectOption as BaseSelectOption, -} from "terracotta"; - -import "./Cascade.css"; - -export const Cascade: typeof BaseSelect = (props) => ( - -); -export const CascadeOption: typeof BaseSelectOption = (props) => ( - -); diff --git a/packages/start/src/shared/ui/Dialog.css b/packages/start/src/shared/ui/Dialog.css deleted file mode 100644 index 198f22735..000000000 --- a/packages/start/src/shared/ui/Dialog.css +++ /dev/null @@ -1,26 +0,0 @@ -[data-start-dialog] { - position: fixed; - inset: 0px; - z-index: 50; - overflow-y: auto; -} - - -[data-start-dialog]>div { - position: relative; - display: flex; - align-items: center; - justify-content: center; - min-height: 100vh; -} - -[data-start-dialog-overlay] { - position: absolute; - inset: 0px; - background-color: rgb(17 24 39 / 0.5); -} - -[data-start-dialog-panel] { - margin: 2rem; - z-index: 10; -} diff --git a/packages/start/src/shared/ui/Dialog.tsx b/packages/start/src/shared/ui/Dialog.tsx deleted file mode 100644 index 1e765a05b..000000000 --- a/packages/start/src/shared/ui/Dialog.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { - Dialog as BaseDialog, - DialogOverlay as BaseDialogOverlay, - DialogPanel as BaseDialogPanel, -} from "terracotta"; - -import "./Dialog.css"; - -export const Dialog: typeof BaseDialog = (props) => ( - -); -export const DialogOverlay: typeof BaseDialogOverlay = (props) => ( - -); -export const DialogPanel: typeof BaseDialogPanel = (props) => ( - -); diff --git a/packages/start/src/shared/ui/IconButton.css b/packages/start/src/shared/ui/IconButton.css deleted file mode 100644 index 3a50ec5b8..000000000 --- a/packages/start/src/shared/ui/IconButton.css +++ /dev/null @@ -1,39 +0,0 @@ -[data-start-icon-button] { - display: flex; - padding: 0.25rem; - border-radius: 9999px; - border-width: 0px; - align-items: center; - justify-content: center; - cursor: pointer; - color: rgb(249 250 251); - background: none; - transition-property: color, background-color, border-color, box-shadow; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; -} - -[data-start-icon-button]:hover { - color: rgb(229 231 235); - background-color: rgb(55 65 81); -} - -[data-start-icon-button]:focus { - outline: 2px solid transparent; - outline-color: rgb(249 250 251); - outline-offset: 2px; -} - -[data-start-icon-button]:focus-visible { - box-shadow: 0 0 0 calc(3px) rgb(17 24 39 / 0.75); -} - -[data-start-icon-button]:active { - color: rgb(243 244 246); - background-color: rgb(31 41 55); -} - -[data-start-icon-button] > svg { - height: 1.25rem; - width: 1.25rem; -} diff --git a/packages/start/src/shared/ui/IconButton.tsx b/packages/start/src/shared/ui/IconButton.tsx deleted file mode 100644 index 57417f601..000000000 --- a/packages/start/src/shared/ui/IconButton.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import { Button as BaseButton } from "terracotta"; -import "./IconButton.css"; - -const IconButton: typeof BaseButton = (props) => ( - -); - -export default IconButton; diff --git a/packages/start/src/shared/ui/Placeholder.css b/packages/start/src/shared/ui/Placeholder.css deleted file mode 100644 index 178046658..000000000 --- a/packages/start/src/shared/ui/Placeholder.css +++ /dev/null @@ -1,12 +0,0 @@ -[data-start-placeholder] { - display: flex; - align-items: center; - justify-content: center; - - width: 100%; - height: 100%; -} - -[data-start-placeholder] > span { - text-align: center; -} \ No newline at end of file diff --git a/packages/start/src/shared/ui/Placeholder.tsx b/packages/start/src/shared/ui/Placeholder.tsx deleted file mode 100644 index b2c28be66..000000000 --- a/packages/start/src/shared/ui/Placeholder.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import type { JSX } from 'solid-js'; -import './Placeholder.css'; - -export interface PlaceholderProps { - children?: JSX.Element; -} - -export default function Placeholder(props: PlaceholderProps): JSX.Element { - return ( -
- {props.children} -
- ); -} \ No newline at end of file diff --git a/packages/start/src/shared/ui/Section.css b/packages/start/src/shared/ui/Section.css deleted file mode 100644 index 67b6878b0..000000000 --- a/packages/start/src/shared/ui/Section.css +++ /dev/null @@ -1,19 +0,0 @@ -[data-start-section] { - display: flex; - flex-direction: column; -} - -[data-start-section-title] { - text-transform: uppercase; -} - - -[data-start-section-content] { - margin-left: 0.5rem; - padding-left: 0.5rem; - border-left: 1px oklch(87% 0.065 274.039) solid; - - width: calc(100% - 2rem); - - overflow: auto; -} diff --git a/packages/start/src/shared/ui/Section.tsx b/packages/start/src/shared/ui/Section.tsx deleted file mode 100644 index 0524ed4f0..000000000 --- a/packages/start/src/shared/ui/Section.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import type { JSX } from "solid-js"; -import { Text, type TextProps } from "./Text.tsx"; - -import './Section.css'; - -export interface SectionProps { - title: string; - options?: TextProps<'span'>['options']; - children: JSX.Element; -} - -export function Section(props: SectionProps): JSX.Element { - return ( -
- - {props.title} - -
- {props.children} -
-
- ); -} diff --git a/packages/start/src/shared/ui/Select.css b/packages/start/src/shared/ui/Select.css deleted file mode 100644 index 1cc2a3131..000000000 --- a/packages/start/src/shared/ui/Select.css +++ /dev/null @@ -1,37 +0,0 @@ -[data-start-select] { - display: flex; - flex-direction: column; - margin: 0; - margin-block: 0; - list-style-type: none; - padding-inline: 0; -} - -[data-start-select] > * + * { - border-top: 1px oklch(87% 0.065 274.039) solid; -} - -[data-start-select-option] { - color: rgb(249 250 251); - padding-top: 0.5rem; - padding-bottom: 0.5rem; - padding-left: 1rem; - padding-right: 1rem; - font-size: 0.875rem; - line-height: 1.25rem; - outline: none; - cursor: pointer; - - transition-property: color, background-color, border-color, box-shadow; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; - - white-space: nowrap; -} - -[data-start-select-option][tc-active], -[data-start-select-option][tc-selected], -[data-start-select-option]:focus { - color: rgb(229 231 235); - background-color: rgb(55 65 81); -} diff --git a/packages/start/src/shared/ui/Select.tsx b/packages/start/src/shared/ui/Select.tsx deleted file mode 100644 index 2d648832a..000000000 --- a/packages/start/src/shared/ui/Select.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { - Select as BaseSelect, - SelectOption as BaseSelectOption, -} from "terracotta"; - -import "./Select.css"; - -export const Select: typeof BaseSelect = (props) => ( - -); -export const SelectOption: typeof BaseSelectOption = (props) => ( - -); diff --git a/packages/start/src/shared/ui/Table.css b/packages/start/src/shared/ui/Table.css deleted file mode 100644 index 6703f4d96..000000000 --- a/packages/start/src/shared/ui/Table.css +++ /dev/null @@ -1,22 +0,0 @@ -[data-start-table] { - border: 1px oklch(70.7% 0.165 254.624) solid; -} - -[data-start-table-header] { - display: flex; - flex-direction: row; - background-color: oklch(93.2% 0.032 255.585); - font-weight: 600; -} - -[data-start-table-row] { - display: flex; - flex-direction: row; - border-top: 1px oklch(70.7% 0.165 254.624) solid; -} - -[data-start-table-cell] { - flex: 1; - padding: 0.5rem 1rem; - overflow: auto; -} diff --git a/packages/start/src/shared/ui/Table.tsx b/packages/start/src/shared/ui/Table.tsx deleted file mode 100644 index 87eeb18f0..000000000 --- a/packages/start/src/shared/ui/Table.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import type { ComponentProps, JSX } from 'solid-js'; - -import './Table.css'; - -type TableProps = ComponentProps<'div'>; - -export function Table(props: TableProps): JSX.Element { - return ( -
- ); -} - -type TableHeaderProps = ComponentProps<'div'>; - -export function TableHeader(props: TableHeaderProps): JSX.Element { - return ( -
- ); -} - -type TableRowProps = ComponentProps<'div'>; - -export function TableRow(props: TableRowProps): JSX.Element { - return ( -
- ); -} - -type TableCellProps = ComponentProps<'div'>; - -export function TableCell(props: TableCellProps): JSX.Element { - return ( -
- ); -} diff --git a/packages/start/src/shared/ui/Tabs.css b/packages/start/src/shared/ui/Tabs.css deleted file mode 100644 index 6143573b2..000000000 --- a/packages/start/src/shared/ui/Tabs.css +++ /dev/null @@ -1,51 +0,0 @@ -[data-start-tab] { - display: flex; - align-items: center; - justify-content: center; - - border-radius: 0.5rem; - cursor: pointer; - - padding-top: 0.5rem; - padding-bottom: 0.5rem; - padding-left: 1rem; - padding-right: 1rem; - font-size: 0.875rem; - line-height: 1.25rem; - border: none; - outline: none; - - transition-property: color, background-color, border-color, box-shadow; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transition-duration: 150ms; -} - -[data-start-tab][tc-active], -[data-start-tab][tc-selected], -[data-start-tab]:hover, -[data-start-tab]:focus { - color: rgb(229 231 235); - background-color: rgb(55 65 81); -} - -[data-start-tab-group] { -} - -[data-start-tab-list] { - display: flex; - gap: 0.5rem; - margin: 0.5rem; -} - -[data-start-tab-panel] { - height: 100%; - - overflow: auto; - - display: flex; - flex-direction: column; - gap: 0.5rem; - padding: 0.5rem; - - border-top: oklch(87% 0.065 274.039) 1px solid; -} diff --git a/packages/start/src/shared/ui/Tabs.tsx b/packages/start/src/shared/ui/Tabs.tsx deleted file mode 100644 index 1ef39f24e..000000000 --- a/packages/start/src/shared/ui/Tabs.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { - Tab as BaseTab, - TabGroup as BaseTabGroup, - TabList as BaseTabList, - TabPanel as BaseTabPanel, -} from "terracotta"; - -import "./Tabs.css"; - -export const Tab: typeof BaseTab = (props) => ( - -); -export const TabGroup: typeof BaseTabGroup = (props) => ( - -); -export const TabPanel: typeof BaseTabPanel = (props) => ( - -); -export const TabList: typeof BaseTabList = (props) => ( - -); - diff --git a/packages/start/src/shared/ui/Text.css b/packages/start/src/shared/ui/Text.css deleted file mode 100644 index a67b817da..000000000 --- a/packages/start/src/shared/ui/Text.css +++ /dev/null @@ -1,69 +0,0 @@ -[data-start-text-size="xs"] { - font-size: 0.75rem; - line-height: calc(1 / 0.75); -} -[data-start-text-size="sm"] { - font-size: 0.875rem; - line-height: calc(1.25 / 0.875); -} -[data-start-text-size="base"] { - font-size: 1rem; - line-height: 1.5; -} -[data-start-text-size="lg"] { - font-size: 1.125rem; - line-height: calc(1.75 / 1.125); -} -[data-start-text-size="xl"] { - font-size: 1.25rem; - line-height: calc(1.75 / 1.25); -} -[data-start-text-size="2xl"] { - font-size: 1.5rem; - line-height: calc(2 / 1.5); -} - -[data-start-text-font="sans"] { - font-family: system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; -} -[data-start-text-font="serif"] { - font-family: ui-serif, Georgia, Cambria, 'Times New Roman', Times, serif; -} -[data-start-text-font="mono"] { - font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace; -} - -[data-start-text-weight="thin"] { - font-weight: 100; -} -[data-start-text-weight="extralight"] { - font-weight: 200; -} -[data-start-text-weight="light"] { - font-weight: 300; -} -[data-start-text-weight="normal"] { - font-weight: 400; -} -[data-start-text-weight="medium"] { - font-weight: 500; -} -[data-start-text-weight="semibold"] { - font-weight: 600; -} -[data-start-text-weight="bold"] { - font-weight: 700; -} -[data-start-text-weight="extrabold"] { - font-weight: 800; -} -[data-start-text-weight="black"] { - font-weight: 900; -} - -[data-start-text-wrap="wrap"] { - white-space: wrap; -} -[data-start-text-wrap="nowrap"] { - white-space: nowrap; -} diff --git a/packages/start/src/shared/ui/Text.tsx b/packages/start/src/shared/ui/Text.tsx deleted file mode 100644 index 44bad1b2d..000000000 --- a/packages/start/src/shared/ui/Text.tsx +++ /dev/null @@ -1,37 +0,0 @@ -import { type ComponentProps, createMemo, type JSX, splitProps } from 'solid-js'; -import { Dynamic } from 'solid-js/web'; - -import './Text.css'; - -export type TextProps = ComponentProps & { - options?: { - as?: T; - size?: 'xs' | 'sm' | 'base' | 'lg' | 'xl' | '2xl'; - font?: 'sans' | 'serif' | 'mono'; - weight?: 'thin' | 'extralight' | 'light' | 'normal' | 'medium' | 'semibold' | 'bold' | 'extrabold'; - wrap?: 'wrap' | 'nowrap'; - }; -}; - -export function Text(props: TextProps): JSX.Element { - const [current, rest] = splitProps(props, ['options']); - - const customization = createMemo>(() => { - const options = Object.assign({}, { - size: 'base', - font: 'mono', - weight: 'normal', - wrap: 'wrap', - }, current.options); - const entries = Object.entries(options); - return Object.fromEntries(entries.map(([key, value]) => [`data-start-text-${key}`, value])) as TextProps; - }); - - return ( - - ); -} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5f8caf4dd..941fb7e35 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -387,8 +387,8 @@ importers: specifier: ^0.12.0 version: 0.12.0 terracotta: - specifier: ^1.1.1 - version: 1.1.1(solid-js@1.9.11) + specifier: ^1.1.0 + version: 1.1.0(solid-js@1.9.11) vite-plugin-solid: specifier: ^2.11.11 version: 2.11.11(@testing-library/jest-dom@6.9.1)(solid-js@1.9.11)(vite@8.1.4(@types/node@25.5.0)(esbuild@0.27.4)(jiti@2.7.0)(terser@5.46.0)) @@ -3179,8 +3179,8 @@ packages: resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} engines: {node: '>=8'} - terracotta@1.1.1: - resolution: {integrity: sha512-Sa6wnvkGMFmPq8N/wQb2aKkIW2eXH0LJvUOEk6QZLBEjqy+LsbzAOpDuqEfOmfA/hexssE6eQve2i1IIOeOh4g==} + terracotta@1.1.0: + resolution: {integrity: sha512-kfQciWUBUBgYkXu7gh3CK3FAJng/iqZslAaY08C+k1Hdx17aVEpcFFb/WPaysxAfcupNH3y53s/pc53xxZauww==} engines: {node: '>=10'} peerDependencies: solid-js: ^1.8 @@ -6247,7 +6247,7 @@ snapshots: term-size@2.2.1: {} - terracotta@1.1.1(solid-js@1.9.11): + terracotta@1.1.0(solid-js@1.9.11): dependencies: solid-js: 1.9.11 solid-use: 0.9.1(solid-js@1.9.11)