@codespark/react 1.0.7 → 1.0.9

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/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 ? {
@@ -331,15 +341,8 @@ function useWorkspace(init) {
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 = useMemo(() => {
335
- const fwInput = workspace.framework;
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(() => {
@@ -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
  }
@@ -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
  });
@@ -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);
@@ -1754,9 +1943,9 @@ 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: [showPreview ? /* @__PURE__ */ jsx(CodesparkPreview, {
1948
+ children: [/* @__PURE__ */ jsx(CodesparkPreview, {
1760
1949
  tailwindcss,
1761
1950
  onConsole,
1762
1951
  onError: (error) => {
@@ -1766,7 +1955,7 @@ function Codespark(props) {
1766
1955
  height: previewHeight,
1767
1956
  preflight,
1768
1957
  children
1769
- }) : null, runtimeError ? /* @__PURE__ */ jsxs("div", {
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 };