@ttsc/playground 0.25.0 → 0.26.1

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.
@@ -1,75 +1,75 @@
1
- "use client";
2
-
3
- import Editor from "@monaco-editor/react";
4
- import { useEffect, useRef, useState } from "react";
5
-
6
- interface ResultViewerProps {
7
- language: "typescript" | "javascript" | "json";
8
- value: string;
9
- }
10
-
11
- /**
12
- * Read-only Monaco pane used to render the compiled / transformed output with a
13
- * copy button. Wraps `<Editor readOnly>` and adds the toast UI.
14
- */
15
- export function ResultViewer({ language, value }: ResultViewerProps) {
16
- const [copied, setCopied] = useState(false);
17
- const copiedTimer = useRef<number | null>(null);
18
-
19
- useEffect(
20
- () => () => {
21
- if (copiedTimer.current !== null)
22
- window.clearTimeout(copiedTimer.current);
23
- },
24
- [],
25
- );
26
-
27
- const onCopy = () => {
28
- void navigator.clipboard.writeText(value);
29
- setCopied(true);
30
- if (copiedTimer.current !== null) window.clearTimeout(copiedTimer.current);
31
- copiedTimer.current = window.setTimeout(() => {
32
- setCopied(false);
33
- copiedTimer.current = null;
34
- }, 1500);
35
- };
36
-
37
- return (
38
- <div className="relative h-full w-full">
39
- {value && (
40
- <button
41
- onClick={onCopy}
42
- className="absolute right-3 top-2 z-10 rounded-md border border-[#b9d5ee] bg-white/90 px-2 py-1 font-mono text-[10px] text-[#235a97] shadow-sm transition-colors hover:bg-[#eaf4ff]"
43
- >
44
- {copied ? "Copied ✓" : "Copy"}
45
- </button>
46
- )}
47
- <Editor
48
- height="100%"
49
- language={language}
50
- theme="vs"
51
- value={value}
52
- path={`output.${
53
- language === "typescript"
54
- ? "ts"
55
- : language === "javascript"
56
- ? "js"
57
- : "json"
58
- }`}
59
- options={{
60
- readOnly: true,
61
- tabSize: 2,
62
- minimap: { enabled: false },
63
- padding: { top: 12, bottom: 12 },
64
- fontSize: 13,
65
- fontFamily:
66
- "ui-monospace, SFMono-Regular, 'JetBrains Mono', 'Fira Code', Consolas, monospace",
67
- smoothScrolling: true,
68
- scrollBeyondLastLine: false,
69
- renderLineHighlight: "none",
70
- wordWrap: "on",
71
- }}
72
- />
73
- </div>
74
- );
75
- }
1
+ "use client";
2
+
3
+ import Editor from "@monaco-editor/react";
4
+ import { useEffect, useRef, useState } from "react";
5
+
6
+ interface ResultViewerProps {
7
+ language: "typescript" | "javascript" | "json";
8
+ value: string;
9
+ }
10
+
11
+ /**
12
+ * Read-only Monaco pane used to render the compiled / transformed output with a
13
+ * copy button. Wraps `<Editor readOnly>` and adds the toast UI.
14
+ */
15
+ export function ResultViewer({ language, value }: ResultViewerProps) {
16
+ const [copied, setCopied] = useState(false);
17
+ const copiedTimer = useRef<number | null>(null);
18
+
19
+ useEffect(
20
+ () => () => {
21
+ if (copiedTimer.current !== null)
22
+ window.clearTimeout(copiedTimer.current);
23
+ },
24
+ [],
25
+ );
26
+
27
+ const onCopy = () => {
28
+ void navigator.clipboard.writeText(value);
29
+ setCopied(true);
30
+ if (copiedTimer.current !== null) window.clearTimeout(copiedTimer.current);
31
+ copiedTimer.current = window.setTimeout(() => {
32
+ setCopied(false);
33
+ copiedTimer.current = null;
34
+ }, 1500);
35
+ };
36
+
37
+ return (
38
+ <div className="relative h-full w-full">
39
+ {value && (
40
+ <button
41
+ onClick={onCopy}
42
+ className="absolute right-3 top-2 z-10 rounded-md border border-[#b9d5ee] bg-white/90 px-2 py-1 font-mono text-[10px] text-[#235a97] shadow-sm transition-colors hover:bg-[#eaf4ff]"
43
+ >
44
+ {copied ? "Copied ✓" : "Copy"}
45
+ </button>
46
+ )}
47
+ <Editor
48
+ height="100%"
49
+ language={language}
50
+ theme="vs"
51
+ value={value}
52
+ path={`output.${
53
+ language === "typescript"
54
+ ? "ts"
55
+ : language === "javascript"
56
+ ? "js"
57
+ : "json"
58
+ }`}
59
+ options={{
60
+ readOnly: true,
61
+ tabSize: 2,
62
+ minimap: { enabled: false },
63
+ padding: { top: 12, bottom: 12 },
64
+ fontSize: 13,
65
+ fontFamily:
66
+ "ui-monospace, SFMono-Regular, 'JetBrains Mono', 'Fira Code', Consolas, monospace",
67
+ smoothScrolling: true,
68
+ scrollBeyondLastLine: false,
69
+ renderLineHighlight: "none",
70
+ wordWrap: "on",
71
+ }}
72
+ />
73
+ </div>
74
+ );
75
+ }
@@ -1,95 +1,95 @@
1
- "use client";
2
-
3
- import Editor, { type Monaco } from "@monaco-editor/react";
4
- import { useCallback, useEffect, useMemo, useRef } from "react";
5
-
6
- import { DEFAULT_PLAYGROUND_COMPILER_OPTIONS } from "../compiler/DEFAULT_PLAYGROUND_COMPILER_OPTIONS";
7
- import type { ISourceEditorProps } from "../structures/ISourceEditorProps";
8
-
9
- export function SourceEditor({
10
- value,
11
- onChange,
12
- extraLibs,
13
- path = "file:///src/playground.ts",
14
- }: ISourceEditorProps) {
15
- const monacoRef = useRef<Monaco | null>(null);
16
- const libDisposables = useRef<{ dispose(): void }[]>([]);
17
- const allExtraLibs = useMemo(
18
- () => (extraLibs ? Object.entries(extraLibs) : []),
19
- [extraLibs],
20
- );
21
-
22
- const installExtraLibs = useCallback(
23
- (monaco: Monaco) => {
24
- for (const disposable of libDisposables.current) disposable.dispose();
25
- libDisposables.current = [];
26
- const tsd = monaco.languages.typescript.typescriptDefaults;
27
- for (const [file, content] of allExtraLibs) {
28
- libDisposables.current.push(tsd.addExtraLib(content, file));
29
- }
30
- },
31
- [allExtraLibs],
32
- );
33
-
34
- useEffect(() => {
35
- if (monacoRef.current) installExtraLibs(monacoRef.current);
36
- return () => {
37
- for (const disposable of libDisposables.current) disposable.dispose();
38
- libDisposables.current = [];
39
- };
40
- }, [installExtraLibs]);
41
-
42
- const handleMount = (_editor: unknown, monaco: Monaco) => {
43
- monacoRef.current = monaco;
44
- const tsd = monaco.languages.typescript.typescriptDefaults;
45
- tsd.setCompilerOptions({
46
- target: monaco.languages.typescript.ScriptTarget.ESNext,
47
- module: monaco.languages.typescript.ModuleKind.ESNext,
48
- moduleResolution: monaco.languages.typescript.ModuleResolutionKind.NodeJs,
49
- esModuleInterop: DEFAULT_PLAYGROUND_COMPILER_OPTIONS.esModuleInterop,
50
- strict: DEFAULT_PLAYGROUND_COMPILER_OPTIONS.strict,
51
- experimentalDecorators:
52
- DEFAULT_PLAYGROUND_COMPILER_OPTIONS.experimentalDecorators,
53
- allowNonTsExtensions: true,
54
- // External .d.ts packs (typia, etc.) routinely reference transitive types
55
- // Monaco cannot reach (deep paths in JSDoc, optional peers). skipLibCheck
56
- // keeps the editor lean by not type-checking the lib pack.
57
- skipLibCheck: true,
58
- });
59
- tsd.setDiagnosticsOptions({
60
- noSemanticValidation: false,
61
- noSyntaxValidation: false,
62
- diagnosticCodesToIgnore: [
63
- // 2307: Cannot find module — JSDoc-only stubbed deps still occasionally
64
- // leak through Monaco's module resolution.
65
- 2307,
66
- ],
67
- });
68
- installExtraLibs(monaco);
69
- };
70
-
71
- return (
72
- <Editor
73
- height="100%"
74
- defaultLanguage="typescript"
75
- theme="vs"
76
- value={value}
77
- onChange={(v) => onChange(v ?? "")}
78
- onMount={handleMount}
79
- path={path}
80
- options={{
81
- tabSize: 2,
82
- minimap: { enabled: false },
83
- padding: { top: 12, bottom: 12 },
84
- fontSize: 13,
85
- fontFamily:
86
- "ui-monospace, SFMono-Regular, 'JetBrains Mono', 'Fira Code', Consolas, monospace",
87
- smoothScrolling: true,
88
- cursorBlinking: "smooth",
89
- scrollBeyondLastLine: false,
90
- renderLineHighlight: "line",
91
- wordWrap: "on",
92
- }}
93
- />
94
- );
95
- }
1
+ "use client";
2
+
3
+ import Editor, { type Monaco } from "@monaco-editor/react";
4
+ import { useCallback, useEffect, useMemo, useRef } from "react";
5
+
6
+ import { DEFAULT_PLAYGROUND_COMPILER_OPTIONS } from "../compiler/DEFAULT_PLAYGROUND_COMPILER_OPTIONS";
7
+ import type { ISourceEditorProps } from "../structures/ISourceEditorProps";
8
+
9
+ export function SourceEditor({
10
+ value,
11
+ onChange,
12
+ extraLibs,
13
+ path = "file:///src/playground.ts",
14
+ }: ISourceEditorProps) {
15
+ const monacoRef = useRef<Monaco | null>(null);
16
+ const libDisposables = useRef<{ dispose(): void }[]>([]);
17
+ const allExtraLibs = useMemo(
18
+ () => (extraLibs ? Object.entries(extraLibs) : []),
19
+ [extraLibs],
20
+ );
21
+
22
+ const installExtraLibs = useCallback(
23
+ (monaco: Monaco) => {
24
+ for (const disposable of libDisposables.current) disposable.dispose();
25
+ libDisposables.current = [];
26
+ const tsd = monaco.languages.typescript.typescriptDefaults;
27
+ for (const [file, content] of allExtraLibs) {
28
+ libDisposables.current.push(tsd.addExtraLib(content, file));
29
+ }
30
+ },
31
+ [allExtraLibs],
32
+ );
33
+
34
+ useEffect(() => {
35
+ if (monacoRef.current) installExtraLibs(monacoRef.current);
36
+ return () => {
37
+ for (const disposable of libDisposables.current) disposable.dispose();
38
+ libDisposables.current = [];
39
+ };
40
+ }, [installExtraLibs]);
41
+
42
+ const handleMount = (_editor: unknown, monaco: Monaco) => {
43
+ monacoRef.current = monaco;
44
+ const tsd = monaco.languages.typescript.typescriptDefaults;
45
+ tsd.setCompilerOptions({
46
+ target: monaco.languages.typescript.ScriptTarget.ESNext,
47
+ module: monaco.languages.typescript.ModuleKind.ESNext,
48
+ moduleResolution: monaco.languages.typescript.ModuleResolutionKind.NodeJs,
49
+ esModuleInterop: DEFAULT_PLAYGROUND_COMPILER_OPTIONS.esModuleInterop,
50
+ strict: DEFAULT_PLAYGROUND_COMPILER_OPTIONS.strict,
51
+ experimentalDecorators:
52
+ DEFAULT_PLAYGROUND_COMPILER_OPTIONS.experimentalDecorators,
53
+ allowNonTsExtensions: true,
54
+ // External .d.ts packs (typia, etc.) routinely reference transitive types
55
+ // Monaco cannot reach (deep paths in JSDoc, optional peers). skipLibCheck
56
+ // keeps the editor lean by not type-checking the lib pack.
57
+ skipLibCheck: true,
58
+ });
59
+ tsd.setDiagnosticsOptions({
60
+ noSemanticValidation: false,
61
+ noSyntaxValidation: false,
62
+ diagnosticCodesToIgnore: [
63
+ // 2307: Cannot find module — JSDoc-only stubbed deps still occasionally
64
+ // leak through Monaco's module resolution.
65
+ 2307,
66
+ ],
67
+ });
68
+ installExtraLibs(monaco);
69
+ };
70
+
71
+ return (
72
+ <Editor
73
+ height="100%"
74
+ defaultLanguage="typescript"
75
+ theme="vs"
76
+ value={value}
77
+ onChange={(v) => onChange(v ?? "")}
78
+ onMount={handleMount}
79
+ path={path}
80
+ options={{
81
+ tabSize: 2,
82
+ minimap: { enabled: false },
83
+ padding: { top: 12, bottom: 12 },
84
+ fontSize: 13,
85
+ fontFamily:
86
+ "ui-monospace, SFMono-Regular, 'JetBrains Mono', 'Fira Code', Consolas, monospace",
87
+ smoothScrolling: true,
88
+ cursorBlinking: "smooth",
89
+ scrollBeyondLastLine: false,
90
+ renderLineHighlight: "line",
91
+ wordWrap: "on",
92
+ }}
93
+ />
94
+ );
95
+ }