@solidjs/start 2.0.3 → 2.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/config/fs-router.js +24 -28
  3. package/dist/shared/dev-toolbar/error-viewer/CodeView.jsx +9 -4
  4. package/dist/shared/dev-toolbar/error-viewer/create-stack-frame.d.ts +2 -1
  5. package/dist/shared/dev-toolbar/error-viewer/create-stack-frame.js +29 -19
  6. package/dist/shared/dev-toolbar/error-viewer/get-source-map.d.ts +2 -2
  7. package/dist/shared/dev-toolbar/error-viewer/get-source-map.js +3 -2
  8. package/dist/shared/dev-toolbar/error-viewer/index.jsx +52 -35
  9. package/dist/shared/dev-toolbar/error-viewer/styles.css +91 -43
  10. package/dist/shared/dev-toolbar/functions/BlobViewer.css +50 -2
  11. package/dist/shared/dev-toolbar/functions/BlobViewer.jsx +23 -4
  12. package/dist/shared/dev-toolbar/functions/FormDataViewer.jsx +9 -6
  13. package/dist/shared/dev-toolbar/functions/HeadersViewer.css +0 -4
  14. package/dist/shared/dev-toolbar/functions/HeadersViewer.jsx +9 -7
  15. package/dist/shared/dev-toolbar/functions/HexViewer.css +36 -17
  16. package/dist/shared/dev-toolbar/functions/HexViewer.jsx +7 -6
  17. package/dist/shared/dev-toolbar/functions/SerovalValue.css +21 -0
  18. package/dist/shared/dev-toolbar/functions/SerovalValue.d.ts +1 -0
  19. package/dist/shared/dev-toolbar/functions/SerovalValue.jsx +4 -2
  20. package/dist/shared/dev-toolbar/functions/SerovalViewer.css +98 -36
  21. package/dist/shared/dev-toolbar/functions/SerovalViewer.jsx +268 -279
  22. package/dist/shared/dev-toolbar/functions/URLSearchParamsViewer.jsx +9 -6
  23. package/dist/shared/dev-toolbar/functions/index.jsx +96 -69
  24. package/dist/shared/dev-toolbar/functions/styles.css +143 -10
  25. package/dist/shared/dev-toolbar/index.css +54 -14
  26. package/dist/shared/dev-toolbar/index.jsx +8 -1
  27. package/dist/shared/ui/Badge.css +21 -10
  28. package/dist/shared/ui/Button.css +7 -6
  29. package/dist/shared/ui/IconButton.css +16 -10
  30. package/dist/shared/ui/Placeholder.css +2 -0
  31. package/dist/shared/ui/Section.css +42 -3
  32. package/dist/shared/ui/Section.d.ts +3 -1
  33. package/dist/shared/ui/Section.jsx +14 -6
  34. package/dist/shared/ui/Select.css +11 -4
  35. package/dist/shared/ui/Tabs.css +30 -16
  36. package/package.json +5 -5
  37. package/dist/shared/ui/Cascade.css +0 -29
  38. package/dist/shared/ui/Cascade.d.ts +0 -4
  39. package/dist/shared/ui/Cascade.jsx +0 -4
  40. package/dist/shared/ui/Dialog.css +0 -25
  41. package/dist/shared/ui/Dialog.d.ts +0 -5
  42. package/dist/shared/ui/Dialog.jsx +0 -5
  43. package/dist/shared/ui/Table.css +0 -22
  44. package/dist/shared/ui/Table.d.ts +0 -11
  45. package/dist/shared/ui/Table.jsx +0 -13
package/CHANGELOG.md CHANGED
@@ -1,5 +1,24 @@
1
1
  # @solidjs/start
2
2
 
3
+ ## 2.0.5
4
+
5
+ ### Patch Changes
6
+
7
+ - eca4cc4: Only strip a whole `index` segment when mapping route files to paths. Route files whose names merely end in "index", such as `routes/reindex.tsx`, were previously served at `/re` instead of `/reindex`.
8
+
9
+ ## 2.0.4
10
+
11
+ ### Patch Changes
12
+
13
+ - ac3f321: Parse stack traces in the dev toolbar's error overlay with `error-stack-parser-es/lite` instead of `error-stack-parser`. The lite entry point is a much smaller, ESM-only parser that returns plain frame objects rather than class instances, and it no longer pulls in the `stackframe` package. Errors that carry no stack are now handled as an empty frame list instead of throwing.
14
+ - ac3f321: Redesign the dev toolbar. The toolbar and its panels share a common set of design tokens, giving them a consistent dark palette, translucent surfaces, and elevation. The server function inspector is now a master-detail split with a persistent call list beside the request/response pane, and the error overlay places the stack frame list beside a code preview that fills the panel. Headers, form data, and URL search params render as aligned key-value tables, the hex viewer gains an offset gutter with the ASCII column aligned per row, and blobs are shown as file cards with their type and size. The seroval body inspector is now an expandable tree with collapsed previews, syntax-colored values, cycle detection, and live promise and stream state, replacing the previous column-based drill-down.
15
+
16
+ Along with the redesign, the toolbar only starts a drag from the toolbar itself rather than from its panels, unhandled promise rejections are captured by the error overlay, the code preview shows more surrounding lines, and a stack frame whose source cannot be loaded now stays listed and reports that its source is unavailable instead of silently rendering nothing.
17
+
18
+ - ac3f321: Use `@jridgewell/trace-mapping` instead of `source-map-js` to resolve original sources in the dev toolbar's error overlay. It decodes mappings lazily, so only the positions actually inspected are resolved, it is significantly smaller in the browser bundle, and it understands indexed source maps.
19
+ - f619c7f: Pre-bundle the dev toolbar's CommonJS dependencies so it no longer throws on every dev page load
20
+ - d43ad1b: Update Solid to 1.9.15 to include the latest lazy loading and hydration fixes
21
+
3
22
  ## 2.0.3
4
23
 
5
24
  ### Patch Changes
@@ -1,20 +1,29 @@
1
1
  import { analyzeModule, BaseFileSystemRouter, cleanPath, } from "./fs-routes/router.js";
2
+ /**
3
+ * Maps a route file to its router path: strips the routes directory and extension,
4
+ * drops a trailing `index` segment (`blog/index` -> `/blog/`, `index` -> `/`) and
5
+ * converts `[param]`, `[[optional]]` and `[...rest]` segments to router syntax.
6
+ */
7
+ function toRoutePath(src, config) {
8
+ const routePath = cleanPath(src, config)
9
+ // remove the initial slash
10
+ .slice(1)
11
+ // only strip a whole `index` segment, not a name that merely ends in "index" (e.g. `reindex`)
12
+ .replace(/(^|\/)index$/, "$1")
13
+ .replace(/\[([^/]+)\]/g, (_, m) => {
14
+ if (m.length > 3 && m.startsWith("...")) {
15
+ return `*${m.slice(3)}`;
16
+ }
17
+ if (m.length > 2 && m.startsWith("[") && m.endsWith("]")) {
18
+ return `:${m.slice(1, -1)}?`;
19
+ }
20
+ return `:${m}`;
21
+ });
22
+ return routePath.length > 0 ? `/${routePath}` : "/";
23
+ }
2
24
  export class SolidStartClientFileRouter extends BaseFileSystemRouter {
3
25
  toPath(src) {
4
- const routePath = cleanPath(src, this.config)
5
- // remove the initial slash
6
- .slice(1)
7
- .replace(/index$/, "")
8
- .replace(/\[([^/]+)\]/g, (_, m) => {
9
- if (m.length > 3 && m.startsWith("...")) {
10
- return `*${m.slice(3)}`;
11
- }
12
- if (m.length > 2 && m.startsWith("[") && m.endsWith("]")) {
13
- return `:${m.slice(1, -1)}?`;
14
- }
15
- return `:${m}`;
16
- });
17
- return routePath?.length > 0 ? `/${routePath}` : "/";
26
+ return toRoutePath(src, this.config);
18
27
  }
19
28
  toRoute(src) {
20
29
  const path = this.toPath(src);
@@ -87,20 +96,7 @@ export class SolidStartServerFileRouter extends BaseFileSystemRouter {
87
96
  super(config);
88
97
  }
89
98
  toPath(src) {
90
- const routePath = cleanPath(src, this.config)
91
- // remove the initial slash
92
- .slice(1)
93
- .replace(/index$/, "")
94
- .replace(/\[([^/]+)\]/g, (_, m) => {
95
- if (m.length > 3 && m.startsWith("...")) {
96
- return `*${m.slice(3)}`;
97
- }
98
- if (m.length > 2 && m.startsWith("[") && m.endsWith("]")) {
99
- return `:${m.slice(1, -1)}?`;
100
- }
101
- return `:${m}`;
102
- });
103
- return routePath?.length > 0 ? `/${routePath}` : "/";
99
+ return toRoutePath(src, this.config);
104
100
  }
105
101
  toRoute(src) {
106
102
  const path = this.toPath(src);
@@ -19,7 +19,7 @@ async function loadHighlighter() {
19
19
  }
20
20
  return HIGHLIGHTER;
21
21
  }
22
- const RANGE = 8;
22
+ const RANGE = 15;
23
23
  export function CodeView(props) {
24
24
  const lines = () => props.content.split("\n").map((item, index) => ({
25
25
  index: index + 1,
@@ -34,9 +34,14 @@ export function CodeView(props) {
34
34
  .join("\n"), async (value) => {
35
35
  const highlighter = await loadHighlighter();
36
36
  const fileExtension = props.fileName.split(/[#?]/)[0].split(".").pop()?.trim();
37
- let lang = fileExtension;
38
- if (fileExtension === "mjs" || fileExtension === "cjs") {
39
- lang = "js";
37
+ // Only these grammars are loaded — anything else would make shiki
38
+ // throw. Fall back to plain JS highlighting for unknown sources.
39
+ let lang = "js";
40
+ if (fileExtension === "jsx" ||
41
+ fileExtension === "ts" ||
42
+ fileExtension === "tsx" ||
43
+ fileExtension === "js") {
44
+ lang = fileExtension;
40
45
  }
41
46
  return highlighter.codeToHtml(value, {
42
47
  theme: "dark-plus",
@@ -1,3 +1,4 @@
1
+ import type { StackFrameLite } from "error-stack-parser-es/lite";
1
2
  import { type Accessor } from "solid-js";
2
3
  export interface StackFrameSource {
3
4
  content: string;
@@ -6,4 +7,4 @@ export interface StackFrameSource {
6
7
  line: number;
7
8
  column: number;
8
9
  }
9
- export declare function createStackFrame(stackframe: StackFrame, isCompiled: () => boolean): Accessor<StackFrameSource>;
10
+ export declare function createStackFrame(stackframe: StackFrameLite, isCompiled: () => boolean): Accessor<StackFrameSource>;
@@ -1,3 +1,4 @@
1
+ import { originalPositionFor, sourceContentFor } from "@jridgewell/trace-mapping";
1
2
  import { createMemo, createResource } from "solid-js";
2
3
  import getSourceMap from "./get-source-map.js";
3
4
  const HTTP_URL_REGEX = /^https?:\/\//;
@@ -20,27 +21,36 @@ function getActualFileSource(path) {
20
21
  }
21
22
  export function createStackFrame(stackframe, isCompiled) {
22
23
  const [data] = createResource(() => ({
23
- fileName: stackframe.fileName,
24
- line: stackframe.lineNumber,
25
- column: stackframe.columnNumber,
26
- functionName: stackframe.functionName,
24
+ fileName: stackframe.file,
25
+ line: stackframe.line,
26
+ column: stackframe.col,
27
+ functionName: stackframe.function,
27
28
  }), async (source) => {
28
29
  if (!source.fileName) {
29
30
  return null;
30
31
  }
31
- const url = getActualFileSource(source.fileName);
32
- const response = await fetch(url);
33
- if (!response.ok) {
32
+ // Sources can be unreachable — node internals, extension scripts,
33
+ // files outside the dev server's allowlist. Treat any failure as
34
+ // "no source" instead of throwing into the error boundary.
35
+ try {
36
+ const url = getActualFileSource(source.fileName);
37
+ const response = await fetch(url);
38
+ if (!response.ok) {
39
+ return null;
40
+ }
41
+ const content = await response.text();
42
+ const sourceMap = await getSourceMap(url, content);
43
+ return {
44
+ source,
45
+ content,
46
+ sourceMap,
47
+ isServer: isServerSource(source.fileName),
48
+ };
49
+ }
50
+ catch (error) {
51
+ console.warn("[start dev toolbar] failed to load source for stack frame", error);
34
52
  return null;
35
53
  }
36
- const content = await response.text();
37
- const sourceMap = await getSourceMap(url, content);
38
- return {
39
- source,
40
- content,
41
- sourceMap,
42
- isServer: isServerSource(source.fileName),
43
- };
44
54
  });
45
55
  const info = createMemo(() => {
46
56
  const current = data();
@@ -52,8 +62,8 @@ export function createStackFrame(stackframe, isCompiled) {
52
62
  if (isServer) {
53
63
  // The position is already original; only the original content needs
54
64
  // to be pulled out of the source map.
55
- const originalContent = sourceMap.sources.length
56
- ? sourceMap.sourceContentFor(sourceMap.sources[0], true)
65
+ const originalContent = sourceMap.sources.length && sourceMap.sources[0] != null
66
+ ? sourceContentFor(sourceMap, sourceMap.sources[0])
57
67
  : null;
58
68
  if (originalContent) {
59
69
  return {
@@ -66,14 +76,14 @@ export function createStackFrame(stackframe, isCompiled) {
66
76
  }
67
77
  }
68
78
  else {
69
- const result = sourceMap.originalPositionFor({
79
+ const result = originalPositionFor(sourceMap, {
70
80
  line: source.line,
71
81
  column: source.column,
72
82
  });
73
83
  if (result.source) {
74
84
  return {
75
85
  ...result,
76
- content: sourceMap.sourceContentFor(result.source, true),
86
+ content: sourceContentFor(sourceMap, result.source),
77
87
  };
78
88
  }
79
89
  }
@@ -1,2 +1,2 @@
1
- import { SourceMapConsumer } from "source-map-js";
2
- export default function getSourceMap(url: string, content: string): Promise<SourceMapConsumer | null>;
1
+ import { type TraceMap } from "@jridgewell/trace-mapping";
2
+ export default function getSourceMap(url: string, content: string): Promise<TraceMap | null>;
@@ -1,4 +1,4 @@
1
- import { SourceMapConsumer } from "source-map-js";
1
+ import { AnyMap } from "@jridgewell/trace-mapping";
2
2
  const INLINE_SOURCEMAP_REGEX = /^data:application\/json[^,]+base64,/;
3
3
  const SOURCEMAP_REGEX = /(?:\/\/[@#][ \t]+sourceMappingURL=([^\s'"]+?)[ \t]*$)|(?:\/\*[@#][ \t]+sourceMappingURL=([^*]+?)[ \t]*(?:\*\/)[ \t]*$)/;
4
4
  export default async function getSourceMap(url, content) {
@@ -21,5 +21,6 @@ export default async function getSourceMap(url, content) {
21
21
  }
22
22
  const response = await fetch(sourceMapUrl);
23
23
  const rawSourceMap = await response.json();
24
- return new SourceMapConsumer(rawSourceMap);
24
+ // AnyMap also handles indexed ("sections") source maps
25
+ return new AnyMap(rawSourceMap);
25
26
  }
@@ -1,5 +1,5 @@
1
1
  // @refresh skip
2
- import ErrorStackParser from "error-stack-parser";
2
+ import { parse as parseErrorStack } from "error-stack-parser-es/lite";
3
3
  import * as htmlToImage from "html-to-image";
4
4
  import { createMemo, createSignal, ErrorBoundary, For, Show, Suspense } from "solid-js";
5
5
  import IconButton from "../../ui/IconButton.jsx";
@@ -48,47 +48,39 @@ function CodeFallback() {
48
48
  <span>Source not available.</span>
49
49
  </div>);
50
50
  }
51
+ // Frame rendered from the raw (unmapped) stack info — used while the source
52
+ // is loading or when it is unreachable, so the frame never vanishes from
53
+ // the list.
54
+ function RawStackFrameOption(props) {
55
+ const fileName = props.frame.file;
56
+ return (<SelectOption value={props.frame} disabled={props.disabled} data-start-error-viewer-stack-frame>
57
+ <span data-start-error-viewer-stack-frame-function>
58
+ {props.frame.function ?? "<anonymous>"}
59
+ </span>
60
+ <span data-start-error-viewer-stack-frame-file>
61
+ {fileName
62
+ ? getFilePath({
63
+ source: fileName,
64
+ content: "",
65
+ line: props.frame.line,
66
+ column: props.frame.col,
67
+ name: props.frame.function,
68
+ })
69
+ : "<unknown source>"}
70
+ </span>
71
+ </SelectOption>);
72
+ }
51
73
  function StackFramesContent(props) {
52
- const stackframes = ErrorStackParser.parse(props.error);
74
+ const stackframes = parseErrorStack(props.error, { allowEmpty: true });
53
75
  const [selectedFrame, setSelectedFrame] = createSignal(stackframes[0]);
54
76
  return (<div data-start-error-viewer-stack-frames-content>
55
- <div data-start-error-viewer-stack-frames-code>
56
- <ErrorBoundary fallback={null}>
57
- {(() => {
58
- const data = createStackFrame(selectedFrame(), () => props.isCompiled);
59
- return (<Suspense fallback={<CodeFallback />}>
60
- <Show when={data()} keyed fallback={<CodeFallback />}>
61
- {source => (<>
62
- <span data-start-error-viewer-stack-frames-code-source>{source.source}</span>
63
- <div data-start-error-viewer-stack-frames-code-container>
64
- <CodeView fileName={source.source} line={source.line} content={source.content}/>
65
- </div>
66
- </>)}
67
- </Show>
68
- </Suspense>);
69
- })()}
70
- </ErrorBoundary>
71
- </div>
72
77
  <Select data-start-error-viewer-stack-frames value={selectedFrame()} onChange={setSelectedFrame}>
73
78
  <For each={stackframes}>
74
- {current => (<ErrorBoundary fallback={<SelectOption value={current} disabled data-start-error-viewer-stack-frame>
75
- <span data-start-error-viewer-stack-frame-function>
76
- {current.functionName ?? "<anonymous>"}
77
- </span>
78
- <span data-start-error-viewer-stack-frame-file>
79
- {getFilePath({
80
- source: current.getFileName(),
81
- content: "",
82
- line: current.getLineNumber(),
83
- column: current.getColumnNumber(),
84
- name: current.getFunctionName(),
85
- })}
86
- </span>
87
- </SelectOption>}>
79
+ {current => (<ErrorBoundary fallback={<RawStackFrameOption frame={current} disabled/>}>
88
80
  {(() => {
89
81
  const data = createStackFrame(current, () => props.isCompiled);
90
- return (<Suspense>
91
- <Show when={data()} keyed>
82
+ return (<Suspense fallback={<RawStackFrameOption frame={current}/>}>
83
+ <Show when={data()} keyed fallback={<RawStackFrameOption frame={current}/>}>
92
84
  {source => (<SelectOption data-start-error-viewer-stack-frame value={current}>
93
85
  <span data-start-error-viewer-stack-frame-function>
94
86
  {source.name ?? "<anonymous>"}
@@ -103,6 +95,31 @@ function StackFramesContent(props) {
103
95
  </ErrorBoundary>)}
104
96
  </For>
105
97
  </Select>
98
+ <div data-start-error-viewer-stack-frames-code>
99
+ <Show when={selectedFrame()} keyed>
100
+ {frame => (
101
+ // Keyed on the frame so a failure inspecting one frame (an
102
+ // unreachable source, a failed highlight) resets when another
103
+ // frame is selected instead of leaving the pane stuck.
104
+ <ErrorBoundary fallback={<CodeFallback />}>
105
+ {(() => {
106
+ const data = createStackFrame(frame, () => props.isCompiled);
107
+ return (<Suspense fallback={<CodeFallback />}>
108
+ <Show when={data()} keyed fallback={<CodeFallback />}>
109
+ {source => (<>
110
+ <span data-start-error-viewer-stack-frames-code-source>
111
+ {source.source}
112
+ </span>
113
+ <div data-start-error-viewer-stack-frames-code-container>
114
+ <CodeView fileName={source.source} line={source.line} content={source.content}/>
115
+ </div>
116
+ </>)}
117
+ </Show>
118
+ </Suspense>);
119
+ })()}
120
+ </ErrorBoundary>)}
121
+ </Show>
122
+ </div>
106
123
  </div>);
107
124
  }
108
125
  function StackFrames(props) {
@@ -3,6 +3,8 @@
3
3
  flex-direction: column;
4
4
 
5
5
  width: 100%;
6
+ height: 100%;
7
+ min-height: 0;
6
8
  }
7
9
 
8
10
  [data-start-error-viewer-navbar] {
@@ -11,6 +13,16 @@
11
13
  align-items: center;
12
14
  justify-content: space-between;
13
15
  gap: 0.5rem;
16
+
17
+ padding: 0.5rem 0.75rem;
18
+
19
+ position: sticky;
20
+ top: 0;
21
+ z-index: 1;
22
+
23
+ background: var(--start-dt-bg-glass);
24
+ backdrop-filter: blur(16px) saturate(140%);
25
+ -webkit-backdrop-filter: blur(16px) saturate(140%);
14
26
  }
15
27
 
16
28
  [data-start-error-viewer-pagination] {
@@ -20,8 +32,8 @@
20
32
  justify-content: center;
21
33
  gap: 0.5rem;
22
34
  border-radius: 9999px;
23
- color: rgb(249 250 251);
24
- background-color: rgb(17 24 39);
35
+ color: var(--start-dt-text);
36
+ background-color: var(--start-dt-surface);
25
37
  padding: 0.25rem;
26
38
  }
27
39
 
@@ -30,23 +42,23 @@
30
42
  }
31
43
 
32
44
  [data-start-error-viewer-button]:hover {
33
- color: rgb(229 231 235);
34
- background-color: rgb(55 65 81);
45
+ color: var(--start-dt-text);
46
+ background-color: var(--start-dt-surface-hover);
35
47
  }
36
48
 
37
49
  [data-start-error-viewer-button]:focus {
38
50
  outline: 2px solid transparent;
39
51
  outline-offset: 2px;
40
- outline-color: rgb(229 231 235);
52
+ outline-color: var(--start-dt-accent);
41
53
  }
42
54
 
43
55
  [data-start-error-viewer-button]:focus-visible {
44
- box-shadow: 0 0 0 calc(3px) rgb(17 24 39 / 0.75);
56
+ box-shadow: 0 0 0 2px var(--start-dt-accent);
45
57
  }
46
58
 
47
59
  [data-start-error-viewer-button]:active {
48
- color: rgb(243 244 246);
49
- background-color: rgb(31 41 55);
60
+ color: var(--start-dt-accent);
61
+ background-color: var(--start-dt-surface-active);
50
62
  }
51
63
 
52
64
  [data-start-error-viewer-button] > svg {
@@ -55,9 +67,11 @@
55
67
  }
56
68
 
57
69
  [data-start-error-viewer-page-counter] {
58
- font-size: 0.875rem;
70
+ font-size: 0.8125rem;
59
71
  line-height: 1.25rem;
60
72
  font-weight: 600;
73
+ font-variant-numeric: tabular-nums;
74
+ color: var(--start-dt-text-muted);
61
75
  }
62
76
 
63
77
  [data-start-error-viewer-navbar-left] {
@@ -73,7 +87,7 @@
73
87
  justify-content: center;
74
88
  gap: 0.25rem;
75
89
  border-radius: 9999px;
76
- color: rgb(249 250 251);
90
+ color: var(--start-dt-text);
77
91
  padding: 0.25rem;
78
92
  }
79
93
 
@@ -83,9 +97,13 @@
83
97
  gap: 0.75rem;
84
98
  padding: 1rem;
85
99
 
100
+ flex: 1;
101
+ min-height: 0;
102
+ overflow: hidden;
103
+
86
104
  border-top-width: 1px;
87
105
  border-top-style: solid;
88
- border-top-color: oklch(87% 0.065 274.039);
106
+ border-top-color: var(--start-dt-border-soft);
89
107
  }
90
108
 
91
109
  [data-start-error-viewer-error-info] {
@@ -95,107 +113,137 @@
95
113
  }
96
114
 
97
115
  [data-start-error-viewer-error-info-name] {
98
- font-weight: 700;
99
- color: rgb(249 250 251);
116
+ font-weight: 600;
117
+ font-size: 0.8125rem;
118
+ text-transform: uppercase;
119
+ letter-spacing: 0.06em;
120
+ color: var(--start-dt-text-muted);
100
121
  }
101
122
 
102
123
  [data-start-error-viewer-error-info-message] {
103
- font-size: 1.5rem;
104
- line-height: 2rem;
105
- color: rgb(239 68 68);
124
+ font-size: 1.25rem;
125
+ line-height: 1.75rem;
126
+ color: var(--start-dt-danger);
106
127
  font-weight: 700;
128
+ font-family:
129
+ ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New",
130
+ monospace;
107
131
  }
108
132
 
109
133
  [data-start-error-viewer-stack-frames-content] {
110
134
  display: flex;
111
- flex-direction: column;
135
+ flex-direction: row;
112
136
  gap: 0.75rem;
137
+
138
+ flex: 1;
139
+ min-height: 0;
113
140
  }
114
141
 
115
142
  [data-start-error-viewer-stack-frames] {
116
- flex: 1 1 0%;
117
- max-height: 16rem;
143
+ width: 38%;
144
+ max-width: 20rem;
145
+ flex-shrink: 0;
118
146
  overflow-y: auto;
147
+
148
+ border: 1px var(--start-dt-border-soft) solid;
149
+ border-radius: 0.5rem;
119
150
  }
120
151
 
121
152
  [data-start-error-viewer-stack-frame] {
122
153
  display: flex;
123
- flex-direction: row;
124
- align-items: center;
125
- justify-content: space-between;
126
- gap: 1rem;
127
- color: rgb(249 250 251);
154
+ flex-direction: column;
155
+ align-items: flex-start;
156
+ gap: 0.125rem;
157
+ color: var(--start-dt-text);
128
158
  cursor: default;
129
159
  user-select: none;
130
160
  padding-top: 0.5rem;
131
161
  padding-bottom: 0.5rem;
132
- padding-left: 1rem;
133
- padding-right: 1rem;
162
+ padding-left: 0.75rem;
163
+ padding-right: 0.75rem;
134
164
  font-size: 0.875rem;
135
165
  line-height: 1.25rem;
136
166
  outline: none;
167
+
168
+ min-width: 0;
169
+ max-width: 100%;
137
170
  }
138
171
 
139
172
  [data-start-error-viewer-stack-frame][tc-active],
140
173
  [data-start-error-viewer-stack-frame][tc-selected],
141
174
  [data-start-error-viewer-stack-frame]:focus {
142
- color: rgb(219 234 254);
143
- background-color: rgb(30 58 138);
175
+ color: var(--start-dt-text);
176
+ background-color: var(--start-dt-accent-soft);
177
+ border-left-color: var(--start-dt-accent);
144
178
  }
145
179
 
146
180
  [data-start-error-viewer-stack-frame-function] {
147
- font-weight: 700;
181
+ font-weight: 600;
182
+ font-family:
183
+ ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New",
184
+ monospace;
148
185
  }
149
186
 
150
187
  [data-start-error-viewer-stack-frame-file] {
151
188
  white-space: nowrap;
189
+ overflow: hidden;
190
+ text-overflow: ellipsis;
191
+ max-width: 100%;
152
192
  font-size: 0.75rem;
153
- /* 12px */
154
193
  line-height: 1rem;
155
- /* 16px */
194
+ color: var(--start-dt-text-muted);
156
195
  }
157
196
 
158
197
  [data-start-error-viewer-stack-frames-code] {
159
- padding: 0.5rem 1rem;
160
- gap: 0.25rem;
198
+ padding: 0.5rem 0.75rem;
199
+ gap: 0.375rem;
161
200
  flex: 1 1 0%;
201
+ min-width: 0;
202
+ min-height: 0;
162
203
  display: flex;
163
204
  flex-direction: column;
164
- align-items: center;
165
- justify-content: center;
205
+ align-items: stretch;
206
+ justify-content: flex-start;
166
207
  border-radius: 0.5rem;
167
- background-color: rgb(17 24 39);
208
+ background-color: var(--start-dt-surface);
209
+ border: 1px var(--start-dt-border-soft) solid;
168
210
  }
169
211
 
170
212
  [data-start-error-viewer-stack-frames-code-fallback] {
171
213
  display: flex;
172
214
  align-items: center;
173
215
  justify-content: center;
174
- color: rgb(249 250 251);
175
- min-height: 16rem;
216
+ color: var(--start-dt-text-muted);
217
+ flex: 1;
218
+ min-height: 8rem;
176
219
  font-size: 0.875rem;
177
220
  line-height: 1.25rem;
178
221
  }
179
222
 
180
223
  [data-start-error-viewer-stack-frames-code-source] {
181
- font-size: 0.875rem;
224
+ font-size: 0.8125rem;
182
225
  line-height: 1.25rem;
183
- color: rgb(249 250 251);
226
+ color: var(--start-dt-text-muted);
227
+ font-family:
228
+ ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New",
229
+ monospace;
184
230
  }
185
231
 
186
232
  [data-start-error-viewer-stack-frames-code-container] {
187
233
  width: 100%;
188
234
  overflow: hidden;
189
235
  min-width: 100%;
190
- max-height: 16rem;
236
+ flex: 1;
237
+ min-height: 0;
191
238
  border-top-width: 1px;
192
239
  border-top-style: solid;
193
- border-top-color: oklch(87% 0.065 274.039);
240
+ border-top-color: var(--start-dt-border-soft);
194
241
  }
195
242
 
196
243
  [data-start-error-viewer-code-view] {
197
244
  overflow: auto;
198
245
  min-width: 100%;
246
+ height: 100%;
199
247
  }
200
248
 
201
249
  [data-start-error-viewer-code-view] > .shiki {
@@ -220,5 +268,5 @@
220
268
  }
221
269
 
222
270
  [data-start-error-viewer-error-line] {
223
- background-color: rgba(239, 68, 68, 0.4);
271
+ background-color: oklch(0.63 0.21 25 / 0.25);
224
272
  }
@@ -1,4 +1,52 @@
1
+ [data-start-blob-viewer] {
2
+ display: flex;
3
+ align-items: center;
4
+ gap: 0.625rem;
5
+
6
+ align-self: flex-start;
7
+
8
+ padding: 0.5rem 0.75rem;
9
+ text-align: left;
10
+ }
11
+
1
12
  [data-start-blob-viewer] svg {
2
- width: 1rem;
3
- height: 1rem;
13
+ width: 1.5rem;
14
+ height: 1.5rem;
15
+ flex-shrink: 0;
16
+
17
+ color: var(--start-dt-accent, currentColor);
18
+ }
19
+
20
+ [data-start-blob-viewer-info] {
21
+ display: flex;
22
+ flex-direction: column;
23
+ align-items: flex-start;
24
+ gap: 0.25rem;
25
+
26
+ min-width: 0;
27
+ }
28
+
29
+ [data-start-blob-viewer-name] {
30
+ font-family:
31
+ ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New",
32
+ monospace;
33
+ font-size: 0.8125rem;
34
+ line-height: 1rem;
35
+ font-weight: 600;
36
+
37
+ max-width: 100%;
38
+ overflow: hidden;
39
+ text-overflow: ellipsis;
40
+ white-space: nowrap;
41
+ }
42
+
43
+ [data-start-blob-viewer-meta] {
44
+ display: flex;
45
+ align-items: center;
46
+ gap: 0.5rem;
47
+
48
+ font-size: 0.75rem;
49
+ line-height: 1rem;
50
+
51
+ color: var(--start-dt-text-muted, inherit);
4
52
  }