@aquiles-ai/renderize 1.2.0 → 1.4.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
@@ -121,26 +121,22 @@ function Renderize({
121
121
  style,
122
122
  onError
123
123
  }) {
124
- const iframeRef = (0, import_react.useRef)(null);
125
- const blobUrlRef = (0, import_react.useRef)(null);
126
- const [key, setKey] = (0, import_react.useState)(0);
124
+ const prevUrlRef = (0, import_react.useRef)(null);
125
+ const [blobUrl, setBlobUrl] = (0, import_react.useState)(null);
127
126
  (0, import_react.useEffect)(() => {
128
127
  if (!code?.trim()) return;
129
- if (blobUrlRef.current) {
130
- URL.revokeObjectURL(blobUrlRef.current);
128
+ if (prevUrlRef.current) {
129
+ URL.revokeObjectURL(prevUrlRef.current);
131
130
  }
132
131
  const html = buildTemplate(code);
133
132
  const blob = new Blob([html], { type: "text/html" });
134
133
  const url = URL.createObjectURL(blob);
135
- blobUrlRef.current = url;
136
- if (iframeRef.current) {
137
- iframeRef.current.src = url;
138
- }
139
- setKey((prev) => prev + 1);
134
+ prevUrlRef.current = url;
135
+ setBlobUrl(url);
140
136
  return () => {
141
- if (blobUrlRef.current) {
142
- URL.revokeObjectURL(blobUrlRef.current);
143
- blobUrlRef.current = null;
137
+ if (prevUrlRef.current) {
138
+ URL.revokeObjectURL(prevUrlRef.current);
139
+ prevUrlRef.current = null;
144
140
  }
145
141
  };
146
142
  }, [code]);
@@ -158,10 +154,10 @@ function Renderize({
158
154
  {
159
155
  className,
160
156
  style: { width, height, overflow: "hidden", ...style },
161
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
157
+ children: blobUrl && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
162
158
  "iframe",
163
159
  {
164
- ref: iframeRef,
160
+ src: blobUrl,
165
161
  title: "Renderize Sandbox",
166
162
  sandbox: "allow-scripts",
167
163
  style: {
@@ -171,7 +167,7 @@ function Renderize({
171
167
  display: "block"
172
168
  }
173
169
  },
174
- key
170
+ blobUrl
175
171
  )
176
172
  }
177
173
  );
package/dist/index.js CHANGED
@@ -95,26 +95,22 @@ function Renderize({
95
95
  style,
96
96
  onError
97
97
  }) {
98
- const iframeRef = useRef(null);
99
- const blobUrlRef = useRef(null);
100
- const [key, setKey] = useState(0);
98
+ const prevUrlRef = useRef(null);
99
+ const [blobUrl, setBlobUrl] = useState(null);
101
100
  useEffect(() => {
102
101
  if (!code?.trim()) return;
103
- if (blobUrlRef.current) {
104
- URL.revokeObjectURL(blobUrlRef.current);
102
+ if (prevUrlRef.current) {
103
+ URL.revokeObjectURL(prevUrlRef.current);
105
104
  }
106
105
  const html = buildTemplate(code);
107
106
  const blob = new Blob([html], { type: "text/html" });
108
107
  const url = URL.createObjectURL(blob);
109
- blobUrlRef.current = url;
110
- if (iframeRef.current) {
111
- iframeRef.current.src = url;
112
- }
113
- setKey((prev) => prev + 1);
108
+ prevUrlRef.current = url;
109
+ setBlobUrl(url);
114
110
  return () => {
115
- if (blobUrlRef.current) {
116
- URL.revokeObjectURL(blobUrlRef.current);
117
- blobUrlRef.current = null;
111
+ if (prevUrlRef.current) {
112
+ URL.revokeObjectURL(prevUrlRef.current);
113
+ prevUrlRef.current = null;
118
114
  }
119
115
  };
120
116
  }, [code]);
@@ -132,10 +128,10 @@ function Renderize({
132
128
  {
133
129
  className,
134
130
  style: { width, height, overflow: "hidden", ...style },
135
- children: /* @__PURE__ */ jsx(
131
+ children: blobUrl && /* @__PURE__ */ jsx(
136
132
  "iframe",
137
133
  {
138
- ref: iframeRef,
134
+ src: blobUrl,
139
135
  title: "Renderize Sandbox",
140
136
  sandbox: "allow-scripts",
141
137
  style: {
@@ -145,7 +141,7 @@ function Renderize({
145
141
  display: "block"
146
142
  }
147
143
  },
148
- key
144
+ blobUrl
149
145
  )
150
146
  }
151
147
  );
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aquiles-ai/renderize",
3
- "version": "1.2.0",
3
+ "version": "1.4.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,3 +1,4 @@
1
+ /// <reference lib="dom" />
1
2
  import React, { useEffect, useRef, useState } from "react";
2
3
  import { buildTemplate } from "./template.js";
3
4
 
@@ -24,35 +25,30 @@ export function Renderize({
24
25
  style,
25
26
  onError,
26
27
  }: RenderizeProps) {
27
- const iframeRef = useRef<HTMLIFrameElement>(null);
28
- const blobUrlRef = useRef<string | null>(null);
29
- const [key, setKey] = useState(0);
28
+ const prevUrlRef = useRef<string | null>(null);
29
+ const [blobUrl, setBlobUrl] = useState<string | null>(null);
30
30
 
31
31
  useEffect(() => {
32
32
  if (!code?.trim()) return;
33
33
 
34
34
  // Revoke previous blob URL to free memory
35
- if (blobUrlRef.current) {
36
- URL.revokeObjectURL(blobUrlRef.current);
35
+ if (prevUrlRef.current) {
36
+ URL.revokeObjectURL(prevUrlRef.current);
37
37
  }
38
38
 
39
39
  const html = buildTemplate(code);
40
40
  const blob = new Blob([html], { type: "text/html" });
41
41
  const url = URL.createObjectURL(blob);
42
42
 
43
- blobUrlRef.current = url;
44
-
45
- if (iframeRef.current) {
46
- iframeRef.current.src = url;
47
- }
48
-
49
- // Force iframe remount when code changes to ensure clean state
50
- setKey((prev) => prev + 1);
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);
51
47
 
52
48
  return () => {
53
- if (blobUrlRef.current) {
54
- URL.revokeObjectURL(blobUrlRef.current);
55
- blobUrlRef.current = null;
49
+ if (prevUrlRef.current) {
50
+ URL.revokeObjectURL(prevUrlRef.current);
51
+ prevUrlRef.current = null;
56
52
  }
57
53
  };
58
54
  }, [code]);
@@ -77,18 +73,22 @@ export function Renderize({
77
73
  className={className}
78
74
  style={{ width, height, overflow: "hidden", ...style }}
79
75
  >
80
- <iframe
81
- key={key}
82
- ref={iframeRef}
83
- title="Renderize Sandbox"
84
- sandbox="allow-scripts"
85
- style={{
86
- width: "100%",
87
- height: "100%",
88
- border: "none",
89
- display: "block",
90
- }}
91
- />
76
+ {blobUrl && (
77
+ <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}
82
+ title="Renderize Sandbox"
83
+ sandbox="allow-scripts"
84
+ style={{
85
+ width: "100%",
86
+ height: "100%",
87
+ border: "none",
88
+ display: "block",
89
+ }}
90
+ />
91
+ )}
92
92
  </div>
93
93
  );
94
94
  }