2025-06-16 16:07:02 +03:00
class EmbedDesigner {
constructor ( ) {
this . params = this . parseURLParams ( ) ;
this . config = this . getInitialConfig ( ) ;
this . initDesignerMode ( ) ;
}
parseURLParams ( ) {
const urlParams = new URLSearchParams ( window . location . search ) ;
const params = { } ;
for ( const [ key , value ] of urlParams . entries ( ) ) {
params [ key ] = decodeURIComponent ( value ) ;
}
return params ;
}
getInitialConfig ( ) {
2025-06-16 23:33:48 +03:00
// Check if we have URL parameters
const hasUrlParams = Object . keys ( this . params ) . length > 0 ;
// If URL params exist, prioritize them over saved config
if ( hasUrlParams ) {
// Start with defaults, then apply saved config, then override with URL params
const savedConfig = this . loadFromLocalStorage ( ) || { } ;
return {
prompt : this . params . prompt || savedConfig . prompt || '' ,
context : this . params . context ? this . params . context . split ( ',' ) . map ( c => c . trim ( ) ) : ( savedConfig . context || [ ] ) ,
model : this . params . model || savedConfig . model || 'gpt-4o' ,
mode : this . params . agentMode || savedConfig . mode || 'chat' ,
thinking : this . params . thinking === 'true' ? true : ( this . params . thinking === 'false' ? false : ( savedConfig . thinking || false ) ) ,
max : this . params . max === 'true' ? true : ( this . params . max === 'false' ? false : ( savedConfig . max || false ) ) ,
lightColor : this . params . lightColor || savedConfig . lightColor || '#3b82f6' ,
darkColor : this . params . darkColor || savedConfig . darkColor || '#60a5fa' ,
height : this . params . height || savedConfig . height || '400' ,
2025-06-17 19:41:56 +03:00
themeMode : this . params . themeMode || savedConfig . themeMode || 'auto' ,
2025-06-18 16:21:53 +03:00
filetree : this . params . filetree ? decodeURIComponent ( this . params . filetree ) . split ( '\n' ) . filter ( f => f . trim ( ) ) : ( savedConfig . filetree || [ ] ) ,
showFiletree : savedConfig . showFiletree !== undefined ? savedConfig . showFiletree : true
2025-06-16 23:33:48 +03:00
} ;
}
// Otherwise, try to load from localStorage
2025-06-16 16:07:02 +03:00
const savedConfig = this . loadFromLocalStorage ( ) ;
if ( savedConfig ) {
return savedConfig ;
}
2025-06-16 23:33:48 +03:00
// Fall back to defaults
2025-06-16 16:07:02 +03:00
return {
2025-06-16 23:33:48 +03:00
prompt : '' ,
context : [ ] ,
model : 'gpt-4o' ,
mode : 'chat' ,
thinking : false ,
max : false ,
lightColor : '#3b82f6' ,
darkColor : '#60a5fa' ,
height : '400' ,
2025-06-17 19:41:56 +03:00
themeMode : 'auto' ,
2025-06-18 16:21:53 +03:00
filetree : [ ] ,
showFiletree : true
2025-06-16 16:07:02 +03:00
} ;
}
loadFromLocalStorage ( ) {
try {
const saved = localStorage . getItem ( 'embedDesignerConfig' ) ;
if ( saved ) {
const config = JSON . parse ( saved ) ;
// Validate the loaded config has all required fields
if ( config && typeof config === 'object' ) {
2025-06-17 19:41:56 +03:00
// Ensure all properties have defaults
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' ,
2025-06-18 16:21:53 +03:00
filetree : config . filetree || [ ] ,
showFiletree : config . showFiletree !== undefined ? config . showFiletree : true
2025-06-17 19:41:56 +03:00
} ;
2025-06-16 16:07:02 +03:00
}
}
} catch ( e ) {
console . error ( 'Error loading from localStorage:' , e ) ;
}
return null ;
}
saveToLocalStorage ( ) {
try {
localStorage . setItem ( 'embedDesignerConfig' , JSON . stringify ( this . config ) ) ;
// Auto-save is silent - no notification
} catch ( e ) {
console . error ( 'Error saving to localStorage:' , e ) ;
}
}
clearLocalStorage ( ) {
try {
localStorage . removeItem ( 'embedDesignerConfig' ) ;
this . showNotification ( 'Settings cleared!' ) ;
} catch ( e ) {
console . error ( 'Error clearing localStorage:' , e ) ;
}
}
initDesignerMode ( ) {
this . setupDesignerElements ( ) ;
this . setupDesignerEvents ( ) ;
this . setupDesignerColors ( ) ;
this . updatePreview ( ) ;
2025-06-16 16:24:18 +03:00
this . updateIframeSnippet ( ) ;
2025-06-16 16:07:02 +03:00
}
setupDesignerElements ( ) {
// Populate form with current config
document . getElementById ( 'designer-prompt' ) . value = this . config . prompt ;
document . getElementById ( 'designer-context' ) . value = this . config . context . join ( ', ' ) ;
2025-06-17 19:41:56 +03:00
document . getElementById ( 'designer-filetree' ) . value = this . config . filetree . join ( '\n' ) ;
2025-06-16 16:07:02 +03:00
// Handle model selection
const modelSelect = document . getElementById ( 'designer-model' ) ;
const customModelInput = document . getElementById ( 'designer-custom-model' ) ;
// Check if model is one of the predefined options
const isPredefinedModel = Array . from ( modelSelect . options ) . some ( opt => opt . value === this . config . model ) ;
if ( isPredefinedModel ) {
modelSelect . value = this . config . model ;
customModelInput . classList . add ( 'hidden' ) ;
} else {
// It's a custom model
modelSelect . value = 'custom' ;
customModelInput . value = this . config . model ;
customModelInput . classList . remove ( 'hidden' ) ;
}
document . getElementById ( 'designer-mode-select' ) . value = this . config . mode ;
document . getElementById ( 'designer-thinking' ) . checked = this . config . thinking ;
document . getElementById ( 'designer-max' ) . checked = this . config . max ;
2025-06-18 16:21:53 +03:00
// Set show filetree checkbox (default to true if not set)
const showFiletreeCheckbox = document . getElementById ( 'designer-show-filetree' ) ;
if ( showFiletreeCheckbox ) {
showFiletreeCheckbox . checked = this . config . showFiletree !== false ;
}
2025-06-16 16:07:02 +03:00
// Set height slider
const heightSlider = document . getElementById ( 'designer-height' ) ;
const heightValue = document . getElementById ( 'height-value' ) ;
if ( heightSlider ) {
heightSlider . value = this . config . height ;
if ( heightValue ) {
heightValue . textContent = this . config . height ;
}
}
// Set theme mode buttons
this . updateThemeModeButtons ( ) ;
// Set color values
const lightColorPicker = document . getElementById ( 'designer-light-color' ) ;
const lightColorText = document . getElementById ( 'designer-light-color-text' ) ;
const darkColorPicker = document . getElementById ( 'designer-dark-color' ) ;
const darkColorText = document . getElementById ( 'designer-dark-color-text' ) ;
if ( lightColorPicker ) {
lightColorPicker . value = this . config . lightColor ;
lightColorText . value = this . config . lightColor ;
}
if ( darkColorPicker ) {
darkColorPicker . value = this . config . darkColor ;
darkColorText . value = this . config . darkColor ;
}
}
updateThemeModeButtons ( ) {
// Update theme mode button states
document . querySelectorAll ( '.theme-mode-btn' ) . forEach ( btn => {
btn . classList . remove ( 'bg-dynamic-primary' , 'text-white' ) ;
btn . classList . add ( 'bg-dynamic-background' , 'text-dynamic-foreground' ) ;
} ) ;
const activeButton = document . getElementById ( ` theme- ${ this . config . themeMode } ` ) ;
if ( activeButton ) {
activeButton . classList . remove ( 'bg-dynamic-background' , 'text-dynamic-foreground' ) ;
activeButton . classList . add ( 'bg-dynamic-primary' , 'text-white' ) ;
}
}
setupDesignerEvents ( ) {
// Form changes update preview
2025-06-18 16:21:53 +03:00
[ 'designer-prompt' , 'designer-context' , 'designer-mode-select' , 'designer-thinking' , 'designer-max' , 'designer-filetree' , 'designer-show-filetree' ] . forEach ( id => {
2025-06-16 16:07:02 +03:00
const element = document . getElementById ( id ) ;
2025-06-18 16:21:53 +03:00
if ( element ) {
element . addEventListener ( 'input' , ( ) => this . updateConfigFromForm ( ) ) ;
element . addEventListener ( 'change' , ( ) => this . updateConfigFromForm ( ) ) ;
}
2025-06-16 16:07:02 +03:00
} ) ;
// Theme mode buttons
document . querySelectorAll ( '.theme-mode-btn' ) . forEach ( btn => {
btn . addEventListener ( 'click' , ( e ) => {
const mode = e . target . id . replace ( 'theme-' , '' ) ;
this . config . themeMode = mode ;
this . updateThemeModeButtons ( ) ;
this . updatePreview ( ) ;
this . saveToLocalStorage ( ) ;
} ) ;
} ) ;
// Color preset buttons
document . querySelectorAll ( '.color-preset' ) . forEach ( btn => {
btn . addEventListener ( 'click' , ( e ) => {
const lightColor = e . currentTarget . getAttribute ( 'data-light' ) ;
const darkColor = e . currentTarget . getAttribute ( 'data-dark' ) ;
// Update color pickers and text inputs
const lightColorPicker = document . getElementById ( 'designer-light-color' ) ;
const lightColorText = document . getElementById ( 'designer-light-color-text' ) ;
const darkColorPicker = document . getElementById ( 'designer-dark-color' ) ;
const darkColorText = document . getElementById ( 'designer-dark-color-text' ) ;
if ( lightColorPicker && lightColor ) {
lightColorPicker . value = lightColor ;
lightColorText . value = lightColor ;
}
if ( darkColorPicker && darkColor ) {
darkColorPicker . value = darkColor ;
darkColorText . value = darkColor ;
}
this . updateConfigFromForm ( ) ;
} ) ;
} ) ;
// Model dropdown special handling
const modelSelect = document . getElementById ( 'designer-model' ) ;
const customModelInput = document . getElementById ( 'designer-custom-model' ) ;
modelSelect . addEventListener ( 'change' , ( ) => {
if ( modelSelect . value === 'custom' ) {
customModelInput . classList . remove ( 'hidden' ) ;
customModelInput . focus ( ) ;
} else {
customModelInput . classList . add ( 'hidden' ) ;
}
this . updateConfigFromForm ( ) ;
} ) ;
// Custom model input
customModelInput . addEventListener ( 'input' , ( ) => this . updateConfigFromForm ( ) ) ;
// Height slider
const heightSlider = document . getElementById ( 'designer-height' ) ;
const heightValue = document . getElementById ( 'height-value' ) ;
if ( heightSlider ) {
heightSlider . addEventListener ( 'input' , ( e ) => {
if ( heightValue ) {
heightValue . textContent = e . target . value ;
}
this . updateConfigFromForm ( ) ;
} ) ;
}
// Color pickers
const lightColorPicker = document . getElementById ( 'designer-light-color' ) ;
const lightColorText = document . getElementById ( 'designer-light-color-text' ) ;
const darkColorPicker = document . getElementById ( 'designer-dark-color' ) ;
const darkColorText = document . getElementById ( 'designer-dark-color-text' ) ;
if ( lightColorPicker ) {
lightColorPicker . addEventListener ( 'input' , ( e ) => {
lightColorText . value = e . target . value ;
this . updateConfigFromForm ( ) ;
} ) ;
}
if ( lightColorText ) {
lightColorText . addEventListener ( 'input' , ( e ) => {
if ( /^#[0-9A-Fa-f]{6}$/ . test ( e . target . value ) ) {
lightColorPicker . value = e . target . value ;
this . updateConfigFromForm ( ) ;
}
} ) ;
}
if ( darkColorPicker ) {
darkColorPicker . addEventListener ( 'input' , ( e ) => {
darkColorText . value = e . target . value ;
this . updateConfigFromForm ( ) ;
} ) ;
}
if ( darkColorText ) {
darkColorText . addEventListener ( 'input' , ( e ) => {
if ( /^#[0-9A-Fa-f]{6}$/ . test ( e . target . value ) ) {
darkColorPicker . value = e . target . value ;
this . updateConfigFromForm ( ) ;
}
} ) ;
}
// Generate embed button
document . getElementById ( 'generate-embed' ) . addEventListener ( 'click' , ( ) => this . showEmbedModal ( ) ) ;
2025-06-16 16:24:18 +03:00
// Iframe snippet click to copy
document . getElementById ( 'iframe-snippet' ) . addEventListener ( 'click' , ( ) => this . copyIframeCode ( ) ) ;
2025-06-16 16:07:02 +03:00
// Reset settings button
document . getElementById ( 'reset-settings' ) . addEventListener ( 'click' , ( ) => {
if ( confirm ( 'Are you sure you want to reset all settings to defaults?' ) ) {
this . clearLocalStorage ( ) ;
// Reset to default config
this . config = {
prompt : '' ,
context : [ ] ,
model : 'gpt-4o' ,
mode : 'chat' ,
thinking : false ,
max : false ,
lightColor : '#3b82f6' ,
darkColor : '#60a5fa' ,
height : '400' ,
2025-06-17 19:41:56 +03:00
themeMode : 'auto' ,
2025-06-18 16:21:53 +03:00
filetree : [ ] ,
showFiletree : true
2025-06-16 16:07:02 +03:00
} ;
// Update UI to reflect defaults
this . setupDesignerElements ( ) ;
this . updatePreview ( ) ;
2025-06-16 16:24:18 +03:00
this . updateIframeSnippet ( ) ;
2025-06-16 16:07:02 +03:00
}
} ) ;
2025-06-18 16:21:53 +03:00
// Example buttons
document . getElementById ( 'vibe-example' ) . addEventListener ( 'click' , ( ) => {
this . loadVibeExample ( ) ;
} ) ;
document . getElementById ( 'chat-example' ) . addEventListener ( 'click' , ( ) => {
this . loadChatExample ( ) ;
2025-06-16 16:24:18 +03:00
} ) ;
2025-06-16 16:07:02 +03:00
// Modal events
document . getElementById ( 'close-modal' ) . addEventListener ( 'click' , ( ) => this . hideEmbedModal ( ) ) ;
document . getElementById ( 'copy-embed-code' ) . addEventListener ( 'click' , ( ) => this . copyEmbedCode ( ) ) ;
document . getElementById ( 'copy-share-url' ) . addEventListener ( 'click' , ( ) => this . copyShareURL ( ) ) ;
// Close modal on backdrop click
document . getElementById ( 'embed-modal' ) . addEventListener ( 'click' , ( e ) => {
if ( e . target . id === 'embed-modal' ) this . hideEmbedModal ( ) ;
} ) ;
}
updateConfigFromForm ( ) {
const heightSlider = document . getElementById ( 'designer-height' ) ;
const modelSelect = document . getElementById ( 'designer-model' ) ;
const customModelInput = document . getElementById ( 'designer-custom-model' ) ;
const lightColorText = document . getElementById ( 'designer-light-color-text' ) ;
const darkColorText = document . getElementById ( 'designer-dark-color-text' ) ;
// Get model value
let modelValue = modelSelect . value ;
if ( modelValue === 'custom' ) {
modelValue = customModelInput . value || 'Custom Model' ;
}
this . config = {
prompt : document . getElementById ( 'designer-prompt' ) . value ,
context : document . getElementById ( 'designer-context' ) . value . split ( ',' ) . map ( c => c . trim ( ) ) . filter ( c => c ) ,
model : modelValue ,
mode : document . getElementById ( 'designer-mode-select' ) . value ,
thinking : document . getElementById ( 'designer-thinking' ) . checked ,
max : document . getElementById ( 'designer-max' ) . checked ,
lightColor : lightColorText ? lightColorText . value : '#3b82f6' ,
darkColor : darkColorText ? darkColorText . value : '#60a5fa' ,
height : heightSlider ? heightSlider . value : '400' ,
2025-06-17 19:41:56 +03:00
themeMode : this . config . themeMode || 'auto' ,
2025-06-18 16:21:53 +03:00
filetree : document . getElementById ( 'designer-filetree' ) . value . split ( '\n' ) . map ( f => f . trim ( ) ) . filter ( f => f ) ,
showFiletree : document . getElementById ( 'designer-show-filetree' ) . checked
2025-06-16 16:07:02 +03:00
} ;
this . updatePreview ( ) ;
this . saveToLocalStorage ( ) ;
2025-06-16 16:24:18 +03:00
this . updateIframeSnippet ( ) ;
}
updateIframeSnippet ( ) {
const snippet = document . getElementById ( 'iframe-snippet' ) ;
if ( ! snippet ) return ;
const code = this . generateEmbedCode ( ) ;
// Show a shortened version in the snippet
const shortCode = code . replace ( /\n/g , ' ' ) . replace ( /\s+/g , ' ' ) ;
snippet . textContent = shortCode ;
2025-06-16 16:07:02 +03:00
}
setupDesignerColors ( ) {
// Set up fixed designer colors - always use default blue theme in light mode
const root = document . documentElement ;
// Always use default blue colors for designer
root . style . setProperty ( '--primary' , '59 130 246' ) ; // Blue-500
root . style . setProperty ( '--background' , '255 255 255' ) ;
root . style . setProperty ( '--foreground' , '15 23 42' ) ;
root . style . setProperty ( '--muted' , '248 250 252' ) ;
root . style . setProperty ( '--muted-foreground' , '100 116 139' ) ;
root . style . setProperty ( '--border' , '226 232 240' ) ;
root . style . setProperty ( '--accent' , '16 185 129' ) ;
}
updateDesignerColors ( ) {
// Deprecated - no longer update designer colors
// Designer maintains fixed color scheme
}
updatePreview ( ) {
const previewContainer = document . getElementById ( 'preview-container' ) ;
const previewWrapper = document . getElementById ( 'preview-wrapper' ) ;
if ( ! previewContainer ) return ;
// Update preview wrapper height
if ( previewWrapper ) {
previewWrapper . style . height = ` ${ this . config . height } px ` ;
}
// Generate preview URL with parameters
const previewUrl = this . generatePreviewURL ( ) ;
// Update iframe src
let iframe = previewContainer . querySelector ( 'iframe' ) ;
if ( ! iframe ) {
iframe = document . createElement ( 'iframe' ) ;
iframe . className = 'w-full h-full border-0 rounded-lg' ;
previewContainer . innerHTML = '' ;
previewContainer . appendChild ( iframe ) ;
}
iframe . src = previewUrl ;
}
generatePreviewURL ( ) {
const params = new URLSearchParams ( ) ;
if ( this . config . prompt ) params . set ( 'prompt' , this . config . prompt ) ;
if ( this . config . context . length > 0 ) params . set ( 'context' , this . config . context . join ( ',' ) ) ;
if ( this . config . model !== 'gpt-4o' ) params . set ( 'model' , this . config . model ) ;
if ( this . config . mode !== 'chat' ) params . set ( 'agentMode' , this . config . mode ) ;
if ( this . config . thinking ) params . set ( 'thinking' , 'true' ) ;
if ( this . config . max ) params . set ( 'max' , 'true' ) ;
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 . themeMode !== 'auto' ) params . set ( 'themeMode' , this . config . themeMode ) ;
2025-06-18 16:21:53 +03:00
if ( this . config . showFiletree && this . config . filetree && this . config . filetree . length > 0 ) params . set ( 'filetree' , encodeURIComponent ( this . config . filetree . join ( '\n' ) ) ) ;
2025-06-16 16:07:02 +03:00
params . set ( 'preview' , 'true' ) ;
return ` /embed-preview/? ${ params . toString ( ) } ` ;
}
generateShareURL ( ) {
const params = new URLSearchParams ( ) ;
if ( this . config . prompt ) params . set ( 'prompt' , this . config . prompt ) ;
if ( this . config . context . length > 0 ) params . set ( 'context' , this . config . context . join ( ',' ) ) ;
if ( this . config . model !== 'gpt-4o' ) params . set ( 'model' , this . config . model ) ;
if ( this . config . mode !== 'chat' ) params . set ( 'agentMode' , this . config . mode ) ;
if ( this . config . thinking ) params . set ( 'thinking' , 'true' ) ;
if ( this . config . max ) params . set ( 'max' , 'true' ) ;
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 . themeMode !== 'auto' ) params . set ( 'themeMode' , this . config . themeMode ) ;
2025-06-18 16:21:53 +03:00
if ( this . config . showFiletree && this . config . filetree && this . config . filetree . length > 0 ) params . set ( 'filetree' , encodeURIComponent ( this . config . filetree . join ( '\n' ) ) ) ;
2025-06-16 16:07:02 +03:00
return ` ${ window . location . origin } /embed-preview/? ${ params . toString ( ) } ` ;
}
generateEmbedCode ( ) {
const url = this . generateShareURL ( ) ;
return ` <iframe
src = "${url}"
width = "100%"
height = "${this.config.height}"
frameborder = "0"
style = "border-radius: 12px; border: 1px solid #e5e7eb;" >
< / i f r a m e > ` ;
}
showEmbedModal ( ) {
const modal = document . getElementById ( 'embed-modal' ) ;
const embedCode = document . getElementById ( 'embed-code' ) ;
const shareUrl = document . getElementById ( 'share-url' ) ;
embedCode . value = this . generateEmbedCode ( ) ;
shareUrl . value = this . generateShareURL ( ) ;
modal . classList . remove ( 'hidden' ) ;
}
hideEmbedModal ( ) {
document . getElementById ( 'embed-modal' ) . classList . add ( 'hidden' ) ;
}
async copyEmbedCode ( ) {
const embedCode = document . getElementById ( 'embed-code' ) . value ;
await this . copyToClipboard ( embedCode ) ;
this . showNotification ( 'Embed code copied to clipboard!' ) ;
}
async copyShareURL ( ) {
const shareUrl = this . generateShareURL ( ) ;
await this . copyToClipboard ( shareUrl ) ;
this . showNotification ( 'Share URL copied to clipboard!' ) ;
}
2025-06-16 16:24:18 +03:00
async copyIframeCode ( ) {
const embedCode = this . generateEmbedCode ( ) ;
await this . copyToClipboard ( embedCode ) ;
this . showNotification ( 'Iframe code copied to clipboard!' ) ;
}
2025-06-16 16:07:02 +03:00
async copyToClipboard ( text ) {
if ( navigator . clipboard && window . isSecureContext ) {
await navigator . clipboard . writeText ( text ) ;
} else {
// Fallback
const textArea = document . createElement ( 'textarea' ) ;
textArea . value = text ;
textArea . style . position = 'fixed' ;
textArea . style . left = '-999999px' ;
textArea . style . top = '-999999px' ;
document . body . appendChild ( textArea ) ;
textArea . focus ( ) ;
textArea . select ( ) ;
document . execCommand ( 'copy' ) ;
textArea . remove ( ) ;
}
}
showNotification ( message , duration = 2000 ) {
const notification = document . getElementById ( 'notification' ) ;
if ( ! notification ) return ;
notification . textContent = message ;
notification . classList . remove ( 'opacity-0' ) ;
notification . classList . add ( 'opacity-100' ) ;
setTimeout ( ( ) => {
notification . classList . remove ( 'opacity-100' ) ;
notification . classList . add ( 'opacity-0' ) ;
} , duration ) ;
}
2025-06-16 16:24:18 +03:00
2025-06-18 16:21:53 +03:00
loadVibeExample ( ) {
// Set vibe coding example values
2025-06-17 19:41:56 +03:00
document . getElementById ( 'designer-prompt' ) . value =
2025-06-18 16:21:53 +03:00
` I'm working on a React e-commerce app. The current ProductList component is getting messy with too much logic.
2025-06-17 19:41:56 +03:00
2025-06-18 16:21:53 +03:00
Can you help me refactor it to :
1. Extract the filtering logic into a custom hook
2. Split the large component into smaller , reusable pieces
3. Add proper TypeScript types
4. Implement virtualization for better performance with large product lists
2025-06-17 19:41:56 +03:00
2025-06-18 16:21:53 +03:00
The component currently handles products display , filtering by category / price , sorting , and pagination all in one file . I want a cleaner architecture . ` ;
2025-06-17 19:41:56 +03:00
2025-06-18 16:21:53 +03:00
document . getElementById ( 'designer-context' ) . value = '@codebase, ProductList.tsx, components/, hooks/' ;
2025-06-17 19:41:56 +03:00
document . getElementById ( 'designer-filetree' ) . value =
2025-06-18 16:21:53 +03:00
` src/
src / components /
src / components / ProductList . tsx *
src / components / ProductCard . tsx
src / components / ProductGrid . tsx
src / components / Filters /
src / components / Filters / CategoryFilter . tsx
src / components / Filters / PriceRangeFilter . tsx
src / components / Filters / index . tsx
src / hooks /
src / hooks / useProducts . ts
src / hooks / useFilters . ts
src / hooks / useInfiniteScroll . ts
src / types /
src / types / product . ts
src / api /
src / api / products . ts
src / utils /
src / utils / formatters . ts
2025-06-17 19:41:56 +03:00
package . json
2025-06-18 16:21:53 +03:00
tsconfig . json ` ;
2025-06-17 19:41:56 +03:00
2025-06-18 16:21:53 +03:00
// Set vibe coding settings
document . getElementById ( 'designer-model' ) . value = 'Claude 4 Opus' ;
2025-06-17 19:41:56 +03:00
document . getElementById ( 'designer-mode-select' ) . value = 'agent' ;
document . getElementById ( 'designer-thinking' ) . checked = true ;
2025-06-18 16:21:53 +03:00
document . getElementById ( 'designer-max' ) . checked = true ;
document . getElementById ( 'designer-show-filetree' ) . checked = true ;
// Update config from form
this . updateConfigFromForm ( ) ;
this . showNotification ( 'Vibe coding example loaded!' ) ;
}
loadChatExample ( ) {
// Set chat example values
document . getElementById ( 'designer-prompt' ) . value =
` I'm planning a dinner party for 8 people this weekend. One person is vegetarian, another is gluten-free, and I want to make something impressive but not too complicated.
Can you suggest a menu with appetizers , main course , and dessert that would work for everyone ? I have about 4 hours to prepare everything and a moderate cooking skill level . ` ;
document . getElementById ( 'designer-context' ) . value = '#Screenshot Kitchen Layout.png, Recipes Collection.pdf' ;
document . getElementById ( 'designer-filetree' ) . value = '' ;
// Set chat settings
document . getElementById ( 'designer-model' ) . value = 'GPT 4o' ;
document . getElementById ( 'designer-mode-select' ) . value = 'chat' ;
document . getElementById ( 'designer-thinking' ) . checked = false ;
document . getElementById ( 'designer-max' ) . checked = false ;
document . getElementById ( 'designer-show-filetree' ) . checked = false ;
2025-06-17 19:41:56 +03:00
// Update config from form
this . updateConfigFromForm ( ) ;
2025-06-16 16:24:18 +03:00
2025-06-18 16:21:53 +03:00
this . showNotification ( 'Chat example loaded!' ) ;
2025-06-16 16:24:18 +03:00
}
2025-06-16 16:07:02 +03:00
}
// Dark mode toggle function
function toggleDarkMode ( ) {
const body = document . body ;
const isDark = body . classList . contains ( 'dark-mode' ) ;
if ( isDark ) {
body . classList . remove ( 'dark-mode' ) ;
localStorage . setItem ( 'darkMode' , 'false' ) ;
document . querySelector ( '.dark-mode-toggle .sun-icon' ) . style . display = 'block' ;
document . querySelector ( '.dark-mode-toggle .moon-icon' ) . style . display = 'none' ;
} else {
body . classList . add ( 'dark-mode' ) ;
localStorage . setItem ( 'darkMode' , 'true' ) ;
document . querySelector ( '.dark-mode-toggle .sun-icon' ) . style . display = 'none' ;
document . querySelector ( '.dark-mode-toggle .moon-icon' ) . style . display = 'block' ;
}
}
// Initialize when DOM is ready
document . addEventListener ( 'DOMContentLoaded' , ( ) => {
window . embedDesigner = new EmbedDesigner ( ) ;
// Initialize dark mode from localStorage
const darkMode = localStorage . getItem ( 'darkMode' ) ;
if ( darkMode === 'true' ) {
document . body . classList . add ( 'dark-mode' ) ;
document . querySelector ( '.dark-mode-toggle .sun-icon' ) . style . display = 'none' ;
document . querySelector ( '.dark-mode-toggle .moon-icon' ) . style . display = 'block' ;
}
} ) ;