From 3c06c95f396b6e911076bc3291d5855ed01b5caa Mon Sep 17 00:00:00 2001 From: "netop://ウィビ" Date: Sun, 26 Apr 2026 20:18:30 -0700 Subject: cleanup and ready for launch --- .gitignore | 1 - .npmignore | 10 +- PLAN.md | 218 ------------ README.md | 14 +- package.json | 50 +-- playground/index.html | 26 +- playground/src/App.svelte | 31 +- playground/src/favicon.svg | 15 + playground/src/main.ts | 10 + source/library/GraphiQL.svelte | 392 +++++++++++++-------- source/library/components/DocExplorer.svelte | 134 +++---- .../components/DocExplorer/FieldView.svelte | 46 +-- .../library/components/DocExplorer/TypeLink.svelte | 16 +- .../library/components/DocExplorer/TypeView.svelte | 71 ++-- source/library/components/Editor.svelte | 9 +- source/library/components/HeadersEditor.svelte | 34 -- source/library/components/HistoryPanel.svelte | 225 ++++++------ source/library/components/ResultViewer.svelte | 97 +++-- source/library/components/Splitter.svelte | 95 ++--- source/library/components/TabBar.svelte | 122 ++++--- source/library/components/Toolbar.svelte | 130 +++++-- source/library/fetcher/apq.ts | 3 +- source/library/fetcher/sse.ts | 12 +- source/library/graphiql.d.ts | 1 + source/library/graphql/markdown.ts | 45 +++ source/library/index.ts | 7 +- source/library/runes.d.ts | 37 -- source/library/state/history.svelte.ts | 2 - source/library/state/session-io.ts | 116 +++--- source/library/state/session.svelte.ts | 34 +- source/library/styles/theme.scss | 47 --- source/library/themes/light.ts | 138 ++++++-- svelte.config.js | 17 +- tests/apq.test.ts | 70 ++-- tests/format.test.ts | 3 +- tests/history.test.ts | 18 +- tests/keyboard.test.ts | 24 +- tests/operations.test.ts | 8 +- tests/session-io.test.ts | 51 +-- tests/storage.test.ts | 80 +++-- tests/timing.test.ts | 21 +- tsconfig.json | 5 +- vite.config.ts | 21 +- vitest.config.ts | 11 +- 44 files changed, 1361 insertions(+), 1156 deletions(-) delete mode 100644 PLAN.md create mode 100644 playground/src/favicon.svg delete mode 100644 source/library/components/HeadersEditor.svelte create mode 100644 source/library/graphiql.d.ts create mode 100644 source/library/graphql/markdown.ts delete mode 100644 source/library/runes.d.ts delete mode 100644 source/library/styles/theme.scss diff --git a/.gitignore b/.gitignore index 88b84bb..fc6689a 100644 --- a/.gitignore +++ b/.gitignore @@ -5,7 +5,6 @@ package-lock.json Thumbs.db # Directories -.claude .svelte-kit dist/ node_modules/ diff --git a/.npmignore b/.npmignore index f1b7da2..56f8952 100644 --- a/.npmignore +++ b/.npmignore @@ -1,9 +1,11 @@ -source/ -tests/ -playground/ -PLAN.md +# Files .gitignore svelte.config.js tsconfig.json vite.config.ts vitest.config.ts + +# Directories +playground/ +source/ +tests/ diff --git a/PLAN.md b/PLAN.md deleted file mode 100644 index f97e7ac..0000000 --- a/PLAN.md +++ /dev/null @@ -1,218 +0,0 @@ -# PLAN.md — @eol/graphiql - -A Svelte 5 GraphiQL alternative. JSR-published under the EOL scope. - -## Current state (v0.2 complete) - -Shipped: - -- HTTP fetcher with injectable `fetch` impl -- Schema introspection and SDL caching -- Session store with tabs, persistence, and rename -- TabBar with double-click inline rename (Enter commits, Escape cancels, blur commits) -- Toolbar with Cmd/Ctrl+Enter run shortcut -- Variables + Headers panes (switchable in bottom-left) -- Debounced localStorage persistence (300ms) with `beforeunload` flush -- Memory storage fallback for SSR -- CodeMirror 6 editor wrapper via `cm6-graphql` with dynamic import (SSR-safe) -- `readOnly` prop on Editor, used by ResultViewer -- Reactive schema updates via `$effect` calling `updateSchema()` -- Public API surface in `src/lib/index.ts` - -Stub files needing implementation: `src/lib/fetcher/sse.ts`, `src/lib/fetcher/websocket.ts`. - -## Coding conventions - -Non-negotiable. Match existing files exactly: - -- Double quotes, semicolons, two-space indent -- No trailing spaces, no unnecessary whitespace -- Svelte component structure: ` diff --git a/playground/src/App.svelte b/playground/src/App.svelte index dc4f0a5..350f956 100644 --- a/playground/src/App.svelte +++ b/playground/src/App.svelte @@ -1,24 +1,33 @@ - + diff --git a/playground/src/favicon.svg b/playground/src/favicon.svg new file mode 100644 index 0000000..80a7a21 --- /dev/null +++ b/playground/src/favicon.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/playground/src/main.ts b/playground/src/main.ts index bf39df9..03a4c37 100644 --- a/playground/src/main.ts +++ b/playground/src/main.ts @@ -1,8 +1,18 @@ + + + +/*** IMPORT ------------------------------------------- ***/ + import { mount } from "svelte"; + +/*** UTILITY ------------------------------------------ ***/ + import App from "./App.svelte"; const target = document.getElementById("app"); +/*** RUNTIME ------------------------------------------ ***/ + if (!target) throw new Error("missing #app target"); diff --git a/source/library/GraphiQL.svelte b/source/library/GraphiQL.svelte index 0f1e0fd..3ffc372 100644 --- a/source/library/GraphiQL.svelte +++ b/source/library/GraphiQL.svelte @@ -1,28 +1,28 @@ @@ -357,11 +397,22 @@ .graphiql { width: 100%; height: 100%; - background-color: var(--graphiql-bg, #1e1e1e); - color: var(--graphiql-fg, #d4d4d4); - display: grid; - font-family: var(--graphiql-font, ui-monospace, SFMono-Regular, monospace); - grid-template-rows: auto auto 1fr; + background-color: var(--uchu-yang); + color: var(--uchu-yin-9); + font-family: "Berkeley Mono", ui-monospace, SFMono-Regular, monospace; + font-size: 16px; + overflow: hidden; + overscroll-behavior: none; + + @media (min-width: 1025px) { + display: grid; + grid-template-rows: auto auto 1fr; + } + + @media (max-width: 1024px) { + display: flex; + flex-direction: column; + } } .panes { @@ -369,6 +420,10 @@ grid-template-columns: 1fr; min-height: 0; + @media (max-width: 1024px) { + height: stretch; + } + &.history-open { grid-template-columns: var(--graphiql-history-width) 6px 1fr; } @@ -382,61 +437,91 @@ } } - .center { - display: grid; - grid-template-columns: var(--graphiql-left-width) 6px calc(100% - var(--graphiql-left-width) - 6px); - min-height: 0; - min-width: 0; - } - + .center, .left { - display: grid; - grid-template-rows: 1fr auto 6px var(--graphiql-bottom-height); + margin-right: -6px; min-height: 0; min-width: 0; } - .query { - min-height: 0; - } + .center { + @media (min-width: 1025px) { + display: grid; + grid-template-columns: var(--graphiql-left-width) 6px calc(100% - var(--graphiql-left-width) - 6px); + } - .switcher { - background-color: var(--graphiql-panel, #252526); - border-top: 1px solid var(--graphiql-border, #333); - display: flex; - } + @media (max-width: 1024px) { + display: flex; + flex-direction: column; + } - .switch { - background: none; - border: none; - cursor: pointer; - font-size: 0.75rem; - letter-spacing: 0.05em; - padding: 0.375rem 0.75rem; - text-transform: uppercase; + .query { + flex: 2; + margin-bottom: -6px; + min-height: 0; + } - &:not(.active) { - color: var(--graphiql-muted, #858585); + .bottom { + flex: 1; + min-height: 0; } - &.active { - color: var(--graphiql-fg, #d4d4d4); + .left { + display: flex; + flex-direction: column; + overflow-x: hidden; + + @media (max-width: 1024px) { + flex: 2; + } } - } - .bottom { - min-height: 0; + .right { + min-height: 0; + + @media (max-width: 1024px) { + border-top: 2px solid var(--uchu-gray-3); + flex: 1; + } + } } - .right { - min-height: 0; + .switcher { + background-color: var(--uchu-gray-2); + display: flex; + flex-direction: row; + + .switch { + background: none; + border: none; + cursor: pointer; + font-family: "Berkeley Mono", ui-monospace, SFMono-Regular, monospace; + font-size: 0.75rem; + font-weight: 600; + letter-spacing: 0.05rem; + padding: 0.375rem 0.75rem; + text-transform: uppercase; + + &:not(.active) { + color: var(--uchu-yin-5); + } + + &.active { + background-color: var(--uchu-gray-3); + } + } } .status { - background-color: var(--graphiql-panel, #252526); - border-top: 1px solid var(--graphiql-border, #333); + background-color: var(--uchu-yellow-2); + border-top: 1px solid var(--uchu-yellow-3); + color: var(--uchu-yellow-9); font-size: 0.75rem; padding: 0.25rem 0.75rem; + + span { + text-transform: uppercase; + } } @@ -473,8 +558,7 @@ class="panes" class:docs-open={docsOpen && schema.schema} class:history-open={historyOpen} - style="--graphiql-history-width: {historyWidth}px; --graphiql-docs-width: {docsWidth}px;" - > + style="--graphiql-history-width: {historyWidth}px; --graphiql-docs-width: {docsWidth}px;"> {#if historyOpen} {/if} +
+ style="--graphiql-left-width: {leftWidth}%;">
-
- - -
+ +
+
+ + +
+ {#if bottomPane === "variables"} {:else} - {/if}
- + + {#if windowWidth >= 1025} + + {/if} +
+ {#if docsOpen && schema.schema} {/if} + {#if schema.error} -
Schema error: {schema.error}
+
Schema error {schema.error}
{/if} diff --git a/source/library/components/DocExplorer.svelte b/source/library/components/DocExplorer.svelte index 536cb2a..48525e1 100644 --- a/source/library/components/DocExplorer.svelte +++ b/source/library/components/DocExplorer.svelte @@ -1,18 +1,19 @@ @@ -200,10 +202,12 @@ onclick={() => gotoIndex(i)}>{crumbLabel(entry)} {/each} +
{#if stack.length === 0}
+
{#each rootTypes as entry} - {/if} - {#if onImport} - - - {/if} - {#if entries.length > 0} - - {/if} -
+
+ History + +
+ {#if onExport} + + {/if} + + {#if onImport} + + + {/if} + + {#if entries.length > 0} + + {/if}
- {#if notice} -
- {notice} - {#if onDismissNotice} - - {/if} -
- {/if}
+ + {#if notice} +
+ {notice} + {#if onDismissNotice} + + {/if} +
+ {/if} +
{#if sorted.length === 0}
No history yet.
@@ -264,16 +271,28 @@ class="star" class:active={entry.favorite} onclick={(e) => { e.stopPropagation(); onFavorite(entry.id); }} - type="button">{entry.favorite ? "★" : "☆"} + type="button"> + {#if entry.favorite} + + + + {:else} + + + + {/if} + +
{entry.title}
{formatTimestamp(entry.timestamp)}
+ + type="button">×
{/each} {/if} diff --git a/source/library/components/ResultViewer.svelte b/source/library/components/ResultViewer.svelte index d277ec8..270965b 100644 --- a/source/library/components/ResultViewer.svelte +++ b/source/library/components/ResultViewer.svelte @@ -1,7 +1,10 @@
Response
+ + {#if metadata} - + {/if} + {#if footer} {/if} diff --git a/source/library/components/Splitter.svelte b/source/library/components/Splitter.svelte index 73d0e10..a758385 100644 --- a/source/library/components/Splitter.svelte +++ b/source/library/components/Splitter.svelte @@ -1,4 +1,5 @@ @@ -145,8 +169,7 @@ } }} role="tab" - tabindex="0" - > + tabindex="0"> {#if editingId === tab.id} e.stopPropagation()} onkeydown={onKeydown} - type="text" - /> + type="text"/> {:else} {tab.title} {/if} + {#if extras}{@render extras({ tab })}{/if} + + onclick={(e) => handleClose(e, tab.id)}>×
{/each} +
diff --git a/source/library/components/Toolbar.svelte b/source/library/components/Toolbar.svelte index 9882b7d..37cc7ce 100644 --- a/source/library/components/Toolbar.svelte +++ b/source/library/components/Toolbar.svelte @@ -1,7 +1,10 @@