@codespark/react 1.0.0
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.
- package/LICENSE +21 -0
- package/README.md +115 -0
- package/dist/codemirror.d.ts +35 -0
- package/dist/codemirror.js +146 -0
- package/dist/index.css +82 -0
- package/dist/index.d.ts +712 -0
- package/dist/index.js +1753 -0
- package/dist/monaco.d.ts +36 -0
- package/dist/monaco.js +323 -0
- package/package.json +71 -0
package/dist/monaco.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { ComponentType } from "react";
|
|
2
|
+
import { EditorProps } from "@monaco-editor/react";
|
|
3
|
+
import * as monaco from "monaco-editor";
|
|
4
|
+
import { ReactCodeMirrorRef } from "@uiw/react-codemirror";
|
|
5
|
+
|
|
6
|
+
//#region src/lib/editor-adapter/index.d.ts
|
|
7
|
+
declare enum EditorEngine {
|
|
8
|
+
Monaco = 0,
|
|
9
|
+
CodeMirror = 1,
|
|
10
|
+
}
|
|
11
|
+
interface EditorInstance {
|
|
12
|
+
[EditorEngine.Monaco]: monaco.editor.IStandaloneCodeEditor;
|
|
13
|
+
[EditorEngine.CodeMirror]: ReactCodeMirrorRef;
|
|
14
|
+
}
|
|
15
|
+
interface EditorAdapter<E extends EditorEngine = any> {
|
|
16
|
+
kind: E;
|
|
17
|
+
instance: EditorInstance[E];
|
|
18
|
+
getValue(): string;
|
|
19
|
+
setValue(value: string, addToHistory?: boolean): void;
|
|
20
|
+
format(): Promise<void>;
|
|
21
|
+
}
|
|
22
|
+
interface EditorEngineComponent<E extends EditorEngine = any, P = object, I = unknown> {
|
|
23
|
+
kind: E;
|
|
24
|
+
Component: ComponentType<P>;
|
|
25
|
+
createAdapter: (instance: I) => EditorAdapter<E>;
|
|
26
|
+
}
|
|
27
|
+
//#endregion
|
|
28
|
+
//#region src/components/editor/monaco/index.d.ts
|
|
29
|
+
interface MonacoProps extends EditorProps {
|
|
30
|
+
readonly id?: string;
|
|
31
|
+
files?: Record<string, string>;
|
|
32
|
+
imports?: Record<string, string>;
|
|
33
|
+
}
|
|
34
|
+
declare const Monaco: EditorEngineComponent<EditorEngine.Monaco, MonacoProps, monaco.editor.IStandaloneCodeEditor>;
|
|
35
|
+
//#endregion
|
|
36
|
+
export { Monaco, MonacoProps };
|
package/dist/monaco.js
ADDED
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
import { shikiToMonaco } from "@shikijs/monaco";
|
|
2
|
+
import parserEstree from "prettier/plugins/estree";
|
|
3
|
+
import parserTypescript from "prettier/plugins/typescript";
|
|
4
|
+
import prettier from "prettier/standalone";
|
|
5
|
+
import { memo, useEffect, useRef, useState } from "react";
|
|
6
|
+
import { createHighlighterCore } from "shiki/core";
|
|
7
|
+
import { createJavaScriptRegexEngine } from "shiki/engine/javascript";
|
|
8
|
+
import { clsx } from "clsx";
|
|
9
|
+
import { twMerge } from "tailwind-merge";
|
|
10
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
11
|
+
|
|
12
|
+
//#region src/lib/editor-adapter/index.ts
|
|
13
|
+
let EditorEngine = /* @__PURE__ */ function(EditorEngine$1) {
|
|
14
|
+
EditorEngine$1[EditorEngine$1["Monaco"] = 0] = "Monaco";
|
|
15
|
+
EditorEngine$1[EditorEngine$1["CodeMirror"] = 1] = "CodeMirror";
|
|
16
|
+
return EditorEngine$1;
|
|
17
|
+
}({});
|
|
18
|
+
|
|
19
|
+
//#endregion
|
|
20
|
+
//#region src/lib/utils.ts
|
|
21
|
+
function cn(...inputs) {
|
|
22
|
+
return twMerge(clsx(inputs));
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
//#endregion
|
|
26
|
+
//#region src/ui/skeleton.tsx
|
|
27
|
+
function Skeleton({ className, ...props }) {
|
|
28
|
+
return /* @__PURE__ */ jsx("div", {
|
|
29
|
+
"data-slot": "skeleton",
|
|
30
|
+
className: cn("bg-accent animate-pulse rounded-md", className),
|
|
31
|
+
...props
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
//#endregion
|
|
36
|
+
//#region src/components/editor/monaco/adapter.ts
|
|
37
|
+
var MonacoEditorAdapter = class {
|
|
38
|
+
constructor(kind, instance) {
|
|
39
|
+
this.kind = kind;
|
|
40
|
+
this.instance = instance;
|
|
41
|
+
}
|
|
42
|
+
getValue() {
|
|
43
|
+
return this.instance.getModel()?.getValue() ?? "";
|
|
44
|
+
}
|
|
45
|
+
setValue(value, _addToHistory) {
|
|
46
|
+
this.instance.getModel()?.setValue(value);
|
|
47
|
+
}
|
|
48
|
+
async format() {
|
|
49
|
+
await this.instance.getAction("editor.action.formatDocument")?.run();
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
//#endregion
|
|
54
|
+
//#region src/components/editor/monaco/index.tsx
|
|
55
|
+
const addedLibs = /* @__PURE__ */ new Set();
|
|
56
|
+
const dtsCacheMap = /* @__PURE__ */ new Map();
|
|
57
|
+
const setup = async () => {
|
|
58
|
+
if (typeof window === "undefined") return;
|
|
59
|
+
const [mod, highlighter] = await Promise.all([import("@monaco-editor/react"), createHighlighterCore({
|
|
60
|
+
themes: [import("shiki/themes/vitesse-light.mjs"), import("shiki/themes/vitesse-dark.mjs")],
|
|
61
|
+
langs: [
|
|
62
|
+
import("shiki/langs/typescript.mjs"),
|
|
63
|
+
import("shiki/langs/tsx.mjs"),
|
|
64
|
+
import("shiki/langs/javascript.mjs"),
|
|
65
|
+
import("shiki/langs/jsx.mjs"),
|
|
66
|
+
import("shiki/langs/json.mjs"),
|
|
67
|
+
import("shiki/langs/css.mjs"),
|
|
68
|
+
import("shiki/langs/html.mjs")
|
|
69
|
+
],
|
|
70
|
+
langAlias: {
|
|
71
|
+
typescript: "tsx",
|
|
72
|
+
javascript: "jsx"
|
|
73
|
+
},
|
|
74
|
+
engine: createJavaScriptRegexEngine()
|
|
75
|
+
})]);
|
|
76
|
+
return mod.loader.init().then((Monaco$1) => {
|
|
77
|
+
Monaco$1.languages.register({ id: "tsx" });
|
|
78
|
+
Monaco$1.languages.register({ id: "jsx" });
|
|
79
|
+
shikiToMonaco(highlighter, Monaco$1);
|
|
80
|
+
Monaco$1.typescript.typescriptDefaults.setEagerModelSync(true);
|
|
81
|
+
Monaco$1.typescript.typescriptDefaults.setDiagnosticsOptions({
|
|
82
|
+
noSemanticValidation: false,
|
|
83
|
+
noSyntaxValidation: false
|
|
84
|
+
});
|
|
85
|
+
Monaco$1.typescript.typescriptDefaults.setCompilerOptions({
|
|
86
|
+
strict: true,
|
|
87
|
+
noImplicitAny: false,
|
|
88
|
+
noUnusedLocals: false,
|
|
89
|
+
noUnusedParameters: false,
|
|
90
|
+
allowUnreachableCode: true,
|
|
91
|
+
allowUnusedLabels: true,
|
|
92
|
+
allowImportingTsExtensions: true,
|
|
93
|
+
target: Monaco$1.typescript.ScriptTarget.ESNext,
|
|
94
|
+
allowNonTsExtensions: true,
|
|
95
|
+
moduleResolution: Monaco$1.typescript.ModuleResolutionKind.NodeJs,
|
|
96
|
+
module: Monaco$1.typescript.ModuleKind.ESNext,
|
|
97
|
+
noEmit: true,
|
|
98
|
+
jsx: Monaco$1.typescript.JsxEmit.Preserve,
|
|
99
|
+
esModuleInterop: true
|
|
100
|
+
});
|
|
101
|
+
Monaco$1.languages.registerDocumentFormattingEditProvider("typescript", { async provideDocumentFormattingEdits(model, options) {
|
|
102
|
+
const text = model.getValue();
|
|
103
|
+
const formatted = await prettier.format(text, {
|
|
104
|
+
parser: "typescript",
|
|
105
|
+
plugins: [parserTypescript, parserEstree],
|
|
106
|
+
tabWidth: options.tabSize,
|
|
107
|
+
useTabs: !options.insertSpaces
|
|
108
|
+
});
|
|
109
|
+
return [{
|
|
110
|
+
range: model.getFullModelRange(),
|
|
111
|
+
text: formatted
|
|
112
|
+
}];
|
|
113
|
+
} });
|
|
114
|
+
}).then(() => mod.default);
|
|
115
|
+
};
|
|
116
|
+
const MONACO_DEFAULT_OPTIONS = {
|
|
117
|
+
fontSize: 14,
|
|
118
|
+
fontFamily: "Fira Code",
|
|
119
|
+
lineHeight: 24,
|
|
120
|
+
padding: {
|
|
121
|
+
top: 16,
|
|
122
|
+
bottom: 16
|
|
123
|
+
},
|
|
124
|
+
automaticLayout: true,
|
|
125
|
+
folding: false,
|
|
126
|
+
scrollBeyondLastLine: false,
|
|
127
|
+
find: { addExtraSpaceOnTop: false },
|
|
128
|
+
minimap: { enabled: false },
|
|
129
|
+
scrollbar: {
|
|
130
|
+
useShadows: false,
|
|
131
|
+
vertical: "auto",
|
|
132
|
+
horizontal: "auto",
|
|
133
|
+
verticalScrollbarSize: 0,
|
|
134
|
+
horizontalScrollbarSize: 0,
|
|
135
|
+
verticalSliderSize: 0,
|
|
136
|
+
horizontalSliderSize: 0
|
|
137
|
+
},
|
|
138
|
+
guides: { indentation: false },
|
|
139
|
+
cursorStyle: "line-thin",
|
|
140
|
+
overviewRulerBorder: false,
|
|
141
|
+
contextmenu: false,
|
|
142
|
+
renderLineHighlightOnlyWhenFocus: true,
|
|
143
|
+
formatOnPaste: true,
|
|
144
|
+
formatOnType: true,
|
|
145
|
+
tabSize: 2,
|
|
146
|
+
insertSpaces: true,
|
|
147
|
+
detectIndentation: false,
|
|
148
|
+
quickSuggestions: true,
|
|
149
|
+
suggestOnTriggerCharacters: true,
|
|
150
|
+
parameterHints: { enabled: true }
|
|
151
|
+
};
|
|
152
|
+
const Monaco = {
|
|
153
|
+
kind: EditorEngine.Monaco,
|
|
154
|
+
Component: memo(function Monaco$1(props) {
|
|
155
|
+
const { value = "", options = {}, onChange, onMount, width, height, id, language, files, imports, ...rest } = props;
|
|
156
|
+
const editorInstance = useRef(null);
|
|
157
|
+
const [monacoInstance, setMonacoInstance] = useState(null);
|
|
158
|
+
const [MonacoEditor, setMonacoEditor] = useState(null);
|
|
159
|
+
const mergedOptions = {
|
|
160
|
+
...MONACO_DEFAULT_OPTIONS,
|
|
161
|
+
...Object.fromEntries(Object.entries(options).filter(([, v]) => v !== void 0))
|
|
162
|
+
};
|
|
163
|
+
const handleEditorDidMount = (editor, monaco) => {
|
|
164
|
+
onMount?.(editor, monaco);
|
|
165
|
+
editorInstance.current = editor;
|
|
166
|
+
setMonacoInstance(monaco);
|
|
167
|
+
};
|
|
168
|
+
const handleEditorContentChange = (value$1, evt) => {
|
|
169
|
+
onChange?.(value$1, evt);
|
|
170
|
+
};
|
|
171
|
+
const addExtraLib = (dts = {}) => {
|
|
172
|
+
Object.entries(dts).forEach(([module, content]) => {
|
|
173
|
+
if (addedLibs.has(module)) return;
|
|
174
|
+
if (module.startsWith("http://") || module.startsWith("https://")) monacoInstance.typescript.typescriptDefaults.addExtraLib(`declare module '${module}' { ${content} }`, module);
|
|
175
|
+
else monacoInstance.typescript.typescriptDefaults.addExtraLib(content || `declare module '${module}'`, `file:///node_modules/${module}/index.d.ts`);
|
|
176
|
+
addedLibs.add(module);
|
|
177
|
+
});
|
|
178
|
+
};
|
|
179
|
+
const createModels = (files$1 = {}) => {
|
|
180
|
+
const prefix = `file:///${id}/`;
|
|
181
|
+
const filePaths = new Set(Object.keys(files$1).map((p) => p.replace(/^(\.\.?\/)+/, "")));
|
|
182
|
+
monacoInstance.editor.getModels().forEach((model) => {
|
|
183
|
+
const uriStr = model.uri.toString();
|
|
184
|
+
if (uriStr.startsWith(prefix)) {
|
|
185
|
+
const modelPath = uriStr.slice(prefix.length);
|
|
186
|
+
if (!filePaths.has(modelPath)) model.dispose();
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
Object.entries(files$1).forEach(([filePath, code]) => {
|
|
190
|
+
const normalizedPath = filePath.replace(/^(\.\.?\/)+/, "");
|
|
191
|
+
const uri = monacoInstance.Uri.parse(`${prefix}${normalizedPath}`);
|
|
192
|
+
if (!monacoInstance.editor.getModel(uri)) {
|
|
193
|
+
const ext = filePath.split(".").pop();
|
|
194
|
+
const lang = ["ts", "tsx"].includes(ext) ? "typescript" : ext === "css" ? "css" : ext === "json" ? "json" : "javascript";
|
|
195
|
+
monacoInstance.editor.createModel(code, lang, uri);
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
};
|
|
199
|
+
const addSuggestions = (paths) => {
|
|
200
|
+
const getRelativePath = (from, to) => {
|
|
201
|
+
const fromParts = from.replace(/^\.\//, "").split("/").slice(0, -1);
|
|
202
|
+
const toParts = to.replace(/^\.\//, "").split("/");
|
|
203
|
+
let commonLength = 0;
|
|
204
|
+
while (commonLength < fromParts.length && commonLength < toParts.length - 1 && fromParts[commonLength] === toParts[commonLength]) commonLength++;
|
|
205
|
+
const upCount = fromParts.length - commonLength;
|
|
206
|
+
return (upCount > 0 ? Array(upCount).fill("..") : ["."]).concat(toParts.slice(commonLength)).join("/");
|
|
207
|
+
};
|
|
208
|
+
return monacoInstance.languages.registerCompletionItemProvider([
|
|
209
|
+
"typescript",
|
|
210
|
+
"typescriptreact",
|
|
211
|
+
"javascript",
|
|
212
|
+
"javascriptreact"
|
|
213
|
+
], {
|
|
214
|
+
triggerCharacters: [
|
|
215
|
+
"/",
|
|
216
|
+
"'",
|
|
217
|
+
"\""
|
|
218
|
+
],
|
|
219
|
+
provideCompletionItems(model, position) {
|
|
220
|
+
const importMatch = model.getValueInRange({
|
|
221
|
+
startLineNumber: position.lineNumber,
|
|
222
|
+
startColumn: 1,
|
|
223
|
+
endLineNumber: position.lineNumber,
|
|
224
|
+
endColumn: position.column
|
|
225
|
+
}).match(/(?:import\s+.*?\s+from\s+|import\s+)(['"])(\.[^'"]*?)$/);
|
|
226
|
+
if (!importMatch) return { suggestions: [] };
|
|
227
|
+
const typedPath = importMatch[2];
|
|
228
|
+
const filePaths = paths.filter((p) => !p.endsWith("/"));
|
|
229
|
+
const suggestions = [];
|
|
230
|
+
const addedPaths = /* @__PURE__ */ new Set();
|
|
231
|
+
const currentPath = model.uri.path.replace(/^\/[^/]+\//, "./");
|
|
232
|
+
for (const filePath of filePaths) {
|
|
233
|
+
if (filePath === currentPath) continue;
|
|
234
|
+
const relativePath = getRelativePath(currentPath, filePath);
|
|
235
|
+
if (!relativePath.startsWith(typedPath)) continue;
|
|
236
|
+
let displayPath = relativePath;
|
|
237
|
+
if (/\.(tsx?|jsx?)$/.test(displayPath)) displayPath = displayPath.replace(/\.(tsx?|jsx?)$/, "");
|
|
238
|
+
if (!addedPaths.has(displayPath)) {
|
|
239
|
+
addedPaths.add(displayPath);
|
|
240
|
+
suggestions.push({
|
|
241
|
+
label: displayPath,
|
|
242
|
+
kind: monacoInstance.languages.CompletionItemKind.File,
|
|
243
|
+
insertText: displayPath.slice(typedPath.length),
|
|
244
|
+
range: {
|
|
245
|
+
startLineNumber: position.lineNumber,
|
|
246
|
+
startColumn: position.column,
|
|
247
|
+
endLineNumber: position.lineNumber,
|
|
248
|
+
endColumn: position.column
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
return { suggestions };
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
};
|
|
257
|
+
useEffect(() => {
|
|
258
|
+
(async () => {
|
|
259
|
+
const MonacoEditorReact = await setup();
|
|
260
|
+
setTimeout(() => {
|
|
261
|
+
if (MonacoEditorReact) setMonacoEditor(() => MonacoEditorReact);
|
|
262
|
+
}, 1e3);
|
|
263
|
+
})();
|
|
264
|
+
}, []);
|
|
265
|
+
useEffect(() => {
|
|
266
|
+
if (typeof window === "undefined" || !monacoInstance || !id) return;
|
|
267
|
+
createModels(files);
|
|
268
|
+
const provider = addSuggestions(Object.keys(files || {}));
|
|
269
|
+
return () => provider?.dispose();
|
|
270
|
+
}, [files, monacoInstance]);
|
|
271
|
+
useEffect(() => {
|
|
272
|
+
if (typeof window === "undefined" || !monacoInstance) return;
|
|
273
|
+
const controllers = /* @__PURE__ */ new Map();
|
|
274
|
+
Promise.all(Object.entries(imports || {}).map(async ([name, url]) => {
|
|
275
|
+
if (dtsCacheMap.has(name)) return [name, dtsCacheMap.get(name)];
|
|
276
|
+
const controller = new AbortController();
|
|
277
|
+
controllers.set(name, controller);
|
|
278
|
+
try {
|
|
279
|
+
const { headers } = await fetch(url, {
|
|
280
|
+
method: "HEAD",
|
|
281
|
+
signal: controller.signal
|
|
282
|
+
});
|
|
283
|
+
const dtsUrl = headers.get("X-TypeScript-Types");
|
|
284
|
+
if (dtsUrl) {
|
|
285
|
+
const dtsContent = await fetch(dtsUrl, { signal: controller.signal }).then((r) => r.text());
|
|
286
|
+
dtsCacheMap.set(name, dtsContent);
|
|
287
|
+
return [name, dtsContent];
|
|
288
|
+
}
|
|
289
|
+
return [name, ""];
|
|
290
|
+
} catch {
|
|
291
|
+
return [name, ""];
|
|
292
|
+
}
|
|
293
|
+
})).then((results) => Object.fromEntries(results)).then(addExtraLib);
|
|
294
|
+
return () => {
|
|
295
|
+
controllers.forEach((controller) => controller.abort());
|
|
296
|
+
};
|
|
297
|
+
}, [imports, monacoInstance]);
|
|
298
|
+
if (!MonacoEditor) return /* @__PURE__ */ jsxs("div", {
|
|
299
|
+
className: "flex flex-col space-y-3 p-5",
|
|
300
|
+
style: { height },
|
|
301
|
+
children: [/* @__PURE__ */ jsx(Skeleton, { className: "w-full flex-1 rounded-xl" }), /* @__PURE__ */ jsxs("div", {
|
|
302
|
+
className: "space-y-3",
|
|
303
|
+
children: [/* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-[80%]" }), /* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-[65%]" })]
|
|
304
|
+
})]
|
|
305
|
+
});
|
|
306
|
+
return /* @__PURE__ */ jsx(MonacoEditor, {
|
|
307
|
+
value,
|
|
308
|
+
language,
|
|
309
|
+
options: mergedOptions,
|
|
310
|
+
width: width ?? "100%",
|
|
311
|
+
height,
|
|
312
|
+
...rest,
|
|
313
|
+
onMount: handleEditorDidMount,
|
|
314
|
+
onChange: handleEditorContentChange
|
|
315
|
+
});
|
|
316
|
+
}),
|
|
317
|
+
createAdapter: (instance) => {
|
|
318
|
+
return new MonacoEditorAdapter(EditorEngine.Monaco, instance);
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
//#endregion
|
|
323
|
+
export { Monaco };
|
package/package.json
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@codespark/react",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "React components for codespark ecosystem",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"react-components",
|
|
8
|
+
"code-editor",
|
|
9
|
+
"live-preview",
|
|
10
|
+
"codespark"
|
|
11
|
+
],
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"import": "./dist/index.js",
|
|
15
|
+
"types": "./dist/index.d.ts"
|
|
16
|
+
},
|
|
17
|
+
"./*": {
|
|
18
|
+
"import": "./dist/*.js",
|
|
19
|
+
"types": "./dist/*.d.ts"
|
|
20
|
+
},
|
|
21
|
+
"./index.css": {
|
|
22
|
+
"style": "./dist/index.css",
|
|
23
|
+
"import": "./dist/index.css"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"files": [
|
|
27
|
+
"dist"
|
|
28
|
+
],
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "tsdown"
|
|
31
|
+
},
|
|
32
|
+
"author": "TonyL1u",
|
|
33
|
+
"license": "MIT",
|
|
34
|
+
"repository": {
|
|
35
|
+
"type": "git",
|
|
36
|
+
"url": "git+https://github.com/codesparkjs/codespark.git",
|
|
37
|
+
"directory": "packages/react"
|
|
38
|
+
},
|
|
39
|
+
"homepage": "https://codesparkjs.com",
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"@codemirror/lang-javascript": "^6.2.4",
|
|
42
|
+
"@codemirror/lang-markdown": "^6.5.0",
|
|
43
|
+
"@codemirror/language-data": "^6.5.2",
|
|
44
|
+
"@codespark/framework": "^1.0.0",
|
|
45
|
+
"@monaco-editor/react": "^4.7.0",
|
|
46
|
+
"@shikijs/monaco": "^3.20.0",
|
|
47
|
+
"@uiw/react-codemirror": "^4.25.4",
|
|
48
|
+
"class-variance-authority": "^0.7.1",
|
|
49
|
+
"clsx": "^2.1.1",
|
|
50
|
+
"lodash-es": "^4.17.23",
|
|
51
|
+
"lucide-react": "^0.562.0",
|
|
52
|
+
"prettier": "^3.7.4",
|
|
53
|
+
"radix-ui": "^1.4.3",
|
|
54
|
+
"react": "^19.2.3",
|
|
55
|
+
"react-dom": "^19.2.3",
|
|
56
|
+
"react-is": "^19.2.3",
|
|
57
|
+
"shiki": "^3.20.0",
|
|
58
|
+
"tailwind-merge": "^3.4.0",
|
|
59
|
+
"tailwindcss": "^4.1.18"
|
|
60
|
+
},
|
|
61
|
+
"devDependencies": {
|
|
62
|
+
"@types/lodash-es": "^4.17.12",
|
|
63
|
+
"@types/mdx": "^2.0.13",
|
|
64
|
+
"@types/node": "^22.19.2",
|
|
65
|
+
"@types/react": "^19.2.7",
|
|
66
|
+
"@types/react-is": "^19.2.0",
|
|
67
|
+
"monaco-editor": "^0.55.1",
|
|
68
|
+
"rollup-plugin-import-raw": "^1.0.2",
|
|
69
|
+
"tsdown": "^0.17.3"
|
|
70
|
+
}
|
|
71
|
+
}
|