@aquiles-ai/renderize 1.4.0 → 1.6.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/dist/index.cjs CHANGED
@@ -29,22 +29,15 @@ var import_react = require("react");
29
29
 
30
30
  // src/template.ts
31
31
  function buildTemplate(code) {
32
- return (
33
- /* html */
34
- `
35
- <!DOCTYPE html>
32
+ return `<!DOCTYPE html>
36
33
  <html lang="en">
37
34
  <head>
38
35
  <meta charset="UTF-8" />
39
36
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
40
37
 
41
- <!-- Tailwind CSS Play CDN -->
42
38
  <script src="https://cdn.tailwindcss.com"></script>
43
-
44
- <!-- Babel standalone: transpiles JSX at runtime -->
45
39
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
46
40
 
47
- <!-- Import map: React + Radix UI + Lucide -->
48
41
  <script type="importmap">
49
42
  {
50
43
  "imports": {
@@ -52,37 +45,37 @@ function buildTemplate(code) {
52
45
  "react/jsx-runtime": "https://esm.sh/react@18/jsx-runtime",
53
46
  "react-dom": "https://esm.sh/react-dom@18",
54
47
  "react-dom/client": "https://esm.sh/react-dom@18/client",
55
- "lucide-react": "https://esm.sh/lucide-react@latest",
48
+ "lucide-react": "https://esm.sh/lucide-react?external=react",
56
49
  "clsx": "https://esm.sh/clsx",
57
50
  "class-variance-authority": "https://esm.sh/class-variance-authority",
58
51
  "tailwind-merge": "https://esm.sh/tailwind-merge",
59
- "@radix-ui/react-accordion": "https://esm.sh/@radix-ui/react-accordion",
60
- "@radix-ui/react-alert-dialog": "https://esm.sh/@radix-ui/react-alert-dialog",
61
- "@radix-ui/react-avatar": "https://esm.sh/@radix-ui/react-avatar",
62
- "@radix-ui/react-checkbox": "https://esm.sh/@radix-ui/react-checkbox",
63
- "@radix-ui/react-collapsible": "https://esm.sh/@radix-ui/react-collapsible",
64
- "@radix-ui/react-context-menu": "https://esm.sh/@radix-ui/react-context-menu",
65
- "@radix-ui/react-dialog": "https://esm.sh/@radix-ui/react-dialog",
66
- "@radix-ui/react-dropdown-menu": "https://esm.sh/@radix-ui/react-dropdown-menu",
67
- "@radix-ui/react-hover-card": "https://esm.sh/@radix-ui/react-hover-card",
68
- "@radix-ui/react-label": "https://esm.sh/@radix-ui/react-label",
69
- "@radix-ui/react-menubar": "https://esm.sh/@radix-ui/react-menubar",
70
- "@radix-ui/react-navigation-menu": "https://esm.sh/@radix-ui/react-navigation-menu",
71
- "@radix-ui/react-popover": "https://esm.sh/@radix-ui/react-popover",
72
- "@radix-ui/react-progress": "https://esm.sh/@radix-ui/react-progress",
73
- "@radix-ui/react-radio-group": "https://esm.sh/@radix-ui/react-radio-group",
74
- "@radix-ui/react-scroll-area": "https://esm.sh/@radix-ui/react-scroll-area",
75
- "@radix-ui/react-select": "https://esm.sh/@radix-ui/react-select",
76
- "@radix-ui/react-separator": "https://esm.sh/@radix-ui/react-separator",
77
- "@radix-ui/react-slider": "https://esm.sh/@radix-ui/react-slider",
78
- "@radix-ui/react-slot": "https://esm.sh/@radix-ui/react-slot",
79
- "@radix-ui/react-switch": "https://esm.sh/@radix-ui/react-switch",
80
- "@radix-ui/react-tabs": "https://esm.sh/@radix-ui/react-tabs",
81
- "@radix-ui/react-toast": "https://esm.sh/@radix-ui/react-toast",
82
- "@radix-ui/react-toggle": "https://esm.sh/@radix-ui/react-toggle",
83
- "@radix-ui/react-toggle-group": "https://esm.sh/@radix-ui/react-toggle-group",
84
- "@radix-ui/react-toolbar": "https://esm.sh/@radix-ui/react-toolbar",
85
- "@radix-ui/react-tooltip": "https://esm.sh/@radix-ui/react-tooltip"
52
+ "@radix-ui/react-accordion": "https://esm.sh/@radix-ui/react-accordion?external=react,react-dom",
53
+ "@radix-ui/react-alert-dialog": "https://esm.sh/@radix-ui/react-alert-dialog?external=react,react-dom",
54
+ "@radix-ui/react-avatar": "https://esm.sh/@radix-ui/react-avatar?external=react,react-dom",
55
+ "@radix-ui/react-checkbox": "https://esm.sh/@radix-ui/react-checkbox?external=react,react-dom",
56
+ "@radix-ui/react-collapsible": "https://esm.sh/@radix-ui/react-collapsible?external=react,react-dom",
57
+ "@radix-ui/react-context-menu": "https://esm.sh/@radix-ui/react-context-menu?external=react,react-dom",
58
+ "@radix-ui/react-dialog": "https://esm.sh/@radix-ui/react-dialog?external=react,react-dom",
59
+ "@radix-ui/react-dropdown-menu": "https://esm.sh/@radix-ui/react-dropdown-menu?external=react,react-dom",
60
+ "@radix-ui/react-hover-card": "https://esm.sh/@radix-ui/react-hover-card?external=react,react-dom",
61
+ "@radix-ui/react-label": "https://esm.sh/@radix-ui/react-label?external=react,react-dom",
62
+ "@radix-ui/react-menubar": "https://esm.sh/@radix-ui/react-menubar?external=react,react-dom",
63
+ "@radix-ui/react-navigation-menu": "https://esm.sh/@radix-ui/react-navigation-menu?external=react,react-dom",
64
+ "@radix-ui/react-popover": "https://esm.sh/@radix-ui/react-popover?external=react,react-dom",
65
+ "@radix-ui/react-progress": "https://esm.sh/@radix-ui/react-progress?external=react,react-dom",
66
+ "@radix-ui/react-radio-group": "https://esm.sh/@radix-ui/react-radio-group?external=react,react-dom",
67
+ "@radix-ui/react-scroll-area": "https://esm.sh/@radix-ui/react-scroll-area?external=react,react-dom",
68
+ "@radix-ui/react-select": "https://esm.sh/@radix-ui/react-select?external=react,react-dom",
69
+ "@radix-ui/react-separator": "https://esm.sh/@radix-ui/react-separator?external=react,react-dom",
70
+ "@radix-ui/react-slider": "https://esm.sh/@radix-ui/react-slider?external=react,react-dom",
71
+ "@radix-ui/react-slot": "https://esm.sh/@radix-ui/react-slot?external=react,react-dom",
72
+ "@radix-ui/react-switch": "https://esm.sh/@radix-ui/react-switch?external=react,react-dom",
73
+ "@radix-ui/react-tabs": "https://esm.sh/@radix-ui/react-tabs?external=react,react-dom",
74
+ "@radix-ui/react-toast": "https://esm.sh/@radix-ui/react-toast?external=react,react-dom",
75
+ "@radix-ui/react-toggle": "https://esm.sh/@radix-ui/react-toggle?external=react,react-dom",
76
+ "@radix-ui/react-toggle-group": "https://esm.sh/@radix-ui/react-toggle-group?external=react,react-dom",
77
+ "@radix-ui/react-toolbar": "https://esm.sh/@radix-ui/react-toolbar?external=react,react-dom",
78
+ "@radix-ui/react-tooltip": "https://esm.sh/@radix-ui/react-tooltip?external=react,react-dom"
86
79
  }
87
80
  }
88
81
  </script>
@@ -96,6 +89,7 @@ function buildTemplate(code) {
96
89
  <div id="root"></div>
97
90
 
98
91
  <script type="text/babel" data-type="module">
92
+ import React, { useState, useEffect, useRef, useCallback, useMemo, useReducer, useContext, createContext } from "react";
99
93
  import { createRoot } from "react-dom/client";
100
94
 
101
95
  // \u2500\u2500 USER CODE START \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
@@ -103,12 +97,10 @@ function buildTemplate(code) {
103
97
  // \u2500\u2500 USER CODE END \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
104
98
 
105
99
  const container = document.getElementById("root");
106
- createRoot(container).render(<App />);
100
+ createRoot(container).render(React.createElement(App));
107
101
  </script>
108
102
  </body>
109
- </html>
110
- `.trim()
111
- );
103
+ </html>`;
112
104
  }
113
105
 
114
106
  // src/Renderize.tsx
@@ -121,24 +113,10 @@ function Renderize({
121
113
  style,
122
114
  onError
123
115
  }) {
124
- const prevUrlRef = (0, import_react.useRef)(null);
125
- const [blobUrl, setBlobUrl] = (0, import_react.useState)(null);
116
+ const [srcDoc, setSrcDoc] = (0, import_react.useState)(null);
126
117
  (0, import_react.useEffect)(() => {
127
118
  if (!code?.trim()) return;
128
- if (prevUrlRef.current) {
129
- URL.revokeObjectURL(prevUrlRef.current);
130
- }
131
- const html = buildTemplate(code);
132
- const blob = new Blob([html], { type: "text/html" });
133
- const url = URL.createObjectURL(blob);
134
- prevUrlRef.current = url;
135
- setBlobUrl(url);
136
- return () => {
137
- if (prevUrlRef.current) {
138
- URL.revokeObjectURL(prevUrlRef.current);
139
- prevUrlRef.current = null;
140
- }
141
- };
119
+ setSrcDoc(buildTemplate(code));
142
120
  }, [code]);
143
121
  (0, import_react.useEffect)(() => {
144
122
  const handler = (event) => {
@@ -154,10 +132,10 @@ function Renderize({
154
132
  {
155
133
  className,
156
134
  style: { width, height, overflow: "hidden", ...style },
157
- children: blobUrl && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
135
+ children: srcDoc && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
158
136
  "iframe",
159
137
  {
160
- src: blobUrl,
138
+ srcDoc,
161
139
  title: "Renderize Sandbox",
162
140
  sandbox: "allow-scripts",
163
141
  style: {
@@ -167,7 +145,7 @@ function Renderize({
167
145
  display: "block"
168
146
  }
169
147
  },
170
- blobUrl
148
+ srcDoc
171
149
  )
172
150
  }
173
151
  );
package/dist/index.d.cts CHANGED
@@ -2,7 +2,7 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import React from 'react';
3
3
 
4
4
  interface RenderizeProps {
5
- /** React code generated by the LLM. Must export a default `App` function component. */
5
+ /** React code generated by the LLM. Must define a function component named App. */
6
6
  code: string;
7
7
  /** Height of the sandbox iframe. Defaults to "100%" */
8
8
  height?: string | number;
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import React from 'react';
3
3
 
4
4
  interface RenderizeProps {
5
- /** React code generated by the LLM. Must export a default `App` function component. */
5
+ /** React code generated by the LLM. Must define a function component named App. */
6
6
  code: string;
7
7
  /** Height of the sandbox iframe. Defaults to "100%" */
8
8
  height?: string | number;
package/dist/index.js CHANGED
@@ -1,24 +1,17 @@
1
1
  // src/Renderize.tsx
2
- import { useEffect, useRef, useState } from "react";
2
+ import { useEffect, useState } from "react";
3
3
 
4
4
  // src/template.ts
5
5
  function buildTemplate(code) {
6
- return (
7
- /* html */
8
- `
9
- <!DOCTYPE html>
6
+ return `<!DOCTYPE html>
10
7
  <html lang="en">
11
8
  <head>
12
9
  <meta charset="UTF-8" />
13
10
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
14
11
 
15
- <!-- Tailwind CSS Play CDN -->
16
12
  <script src="https://cdn.tailwindcss.com"></script>
17
-
18
- <!-- Babel standalone: transpiles JSX at runtime -->
19
13
  <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
20
14
 
21
- <!-- Import map: React + Radix UI + Lucide -->
22
15
  <script type="importmap">
23
16
  {
24
17
  "imports": {
@@ -26,37 +19,37 @@ function buildTemplate(code) {
26
19
  "react/jsx-runtime": "https://esm.sh/react@18/jsx-runtime",
27
20
  "react-dom": "https://esm.sh/react-dom@18",
28
21
  "react-dom/client": "https://esm.sh/react-dom@18/client",
29
- "lucide-react": "https://esm.sh/lucide-react@latest",
22
+ "lucide-react": "https://esm.sh/lucide-react?external=react",
30
23
  "clsx": "https://esm.sh/clsx",
31
24
  "class-variance-authority": "https://esm.sh/class-variance-authority",
32
25
  "tailwind-merge": "https://esm.sh/tailwind-merge",
33
- "@radix-ui/react-accordion": "https://esm.sh/@radix-ui/react-accordion",
34
- "@radix-ui/react-alert-dialog": "https://esm.sh/@radix-ui/react-alert-dialog",
35
- "@radix-ui/react-avatar": "https://esm.sh/@radix-ui/react-avatar",
36
- "@radix-ui/react-checkbox": "https://esm.sh/@radix-ui/react-checkbox",
37
- "@radix-ui/react-collapsible": "https://esm.sh/@radix-ui/react-collapsible",
38
- "@radix-ui/react-context-menu": "https://esm.sh/@radix-ui/react-context-menu",
39
- "@radix-ui/react-dialog": "https://esm.sh/@radix-ui/react-dialog",
40
- "@radix-ui/react-dropdown-menu": "https://esm.sh/@radix-ui/react-dropdown-menu",
41
- "@radix-ui/react-hover-card": "https://esm.sh/@radix-ui/react-hover-card",
42
- "@radix-ui/react-label": "https://esm.sh/@radix-ui/react-label",
43
- "@radix-ui/react-menubar": "https://esm.sh/@radix-ui/react-menubar",
44
- "@radix-ui/react-navigation-menu": "https://esm.sh/@radix-ui/react-navigation-menu",
45
- "@radix-ui/react-popover": "https://esm.sh/@radix-ui/react-popover",
46
- "@radix-ui/react-progress": "https://esm.sh/@radix-ui/react-progress",
47
- "@radix-ui/react-radio-group": "https://esm.sh/@radix-ui/react-radio-group",
48
- "@radix-ui/react-scroll-area": "https://esm.sh/@radix-ui/react-scroll-area",
49
- "@radix-ui/react-select": "https://esm.sh/@radix-ui/react-select",
50
- "@radix-ui/react-separator": "https://esm.sh/@radix-ui/react-separator",
51
- "@radix-ui/react-slider": "https://esm.sh/@radix-ui/react-slider",
52
- "@radix-ui/react-slot": "https://esm.sh/@radix-ui/react-slot",
53
- "@radix-ui/react-switch": "https://esm.sh/@radix-ui/react-switch",
54
- "@radix-ui/react-tabs": "https://esm.sh/@radix-ui/react-tabs",
55
- "@radix-ui/react-toast": "https://esm.sh/@radix-ui/react-toast",
56
- "@radix-ui/react-toggle": "https://esm.sh/@radix-ui/react-toggle",
57
- "@radix-ui/react-toggle-group": "https://esm.sh/@radix-ui/react-toggle-group",
58
- "@radix-ui/react-toolbar": "https://esm.sh/@radix-ui/react-toolbar",
59
- "@radix-ui/react-tooltip": "https://esm.sh/@radix-ui/react-tooltip"
26
+ "@radix-ui/react-accordion": "https://esm.sh/@radix-ui/react-accordion?external=react,react-dom",
27
+ "@radix-ui/react-alert-dialog": "https://esm.sh/@radix-ui/react-alert-dialog?external=react,react-dom",
28
+ "@radix-ui/react-avatar": "https://esm.sh/@radix-ui/react-avatar?external=react,react-dom",
29
+ "@radix-ui/react-checkbox": "https://esm.sh/@radix-ui/react-checkbox?external=react,react-dom",
30
+ "@radix-ui/react-collapsible": "https://esm.sh/@radix-ui/react-collapsible?external=react,react-dom",
31
+ "@radix-ui/react-context-menu": "https://esm.sh/@radix-ui/react-context-menu?external=react,react-dom",
32
+ "@radix-ui/react-dialog": "https://esm.sh/@radix-ui/react-dialog?external=react,react-dom",
33
+ "@radix-ui/react-dropdown-menu": "https://esm.sh/@radix-ui/react-dropdown-menu?external=react,react-dom",
34
+ "@radix-ui/react-hover-card": "https://esm.sh/@radix-ui/react-hover-card?external=react,react-dom",
35
+ "@radix-ui/react-label": "https://esm.sh/@radix-ui/react-label?external=react,react-dom",
36
+ "@radix-ui/react-menubar": "https://esm.sh/@radix-ui/react-menubar?external=react,react-dom",
37
+ "@radix-ui/react-navigation-menu": "https://esm.sh/@radix-ui/react-navigation-menu?external=react,react-dom",
38
+ "@radix-ui/react-popover": "https://esm.sh/@radix-ui/react-popover?external=react,react-dom",
39
+ "@radix-ui/react-progress": "https://esm.sh/@radix-ui/react-progress?external=react,react-dom",
40
+ "@radix-ui/react-radio-group": "https://esm.sh/@radix-ui/react-radio-group?external=react,react-dom",
41
+ "@radix-ui/react-scroll-area": "https://esm.sh/@radix-ui/react-scroll-area?external=react,react-dom",
42
+ "@radix-ui/react-select": "https://esm.sh/@radix-ui/react-select?external=react,react-dom",
43
+ "@radix-ui/react-separator": "https://esm.sh/@radix-ui/react-separator?external=react,react-dom",
44
+ "@radix-ui/react-slider": "https://esm.sh/@radix-ui/react-slider?external=react,react-dom",
45
+ "@radix-ui/react-slot": "https://esm.sh/@radix-ui/react-slot?external=react,react-dom",
46
+ "@radix-ui/react-switch": "https://esm.sh/@radix-ui/react-switch?external=react,react-dom",
47
+ "@radix-ui/react-tabs": "https://esm.sh/@radix-ui/react-tabs?external=react,react-dom",
48
+ "@radix-ui/react-toast": "https://esm.sh/@radix-ui/react-toast?external=react,react-dom",
49
+ "@radix-ui/react-toggle": "https://esm.sh/@radix-ui/react-toggle?external=react,react-dom",
50
+ "@radix-ui/react-toggle-group": "https://esm.sh/@radix-ui/react-toggle-group?external=react,react-dom",
51
+ "@radix-ui/react-toolbar": "https://esm.sh/@radix-ui/react-toolbar?external=react,react-dom",
52
+ "@radix-ui/react-tooltip": "https://esm.sh/@radix-ui/react-tooltip?external=react,react-dom"
60
53
  }
61
54
  }
62
55
  </script>
@@ -70,6 +63,7 @@ function buildTemplate(code) {
70
63
  <div id="root"></div>
71
64
 
72
65
  <script type="text/babel" data-type="module">
66
+ import React, { useState, useEffect, useRef, useCallback, useMemo, useReducer, useContext, createContext } from "react";
73
67
  import { createRoot } from "react-dom/client";
74
68
 
75
69
  // \u2500\u2500 USER CODE START \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
@@ -77,12 +71,10 @@ function buildTemplate(code) {
77
71
  // \u2500\u2500 USER CODE END \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
78
72
 
79
73
  const container = document.getElementById("root");
80
- createRoot(container).render(<App />);
74
+ createRoot(container).render(React.createElement(App));
81
75
  </script>
82
76
  </body>
83
- </html>
84
- `.trim()
85
- );
77
+ </html>`;
86
78
  }
87
79
 
88
80
  // src/Renderize.tsx
@@ -95,24 +87,10 @@ function Renderize({
95
87
  style,
96
88
  onError
97
89
  }) {
98
- const prevUrlRef = useRef(null);
99
- const [blobUrl, setBlobUrl] = useState(null);
90
+ const [srcDoc, setSrcDoc] = useState(null);
100
91
  useEffect(() => {
101
92
  if (!code?.trim()) return;
102
- if (prevUrlRef.current) {
103
- URL.revokeObjectURL(prevUrlRef.current);
104
- }
105
- const html = buildTemplate(code);
106
- const blob = new Blob([html], { type: "text/html" });
107
- const url = URL.createObjectURL(blob);
108
- prevUrlRef.current = url;
109
- setBlobUrl(url);
110
- return () => {
111
- if (prevUrlRef.current) {
112
- URL.revokeObjectURL(prevUrlRef.current);
113
- prevUrlRef.current = null;
114
- }
115
- };
93
+ setSrcDoc(buildTemplate(code));
116
94
  }, [code]);
117
95
  useEffect(() => {
118
96
  const handler = (event) => {
@@ -128,10 +106,10 @@ function Renderize({
128
106
  {
129
107
  className,
130
108
  style: { width, height, overflow: "hidden", ...style },
131
- children: blobUrl && /* @__PURE__ */ jsx(
109
+ children: srcDoc && /* @__PURE__ */ jsx(
132
110
  "iframe",
133
111
  {
134
- src: blobUrl,
112
+ srcDoc,
135
113
  title: "Renderize Sandbox",
136
114
  sandbox: "allow-scripts",
137
115
  style: {
@@ -141,7 +119,7 @@ function Renderize({
141
119
  display: "block"
142
120
  }
143
121
  },
144
- blobUrl
122
+ srcDoc
145
123
  )
146
124
  }
147
125
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aquiles-ai/renderize",
3
- "version": "1.4.0",
3
+ "version": "1.6.0",
4
4
  "description": "Drop-in sandbox component that executes AI-generated React code with zero configuration.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
package/src/Renderize.tsx CHANGED
@@ -1,9 +1,9 @@
1
1
  /// <reference lib="dom" />
2
- import React, { useEffect, useRef, useState } from "react";
2
+ import React, { useEffect, useState } from "react";
3
3
  import { buildTemplate } from "./template.js";
4
4
 
5
5
  export interface RenderizeProps {
6
- /** React code generated by the LLM. Must export a default `App` function component. */
6
+ /** React code generated by the LLM. Must define a function component named App. */
7
7
  code: string;
8
8
  /** Height of the sandbox iframe. Defaults to "100%" */
9
9
  height?: string | number;
@@ -25,32 +25,13 @@ export function Renderize({
25
25
  style,
26
26
  onError,
27
27
  }: RenderizeProps) {
28
- const prevUrlRef = useRef<string | null>(null);
29
- const [blobUrl, setBlobUrl] = useState<string | null>(null);
28
+ const [srcDoc, setSrcDoc] = useState<string | null>(null);
30
29
 
31
30
  useEffect(() => {
32
31
  if (!code?.trim()) return;
33
-
34
- // Revoke previous blob URL to free memory
35
- if (prevUrlRef.current) {
36
- URL.revokeObjectURL(prevUrlRef.current);
37
- }
38
-
39
- const html = buildTemplate(code);
40
- const blob = new Blob([html], { type: "text/html" });
41
- const url = URL.createObjectURL(blob);
42
-
43
- prevUrlRef.current = url;
44
- // Storing the URL in state ensures the iframe src prop
45
- // and the actual DOM element are always in sync
46
- setBlobUrl(url);
47
-
48
- return () => {
49
- if (prevUrlRef.current) {
50
- URL.revokeObjectURL(prevUrlRef.current);
51
- prevUrlRef.current = null;
52
- }
53
- };
32
+ // srcdoc works with sandbox="allow-scripts" — no blob URL needed,
33
+ // no same-origin restriction, content is inlined directly
34
+ setSrcDoc(buildTemplate(code));
54
35
  }, [code]);
55
36
 
56
37
  // Forward runtime errors from the iframe to the parent
@@ -73,12 +54,12 @@ export function Renderize({
73
54
  className={className}
74
55
  style={{ width, height, overflow: "hidden", ...style }}
75
56
  >
76
- {blobUrl && (
57
+ {srcDoc && (
77
58
  <iframe
78
- // key forces a full remount when the URL changes,
79
- // guaranteeing a clean JS context on every new code
80
- key={blobUrl}
81
- src={blobUrl}
59
+ // key forces a full remount on every new render,
60
+ // guaranteeing a clean JS context each time
61
+ key={srcDoc}
62
+ srcDoc={srcDoc}
82
63
  title="Renderize Sandbox"
83
64
  sandbox="allow-scripts"
84
65
  style={{
package/src/template.ts CHANGED
@@ -1,18 +1,13 @@
1
1
  export function buildTemplate(code: string): string {
2
- return /* html */ `
3
- <!DOCTYPE html>
2
+ return `<!DOCTYPE html>
4
3
  <html lang="en">
5
4
  <head>
6
5
  <meta charset="UTF-8" />
7
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
8
7
 
9
- <!-- Tailwind CSS Play CDN -->
10
- <script src="https://cdn.tailwindcss.com"></script>
8
+ <script src="https://cdn.tailwindcss.com"><\/script>
9
+ <script src="https://unpkg.com/@babel/standalone/babel.min.js"><\/script>
11
10
 
12
- <!-- Babel standalone: transpiles JSX at runtime -->
13
- <script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
14
-
15
- <!-- Import map: React + Radix UI + Lucide -->
16
11
  <script type="importmap">
17
12
  {
18
13
  "imports": {
@@ -20,50 +15,51 @@ export function buildTemplate(code: string): string {
20
15
  "react/jsx-runtime": "https://esm.sh/react@18/jsx-runtime",
21
16
  "react-dom": "https://esm.sh/react-dom@18",
22
17
  "react-dom/client": "https://esm.sh/react-dom@18/client",
23
- "lucide-react": "https://esm.sh/lucide-react@latest",
18
+ "lucide-react": "https://esm.sh/lucide-react?external=react",
24
19
  "clsx": "https://esm.sh/clsx",
25
20
  "class-variance-authority": "https://esm.sh/class-variance-authority",
26
21
  "tailwind-merge": "https://esm.sh/tailwind-merge",
27
- "@radix-ui/react-accordion": "https://esm.sh/@radix-ui/react-accordion",
28
- "@radix-ui/react-alert-dialog": "https://esm.sh/@radix-ui/react-alert-dialog",
29
- "@radix-ui/react-avatar": "https://esm.sh/@radix-ui/react-avatar",
30
- "@radix-ui/react-checkbox": "https://esm.sh/@radix-ui/react-checkbox",
31
- "@radix-ui/react-collapsible": "https://esm.sh/@radix-ui/react-collapsible",
32
- "@radix-ui/react-context-menu": "https://esm.sh/@radix-ui/react-context-menu",
33
- "@radix-ui/react-dialog": "https://esm.sh/@radix-ui/react-dialog",
34
- "@radix-ui/react-dropdown-menu": "https://esm.sh/@radix-ui/react-dropdown-menu",
35
- "@radix-ui/react-hover-card": "https://esm.sh/@radix-ui/react-hover-card",
36
- "@radix-ui/react-label": "https://esm.sh/@radix-ui/react-label",
37
- "@radix-ui/react-menubar": "https://esm.sh/@radix-ui/react-menubar",
38
- "@radix-ui/react-navigation-menu": "https://esm.sh/@radix-ui/react-navigation-menu",
39
- "@radix-ui/react-popover": "https://esm.sh/@radix-ui/react-popover",
40
- "@radix-ui/react-progress": "https://esm.sh/@radix-ui/react-progress",
41
- "@radix-ui/react-radio-group": "https://esm.sh/@radix-ui/react-radio-group",
42
- "@radix-ui/react-scroll-area": "https://esm.sh/@radix-ui/react-scroll-area",
43
- "@radix-ui/react-select": "https://esm.sh/@radix-ui/react-select",
44
- "@radix-ui/react-separator": "https://esm.sh/@radix-ui/react-separator",
45
- "@radix-ui/react-slider": "https://esm.sh/@radix-ui/react-slider",
46
- "@radix-ui/react-slot": "https://esm.sh/@radix-ui/react-slot",
47
- "@radix-ui/react-switch": "https://esm.sh/@radix-ui/react-switch",
48
- "@radix-ui/react-tabs": "https://esm.sh/@radix-ui/react-tabs",
49
- "@radix-ui/react-toast": "https://esm.sh/@radix-ui/react-toast",
50
- "@radix-ui/react-toggle": "https://esm.sh/@radix-ui/react-toggle",
51
- "@radix-ui/react-toggle-group": "https://esm.sh/@radix-ui/react-toggle-group",
52
- "@radix-ui/react-toolbar": "https://esm.sh/@radix-ui/react-toolbar",
53
- "@radix-ui/react-tooltip": "https://esm.sh/@radix-ui/react-tooltip"
22
+ "@radix-ui/react-accordion": "https://esm.sh/@radix-ui/react-accordion?external=react,react-dom",
23
+ "@radix-ui/react-alert-dialog": "https://esm.sh/@radix-ui/react-alert-dialog?external=react,react-dom",
24
+ "@radix-ui/react-avatar": "https://esm.sh/@radix-ui/react-avatar?external=react,react-dom",
25
+ "@radix-ui/react-checkbox": "https://esm.sh/@radix-ui/react-checkbox?external=react,react-dom",
26
+ "@radix-ui/react-collapsible": "https://esm.sh/@radix-ui/react-collapsible?external=react,react-dom",
27
+ "@radix-ui/react-context-menu": "https://esm.sh/@radix-ui/react-context-menu?external=react,react-dom",
28
+ "@radix-ui/react-dialog": "https://esm.sh/@radix-ui/react-dialog?external=react,react-dom",
29
+ "@radix-ui/react-dropdown-menu": "https://esm.sh/@radix-ui/react-dropdown-menu?external=react,react-dom",
30
+ "@radix-ui/react-hover-card": "https://esm.sh/@radix-ui/react-hover-card?external=react,react-dom",
31
+ "@radix-ui/react-label": "https://esm.sh/@radix-ui/react-label?external=react,react-dom",
32
+ "@radix-ui/react-menubar": "https://esm.sh/@radix-ui/react-menubar?external=react,react-dom",
33
+ "@radix-ui/react-navigation-menu": "https://esm.sh/@radix-ui/react-navigation-menu?external=react,react-dom",
34
+ "@radix-ui/react-popover": "https://esm.sh/@radix-ui/react-popover?external=react,react-dom",
35
+ "@radix-ui/react-progress": "https://esm.sh/@radix-ui/react-progress?external=react,react-dom",
36
+ "@radix-ui/react-radio-group": "https://esm.sh/@radix-ui/react-radio-group?external=react,react-dom",
37
+ "@radix-ui/react-scroll-area": "https://esm.sh/@radix-ui/react-scroll-area?external=react,react-dom",
38
+ "@radix-ui/react-select": "https://esm.sh/@radix-ui/react-select?external=react,react-dom",
39
+ "@radix-ui/react-separator": "https://esm.sh/@radix-ui/react-separator?external=react,react-dom",
40
+ "@radix-ui/react-slider": "https://esm.sh/@radix-ui/react-slider?external=react,react-dom",
41
+ "@radix-ui/react-slot": "https://esm.sh/@radix-ui/react-slot?external=react,react-dom",
42
+ "@radix-ui/react-switch": "https://esm.sh/@radix-ui/react-switch?external=react,react-dom",
43
+ "@radix-ui/react-tabs": "https://esm.sh/@radix-ui/react-tabs?external=react,react-dom",
44
+ "@radix-ui/react-toast": "https://esm.sh/@radix-ui/react-toast?external=react,react-dom",
45
+ "@radix-ui/react-toggle": "https://esm.sh/@radix-ui/react-toggle?external=react,react-dom",
46
+ "@radix-ui/react-toggle-group": "https://esm.sh/@radix-ui/react-toggle-group?external=react,react-dom",
47
+ "@radix-ui/react-toolbar": "https://esm.sh/@radix-ui/react-toolbar?external=react,react-dom",
48
+ "@radix-ui/react-tooltip": "https://esm.sh/@radix-ui/react-tooltip?external=react,react-dom"
54
49
  }
55
50
  }
56
- </script>
51
+ <\/script>
57
52
 
58
53
  <style>
59
54
  * { box-sizing: border-box; }
60
55
  body { margin: 0; padding: 0; }
61
- </style>
62
- </head>
56
+ <\/style>
57
+ <\/head>
63
58
  <body>
64
- <div id="root"></div>
59
+ <div id="root"><\/div>
65
60
 
66
61
  <script type="text/babel" data-type="module">
62
+ import React, { useState, useEffect, useRef, useCallback, useMemo, useReducer, useContext, createContext } from "react";
67
63
  import { createRoot } from "react-dom/client";
68
64
 
69
65
  // ── USER CODE START ──────────────────────────────────────────────
@@ -71,9 +67,8 @@ export function buildTemplate(code: string): string {
71
67
  // ── USER CODE END ────────────────────────────────────────────────
72
68
 
73
69
  const container = document.getElementById("root");
74
- createRoot(container).render(<App />);
75
- </script>
76
- </body>
77
- </html>
78
- `.trim();
70
+ createRoot(container).render(React.createElement(App));
71
+ <\/script>
72
+ <\/body>
73
+ <\/html>`;
79
74
  }