mirror of
https://github.com/f/awesome-chatgpt-prompts.git
synced 2025-06-23 16:05:21 +00:00
Compare commits
No commits in common. "e06e0e7e616bac3df9b8916551bbd975970cff3a" and "6476e2c4378a537143d3cc94bf4daab5d466db6f" have entirely different histories.
e06e0e7e61
...
6476e2c437
@ -29,17 +29,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body class="bg-dynamic-background text-dynamic-foreground overflow-hidden">
|
<body class="bg-dynamic-background text-dynamic-foreground overflow-hidden">
|
||||||
<!-- Viewer Mode -->
|
<!-- Viewer Mode -->
|
||||||
<div id="viewer-mode" class="viewer-mode h-screen flex">
|
<div id="viewer-mode" class="viewer-mode h-screen flex flex-col p-2 sm:p-4">
|
||||||
<!-- Sidebar - File Tree -->
|
|
||||||
<div id="file-sidebar" class="hidden w-40 sm:w-44 border-r border-dynamic-border bg-dynamic-muted/30 flex-shrink-0 overflow-y-auto custom-scrollbar">
|
|
||||||
<div class="p-2 border-b border-dynamic-border">
|
|
||||||
<h3 class="text-[10px] font-semibold text-dynamic-muted-foreground uppercase tracking-wider">Files</h3>
|
|
||||||
</div>
|
|
||||||
<div id="file-tree" class="p-1"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Main Content -->
|
|
||||||
<div class="flex-1 flex flex-col p-2 sm:p-4">
|
|
||||||
<!-- Top Bar with Context Pills and Edit Button -->
|
<!-- Top Bar with Context Pills and Edit Button -->
|
||||||
<div class="flex justify-between items-start gap-2 mb-0 sm:mb-2">
|
<div class="flex justify-between items-start gap-2 mb-0 sm:mb-2">
|
||||||
<!-- Context Pills -->
|
<!-- Context Pills -->
|
||||||
@ -56,7 +46,7 @@
|
|||||||
|
|
||||||
<!-- Main Prompt Interface - Full Height -->
|
<!-- Main Prompt Interface - Full Height -->
|
||||||
<div class="flex-1 flex flex-col">
|
<div class="flex-1 flex flex-col">
|
||||||
<div id="prompt-container" class="flex-1 bg-dynamic-muted border border-dynamic-border rounded-xl p-3 relative focus-within:border-dynamic-primary transition-colors flex flex-col">
|
<div id="prompt-container" class="flex-1 bg-dynamic-muted border border-dynamic-border rounded-xl p-3 sm:p-6 relative focus-within:border-dynamic-primary transition-colors flex flex-col">
|
||||||
<div id="prompt-text" class="flex-1 text-dynamic-foreground leading-relaxed whitespace-pre-wrap overflow-y-auto custom-scrollbar text-sm sm:text-base"></div>
|
<div id="prompt-text" class="flex-1 text-dynamic-foreground leading-relaxed whitespace-pre-wrap overflow-y-auto custom-scrollbar text-sm sm:text-base"></div>
|
||||||
<div id="prompt-placeholder" class="text-dynamic-muted-foreground italic absolute top-3 sm:top-6 left-3 sm:left-6 pointer-events-none text-sm sm:text-base">← Enter your prompt on designer...</div>
|
<div id="prompt-placeholder" class="text-dynamic-muted-foreground italic absolute top-3 sm:top-6 left-3 sm:left-6 pointer-events-none text-sm sm:text-base">← Enter your prompt on designer...</div>
|
||||||
</div>
|
</div>
|
||||||
@ -75,7 +65,6 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Notification -->
|
<!-- Notification -->
|
||||||
<div id="notification" class="fixed top-4 right-4 bg-dynamic-accent text-white px-4 py-2 rounded-lg font-medium opacity-0 transition-opacity z-50 pointer-events-none"></div>
|
<div id="notification" class="fixed top-4 right-4 bg-dynamic-accent text-white px-4 py-2 rounded-lg font-medium opacity-0 transition-opacity z-50 pointer-events-none"></div>
|
||||||
|
@ -226,19 +226,6 @@
|
|||||||
<span>800px</span>
|
<span>800px</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- File Tree -->
|
|
||||||
<div class="space-y-2">
|
|
||||||
<label class="text-sm font-medium text-dynamic-muted-foreground">File Tree</label>
|
|
||||||
<textarea id="designer-filetree"
|
|
||||||
class="w-full p-3 bg-dynamic-background border border-dynamic-border rounded-lg text-sm resize-none focus-ring custom-scrollbar touch-target font-mono"
|
|
||||||
rows="6"
|
|
||||||
placeholder="Enter files (one per line): index.html styles/main.css scripts/app.js components/header.vue"></textarea>
|
|
||||||
<p class="text-xs text-dynamic-muted-foreground">
|
|
||||||
Enter filenames one per line. Use forward slashes for folders (e.g., folder/file.js).
|
|
||||||
Add * at the end of a filename to highlight it (e.g., main.js*)
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -1906,7 +1906,7 @@ Contributed by: [@tanoojoy](https://github.com/tanoojoy)
|
|||||||
> person texting and nothing else. Your level of drunkenness will be
|
> person texting and nothing else. Your level of drunkenness will be
|
||||||
> deliberately and randomly make a lot of grammar and spelling mistakes in your
|
> deliberately and randomly make a lot of grammar and spelling mistakes in your
|
||||||
> answers. You will also randomly ignore what I said and say something random
|
> answers. You will also randomly ignore what I said and say something random
|
||||||
> with the same level of drunkenness I mentioned. Do not write explanations on
|
> with the same level of drunkeness I mentionned. Do not write explanations on
|
||||||
> replies. My first sentence is "how are you?"
|
> replies. My first sentence is "how are you?"
|
||||||
|
|
||||||
## Act as a Mathematical History Teacher
|
## Act as a Mathematical History Teacher
|
||||||
@ -2116,7 +2116,7 @@ Contributed by: [@TheLime1](https://github.com/TheLime1)
|
|||||||
> provide a detailed note list that includes examples from the lecture and
|
> provide a detailed note list that includes examples from the lecture and
|
||||||
> focuses on notes that you believe will end up in quiz questions. Additionally,
|
> focuses on notes that you believe will end up in quiz questions. Additionally,
|
||||||
> please make a separate list for notes that have numbers and data in them and
|
> please make a separate list for notes that have numbers and data in them and
|
||||||
> another separated list for the examples that included in this lecture. The
|
> another seperated list for the examples that included in this lecture. The
|
||||||
> notes should be concise and easy to read.
|
> notes should be concise and easy to read.
|
||||||
|
|
||||||
## Act as a Literary Critic
|
## Act as a Literary Critic
|
||||||
|
@ -24,8 +24,7 @@ class EmbedPreview {
|
|||||||
max: this.params.max === 'true',
|
max: this.params.max === 'true',
|
||||||
lightColor: this.params.lightColor || '#3b82f6',
|
lightColor: this.params.lightColor || '#3b82f6',
|
||||||
darkColor: this.params.darkColor || '#60a5fa',
|
darkColor: this.params.darkColor || '#60a5fa',
|
||||||
themeMode: this.params.themeMode || 'auto',
|
themeMode: this.params.themeMode || 'auto'
|
||||||
filetree: this.params.filetree ? decodeURIComponent(this.params.filetree).split('\n').filter(f => f.trim()) : []
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,7 +188,6 @@ class EmbedPreview {
|
|||||||
this.renderContextPills();
|
this.renderContextPills();
|
||||||
this.renderPromptText();
|
this.renderPromptText();
|
||||||
this.renderSettingsPills();
|
this.renderSettingsPills();
|
||||||
this.renderFileTree();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
renderContextPills() {
|
renderContextPills() {
|
||||||
@ -343,7 +341,7 @@ class EmbedPreview {
|
|||||||
}
|
}
|
||||||
|
|
||||||
highlightMentions(text) {
|
highlightMentions(text) {
|
||||||
return text.replace(/@([\w\.\/\:\-\&\=\?]+)/g, '<span class="mention">@$1</span>');
|
return text.replace(/@(\w+)/g, '<span class="mention">@$1</span>');
|
||||||
}
|
}
|
||||||
|
|
||||||
capitalizeFirst(str) {
|
capitalizeFirst(str) {
|
||||||
@ -415,143 +413,6 @@ class EmbedPreview {
|
|||||||
notification.classList.add('opacity-0');
|
notification.classList.add('opacity-0');
|
||||||
}, 2000);
|
}, 2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
buildFileTree(paths) {
|
|
||||||
const tree = {};
|
|
||||||
|
|
||||||
paths.forEach(path => {
|
|
||||||
// Check if the path ends with an asterisk
|
|
||||||
const isHighlighted = path.endsWith('*');
|
|
||||||
// Remove asterisk if present
|
|
||||||
const cleanPath = isHighlighted ? path.slice(0, -1) : path;
|
|
||||||
|
|
||||||
const parts = cleanPath.split('/');
|
|
||||||
let current = tree;
|
|
||||||
|
|
||||||
parts.forEach((part, index) => {
|
|
||||||
if (!current[part]) {
|
|
||||||
current[part] = {
|
|
||||||
name: part,
|
|
||||||
isFile: index === parts.length - 1,
|
|
||||||
isHighlighted: index === parts.length - 1 && isHighlighted,
|
|
||||||
children: {}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (index < parts.length - 1) {
|
|
||||||
current = current[part].children;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return tree;
|
|
||||||
}
|
|
||||||
|
|
||||||
renderFileTree() {
|
|
||||||
const sidebar = document.getElementById('file-sidebar');
|
|
||||||
const treeContainer = document.getElementById('file-tree');
|
|
||||||
|
|
||||||
if (!sidebar || !treeContainer) return;
|
|
||||||
|
|
||||||
// Show/hide sidebar based on whether there are files
|
|
||||||
if (this.config.filetree && this.config.filetree.length > 0) {
|
|
||||||
sidebar.classList.remove('hidden');
|
|
||||||
|
|
||||||
// Build tree structure
|
|
||||||
const tree = this.buildFileTree(this.config.filetree);
|
|
||||||
|
|
||||||
// Clear existing content
|
|
||||||
treeContainer.innerHTML = '';
|
|
||||||
|
|
||||||
// Render tree
|
|
||||||
this.renderTreeNode(tree, treeContainer, 0);
|
|
||||||
} else {
|
|
||||||
sidebar.classList.add('hidden');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
renderTreeNode(node, container, level) {
|
|
||||||
const sortedKeys = Object.keys(node).sort((a, b) => {
|
|
||||||
// Folders first, then files
|
|
||||||
const aIsFile = node[a].isFile;
|
|
||||||
const bIsFile = node[b].isFile;
|
|
||||||
if (aIsFile !== bIsFile) return aIsFile ? 1 : -1;
|
|
||||||
return a.localeCompare(b);
|
|
||||||
});
|
|
||||||
|
|
||||||
sortedKeys.forEach(key => {
|
|
||||||
const item = node[key];
|
|
||||||
const itemElement = document.createElement('div');
|
|
||||||
|
|
||||||
// Add highlighting class if the file is marked
|
|
||||||
if (item.isHighlighted) {
|
|
||||||
itemElement.className = 'flex items-center gap-1 py-0.5 px-1.5 bg-dynamic-primary/20 rounded cursor-pointer text-xs text-dynamic-foreground font-medium transition-all hover:bg-dynamic-primary/30';
|
|
||||||
} else {
|
|
||||||
itemElement.className = 'flex items-center gap-1 py-0.5 px-1.5 hover:bg-dynamic-primary/10 rounded cursor-pointer text-xs text-dynamic-foreground/80 hover:text-dynamic-foreground transition-colors';
|
|
||||||
}
|
|
||||||
|
|
||||||
itemElement.style.paddingLeft = `${level * 12 + 6}px`;
|
|
||||||
|
|
||||||
// Add icon
|
|
||||||
const icon = document.createElement('span');
|
|
||||||
icon.className = 'flex-shrink-0';
|
|
||||||
|
|
||||||
if (item.isFile) {
|
|
||||||
// File icon with different colors based on extension
|
|
||||||
const ext = key.split('.').pop().toLowerCase();
|
|
||||||
let iconColor = 'text-dynamic-muted-foreground';
|
|
||||||
|
|
||||||
// If highlighted, use primary color for icon
|
|
||||||
if (item.isHighlighted) {
|
|
||||||
iconColor = 'text-dynamic-primary';
|
|
||||||
} else {
|
|
||||||
// Color code common file types
|
|
||||||
if (['js', 'jsx', 'ts', 'tsx'].includes(ext)) {
|
|
||||||
iconColor = 'text-yellow-500';
|
|
||||||
} else if (['css', 'scss', 'sass', 'less'].includes(ext)) {
|
|
||||||
iconColor = 'text-blue-500';
|
|
||||||
} else if (['html', 'htm'].includes(ext)) {
|
|
||||||
iconColor = 'text-orange-500';
|
|
||||||
} else if (['vue', 'svelte'].includes(ext)) {
|
|
||||||
iconColor = 'text-green-500';
|
|
||||||
} else if (['json', 'xml', 'yaml', 'yml'].includes(ext)) {
|
|
||||||
iconColor = 'text-purple-500';
|
|
||||||
} else if (['md', 'mdx'].includes(ext)) {
|
|
||||||
iconColor = 'text-gray-500';
|
|
||||||
} else if (['png', 'jpg', 'jpeg', 'gif', 'svg', 'webp'].includes(ext)) {
|
|
||||||
iconColor = 'text-pink-500';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
icon.innerHTML = `<svg class="w-3 h-3 ${iconColor}" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M4 2a2 2 0 00-2 2v12a2 2 0 002 2h12a2 2 0 002-2V7.414A2 2 0 0017.414 6L14 2.586A2 2 0 0012.586 2H4zm2 4a1 1 0 011-1h4a1 1 0 110 2H7a1 1 0 01-1-1zm1 3a1 1 0 100 2h6a1 1 0 100-2H7zm-1 5a1 1 0 011-1h6a1 1 0 110 2H7a1 1 0 01-1-1z" clip-rule="evenodd"/></svg>`;
|
|
||||||
} else {
|
|
||||||
// Folder icon
|
|
||||||
icon.innerHTML = '<svg class="w-3 h-3 text-dynamic-primary" viewBox="0 0 20 20" fill="currentColor"><path d="M2 6a2 2 0 012-2h5l2 2h5a2 2 0 012 2v6a2 2 0 01-2 2H4a2 2 0 01-2-2V6z"/></svg>';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add name
|
|
||||||
const nameSpan = document.createElement('span');
|
|
||||||
nameSpan.className = 'truncate flex-1';
|
|
||||||
nameSpan.textContent = item.name;
|
|
||||||
|
|
||||||
itemElement.appendChild(icon);
|
|
||||||
itemElement.appendChild(nameSpan);
|
|
||||||
|
|
||||||
// Add a star indicator for highlighted files
|
|
||||||
if (item.isHighlighted) {
|
|
||||||
const starIcon = document.createElement('span');
|
|
||||||
starIcon.className = 'ml-auto text-dynamic-primary';
|
|
||||||
starIcon.innerHTML = '<svg class="w-2.5 h-2.5" viewBox="0 0 20 20" fill="currentColor"><path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"/></svg>';
|
|
||||||
itemElement.appendChild(starIcon);
|
|
||||||
}
|
|
||||||
|
|
||||||
container.appendChild(itemElement);
|
|
||||||
|
|
||||||
// Recursively render children
|
|
||||||
if (!item.isFile && Object.keys(item.children).length > 0) {
|
|
||||||
this.renderTreeNode(item.children, container, level + 1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize when DOM is ready
|
// Initialize when DOM is ready
|
||||||
|
@ -109,8 +109,8 @@
|
|||||||
|
|
||||||
@media (max-width: 640px) {
|
@media (max-width: 640px) {
|
||||||
#prompt-container {
|
#prompt-container {
|
||||||
height: calc(100vh - 90px); /* Smaller on mobile */
|
height: calc(100vh - 120px); /* Smaller on mobile */
|
||||||
max-height: calc(100vh - 90px);
|
max-height: calc(100vh - 120px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,6 +119,7 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
overflow-y: auto !important;
|
overflow-y: auto !important;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
white-space: wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Responsive improvements */
|
/* Responsive improvements */
|
||||||
@ -185,13 +186,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Hide file sidebar on mobile devices */
|
|
||||||
@media (max-width: 640px) {
|
|
||||||
#file-sidebar {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ensure proper touch behavior */
|
/* Ensure proper touch behavior */
|
||||||
@media (hover: none) and (pointer: coarse) {
|
@media (hover: none) and (pointer: coarse) {
|
||||||
/* All interactive elements get proper touch targets */
|
/* All interactive elements get proper touch targets */
|
||||||
|
@ -29,17 +29,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body class="bg-dynamic-background text-dynamic-foreground overflow-hidden">
|
<body class="bg-dynamic-background text-dynamic-foreground overflow-hidden">
|
||||||
<!-- Viewer Mode -->
|
<!-- Viewer Mode -->
|
||||||
<div id="viewer-mode" class="viewer-mode h-screen flex">
|
<div id="viewer-mode" class="viewer-mode h-screen flex flex-col p-2 sm:p-4">
|
||||||
<!-- Sidebar - File Tree -->
|
|
||||||
<div id="file-sidebar" class="hidden w-40 sm:w-44 border-r border-dynamic-border bg-dynamic-muted/30 flex-shrink-0 overflow-y-auto custom-scrollbar">
|
|
||||||
<div class="p-2 border-b border-dynamic-border">
|
|
||||||
<h3 class="text-[10px] font-semibold text-dynamic-muted-foreground uppercase tracking-wider">Files</h3>
|
|
||||||
</div>
|
|
||||||
<div id="file-tree" class="p-1"></div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Main Content -->
|
|
||||||
<div class="flex-1 flex flex-col p-2 sm:p-4">
|
|
||||||
<!-- Top Bar with Context Pills and Edit Button -->
|
<!-- Top Bar with Context Pills and Edit Button -->
|
||||||
<div class="flex justify-between items-start gap-2 mb-0 sm:mb-2">
|
<div class="flex justify-between items-start gap-2 mb-0 sm:mb-2">
|
||||||
<!-- Context Pills -->
|
<!-- Context Pills -->
|
||||||
@ -56,7 +46,7 @@
|
|||||||
|
|
||||||
<!-- Main Prompt Interface - Full Height -->
|
<!-- Main Prompt Interface - Full Height -->
|
||||||
<div class="flex-1 flex flex-col">
|
<div class="flex-1 flex flex-col">
|
||||||
<div id="prompt-container" class="flex-1 bg-dynamic-muted border border-dynamic-border rounded-xl p-3 relative focus-within:border-dynamic-primary transition-colors flex flex-col">
|
<div id="prompt-container" class="flex-1 bg-dynamic-muted border border-dynamic-border rounded-xl p-3 sm:p-6 relative focus-within:border-dynamic-primary transition-colors flex flex-col">
|
||||||
<div id="prompt-text" class="flex-1 text-dynamic-foreground leading-relaxed whitespace-pre-wrap overflow-y-auto custom-scrollbar text-sm sm:text-base"></div>
|
<div id="prompt-text" class="flex-1 text-dynamic-foreground leading-relaxed whitespace-pre-wrap overflow-y-auto custom-scrollbar text-sm sm:text-base"></div>
|
||||||
<div id="prompt-placeholder" class="text-dynamic-muted-foreground italic absolute top-3 sm:top-6 left-3 sm:left-6 pointer-events-none text-sm sm:text-base">← Enter your prompt on designer...</div>
|
<div id="prompt-placeholder" class="text-dynamic-muted-foreground italic absolute top-3 sm:top-6 left-3 sm:left-6 pointer-events-none text-sm sm:text-base">← Enter your prompt on designer...</div>
|
||||||
</div>
|
</div>
|
||||||
@ -75,7 +65,6 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Notification -->
|
<!-- Notification -->
|
||||||
<div id="notification" class="fixed top-4 right-4 bg-dynamic-accent text-white px-4 py-2 rounded-lg font-medium opacity-0 transition-opacity z-50 pointer-events-none"></div>
|
<div id="notification" class="fixed top-4 right-4 bg-dynamic-accent text-white px-4 py-2 rounded-lg font-medium opacity-0 transition-opacity z-50 pointer-events-none"></div>
|
||||||
|
@ -32,8 +32,7 @@ class EmbedDesigner {
|
|||||||
lightColor: this.params.lightColor || savedConfig.lightColor || '#3b82f6',
|
lightColor: this.params.lightColor || savedConfig.lightColor || '#3b82f6',
|
||||||
darkColor: this.params.darkColor || savedConfig.darkColor || '#60a5fa',
|
darkColor: this.params.darkColor || savedConfig.darkColor || '#60a5fa',
|
||||||
height: this.params.height || savedConfig.height || '400',
|
height: this.params.height || savedConfig.height || '400',
|
||||||
themeMode: this.params.themeMode || savedConfig.themeMode || 'auto',
|
themeMode: this.params.themeMode || savedConfig.themeMode || 'auto'
|
||||||
filetree: this.params.filetree ? decodeURIComponent(this.params.filetree).split('\n').filter(f => f.trim()) : (savedConfig.filetree || [])
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,8 +53,7 @@ class EmbedDesigner {
|
|||||||
lightColor: '#3b82f6',
|
lightColor: '#3b82f6',
|
||||||
darkColor: '#60a5fa',
|
darkColor: '#60a5fa',
|
||||||
height: '400',
|
height: '400',
|
||||||
themeMode: 'auto',
|
themeMode: 'auto'
|
||||||
filetree: []
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,20 +64,7 @@ class EmbedDesigner {
|
|||||||
const config = JSON.parse(saved);
|
const config = JSON.parse(saved);
|
||||||
// Validate the loaded config has all required fields
|
// Validate the loaded config has all required fields
|
||||||
if (config && typeof config === 'object') {
|
if (config && typeof config === 'object') {
|
||||||
// Ensure all properties have defaults
|
return config;
|
||||||
return {
|
|
||||||
prompt: config.prompt || '',
|
|
||||||
context: config.context || [],
|
|
||||||
model: config.model || 'gpt-4o',
|
|
||||||
mode: config.mode || 'chat',
|
|
||||||
thinking: config.thinking || false,
|
|
||||||
max: config.max || false,
|
|
||||||
lightColor: config.lightColor || '#3b82f6',
|
|
||||||
darkColor: config.darkColor || '#60a5fa',
|
|
||||||
height: config.height || '400',
|
|
||||||
themeMode: config.themeMode || 'auto',
|
|
||||||
filetree: config.filetree || []
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -118,7 +103,6 @@ class EmbedDesigner {
|
|||||||
// Populate form with current config
|
// Populate form with current config
|
||||||
document.getElementById('designer-prompt').value = this.config.prompt;
|
document.getElementById('designer-prompt').value = this.config.prompt;
|
||||||
document.getElementById('designer-context').value = this.config.context.join(', ');
|
document.getElementById('designer-context').value = this.config.context.join(', ');
|
||||||
document.getElementById('designer-filetree').value = this.config.filetree.join('\n');
|
|
||||||
|
|
||||||
// Handle model selection
|
// Handle model selection
|
||||||
const modelSelect = document.getElementById('designer-model');
|
const modelSelect = document.getElementById('designer-model');
|
||||||
@ -186,7 +170,7 @@ class EmbedDesigner {
|
|||||||
|
|
||||||
setupDesignerEvents() {
|
setupDesignerEvents() {
|
||||||
// Form changes update preview
|
// Form changes update preview
|
||||||
['designer-prompt', 'designer-context', 'designer-mode-select', 'designer-thinking', 'designer-max', 'designer-filetree'].forEach(id => {
|
['designer-prompt', 'designer-context', 'designer-mode-select', 'designer-thinking', 'designer-max'].forEach(id => {
|
||||||
const element = document.getElementById(id);
|
const element = document.getElementById(id);
|
||||||
element.addEventListener('input', () => this.updateConfigFromForm());
|
element.addEventListener('input', () => this.updateConfigFromForm());
|
||||||
element.addEventListener('change', () => this.updateConfigFromForm());
|
element.addEventListener('change', () => this.updateConfigFromForm());
|
||||||
@ -316,8 +300,7 @@ class EmbedDesigner {
|
|||||||
lightColor: '#3b82f6',
|
lightColor: '#3b82f6',
|
||||||
darkColor: '#60a5fa',
|
darkColor: '#60a5fa',
|
||||||
height: '400',
|
height: '400',
|
||||||
themeMode: 'auto',
|
themeMode: 'auto'
|
||||||
filetree: []
|
|
||||||
};
|
};
|
||||||
// Update UI to reflect defaults
|
// Update UI to reflect defaults
|
||||||
this.setupDesignerElements();
|
this.setupDesignerElements();
|
||||||
@ -365,8 +348,7 @@ class EmbedDesigner {
|
|||||||
lightColor: lightColorText ? lightColorText.value : '#3b82f6',
|
lightColor: lightColorText ? lightColorText.value : '#3b82f6',
|
||||||
darkColor: darkColorText ? darkColorText.value : '#60a5fa',
|
darkColor: darkColorText ? darkColorText.value : '#60a5fa',
|
||||||
height: heightSlider ? heightSlider.value : '400',
|
height: heightSlider ? heightSlider.value : '400',
|
||||||
themeMode: this.config.themeMode || 'auto',
|
themeMode: this.config.themeMode || 'auto'
|
||||||
filetree: document.getElementById('designer-filetree').value.split('\n').map(f => f.trim()).filter(f => f)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.updatePreview();
|
this.updatePreview();
|
||||||
@ -439,7 +421,6 @@ class EmbedDesigner {
|
|||||||
if (this.config.lightColor !== '#3b82f6') params.set('lightColor', this.config.lightColor);
|
if (this.config.lightColor !== '#3b82f6') params.set('lightColor', this.config.lightColor);
|
||||||
if (this.config.darkColor !== '#60a5fa') params.set('darkColor', this.config.darkColor);
|
if (this.config.darkColor !== '#60a5fa') params.set('darkColor', this.config.darkColor);
|
||||||
if (this.config.themeMode !== 'auto') params.set('themeMode', this.config.themeMode);
|
if (this.config.themeMode !== 'auto') params.set('themeMode', this.config.themeMode);
|
||||||
if (this.config.filetree && this.config.filetree.length > 0) params.set('filetree', encodeURIComponent(this.config.filetree.join('\n')));
|
|
||||||
params.set('preview', 'true');
|
params.set('preview', 'true');
|
||||||
|
|
||||||
return `/embed-preview/?${params.toString()}`;
|
return `/embed-preview/?${params.toString()}`;
|
||||||
@ -456,7 +437,6 @@ class EmbedDesigner {
|
|||||||
if (this.config.lightColor !== '#3b82f6') params.set('lightColor', this.config.lightColor);
|
if (this.config.lightColor !== '#3b82f6') params.set('lightColor', this.config.lightColor);
|
||||||
if (this.config.darkColor !== '#60a5fa') params.set('darkColor', this.config.darkColor);
|
if (this.config.darkColor !== '#60a5fa') params.set('darkColor', this.config.darkColor);
|
||||||
if (this.config.themeMode !== 'auto') params.set('themeMode', this.config.themeMode);
|
if (this.config.themeMode !== 'auto') params.set('themeMode', this.config.themeMode);
|
||||||
if (this.config.filetree && this.config.filetree.length > 0) params.set('filetree', encodeURIComponent(this.config.filetree.join('\n')));
|
|
||||||
|
|
||||||
return `${window.location.origin}/embed-preview/?${params.toString()}`;
|
return `${window.location.origin}/embed-preview/?${params.toString()}`;
|
||||||
}
|
}
|
||||||
@ -538,40 +518,27 @@ class EmbedDesigner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
loadExample() {
|
loadExample() {
|
||||||
// Set example values
|
// Set example data
|
||||||
document.getElementById('designer-prompt').value =
|
this.config = {
|
||||||
`You are a senior React developer. I need help building a modern e-commerce product listing component.
|
prompt: 'Build an MCP server that works with Weather API. See @Web for cool weather APIs.',
|
||||||
|
context: ['@Web', 'https://modelcontextprotocol.io/full-llms.txt'],
|
||||||
|
model: 'Claude 4 Sonnet',
|
||||||
|
mode: 'agent',
|
||||||
|
thinking: true,
|
||||||
|
max: true,
|
||||||
|
lightColor: '#3b82f6',
|
||||||
|
darkColor: '#60a5fa',
|
||||||
|
height: '250',
|
||||||
|
themeMode: 'auto'
|
||||||
|
};
|
||||||
|
|
||||||
Requirements:
|
// Update all form elements
|
||||||
- Use React hooks and functional components
|
this.setupDesignerElements();
|
||||||
- Implement product filtering by category and price range
|
this.updatePreview();
|
||||||
- Add smooth animations for product cards
|
this.updateIframeSnippet();
|
||||||
- Make it fully responsive with a grid layout
|
this.saveToLocalStorage();
|
||||||
- Include loading states and error handling
|
|
||||||
|
|
||||||
The component should fetch data from a REST API and display products with images, titles, prices, and ratings. Please provide clean, well-commented code following React best practices.`;
|
|
||||||
|
|
||||||
document.getElementById('designer-context').value = '@codebase, ProductList.jsx';
|
|
||||||
document.getElementById('designer-filetree').value =
|
|
||||||
`src/components/ProductList.jsx*
|
|
||||||
src/components/ProductCard.jsx
|
|
||||||
src/components/Filters.jsx
|
|
||||||
src/hooks/useProducts.js
|
|
||||||
src/api/products.js
|
|
||||||
src/styles/products.css
|
|
||||||
src/utils/formatters.js
|
|
||||||
public/index.html
|
|
||||||
package.json
|
|
||||||
README.md`;
|
|
||||||
|
|
||||||
// Set some example settings
|
|
||||||
document.getElementById('designer-model').value = 'Claude 3.7 Sonnet';
|
|
||||||
document.getElementById('designer-mode-select').value = 'agent';
|
|
||||||
document.getElementById('designer-thinking').checked = true;
|
|
||||||
|
|
||||||
// Update config from form
|
|
||||||
this.updateConfigFromForm();
|
|
||||||
|
|
||||||
|
// Show notification
|
||||||
this.showNotification('Example loaded!');
|
this.showNotification('Example loaded!');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -226,19 +226,6 @@
|
|||||||
<span>800px</span>
|
<span>800px</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- File Tree -->
|
|
||||||
<div class="space-y-2">
|
|
||||||
<label class="text-sm font-medium text-dynamic-muted-foreground">File Tree</label>
|
|
||||||
<textarea id="designer-filetree"
|
|
||||||
class="w-full p-3 bg-dynamic-background border border-dynamic-border rounded-lg text-sm resize-none focus-ring custom-scrollbar touch-target font-mono"
|
|
||||||
rows="6"
|
|
||||||
placeholder="Enter files (one per line): index.html styles/main.css scripts/app.js components/header.vue"></textarea>
|
|
||||||
<p class="text-xs text-dynamic-muted-foreground">
|
|
||||||
Enter filenames one per line. Use forward slashes for folders (e.g., folder/file.js).
|
|
||||||
Add * at the end of a filename to highlight it (e.g., main.js*)
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
|
|
||||||
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
|
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
|
||||||
<link rel="stylesheet" href="/style.css?v=6476e2c4378a537143d3cc94bf4daab5d466db6f">
|
<link rel="stylesheet" href="/style.css?v=a8a69caf7649bb8f02c225029af543967973a65f">
|
||||||
</head>
|
</head>
|
||||||
<body class="">
|
<body class="">
|
||||||
<div class="layout-wrapper">
|
<div class="layout-wrapper">
|
||||||
@ -2394,7 +2394,7 @@ take it from there.</p>
|
|||||||
person texting and nothing else. Your level of drunkenness will be
|
person texting and nothing else. Your level of drunkenness will be
|
||||||
deliberately and randomly make a lot of grammar and spelling mistakes in your
|
deliberately and randomly make a lot of grammar and spelling mistakes in your
|
||||||
answers. You will also randomly ignore what I said and say something random
|
answers. You will also randomly ignore what I said and say something random
|
||||||
with the same level of drunkenness I mentioned. Do not write explanations on
|
with the same level of drunkeness I mentionned. Do not write explanations on
|
||||||
replies. My first sentence is “how are you?”</p>
|
replies. My first sentence is “how are you?”</p>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
|
|
||||||
@ -2636,7 +2636,7 @@ will tell me the right answer. Then you will ask me the next question.</p>
|
|||||||
provide a detailed note list that includes examples from the lecture and
|
provide a detailed note list that includes examples from the lecture and
|
||||||
focuses on notes that you believe will end up in quiz questions. Additionally,
|
focuses on notes that you believe will end up in quiz questions. Additionally,
|
||||||
please make a separate list for notes that have numbers and data in them and
|
please make a separate list for notes that have numbers and data in them and
|
||||||
another separated list for the examples that included in this lecture. The
|
another seperated list for the examples that included in this lecture. The
|
||||||
notes should be concise and easy to read.</p>
|
notes should be concise and easy to read.</p>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
|
|
||||||
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
|
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
|
||||||
<link rel="stylesheet" href="/style.css?v=6476e2c4378a537143d3cc94bf4daab5d466db6f">
|
<link rel="stylesheet" href="/style.css?v=a8a69caf7649bb8f02c225029af543967973a65f">
|
||||||
</head>
|
</head>
|
||||||
<body class="vibe">
|
<body class="vibe">
|
||||||
<div class="layout-wrapper">
|
<div class="layout-wrapper">
|
||||||
|
@ -24,8 +24,7 @@ class EmbedPreview {
|
|||||||
max: this.params.max === 'true',
|
max: this.params.max === 'true',
|
||||||
lightColor: this.params.lightColor || '#3b82f6',
|
lightColor: this.params.lightColor || '#3b82f6',
|
||||||
darkColor: this.params.darkColor || '#60a5fa',
|
darkColor: this.params.darkColor || '#60a5fa',
|
||||||
themeMode: this.params.themeMode || 'auto',
|
themeMode: this.params.themeMode || 'auto'
|
||||||
filetree: this.params.filetree ? decodeURIComponent(this.params.filetree).split('\n').filter(f => f.trim()) : []
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,7 +188,6 @@ class EmbedPreview {
|
|||||||
this.renderContextPills();
|
this.renderContextPills();
|
||||||
this.renderPromptText();
|
this.renderPromptText();
|
||||||
this.renderSettingsPills();
|
this.renderSettingsPills();
|
||||||
this.renderFileTree();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
renderContextPills() {
|
renderContextPills() {
|
||||||
@ -415,143 +413,6 @@ class EmbedPreview {
|
|||||||
notification.classList.add('opacity-0');
|
notification.classList.add('opacity-0');
|
||||||
}, 2000);
|
}, 2000);
|
||||||
}
|
}
|
||||||
|
|
||||||
buildFileTree(paths) {
|
|
||||||
const tree = {};
|
|
||||||
|
|
||||||
paths.forEach(path => {
|
|
||||||
// Check if the path ends with an asterisk
|
|
||||||
const isHighlighted = path.endsWith('*');
|
|
||||||
// Remove asterisk if present
|
|
||||||
const cleanPath = isHighlighted ? path.slice(0, -1) : path;
|
|
||||||
|
|
||||||
const parts = cleanPath.split('/');
|
|
||||||
let current = tree;
|
|
||||||
|
|
||||||
parts.forEach((part, index) => {
|
|
||||||
if (!current[part]) {
|
|
||||||
current[part] = {
|
|
||||||
name: part,
|
|
||||||
isFile: index === parts.length - 1,
|
|
||||||
isHighlighted: index === parts.length - 1 && isHighlighted,
|
|
||||||
children: {}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
if (index < parts.length - 1) {
|
|
||||||
current = current[part].children;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return tree;
|
|
||||||
}
|
|
||||||
|
|
||||||
renderFileTree() {
|
|
||||||
const sidebar = document.getElementById('file-sidebar');
|
|
||||||
const treeContainer = document.getElementById('file-tree');
|
|
||||||
|
|
||||||
if (!sidebar || !treeContainer) return;
|
|
||||||
|
|
||||||
// Show/hide sidebar based on whether there are files
|
|
||||||
if (this.config.filetree && this.config.filetree.length > 0) {
|
|
||||||
sidebar.classList.remove('hidden');
|
|
||||||
|
|
||||||
// Build tree structure
|
|
||||||
const tree = this.buildFileTree(this.config.filetree);
|
|
||||||
|
|
||||||
// Clear existing content
|
|
||||||
treeContainer.innerHTML = '';
|
|
||||||
|
|
||||||
// Render tree
|
|
||||||
this.renderTreeNode(tree, treeContainer, 0);
|
|
||||||
} else {
|
|
||||||
sidebar.classList.add('hidden');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
renderTreeNode(node, container, level) {
|
|
||||||
const sortedKeys = Object.keys(node).sort((a, b) => {
|
|
||||||
// Folders first, then files
|
|
||||||
const aIsFile = node[a].isFile;
|
|
||||||
const bIsFile = node[b].isFile;
|
|
||||||
if (aIsFile !== bIsFile) return aIsFile ? 1 : -1;
|
|
||||||
return a.localeCompare(b);
|
|
||||||
});
|
|
||||||
|
|
||||||
sortedKeys.forEach(key => {
|
|
||||||
const item = node[key];
|
|
||||||
const itemElement = document.createElement('div');
|
|
||||||
|
|
||||||
// Add highlighting class if the file is marked
|
|
||||||
if (item.isHighlighted) {
|
|
||||||
itemElement.className = 'flex items-center gap-1 py-0.5 px-1.5 bg-dynamic-primary/20 rounded cursor-pointer text-xs text-dynamic-foreground font-medium transition-all hover:bg-dynamic-primary/30';
|
|
||||||
} else {
|
|
||||||
itemElement.className = 'flex items-center gap-1 py-0.5 px-1.5 hover:bg-dynamic-primary/10 rounded cursor-pointer text-xs text-dynamic-foreground/80 hover:text-dynamic-foreground transition-colors';
|
|
||||||
}
|
|
||||||
|
|
||||||
itemElement.style.paddingLeft = `${level * 12 + 6}px`;
|
|
||||||
|
|
||||||
// Add icon
|
|
||||||
const icon = document.createElement('span');
|
|
||||||
icon.className = 'flex-shrink-0';
|
|
||||||
|
|
||||||
if (item.isFile) {
|
|
||||||
// File icon with different colors based on extension
|
|
||||||
const ext = key.split('.').pop().toLowerCase();
|
|
||||||
let iconColor = 'text-dynamic-muted-foreground';
|
|
||||||
|
|
||||||
// If highlighted, use primary color for icon
|
|
||||||
if (item.isHighlighted) {
|
|
||||||
iconColor = 'text-dynamic-primary';
|
|
||||||
} else {
|
|
||||||
// Color code common file types
|
|
||||||
if (['js', 'jsx', 'ts', 'tsx'].includes(ext)) {
|
|
||||||
iconColor = 'text-yellow-500';
|
|
||||||
} else if (['css', 'scss', 'sass', 'less'].includes(ext)) {
|
|
||||||
iconColor = 'text-blue-500';
|
|
||||||
} else if (['html', 'htm'].includes(ext)) {
|
|
||||||
iconColor = 'text-orange-500';
|
|
||||||
} else if (['vue', 'svelte'].includes(ext)) {
|
|
||||||
iconColor = 'text-green-500';
|
|
||||||
} else if (['json', 'xml', 'yaml', 'yml'].includes(ext)) {
|
|
||||||
iconColor = 'text-purple-500';
|
|
||||||
} else if (['md', 'mdx'].includes(ext)) {
|
|
||||||
iconColor = 'text-gray-500';
|
|
||||||
} else if (['png', 'jpg', 'jpeg', 'gif', 'svg', 'webp'].includes(ext)) {
|
|
||||||
iconColor = 'text-pink-500';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
icon.innerHTML = `<svg class="w-3 h-3 ${iconColor}" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M4 2a2 2 0 00-2 2v12a2 2 0 002 2h12a2 2 0 002-2V7.414A2 2 0 0017.414 6L14 2.586A2 2 0 0012.586 2H4zm2 4a1 1 0 011-1h4a1 1 0 110 2H7a1 1 0 01-1-1zm1 3a1 1 0 100 2h6a1 1 0 100-2H7zm-1 5a1 1 0 011-1h6a1 1 0 110 2H7a1 1 0 01-1-1z" clip-rule="evenodd"/></svg>`;
|
|
||||||
} else {
|
|
||||||
// Folder icon
|
|
||||||
icon.innerHTML = '<svg class="w-3 h-3 text-dynamic-primary" viewBox="0 0 20 20" fill="currentColor"><path d="M2 6a2 2 0 012-2h5l2 2h5a2 2 0 012 2v6a2 2 0 01-2 2H4a2 2 0 01-2-2V6z"/></svg>';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add name
|
|
||||||
const nameSpan = document.createElement('span');
|
|
||||||
nameSpan.className = 'truncate flex-1';
|
|
||||||
nameSpan.textContent = item.name;
|
|
||||||
|
|
||||||
itemElement.appendChild(icon);
|
|
||||||
itemElement.appendChild(nameSpan);
|
|
||||||
|
|
||||||
// Add a star indicator for highlighted files
|
|
||||||
if (item.isHighlighted) {
|
|
||||||
const starIcon = document.createElement('span');
|
|
||||||
starIcon.className = 'ml-auto text-dynamic-primary';
|
|
||||||
starIcon.innerHTML = '<svg class="w-2.5 h-2.5" viewBox="0 0 20 20" fill="currentColor"><path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z"/></svg>';
|
|
||||||
itemElement.appendChild(starIcon);
|
|
||||||
}
|
|
||||||
|
|
||||||
container.appendChild(itemElement);
|
|
||||||
|
|
||||||
// Recursively render children
|
|
||||||
if (!item.isFile && Object.keys(item.children).length > 0) {
|
|
||||||
this.renderTreeNode(item.children, container, level + 1);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize when DOM is ready
|
// Initialize when DOM is ready
|
||||||
|
@ -109,8 +109,8 @@
|
|||||||
|
|
||||||
@media (max-width: 640px) {
|
@media (max-width: 640px) {
|
||||||
#prompt-container {
|
#prompt-container {
|
||||||
height: calc(100vh - 90px); /* Smaller on mobile */
|
height: calc(100vh - 120px); /* Smaller on mobile */
|
||||||
max-height: calc(100vh - 90px);
|
max-height: calc(100vh - 120px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,6 +119,7 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
overflow-y: auto !important;
|
overflow-y: auto !important;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
white-space: wrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Responsive improvements */
|
/* Responsive improvements */
|
||||||
@ -185,13 +186,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Hide file sidebar on mobile devices */
|
|
||||||
@media (max-width: 640px) {
|
|
||||||
#file-sidebar {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ensure proper touch behavior */
|
/* Ensure proper touch behavior */
|
||||||
@media (hover: none) and (pointer: coarse) {
|
@media (hover: none) and (pointer: coarse) {
|
||||||
/* All interactive elements get proper touch targets */
|
/* All interactive elements get proper touch targets */
|
||||||
|
@ -32,8 +32,7 @@ class EmbedDesigner {
|
|||||||
lightColor: this.params.lightColor || savedConfig.lightColor || '#3b82f6',
|
lightColor: this.params.lightColor || savedConfig.lightColor || '#3b82f6',
|
||||||
darkColor: this.params.darkColor || savedConfig.darkColor || '#60a5fa',
|
darkColor: this.params.darkColor || savedConfig.darkColor || '#60a5fa',
|
||||||
height: this.params.height || savedConfig.height || '400',
|
height: this.params.height || savedConfig.height || '400',
|
||||||
themeMode: this.params.themeMode || savedConfig.themeMode || 'auto',
|
themeMode: this.params.themeMode || savedConfig.themeMode || 'auto'
|
||||||
filetree: this.params.filetree ? decodeURIComponent(this.params.filetree).split('\n').filter(f => f.trim()) : (savedConfig.filetree || [])
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,8 +53,7 @@ class EmbedDesigner {
|
|||||||
lightColor: '#3b82f6',
|
lightColor: '#3b82f6',
|
||||||
darkColor: '#60a5fa',
|
darkColor: '#60a5fa',
|
||||||
height: '400',
|
height: '400',
|
||||||
themeMode: 'auto',
|
themeMode: 'auto'
|
||||||
filetree: []
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,20 +64,7 @@ class EmbedDesigner {
|
|||||||
const config = JSON.parse(saved);
|
const config = JSON.parse(saved);
|
||||||
// Validate the loaded config has all required fields
|
// Validate the loaded config has all required fields
|
||||||
if (config && typeof config === 'object') {
|
if (config && typeof config === 'object') {
|
||||||
// Ensure all properties have defaults
|
return config;
|
||||||
return {
|
|
||||||
prompt: config.prompt || '',
|
|
||||||
context: config.context || [],
|
|
||||||
model: config.model || 'gpt-4o',
|
|
||||||
mode: config.mode || 'chat',
|
|
||||||
thinking: config.thinking || false,
|
|
||||||
max: config.max || false,
|
|
||||||
lightColor: config.lightColor || '#3b82f6',
|
|
||||||
darkColor: config.darkColor || '#60a5fa',
|
|
||||||
height: config.height || '400',
|
|
||||||
themeMode: config.themeMode || 'auto',
|
|
||||||
filetree: config.filetree || []
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -118,7 +103,6 @@ class EmbedDesigner {
|
|||||||
// Populate form with current config
|
// Populate form with current config
|
||||||
document.getElementById('designer-prompt').value = this.config.prompt;
|
document.getElementById('designer-prompt').value = this.config.prompt;
|
||||||
document.getElementById('designer-context').value = this.config.context.join(', ');
|
document.getElementById('designer-context').value = this.config.context.join(', ');
|
||||||
document.getElementById('designer-filetree').value = this.config.filetree.join('\n');
|
|
||||||
|
|
||||||
// Handle model selection
|
// Handle model selection
|
||||||
const modelSelect = document.getElementById('designer-model');
|
const modelSelect = document.getElementById('designer-model');
|
||||||
@ -186,7 +170,7 @@ class EmbedDesigner {
|
|||||||
|
|
||||||
setupDesignerEvents() {
|
setupDesignerEvents() {
|
||||||
// Form changes update preview
|
// Form changes update preview
|
||||||
['designer-prompt', 'designer-context', 'designer-mode-select', 'designer-thinking', 'designer-max', 'designer-filetree'].forEach(id => {
|
['designer-prompt', 'designer-context', 'designer-mode-select', 'designer-thinking', 'designer-max'].forEach(id => {
|
||||||
const element = document.getElementById(id);
|
const element = document.getElementById(id);
|
||||||
element.addEventListener('input', () => this.updateConfigFromForm());
|
element.addEventListener('input', () => this.updateConfigFromForm());
|
||||||
element.addEventListener('change', () => this.updateConfigFromForm());
|
element.addEventListener('change', () => this.updateConfigFromForm());
|
||||||
@ -316,8 +300,7 @@ class EmbedDesigner {
|
|||||||
lightColor: '#3b82f6',
|
lightColor: '#3b82f6',
|
||||||
darkColor: '#60a5fa',
|
darkColor: '#60a5fa',
|
||||||
height: '400',
|
height: '400',
|
||||||
themeMode: 'auto',
|
themeMode: 'auto'
|
||||||
filetree: []
|
|
||||||
};
|
};
|
||||||
// Update UI to reflect defaults
|
// Update UI to reflect defaults
|
||||||
this.setupDesignerElements();
|
this.setupDesignerElements();
|
||||||
@ -365,8 +348,7 @@ class EmbedDesigner {
|
|||||||
lightColor: lightColorText ? lightColorText.value : '#3b82f6',
|
lightColor: lightColorText ? lightColorText.value : '#3b82f6',
|
||||||
darkColor: darkColorText ? darkColorText.value : '#60a5fa',
|
darkColor: darkColorText ? darkColorText.value : '#60a5fa',
|
||||||
height: heightSlider ? heightSlider.value : '400',
|
height: heightSlider ? heightSlider.value : '400',
|
||||||
themeMode: this.config.themeMode || 'auto',
|
themeMode: this.config.themeMode || 'auto'
|
||||||
filetree: document.getElementById('designer-filetree').value.split('\n').map(f => f.trim()).filter(f => f)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.updatePreview();
|
this.updatePreview();
|
||||||
@ -439,7 +421,6 @@ class EmbedDesigner {
|
|||||||
if (this.config.lightColor !== '#3b82f6') params.set('lightColor', this.config.lightColor);
|
if (this.config.lightColor !== '#3b82f6') params.set('lightColor', this.config.lightColor);
|
||||||
if (this.config.darkColor !== '#60a5fa') params.set('darkColor', this.config.darkColor);
|
if (this.config.darkColor !== '#60a5fa') params.set('darkColor', this.config.darkColor);
|
||||||
if (this.config.themeMode !== 'auto') params.set('themeMode', this.config.themeMode);
|
if (this.config.themeMode !== 'auto') params.set('themeMode', this.config.themeMode);
|
||||||
if (this.config.filetree && this.config.filetree.length > 0) params.set('filetree', encodeURIComponent(this.config.filetree.join('\n')));
|
|
||||||
params.set('preview', 'true');
|
params.set('preview', 'true');
|
||||||
|
|
||||||
return `/embed-preview/?${params.toString()}`;
|
return `/embed-preview/?${params.toString()}`;
|
||||||
@ -456,7 +437,6 @@ class EmbedDesigner {
|
|||||||
if (this.config.lightColor !== '#3b82f6') params.set('lightColor', this.config.lightColor);
|
if (this.config.lightColor !== '#3b82f6') params.set('lightColor', this.config.lightColor);
|
||||||
if (this.config.darkColor !== '#60a5fa') params.set('darkColor', this.config.darkColor);
|
if (this.config.darkColor !== '#60a5fa') params.set('darkColor', this.config.darkColor);
|
||||||
if (this.config.themeMode !== 'auto') params.set('themeMode', this.config.themeMode);
|
if (this.config.themeMode !== 'auto') params.set('themeMode', this.config.themeMode);
|
||||||
if (this.config.filetree && this.config.filetree.length > 0) params.set('filetree', encodeURIComponent(this.config.filetree.join('\n')));
|
|
||||||
|
|
||||||
return `${window.location.origin}/embed-preview/?${params.toString()}`;
|
return `${window.location.origin}/embed-preview/?${params.toString()}`;
|
||||||
}
|
}
|
||||||
@ -538,40 +518,27 @@ class EmbedDesigner {
|
|||||||
}
|
}
|
||||||
|
|
||||||
loadExample() {
|
loadExample() {
|
||||||
// Set example values
|
// Set example data
|
||||||
document.getElementById('designer-prompt').value =
|
this.config = {
|
||||||
`You are a senior React developer. I need help building a modern e-commerce product listing component.
|
prompt: 'Build an MCP server that works with Weather API. See @Web for cool weather APIs.',
|
||||||
|
context: ['@Web', 'https://modelcontextprotocol.io/full-llms.txt'],
|
||||||
|
model: 'Claude 4 Sonnet',
|
||||||
|
mode: 'agent',
|
||||||
|
thinking: true,
|
||||||
|
max: true,
|
||||||
|
lightColor: '#3b82f6',
|
||||||
|
darkColor: '#60a5fa',
|
||||||
|
height: '250',
|
||||||
|
themeMode: 'auto'
|
||||||
|
};
|
||||||
|
|
||||||
Requirements:
|
// Update all form elements
|
||||||
- Use React hooks and functional components
|
this.setupDesignerElements();
|
||||||
- Implement product filtering by category and price range
|
this.updatePreview();
|
||||||
- Add smooth animations for product cards
|
this.updateIframeSnippet();
|
||||||
- Make it fully responsive with a grid layout
|
this.saveToLocalStorage();
|
||||||
- Include loading states and error handling
|
|
||||||
|
|
||||||
The component should fetch data from a REST API and display products with images, titles, prices, and ratings. Please provide clean, well-commented code following React best practices.`;
|
|
||||||
|
|
||||||
document.getElementById('designer-context').value = '@codebase, ProductList.jsx';
|
|
||||||
document.getElementById('designer-filetree').value =
|
|
||||||
`src/components/ProductList.jsx*
|
|
||||||
src/components/ProductCard.jsx
|
|
||||||
src/components/Filters.jsx
|
|
||||||
src/hooks/useProducts.js
|
|
||||||
src/api/products.js
|
|
||||||
src/styles/products.css
|
|
||||||
src/utils/formatters.js
|
|
||||||
public/index.html
|
|
||||||
package.json
|
|
||||||
README.md`;
|
|
||||||
|
|
||||||
// Set some example settings
|
|
||||||
document.getElementById('designer-model').value = 'Claude 3.7 Sonnet';
|
|
||||||
document.getElementById('designer-mode-select').value = 'agent';
|
|
||||||
document.getElementById('designer-thinking').checked = true;
|
|
||||||
|
|
||||||
// Update config from form
|
|
||||||
this.updateConfigFromForm();
|
|
||||||
|
|
||||||
|
// Show notification
|
||||||
this.showNotification('Example loaded!');
|
this.showNotification('Example loaded!');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user