@codespark/react 1.0.6 → 1.0.8
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/dist/codemirror.d.ts +6249 -3
- package/dist/codemirror.js +6 -5
- package/dist/index.d.ts +6269 -11
- package/dist/index.js +248 -59
- package/dist/monaco.d.ts +6250 -4
- package/dist/monaco.js +23 -22
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -57,6 +57,16 @@ function useLatest(value) {
|
|
|
57
57
|
ref.current = value;
|
|
58
58
|
return ref;
|
|
59
59
|
}
|
|
60
|
+
function useFramework(workspace) {
|
|
61
|
+
const framework = useMemo(() => {
|
|
62
|
+
const fwInput = workspace.framework;
|
|
63
|
+
if (typeof fwInput === "string") return registry.get(fwInput);
|
|
64
|
+
if (typeof fwInput === "function") return new fwInput();
|
|
65
|
+
return fwInput;
|
|
66
|
+
}, []);
|
|
67
|
+
if (!framework) throw new Error(`Framework not found: ${workspace.framework}`);
|
|
68
|
+
return framework;
|
|
69
|
+
}
|
|
60
70
|
function getLanguageFromFile(name) {
|
|
61
71
|
const ext = name.split(".").pop()?.toLowerCase();
|
|
62
72
|
return ext ? {
|
|
@@ -131,10 +141,10 @@ var Workspace = class extends OPFS {
|
|
|
131
141
|
constructor(config) {
|
|
132
142
|
super();
|
|
133
143
|
this.config = config;
|
|
134
|
-
const { id, OPFS
|
|
144
|
+
const { id, OPFS = false, files } = config;
|
|
135
145
|
this.id = id || "";
|
|
136
146
|
this.initialFiles = { ...files };
|
|
137
|
-
if (OPFS
|
|
147
|
+
if (OPFS) super.initOPFS(this.files);
|
|
138
148
|
}
|
|
139
149
|
notifyListeners() {
|
|
140
150
|
this.listeners.forEach((fn) => fn());
|
|
@@ -320,33 +330,26 @@ var Workspace = class extends OPFS {
|
|
|
320
330
|
* @returns Workspace state including files, compiled code, and the workspace instance
|
|
321
331
|
*/
|
|
322
332
|
function useWorkspace(init) {
|
|
323
|
-
const uid
|
|
333
|
+
const uid = useId();
|
|
324
334
|
const context = useCodespark();
|
|
325
335
|
const workspace = useMemo(() => {
|
|
326
336
|
let ws;
|
|
327
337
|
if (init instanceof Workspace) ws = init;
|
|
328
338
|
else if (init) ws = new Workspace(init);
|
|
329
339
|
else ws = context?.workspace;
|
|
330
|
-
if (!ws?.id) ws?.[INTERNAL_SET_ID](`workspace${uid
|
|
340
|
+
if (!ws?.id) ws?.[INTERNAL_SET_ID](`workspace${uid}`);
|
|
331
341
|
return ws;
|
|
332
342
|
}, []);
|
|
333
343
|
if (!workspace) throw Error("Can not find any workspace instance. Make sure provide a workspace during runtime.");
|
|
334
|
-
const framework =
|
|
335
|
-
|
|
336
|
-
if (typeof fwInput === "string") return registry.get(fwInput);
|
|
337
|
-
if (typeof fwInput === "function") return new fwInput();
|
|
338
|
-
return fwInput;
|
|
339
|
-
}, []);
|
|
340
|
-
if (!framework) throw new Error(`Framework not found: ${workspace.framework}`);
|
|
341
|
-
const standalone = context ? false : !workspace[INTERNAL_BOUND]();
|
|
342
|
-
const subscribe = useMemo(() => standalone ? (cb) => workspace[INTERNAL_SUBSCRIBE](cb) : NOOP_SUBSCRIBE, []);
|
|
344
|
+
const framework = useFramework(workspace);
|
|
345
|
+
const subscribe = useMemo(() => (context ? false : !workspace[INTERNAL_BOUND]()) ? (cb) => workspace[INTERNAL_SUBSCRIBE](cb) : NOOP_SUBSCRIBE, []);
|
|
343
346
|
const files = useSyncExternalStore(subscribe, () => workspace.files, () => workspace.files);
|
|
344
347
|
const currentFile = useSyncExternalStore(subscribe, () => workspace.currentFile, () => workspace.currentFile);
|
|
345
348
|
const derivedState = useMemo(() => {
|
|
346
349
|
if (context) {
|
|
347
|
-
const { fileTree
|
|
350
|
+
const { fileTree, vendor, compiled, compileError } = context;
|
|
348
351
|
return {
|
|
349
|
-
fileTree
|
|
352
|
+
fileTree,
|
|
350
353
|
vendor,
|
|
351
354
|
compiled,
|
|
352
355
|
compileError
|
|
@@ -393,13 +396,13 @@ function useWorkspace(init) {
|
|
|
393
396
|
return root;
|
|
394
397
|
})();
|
|
395
398
|
try {
|
|
396
|
-
framework.analyze(
|
|
397
|
-
const compiled = framework.compile();
|
|
399
|
+
framework.analyze(files);
|
|
400
|
+
const compiled = framework.compile(workspace.entry);
|
|
398
401
|
workspace[INTERNAL_EMIT]("compiled", compiled);
|
|
399
402
|
const modules = framework.getOutput(LoaderType.ESModule);
|
|
400
403
|
const styles = framework.getOutput(LoaderType.Style);
|
|
401
404
|
const scripts = framework.getOutput(LoaderType.Script);
|
|
402
|
-
const externals = modules.flatMap(({ externals
|
|
405
|
+
const externals = modules.flatMap(({ externals }) => externals).reduce((acc, { name, imported }) => {
|
|
403
406
|
if (!acc[name]) acc[name] = /* @__PURE__ */ new Set();
|
|
404
407
|
imported.forEach((i) => acc[name].add(i));
|
|
405
408
|
return acc;
|
|
@@ -542,10 +545,10 @@ function CodesparkProvider(props) {
|
|
|
542
545
|
|
|
543
546
|
//#endregion
|
|
544
547
|
//#region src/lib/editor-adapter/index.ts
|
|
545
|
-
let EditorEngine = /* @__PURE__ */ function(EditorEngine
|
|
546
|
-
EditorEngine
|
|
547
|
-
EditorEngine
|
|
548
|
-
return EditorEngine
|
|
548
|
+
let EditorEngine = /* @__PURE__ */ function(EditorEngine) {
|
|
549
|
+
EditorEngine[EditorEngine["Monaco"] = 0] = "Monaco";
|
|
550
|
+
EditorEngine[EditorEngine["CodeMirror"] = 1] = "CodeMirror";
|
|
551
|
+
return EditorEngine;
|
|
549
552
|
}({});
|
|
550
553
|
|
|
551
554
|
//#endregion
|
|
@@ -574,7 +577,7 @@ const buttonVariants = cva("inline-flex items-center justify-center gap-2 whites
|
|
|
574
577
|
size: "default"
|
|
575
578
|
}
|
|
576
579
|
});
|
|
577
|
-
const Button = React.forwardRef(function Button
|
|
580
|
+
const Button = React.forwardRef(function Button({ className, variant = "default", size = "default", asChild = false, ...props }, ref) {
|
|
578
581
|
return /* @__PURE__ */ jsx(asChild ? Slot.Root : "button", {
|
|
579
582
|
"data-slot": "button",
|
|
580
583
|
"data-variant": variant,
|
|
@@ -596,10 +599,7 @@ const Icons = {
|
|
|
596
599
|
xmlns: "http://www.w3.org/2000/svg",
|
|
597
600
|
viewBox: "0 0 24 24",
|
|
598
601
|
...props,
|
|
599
|
-
children: /* @__PURE__ */ jsx("path", {
|
|
600
|
-
fill: "currentColor",
|
|
601
|
-
d: "M12.043 23.968c.479-.004.953-.029 1.426-.094a11.805 11.805 0 0 0 3.146-.863 12.404 12.404 0 0 0 3.793-2.542 11.977 11.977 0 0 0 2.44-3.427 11.794 11.794 0 0 0 1.02-3.476c.149-1.16.135-2.346-.045-3.499a11.96 11.96 0 0 0-.793-2.788 11.197 11.197 0 0 0-.854-1.617c-1.168-1.837-2.861-3.314-4.81-4.3a12.835 12.835 0 0 0-2.172-.87h-.005c.119.063.24.132.345.201.12.074.239.146.351.225a8.93 8.93 0 0 1 1.559 1.33c1.063 1.145 1.797 2.548 2.218 4.041.284.982.434 1.998.495 3.017.044.743.044 1.491-.047 2.229-.149 1.27-.554 2.51-1.228 3.596a7.475 7.475 0 0 1-1.903 2.084c-1.244.928-2.877 1.482-4.436 1.114a3.916 3.916 0 0 1-.748-.258 4.692 4.692 0 0 1-.779-.45 6.08 6.08 0 0 1-1.244-1.105 6.507 6.507 0 0 1-1.049-1.747 7.366 7.366 0 0 1-.494-2.54c-.03-1.273.225-2.553.854-3.67a6.43 6.43 0 0 1 1.663-1.918c.225-.178.464-.333.704-.479l.016-.007a5.121 5.121 0 0 0-1.441-.12 4.963 4.963 0 0 0-1.228.24c-.359.12-.704.27-1.019.45a6.146 6.146 0 0 0-.733.494c-.211.18-.42.36-.615.555-1.123 1.153-1.768 2.682-2.022 4.256-.15.973-.15 1.96-.091 2.95.105 1.395.391 2.787.945 4.062a8.518 8.518 0 0 0 1.348 2.173 8.14 8.14 0 0 0 3.132 2.23 7.934 7.934 0 0 0 2.113.54c.074.015.149.015.209.015zm-2.934-.398a4.102 4.102 0 0 1-.45-.228 8.5 8.5 0 0 1-2.038-1.534c-1.094-1.137-1.827-2.566-2.247-4.08a15.184 15.184 0 0 1-.495-3.172 12.14 12.14 0 0 1 .046-2.082c.135-1.257.495-2.501 1.124-3.58a6.889 6.889 0 0 1 1.783-2.053 6.23 6.23 0 0 1 1.633-.9 5.363 5.363 0 0 1 3.522-.045c.029 0 .029 0 .045.03.015.015.045.015.06.03.045.016.104.045.165.074.239.12.479.271.704.42a6.294 6.294 0 0 1 2.097 2.502c.42.914.615 1.934.631 2.938.014 1.079-.18 2.157-.645 3.146a6.42 6.42 0 0 1-2.638 2.832c.09.03.18.045.271.075.225.044.449.074.688.074 1.468.045 2.892-.66 3.94-1.647.195-.18.375-.375.54-.585.225-.27.435-.54.614-.823.239-.375.435-.75.614-1.154a8.112 8.112 0 0 0 .509-1.664c.196-1.004.211-2.022.149-3.026-.135-2.022-.673-4.045-1.842-5.724a9.054 9.054 0 0 0-.555-.719 9.868 9.868 0 0 0-1.063-1.034 8.477 8.477 0 0 0-1.363-.915 9.927 9.927 0 0 0-1.692-.598l-.3-.06c-.209-.03-.42-.044-.634-.06a8.453 8.453 0 0 0-1.015.016c-.704.045-1.412.16-2.112.337C5.799 1.227 2.863 3.566 1.3 6.67A11.834 11.834 0 0 0 .238 9.801a11.81 11.81 0 0 0-.104 3.775c.12 1.02.374 2.023.778 2.977.227.57.511 1.124.825 1.648 1.094 1.783 2.683 3.236 4.51 4.24.688.39 1.408.69 2.157.944.226.074.45.15.689.21z"
|
|
602
|
-
})
|
|
602
|
+
children: /* @__PURE__ */ jsx("path", { d: "M12.043 23.968c.479-.004.953-.029 1.426-.094a11.805 11.805 0 0 0 3.146-.863 12.404 12.404 0 0 0 3.793-2.542 11.977 11.977 0 0 0 2.44-3.427 11.794 11.794 0 0 0 1.02-3.476c.149-1.16.135-2.346-.045-3.499a11.96 11.96 0 0 0-.793-2.788 11.197 11.197 0 0 0-.854-1.617c-1.168-1.837-2.861-3.314-4.81-4.3a12.835 12.835 0 0 0-2.172-.87h-.005c.119.063.24.132.345.201.12.074.239.146.351.225a8.93 8.93 0 0 1 1.559 1.33c1.063 1.145 1.797 2.548 2.218 4.041.284.982.434 1.998.495 3.017.044.743.044 1.491-.047 2.229-.149 1.27-.554 2.51-1.228 3.596a7.475 7.475 0 0 1-1.903 2.084c-1.244.928-2.877 1.482-4.436 1.114a3.916 3.916 0 0 1-.748-.258 4.692 4.692 0 0 1-.779-.45 6.08 6.08 0 0 1-1.244-1.105 6.507 6.507 0 0 1-1.049-1.747 7.366 7.366 0 0 1-.494-2.54c-.03-1.273.225-2.553.854-3.67a6.43 6.43 0 0 1 1.663-1.918c.225-.178.464-.333.704-.479l.016-.007a5.121 5.121 0 0 0-1.441-.12 4.963 4.963 0 0 0-1.228.24c-.359.12-.704.27-1.019.45a6.146 6.146 0 0 0-.733.494c-.211.18-.42.36-.615.555-1.123 1.153-1.768 2.682-2.022 4.256-.15.973-.15 1.96-.091 2.95.105 1.395.391 2.787.945 4.062a8.518 8.518 0 0 0 1.348 2.173 8.14 8.14 0 0 0 3.132 2.23 7.934 7.934 0 0 0 2.113.54c.074.015.149.015.209.015zm-2.934-.398a4.102 4.102 0 0 1-.45-.228 8.5 8.5 0 0 1-2.038-1.534c-1.094-1.137-1.827-2.566-2.247-4.08a15.184 15.184 0 0 1-.495-3.172 12.14 12.14 0 0 1 .046-2.082c.135-1.257.495-2.501 1.124-3.58a6.889 6.889 0 0 1 1.783-2.053 6.23 6.23 0 0 1 1.633-.9 5.363 5.363 0 0 1 3.522-.045c.029 0 .029 0 .045.03.015.015.045.015.06.03.045.016.104.045.165.074.239.12.479.271.704.42a6.294 6.294 0 0 1 2.097 2.502c.42.914.615 1.934.631 2.938.014 1.079-.18 2.157-.645 3.146a6.42 6.42 0 0 1-2.638 2.832c.09.03.18.045.271.075.225.044.449.074.688.074 1.468.045 2.892-.66 3.94-1.647.195-.18.375-.375.54-.585.225-.27.435-.54.614-.823.239-.375.435-.75.614-1.154a8.112 8.112 0 0 0 .509-1.664c.196-1.004.211-2.022.149-3.026-.135-2.022-.673-4.045-1.842-5.724a9.054 9.054 0 0 0-.555-.719 9.868 9.868 0 0 0-1.063-1.034 8.477 8.477 0 0 0-1.363-.915 9.927 9.927 0 0 0-1.692-.598l-.3-.06c-.209-.03-.42-.044-.634-.06a8.453 8.453 0 0 0-1.015.016c-.704.045-1.412.16-2.112.337C5.799 1.227 2.863 3.566 1.3 6.67A11.834 11.834 0 0 0 .238 9.801a11.81 11.81 0 0 0-.104 3.775c.12 1.02.374 2.023.778 2.977.227.57.511 1.124.825 1.648 1.094 1.783 2.683 3.236 4.51 4.24.688.39 1.408.69 2.157.944.226.074.45.15.689.21z" })
|
|
603
603
|
}),
|
|
604
604
|
ts: (props) => /* @__PURE__ */ jsx("svg", {
|
|
605
605
|
xmlns: "http://www.w3.org/2000/svg",
|
|
@@ -616,12 +616,13 @@ const Icons = {
|
|
|
616
616
|
};
|
|
617
617
|
function getIconForLanguageExtension(language) {
|
|
618
618
|
switch (language) {
|
|
619
|
-
case "json": return /* @__PURE__ */ jsx(Icons.json, {});
|
|
619
|
+
case "json": return /* @__PURE__ */ jsx(Icons.json, { className: "fill-foreground" });
|
|
620
620
|
case "css": return /* @__PURE__ */ jsx(Icons.css, { className: "fill-foreground" });
|
|
621
621
|
case "js":
|
|
622
622
|
case "jsx":
|
|
623
623
|
case "ts":
|
|
624
624
|
case "tsx":
|
|
625
|
+
case "javascript":
|
|
625
626
|
case "typescript": return /* @__PURE__ */ jsx(Icons.ts, { className: "fill-foreground" });
|
|
626
627
|
default: return /* @__PURE__ */ jsx(FileIcon, {});
|
|
627
628
|
}
|
|
@@ -731,7 +732,7 @@ const LANGUAGE_EXTENSIONS = {
|
|
|
731
732
|
};
|
|
732
733
|
const CodeMirror = {
|
|
733
734
|
kind: EditorEngine.CodeMirror,
|
|
734
|
-
Component: memo(function CodeMirror
|
|
735
|
+
Component: memo(function CodeMirror(props) {
|
|
735
736
|
const { id, basicSetup, extensions = [], width, height, fontFamily, lang, onMount, ...rest } = props;
|
|
736
737
|
const [mounted, setMounted] = useState(false);
|
|
737
738
|
const editorRef = useRef(null);
|
|
@@ -794,8 +795,8 @@ function CodesparkEditor(props) {
|
|
|
794
795
|
entry: "./App.tsx",
|
|
795
796
|
files: { "./App.tsx": value }
|
|
796
797
|
}));
|
|
797
|
-
const uid
|
|
798
|
-
const editorId = id ?? `editor${uid
|
|
798
|
+
const uid = useId();
|
|
799
|
+
const editorId = id ?? `editor${uid}`;
|
|
799
800
|
const editorRef = useRef(null);
|
|
800
801
|
const currentFileRef = useLatest(currentFile);
|
|
801
802
|
const { copyToClipboard, isCopied } = useCopyToClipboard();
|
|
@@ -838,14 +839,14 @@ function CodesparkEditor(props) {
|
|
|
838
839
|
workspace[INTERNAL_REGISTER_EDITOR](editorId, adapter);
|
|
839
840
|
}, []);
|
|
840
841
|
const renderEditor = () => {
|
|
841
|
-
const id
|
|
842
|
+
const id = `${workspace.id}${editorId}`;
|
|
842
843
|
if (editor.kind === EditorEngine.Monaco && propsTypeGuard(props, editor, EditorEngine.Monaco)) {
|
|
843
844
|
const { height, width, wrapperProps, options, onChange, onMount } = props;
|
|
844
845
|
const { fontFamily = globalFontFamily } = options || {};
|
|
845
846
|
return /* @__PURE__ */ jsx(editor.Component, {
|
|
846
|
-
id
|
|
847
|
+
id,
|
|
847
848
|
value: value || currentFile.code,
|
|
848
|
-
path: `file:///${id
|
|
849
|
+
path: `file:///${id}/${currentFile.path.replace(/^(\.\.?\/)+/, "")}`,
|
|
849
850
|
theme: theme === "light" ? "vitesse-light" : "vitesse-dark",
|
|
850
851
|
files,
|
|
851
852
|
imports: vendor.imports,
|
|
@@ -876,7 +877,7 @@ function CodesparkEditor(props) {
|
|
|
876
877
|
if (editor.kind === EditorEngine.CodeMirror && propsTypeGuard(props, editor, EditorEngine.CodeMirror)) {
|
|
877
878
|
const { height, width, basicSetup, fontFamily, readOnly, onChange, onMount } = props;
|
|
878
879
|
return /* @__PURE__ */ jsx(editor.Component, {
|
|
879
|
-
id
|
|
880
|
+
id,
|
|
880
881
|
className,
|
|
881
882
|
value: value || currentFile.code,
|
|
882
883
|
height: height ?? "200px",
|
|
@@ -918,7 +919,7 @@ function CodesparkEditor(props) {
|
|
|
918
919
|
className: "border-border flex items-center justify-between p-2",
|
|
919
920
|
children: [/* @__PURE__ */ jsxs("div", {
|
|
920
921
|
className: "[&_svg]:text-code-foreground flex items-center gap-x-2 px-2 [&_svg]:size-4 [&_svg]:opacity-70",
|
|
921
|
-
children: [getIconForLanguageExtension("typescript"), /* @__PURE__ */ jsx("span", {
|
|
922
|
+
children: [getIconForLanguageExtension(currentFile.language ?? "typescript"), /* @__PURE__ */ jsx("span", {
|
|
922
923
|
className: "text-card-foreground",
|
|
923
924
|
children: currentFile.path.replace(/^(\.\.?\/)+/, "")
|
|
924
925
|
})]
|
|
@@ -932,11 +933,12 @@ function CodesparkEditor(props) {
|
|
|
932
933
|
if (isValidElement(t)) return t;
|
|
933
934
|
const item = typeof t === "string" ? toolboxItems[t] : t;
|
|
934
935
|
if (!item) return null;
|
|
935
|
-
const { tooltip, icon, asChild = true, onClick, render } = item;
|
|
936
|
+
const { tooltip, disabled = false, icon, asChild = true, onClick, render } = item;
|
|
936
937
|
function renderTriggerContent() {
|
|
937
938
|
if (icon) return /* @__PURE__ */ jsx(Button, {
|
|
938
939
|
variant: "ghost",
|
|
939
940
|
size: "icon-sm",
|
|
941
|
+
disabled,
|
|
940
942
|
onClick: () => onClick?.(editorRef.current),
|
|
941
943
|
children: icon
|
|
942
944
|
});
|
|
@@ -1165,11 +1167,11 @@ function useInjections(children) {
|
|
|
1165
1167
|
Children.forEach(children, (child) => {
|
|
1166
1168
|
if (isValidElement(child)) {
|
|
1167
1169
|
if (child.type === Style) {
|
|
1168
|
-
const { children
|
|
1169
|
-
result.push(`<style${serializeAttributes(attrs)}>${children
|
|
1170
|
+
const { children, ...attrs } = child.props;
|
|
1171
|
+
result.push(`<style${serializeAttributes(attrs)}>${children?.trim() || ""}</style>`);
|
|
1170
1172
|
} else if (child.type === Script) {
|
|
1171
|
-
const { children
|
|
1172
|
-
result.push(`<script${serializeAttributes(attrs)}>${children
|
|
1173
|
+
const { children, ...attrs } = child.props;
|
|
1174
|
+
result.push(`<script${serializeAttributes(attrs)}>${children?.trim() || ""}<\/script>`);
|
|
1173
1175
|
} else if (child.type === Link) {
|
|
1174
1176
|
const attrs = child.props;
|
|
1175
1177
|
result.push(`<link${serializeAttributes(attrs)} />`);
|
|
@@ -1428,13 +1430,13 @@ var TailwindCSSJit = class TailwindCSSJit {
|
|
|
1428
1430
|
return this.env.querySelectorAll(`style[type="${TailwindCSSJit.STYLE_TYPE}"]`);
|
|
1429
1431
|
}
|
|
1430
1432
|
async createCompiler() {
|
|
1431
|
-
let css
|
|
1432
|
-
for (const sheet of this.stylesheets) css
|
|
1433
|
-
if (!css
|
|
1434
|
-
if (this.lastCss === css
|
|
1435
|
-
this.lastCss = css
|
|
1433
|
+
let css = "";
|
|
1434
|
+
for (const sheet of this.stylesheets) css += sheet.textContent + "\n";
|
|
1435
|
+
if (!css.includes("@import")) css = `@import "tailwindcss";${css}`;
|
|
1436
|
+
if (this.lastCss === css) return;
|
|
1437
|
+
this.lastCss = css;
|
|
1436
1438
|
try {
|
|
1437
|
-
this.compiler = await tailwindcss.compile(css
|
|
1439
|
+
this.compiler = await tailwindcss.compile(css, {
|
|
1438
1440
|
base: "/",
|
|
1439
1441
|
loadStylesheet: this.loadStylesheet,
|
|
1440
1442
|
loadModule: this.loadModule
|
|
@@ -1522,8 +1524,8 @@ function useTailwindCSS() {
|
|
|
1522
1524
|
});
|
|
1523
1525
|
};
|
|
1524
1526
|
const rebuild = async (kind) => {
|
|
1525
|
-
const css
|
|
1526
|
-
if (css
|
|
1527
|
+
const css = await jitRef.current?.rebuild(kind);
|
|
1528
|
+
if (css !== void 0 && sheetRef.current) sheetRef.current.textContent = css;
|
|
1527
1529
|
};
|
|
1528
1530
|
const mount = (doc) => {
|
|
1529
1531
|
jitRef.current ??= new TailwindCSSJit(doc);
|
|
@@ -1623,7 +1625,7 @@ body {
|
|
|
1623
1625
|
function CodesparkPreview(props) {
|
|
1624
1626
|
const { imports: globalImports, theme: globalTheme } = useConfig();
|
|
1625
1627
|
const { workspace: contextWorkspace, imports: contextImports, theme: contextTheme, framework: contextFramework } = useCodespark() || {};
|
|
1626
|
-
const { code = "", framework = contextFramework, className, tailwindcss
|
|
1628
|
+
const { code = "", framework = contextFramework, className, tailwindcss = true, preflight = true, imports, theme = contextTheme ?? globalTheme ?? "light", children, height, onError, onLoad, onRendered, onConsole } = props;
|
|
1627
1629
|
const { compiled, vendor, workspace } = useWorkspace(props.workspace ?? contextWorkspace ?? new Workspace({
|
|
1628
1630
|
entry: "./App.tsx",
|
|
1629
1631
|
files: { "./App.tsx": code },
|
|
@@ -1653,12 +1655,12 @@ function CodesparkPreview(props) {
|
|
|
1653
1655
|
onConsole
|
|
1654
1656
|
});
|
|
1655
1657
|
useEffect(() => {
|
|
1656
|
-
if (!tailwindcss
|
|
1658
|
+
if (!tailwindcss) unmountTailwind();
|
|
1657
1659
|
else readyRef.current.promise.then((doc) => {
|
|
1658
1660
|
if (doc) mountTailwind(doc);
|
|
1659
1661
|
});
|
|
1660
1662
|
return unmountTailwind;
|
|
1661
|
-
}, [tailwindcss
|
|
1663
|
+
}, [tailwindcss]);
|
|
1662
1664
|
useEffect(() => {
|
|
1663
1665
|
if (typeof window === "undefined" || !code) return;
|
|
1664
1666
|
workspace.setFile(workspace.entry, code);
|
|
@@ -1693,6 +1695,193 @@ function CodesparkPreview(props) {
|
|
|
1693
1695
|
});
|
|
1694
1696
|
}
|
|
1695
1697
|
|
|
1698
|
+
//#endregion
|
|
1699
|
+
//#region src/ui/input.tsx
|
|
1700
|
+
function Input({ className, type, ...props }) {
|
|
1701
|
+
return /* @__PURE__ */ jsx("input", {
|
|
1702
|
+
type,
|
|
1703
|
+
"data-slot": "input",
|
|
1704
|
+
className: cn("dark:bg-input/30 border-input focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 disabled:bg-input/50 dark:disabled:bg-input/80 file:text-foreground placeholder:text-muted-foreground h-8 w-full min-w-0 rounded-lg border bg-transparent px-2.5 py-1 text-base transition-colors outline-none file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:ring-3 disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:ring-3 md:text-sm", className),
|
|
1705
|
+
...props
|
|
1706
|
+
});
|
|
1707
|
+
}
|
|
1708
|
+
|
|
1709
|
+
//#endregion
|
|
1710
|
+
//#region src/ui/input-group.tsx
|
|
1711
|
+
function InputGroup({ className, ...props }) {
|
|
1712
|
+
return /* @__PURE__ */ jsx("div", {
|
|
1713
|
+
"data-slot": "input-group",
|
|
1714
|
+
role: "group",
|
|
1715
|
+
className: cn("border-input dark:bg-input/30 has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50 has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[[data-slot][aria-invalid=true]]:border-destructive dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40 has-disabled:bg-input/50 dark:has-disabled:bg-input/80 group/input-group relative flex h-8 w-full min-w-0 items-center rounded-lg border transition-colors outline-none in-data-[slot=combobox-content]:focus-within:border-inherit in-data-[slot=combobox-content]:focus-within:ring-0 has-disabled:opacity-50 has-[[data-slot=input-group-control]:focus-visible]:ring-3 has-[[data-slot][aria-invalid=true]]:ring-3 has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>textarea]:h-auto has-[>[data-align=block-end]]:[&>input]:pt-3 has-[>[data-align=block-start]]:[&>input]:pb-3 has-[>[data-align=inline-end]]:[&>input]:pr-1.5 has-[>[data-align=inline-start]]:[&>input]:pl-1.5", className),
|
|
1716
|
+
...props
|
|
1717
|
+
});
|
|
1718
|
+
}
|
|
1719
|
+
const inputGroupAddonVariants = cva("text-muted-foreground h-auto gap-2 py-1.5 text-sm font-medium group-data-[disabled=true]/input-group:opacity-50 [&>kbd]:rounded-[calc(var(--radius)-5px)] [&>svg:not([class*='size-'])]:size-4 flex cursor-text items-center justify-center select-none", {
|
|
1720
|
+
variants: { align: {
|
|
1721
|
+
"inline-start": "pl-2 has-[>button]:ml-[-0.3rem] has-[>kbd]:ml-[-0.15rem] order-first",
|
|
1722
|
+
"inline-end": "pr-2 has-[>button]:mr-[-0.3rem] has-[>kbd]:mr-[-0.15rem] order-last",
|
|
1723
|
+
"block-start": "px-2.5 pt-2 group-has-[>input]/input-group:pt-2 [.border-b]:pb-2 order-first w-full justify-start",
|
|
1724
|
+
"block-end": "px-2.5 pb-2 group-has-[>input]/input-group:pb-2 [.border-t]:pt-2 order-last w-full justify-start"
|
|
1725
|
+
} },
|
|
1726
|
+
defaultVariants: { align: "inline-start" }
|
|
1727
|
+
});
|
|
1728
|
+
function InputGroupAddon({ className, align = "inline-start", ...props }) {
|
|
1729
|
+
return /* @__PURE__ */ jsx("div", {
|
|
1730
|
+
role: "group",
|
|
1731
|
+
"data-slot": "input-group-addon",
|
|
1732
|
+
"data-align": align,
|
|
1733
|
+
className: cn(inputGroupAddonVariants({ align }), className),
|
|
1734
|
+
onClick: (e) => {
|
|
1735
|
+
if (e.target.closest("button")) return;
|
|
1736
|
+
e.currentTarget.parentElement?.querySelector("input")?.focus();
|
|
1737
|
+
},
|
|
1738
|
+
...props
|
|
1739
|
+
});
|
|
1740
|
+
}
|
|
1741
|
+
const inputGroupButtonVariants = cva("gap-2 text-sm shadow-none flex items-center", {
|
|
1742
|
+
variants: { size: {
|
|
1743
|
+
xs: "h-6 gap-1 rounded-[calc(var(--radius)-3px)] px-1.5 [&>svg:not([class*='size-'])]:size-3.5",
|
|
1744
|
+
sm: "",
|
|
1745
|
+
"icon-xs": "size-6 rounded-[calc(var(--radius)-3px)] p-0 has-[>svg]:p-0",
|
|
1746
|
+
"icon-sm": "size-8 p-0 has-[>svg]:p-0"
|
|
1747
|
+
} },
|
|
1748
|
+
defaultVariants: { size: "xs" }
|
|
1749
|
+
});
|
|
1750
|
+
function InputGroupButton({ className, type = "button", variant = "ghost", size = "xs", ...props }) {
|
|
1751
|
+
return /* @__PURE__ */ jsx(Button, {
|
|
1752
|
+
type,
|
|
1753
|
+
"data-size": size,
|
|
1754
|
+
variant,
|
|
1755
|
+
className: cn(inputGroupButtonVariants({ size }), className),
|
|
1756
|
+
...props
|
|
1757
|
+
});
|
|
1758
|
+
}
|
|
1759
|
+
function InputGroupInput({ className, ...props }) {
|
|
1760
|
+
return /* @__PURE__ */ jsx(Input, {
|
|
1761
|
+
"data-slot": "input-group-control",
|
|
1762
|
+
className: cn("flex-1 rounded-none border-0 bg-transparent shadow-none ring-0 focus-visible:ring-0 disabled:bg-transparent aria-invalid:ring-0 dark:bg-transparent dark:disabled:bg-transparent", className),
|
|
1763
|
+
...props
|
|
1764
|
+
});
|
|
1765
|
+
}
|
|
1766
|
+
|
|
1767
|
+
//#endregion
|
|
1768
|
+
//#region src/components/browser/index.tsx
|
|
1769
|
+
const parseUrlInput = (input) => {
|
|
1770
|
+
let path = input.trim();
|
|
1771
|
+
path = path.replace(/^https?:\/\//, "");
|
|
1772
|
+
path = path.replace(/^localhost(:\d+)?/, "");
|
|
1773
|
+
if (!path.startsWith("/")) path = "/" + path;
|
|
1774
|
+
return path;
|
|
1775
|
+
};
|
|
1776
|
+
function CodesparkBrowser(props) {
|
|
1777
|
+
const { workspace: contextWorkspace } = useCodespark() || {};
|
|
1778
|
+
const { defaultPath = "/", onPathChange, loading = false, className, onLoad } = props;
|
|
1779
|
+
const { workspace } = useWorkspace(props.workspace ?? contextWorkspace);
|
|
1780
|
+
const [currentPath, setCurrentPath] = useState(defaultPath);
|
|
1781
|
+
const framework = useMemo(() => {
|
|
1782
|
+
const fwInput = workspace.framework;
|
|
1783
|
+
if (typeof fwInput === "string") return registry.get(fwInput);
|
|
1784
|
+
if (typeof fwInput === "function") return new fwInput();
|
|
1785
|
+
return fwInput;
|
|
1786
|
+
}, []);
|
|
1787
|
+
const supported = (fw) => fw?.name === "node-http" || fw?.name === "node-vite";
|
|
1788
|
+
const [src, setSrc] = useState("about:blank");
|
|
1789
|
+
useEffect(() => {
|
|
1790
|
+
if (!supported(framework)) return;
|
|
1791
|
+
framework.on("serverReady", () => {
|
|
1792
|
+
handleRequest("/");
|
|
1793
|
+
});
|
|
1794
|
+
framework.on("serverShutdown", () => {
|
|
1795
|
+
setSrc("about:blank");
|
|
1796
|
+
});
|
|
1797
|
+
const handleMessage = (event) => {
|
|
1798
|
+
if (event.data?.type === "navigate") {
|
|
1799
|
+
const path = event.data.path;
|
|
1800
|
+
setCurrentPath(path);
|
|
1801
|
+
handleRequest(path);
|
|
1802
|
+
}
|
|
1803
|
+
};
|
|
1804
|
+
window.addEventListener("message", handleMessage);
|
|
1805
|
+
return () => {
|
|
1806
|
+
window.removeEventListener("message", handleMessage);
|
|
1807
|
+
};
|
|
1808
|
+
}, []);
|
|
1809
|
+
const handleRequest = (path) => {
|
|
1810
|
+
if (!supported(framework)) return;
|
|
1811
|
+
framework.request(path).then(setSrc);
|
|
1812
|
+
};
|
|
1813
|
+
const handleAddressSubmit = (e) => {
|
|
1814
|
+
e.preventDefault();
|
|
1815
|
+
const path = parseUrlInput(currentPath);
|
|
1816
|
+
setCurrentPath(path);
|
|
1817
|
+
handleRequest(path);
|
|
1818
|
+
};
|
|
1819
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
1820
|
+
className: cn("relative flex flex-col", className),
|
|
1821
|
+
children: [
|
|
1822
|
+
loading ? /* @__PURE__ */ jsx("div", {
|
|
1823
|
+
className: "absolute right-2 bottom-2 z-10 h-8 w-8 **:box-border",
|
|
1824
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
1825
|
+
className: "flex -translate-x-1 translate-y-[9px] scale-[0.13] **:absolute **:h-24 **:w-24",
|
|
1826
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
1827
|
+
className: "fill-mode-forwards **:border-foreground **:bg-background transform-[rotateX(-25.5deg)_rotateY(45deg)] animate-[cube-rotate_1s_linear_infinite] transform-3d **:rounded-lg **:border-10",
|
|
1828
|
+
children: [
|
|
1829
|
+
/* @__PURE__ */ jsx("div", { className: "origin-[50%_50%] transform-[rotateX(90deg)_translateZ(44px)]" }),
|
|
1830
|
+
/* @__PURE__ */ jsx("div", { className: "origin-[50%_50%] transform-[rotateY(90deg)_translateZ(44px)]" }),
|
|
1831
|
+
/* @__PURE__ */ jsx("div", { className: "origin-[50%_50%] transform-[rotateX(-90deg)_translateZ(44px)]" }),
|
|
1832
|
+
/* @__PURE__ */ jsx("div", { className: "origin-[50%_50%] transform-[rotateY(-90deg)_translateZ(44px)]" }),
|
|
1833
|
+
/* @__PURE__ */ jsx("div", { className: "origin-[50%_50%] transform-[rotateY(0deg)_translateZ(44px)]" }),
|
|
1834
|
+
/* @__PURE__ */ jsx("div", { className: "origin-[50%_50%] transform-[rotateY(-180deg)_translateZ(44px)]" })
|
|
1835
|
+
]
|
|
1836
|
+
})
|
|
1837
|
+
})
|
|
1838
|
+
}) : null,
|
|
1839
|
+
/* @__PURE__ */ jsx("form", {
|
|
1840
|
+
onSubmit: handleAddressSubmit,
|
|
1841
|
+
className: "bg-muted/50 border-border relative z-10 flex items-center gap-2 border-b p-2",
|
|
1842
|
+
children: /* @__PURE__ */ jsxs(InputGroup, { children: [/* @__PURE__ */ jsx(InputGroupInput, {
|
|
1843
|
+
value: currentPath,
|
|
1844
|
+
onChange: (e) => {
|
|
1845
|
+
const path = e.target.value;
|
|
1846
|
+
setCurrentPath(path);
|
|
1847
|
+
onPathChange?.(path);
|
|
1848
|
+
},
|
|
1849
|
+
onKeyDown: (e) => {
|
|
1850
|
+
if (e.key === "Enter") handleAddressSubmit(e);
|
|
1851
|
+
}
|
|
1852
|
+
}), /* @__PURE__ */ jsx(InputGroupAddon, {
|
|
1853
|
+
align: "inline-end",
|
|
1854
|
+
children: /* @__PURE__ */ jsx(InputGroupButton, {
|
|
1855
|
+
type: "submit",
|
|
1856
|
+
variant: "secondary",
|
|
1857
|
+
children: "Go"
|
|
1858
|
+
})
|
|
1859
|
+
})] })
|
|
1860
|
+
}),
|
|
1861
|
+
src === "about:blank" ? /* @__PURE__ */ jsxs("div", {
|
|
1862
|
+
className: "bg-background flex h-full w-full flex-1 flex-col items-center justify-center gap-4",
|
|
1863
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
1864
|
+
className: "text-muted-foreground/50 text-sm",
|
|
1865
|
+
children: "Ready to preview"
|
|
1866
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
1867
|
+
className: "text-muted-foreground/30 flex gap-2 text-xs",
|
|
1868
|
+
children: [
|
|
1869
|
+
/* @__PURE__ */ jsx("span", { children: "localhost" }),
|
|
1870
|
+
/* @__PURE__ */ jsx("span", { children: "•" }),
|
|
1871
|
+
/* @__PURE__ */ jsx("span", { children: "Press Go to navigate" })
|
|
1872
|
+
]
|
|
1873
|
+
})]
|
|
1874
|
+
}) : /* @__PURE__ */ jsx("iframe", {
|
|
1875
|
+
src,
|
|
1876
|
+
className: "h-full w-full flex-1",
|
|
1877
|
+
onLoad: (e) => {
|
|
1878
|
+
onLoad?.(e.target);
|
|
1879
|
+
}
|
|
1880
|
+
})
|
|
1881
|
+
]
|
|
1882
|
+
});
|
|
1883
|
+
}
|
|
1884
|
+
|
|
1696
1885
|
//#endregion
|
|
1697
1886
|
//#region src/index.tsx
|
|
1698
1887
|
registerFramework(react);
|
|
@@ -1704,7 +1893,7 @@ registerFramework(react);
|
|
|
1704
1893
|
* Supports both single-file mode (via `code` prop) and multi-file mode (via `files` prop).
|
|
1705
1894
|
*/
|
|
1706
1895
|
function Codespark(props) {
|
|
1707
|
-
const { code, files, name = "./App.tsx", theme, editor, framework = "react", showEditor = true, showPreview = true, showFileExplorer = true, readonly: readOnly, className, toolbox, tailwindcss
|
|
1896
|
+
const { code, files, name = "./App.tsx", theme, editor, framework = "react", showEditor = true, showPreview = true, showFileExplorer = true, readonly: readOnly, className, toolbox, tailwindcss, onConsole, onError, children, defaultExpanded, getWorkspace, editorHeight, previewHeight, orientation = "vertical", preflight } = props;
|
|
1708
1897
|
const { workspace, fileTree, compileError } = useWorkspace({
|
|
1709
1898
|
entry: name,
|
|
1710
1899
|
files: files ?? { [name]: code || "" },
|
|
@@ -1754,10 +1943,10 @@ function Codespark(props) {
|
|
|
1754
1943
|
theme,
|
|
1755
1944
|
children: /* @__PURE__ */ jsxs("div", {
|
|
1756
1945
|
className: cn("border-border relative grid w-full overflow-hidden rounded-lg border", orientation === "horizontal" && "grid-cols-[2fr_1fr]", className),
|
|
1757
|
-
children: [/* @__PURE__ */ jsxs("div", {
|
|
1946
|
+
children: [showPreview ? /* @__PURE__ */ jsxs("div", {
|
|
1758
1947
|
className: cn("border-border relative", showPreview && showEditor ? orientation === "vertical" ? "border-b" : "border-l" : "", orientation === "horizontal" && "order-2"),
|
|
1759
|
-
children: [
|
|
1760
|
-
tailwindcss
|
|
1948
|
+
children: [/* @__PURE__ */ jsx(CodesparkPreview, {
|
|
1949
|
+
tailwindcss,
|
|
1761
1950
|
onConsole,
|
|
1762
1951
|
onError: (error) => {
|
|
1763
1952
|
onError?.(error);
|
|
@@ -1766,7 +1955,7 @@ function Codespark(props) {
|
|
|
1766
1955
|
height: previewHeight,
|
|
1767
1956
|
preflight,
|
|
1768
1957
|
children
|
|
1769
|
-
})
|
|
1958
|
+
}), runtimeError ? /* @__PURE__ */ jsxs("div", {
|
|
1770
1959
|
className: "bg-background absolute inset-0 z-20 overflow-auto p-6",
|
|
1771
1960
|
children: [/* @__PURE__ */ jsx("div", {
|
|
1772
1961
|
className: "text-2xl text-red-500",
|
|
@@ -1776,7 +1965,7 @@ function Codespark(props) {
|
|
|
1776
1965
|
children: runtimeError.stack || runtimeError.message
|
|
1777
1966
|
})]
|
|
1778
1967
|
}) : null]
|
|
1779
|
-
}), showEditor ? /* @__PURE__ */ jsxs("div", {
|
|
1968
|
+
}) : null, showEditor ? /* @__PURE__ */ jsxs("div", {
|
|
1780
1969
|
className: cn("flex h-full w-full divide-x", orientation === "horizontal" && "order-1"),
|
|
1781
1970
|
children: [expanded && showFileExplorer ? /* @__PURE__ */ jsx(CodesparkFileExplorer, {}) : null, renderEditor()]
|
|
1782
1971
|
}) : null]
|
|
@@ -1792,4 +1981,4 @@ const useMDXComponents = () => {
|
|
|
1792
1981
|
};
|
|
1793
1982
|
|
|
1794
1983
|
//#endregion
|
|
1795
|
-
export { Codespark, CodesparkEditor, CodesparkFileExplorer, CodesparkPreview, CodesparkProvider, ConfigProvider, EditorEngine, Link, Script, Style, Workspace, createWorkspace, useMDXComponents, useWorkspace };
|
|
1984
|
+
export { Codespark, CodesparkBrowser, CodesparkEditor, CodesparkFileExplorer, CodesparkPreview, CodesparkProvider, ConfigProvider, EditorEngine, Link, Script, Style, Workspace, createWorkspace, useMDXComponents, useWorkspace };
|