khulnasoft commited on
Commit
090f5c2
·
verified ·
1 Parent(s): 2c11877

Create components/GeneratedContent.tsx

Browse files
Files changed (1) hide show
  1. components/GeneratedContent.tsx +127 -0
components/GeneratedContent.tsx ADDED
@@ -0,0 +1,127 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * @license
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ /* tslint:disable */
6
+ import React, {useEffect, useRef} from 'react';
7
+ import {InteractionData} from '../types';
8
+
9
+ interface GeneratedContentProps {
10
+ htmlContent: string;
11
+ onInteract: (data: InteractionData) => void;
12
+ appContext: string | null;
13
+ isLoading: boolean; // Added isLoading prop
14
+ }
15
+
16
+ export const GeneratedContent: React.FC<GeneratedContentProps> = ({
17
+ htmlContent,
18
+ onInteract,
19
+ appContext,
20
+ isLoading,
21
+ }) => {
22
+ const contentRef = useRef<HTMLDivElement>(null);
23
+ const processedHtmlContentRef = useRef<string | null>(null); // Ref to track processed content
24
+
25
+ useEffect(() => {
26
+ const container = contentRef.current;
27
+ if (!container) return;
28
+
29
+ const handleClick = (event: MouseEvent) => {
30
+ let targetElement = event.target as HTMLElement;
31
+
32
+ while (
33
+ targetElement &&
34
+ targetElement !== container &&
35
+ !targetElement.dataset.interactionId
36
+ ) {
37
+ targetElement = targetElement.parentElement as HTMLElement;
38
+ }
39
+
40
+ if (targetElement && targetElement.dataset.interactionId) {
41
+ event.preventDefault();
42
+
43
+ let interactionValue: string | undefined =
44
+ targetElement.dataset.interactionValue;
45
+
46
+ if (targetElement.dataset.valueFrom) {
47
+ const inputElement = document.getElementById(
48
+ targetElement.dataset.valueFrom,
49
+ ) as HTMLInputElement | HTMLTextAreaElement;
50
+ if (inputElement) {
51
+ interactionValue = inputElement.value;
52
+ }
53
+ }
54
+
55
+ const interactionData: InteractionData = {
56
+ id: targetElement.dataset.interactionId,
57
+ type: targetElement.dataset.interactionType || 'generic_click',
58
+ value: interactionValue,
59
+ elementType: targetElement.tagName.toLowerCase(),
60
+ elementText: (
61
+ targetElement.innerText ||
62
+ (targetElement as HTMLInputElement).value ||
63
+ ''
64
+ )
65
+ .trim()
66
+ .substring(0, 75),
67
+ appContext: appContext,
68
+ };
69
+ onInteract(interactionData);
70
+ }
71
+ };
72
+
73
+ container.addEventListener('click', handleClick);
74
+
75
+ // Process scripts only when loading is complete and content has changed
76
+ if (!isLoading) {
77
+ if (htmlContent !== processedHtmlContentRef.current) {
78
+ const scripts = Array.from(container.getElementsByTagName('script'));
79
+ scripts.forEach((oldScript) => {
80
+ try {
81
+ const newScript = document.createElement('script');
82
+ Array.from(oldScript.attributes).forEach((attr) =>
83
+ newScript.setAttribute(attr.name, attr.value),
84
+ );
85
+ newScript.text = oldScript.innerHTML;
86
+
87
+ if (oldScript.parentNode) {
88
+ oldScript.parentNode.replaceChild(newScript, oldScript);
89
+ } else {
90
+ console.warn(
91
+ 'Script tag found without a parent node:',
92
+ oldScript,
93
+ );
94
+ }
95
+ } catch (e) {
96
+ console.error(
97
+ 'Error processing/executing script tag. This usually indicates a syntax error in the LLM-generated script.',
98
+ {
99
+ scriptContent:
100
+ oldScript.innerHTML.substring(0, 500) +
101
+ (oldScript.innerHTML.length > 500 ? '...' : ''),
102
+ error: e,
103
+ },
104
+ );
105
+ }
106
+ });
107
+ processedHtmlContentRef.current = htmlContent; // Mark this content as processed
108
+ }
109
+ } else {
110
+ // If loading, reset the processed content ref. This ensures that when loading finishes,
111
+ // the new content (even if identical to a previous state before loading) is processed.
112
+ processedHtmlContentRef.current = null;
113
+ }
114
+
115
+ return () => {
116
+ container.removeEventListener('click', handleClick);
117
+ };
118
+ }, [htmlContent, onInteract, appContext, isLoading]);
119
+
120
+ return (
121
+ <div
122
+ ref={contentRef}
123
+ className="w-full h-full overflow-y-auto"
124
+ dangerouslySetInnerHTML={{__html: htmlContent}}
125
+ />
126
+ );
127
+ };