NAWAM Labs 

import React, { useState, useEffect } from 'react'; import { Aperture, Settings, Moon, Sun, User, Image as ImageIcon, Video, Lock, Clipboard, Loader2, UploadCloud, X, Link, RotateCcw, WandSparkles, Crown } from 'lucide-react'; // -- Data dan Konfigurasi -- // const translations = { id: { title: "Prompt Generator", by: "by Nawam", login: "Login", settings: "Pengaturan", premiumAccessTitle: "Buka Fitur Premium", premiumAccessPrompt: "Masukkan kata sandi untuk membuka fitur premium:", premiumAccessSubmit: "Buka Akses", premiumUnlocked: "Fitur premium telah dibuka!", premiumWrongPass: "Kata sandi salah.", imagePromptTab: "Prompt Gambar", videoPromptTab: "Prompt Video", providerLabel: "Pilih Penyedia", keywordsLabel: "Masukkan Kata Kunci/Deskripsi", generateButton: "Buat Prompt", generatingButton: "Membuat...", resetButton: "Atur Ulang", advancedOptionsTitle: "Opsi Tingkat Lanjut", variationsLabel: "Jumlah Variasi", visualStyleLabel: "Gaya Visual", lightingLabel: "Pencahayaan", compositionLabel: "Komposisi", shotTypeLabel: "Jenis Tembakan", moodLabel: "Suasana/Atmosfer", durationLabel: "Durasi (detik)", frameRateLabel: "Frame Rate (fps)", aspectRatioLabel: "Rasio Aspek", negativePromptLabel: "Prompt Negatif (apa yang harus dihindari)", chaosLabel: "Tingkat Kekacauan (Chaos)", freeStylesLabel: "Opsi Gratis", premiumStylesLabel: "Opsi Premium", promptResultLabel: "Hasil Prompt", copyButton: "Salin", copiedButton: "Tersalin!", uploadFeature: { title: "Deskripsikan dari Gambar", }, adSlot: "Slot Iklan (Versi Gratis)", footerVersion: "Versi", footerLanguage: "Bahasa", errorOccurred: "Terjadi kesalahan. Silakan coba lagi.", errorKeywords: "Kata kunci tidak boleh kosong.", }, en: { title: "Prompt Generator", by: "by Nawam", login: "Login", settings: "Settings", premiumAccessTitle: "Unlock Premium Features", premiumAccessPrompt: "Enter password to unlock premium features:", premiumAccessSubmit: "Unlock", premiumUnlocked: "Premium features unlocked!", premiumWrongPass: "Incorrect password.", imagePromptTab: "Image Prompt", videoPromptTab: "Video Prompt", providerLabel: "Select Provider", keywordsLabel: "Enter Keywords/Description", generateButton: "Generate Prompt", generatingButton: "Generating...", resetButton: "Reset", advancedOptionsTitle: "Advanced Options", variationsLabel: "Number of Variations", visualStyleLabel: "Visual Style", lightingLabel: "Lighting", compositionLabel: "Composition", shotTypeLabel: "Shot Type", moodLabel: "Mood/Atmosphere", durationLabel: "Duration (seconds)", frameRateLabel: "Frame Rate (fps)", aspectRatioLabel: "Aspect Ratio", negativePromptLabel: "Negative Prompt (what to avoid)", chaosLabel: "Chaos Level", freeStylesLabel: "Free Options", premiumStylesLabel: "Premium Options", promptResultLabel: "Prompt Result", copyButton: "Copy", copiedButton: "Copied!", uploadFeature: { title: "Describe from Image", cta: "Upload Image", or: "or", urlPlaceholder: "Paste image link here...", }, adSlot: "Ad Slot (Free Version)", footerVersion: "Version", footerLanguage: "Language", errorOccurred: "An error occurred. Please try again.", errorKeywords: "Keywords cannot be empty.", } }; const imageProviders = ["Midjourney", "Imagen 3", "DALL-E 3", "Stable Diffusion"]; const videoProviders = ["Sora", "Veo", "Kling", "Stable Video"]; const aspectRatios = ["16:9 (Landscape)", "1:1 (Square)", "9:16 (Portrait)", "4:3 (Classic)", "3:2 (Photo)"]; const optionsData = { visualStyleImage: { free: ["Default", "Photorealistic", "Digital Art", "Illustration"], premium: ["Anime (80s style)", "Epic Fantasy Painting", "Ghibli Style", "Pixel Art", "3D Model Render", "Vaporwave", "Cyberpunk"] }, visualStyleVideo: { free: ["Default", "Cinematic", "Documentary", "Home Video"], premium: ["Found Footage", "Music Video", "Noir Film", "Time-lapse", "Slow Motion", "Wes Anderson Style", "Animated (2D)"] }, lighting: { free: ["Default", "Natural Light", "Studio Light", "Dramatic Lighting"], premium: ["Cinematic Lighting", "Golden Hour", "Blue Hour", "Rim Lighting", "Neon Lights", "Volumetric Lighting"] }, composition: { free: ["Default", "Centered", "Asymmetrical", "Close-up"], premium: ["Rule of Thirds", "Leading Lines", "Dutch Angle", "Bird's-eye View", "Worm's-eye View", "Symmetrical"] }, shotType: { free: ["Default", "Medium Shot", "Wide Shot", "Close-up Shot"], premium: ["Extreme Wide Shot", "Cowboy Shot", "Point of View (POV)", "Crane Shot", "Drone Shot", "Tracking Shot"] }, mood: { free: ["Default", "Happy", "Sad", "Mysterious"], premium: ["Serene", "Suspenseful", "Nostalgic", "Energetic", "Eerie", "Romantic", "Tense"] }, duration: { free: ["Default", "5s", "10s", "15s"], premium: ["3s", "20s", "30s", "60s"] }, frameRate: { free: ["Default", "24fps (Cinematic)", "30fps (Standard)"], premium: ["12fps (Animation)", "60fps (Smooth)", "120fps (Slow-mo)"] } }; // -- Komponen UI -- // const Header = ({ isDarkMode, toggleTheme, onUnlockPremium, t, isPremium }) => (

{t.title} {t.by}

{isPremium && }
); const Tab = ({ label, icon, isActive, onClick }) => ( ); const PromptOutput = ({ prompts, isLoading, t, variationCount }) => { const [copied, setCopied] = useState(null); const handleCopy = (text, index) => { if (!text) return; const textArea = document.createElement("textarea"); textArea.value = text; document.body.appendChild(textArea); textArea.select(); try { document.execCommand('copy'); setCopied(index); setTimeout(() => setCopied(null), 2000); } catch (err) { console.error('Gagal menyalin teks: ', err); } document.body.removeChild(textArea); }; if (isLoading) { return (
{Array.from({ length: variationCount }).map((_, i) => (
))}
) } if (!prompts || prompts.length === 0) return null; return (

{t.promptResultLabel} ({prompts.length})

{prompts.map((prompt, index) => (

{prompt}

))}
); } const PremiumModal = ({ t, onClose, onUnlock }) => { const [password, setPassword] = useState(''); const [error, setError] = useState(''); const handleSubmit = (e) => { e.preventDefault(); if (password === 'premium') { onUnlock(); onClose(); } else { setError(t.premiumWrongPass); } }; return (
e.stopPropagation()}>

{t.premiumAccessTitle}

setPassword(e.target.value)} className="w-full p-2 border border-gray-300 rounded-lg bg-white dark:bg-gray-700 dark:border-gray-600 dark:text-white focus:ring-2 focus:ring-blue-500 focus:border-blue-500" autoFocus /> {error &&

{error}

}
); }; const OptionDropdown = ({ label, value, onChange, options, isPremium, t }) => (
); // Komponen utama untuk Generator const PromptGenerator = ({ language, t, isPremium, onUnlockPremium }) => { // State const [activeTab, setActiveTab] = useState('image'); const [provider, setProvider] = useState('Midjourney'); const [keywords, setKeywords] = useState(''); const [generatedPrompts, setGeneratedPrompts] = useState([]); const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(''); const [uploadedImage, setUploadedImage] = useState(null); const [imageUrl, setImageUrl] = useState(''); const [isDescribing, setIsDescribing] = useState(false); const [visualStyle, setVisualStyle] = useState(optionsData.visualStyleImage.free[0]); const [lighting, setLighting] = useState(optionsData.lighting.free[0]); const [composition, setComposition] = useState(optionsData.composition.free[0]); const [shotType, setShotType] = useState(optionsData.shotType.free[0]); const [mood, setMood] = useState(optionsData.mood.free[0]); const [duration, setDuration] = useState(optionsData.duration.free[0]); const [frameRate, setFrameRate] = useState(optionsData.frameRate.free[0]); const [aspectRatio, setAspectRatio] = useState(aspectRatios[0]); const [negativePrompt, setNegativePrompt] = useState(''); const [chaos, setChaos] = useState(0); const [variationCount, setVariationCount] = useState(1); const currentProviders = activeTab === 'image' ? imageProviders : videoProviders; const resetStatesToDefault = () => { setProvider(currentProviders[0]); setVisualStyle(activeTab === 'image' ? optionsData.visualStyleImage.free[0] : optionsData.visualStyleVideo.free[0]); setLighting(optionsData.lighting.free[0]); setComposition(optionsData.composition.free[0]); setShotType(optionsData.shotType.free[0]); setMood(optionsData.mood.free[0]); setDuration(optionsData.duration.free[0]); setFrameRate(optionsData.frameRate.free[0]); }; useEffect(() => { resetStatesToDefault(); }, [activeTab, language]); useEffect(() => { if (!isPremium && variationCount > 2) { setVariationCount(2); } }, [isPremium, variationCount]); const handleReset = () => { setKeywords(''); setGeneratedPrompts([]); setError(''); setUploadedImage(null); setImageUrl(''); resetStatesToDefault(); setAspectRatio(aspectRatios[0]); setNegativePrompt(''); setChaos(0); setVariationCount(1); }; const cleanPrompt = (text) => text.replace(/^(prompt:|here is your prompt:|sure, here's a prompt:|```json|```\s*)/gim, '').replace(/(\r\n|\n|\r)/gm," ").replace(/(--[a-zA-Z]+)\s+:/g, '$1 ').trim(); const handleImageUpload = (e) => { if(!isPremium) return; const file = e.target.files[0]; if (file?.type.startsWith('image/')) { const reader = new FileReader(); reader.onloadend = () => { setUploadedImage(reader.result); setImageUrl(''); generateDescriptionFromImage(reader.result.split(',')[1]); }; reader.readAsDataURL(file); } }; const generateDescriptionFromImage = async (base64ImageData) => { if (!isPremium) return; setIsDescribing(true); setError(''); setGeneratedPrompts([]); const promptText = language === 'id' ? "Deskripsikan gambar ini secara ringkas tapi detil (subjek utama, aksi, lingkungan, dan gaya visual) untuk membuat prompt AI." : "Briefly but descriptively describe this image (main subject, action, environment, and visual style) for an AI prompt."; const payload = { contents: [{ role: "user", parts: [{ text: promptText }, { inlineData: { mimeType: "image/jpeg", data: base64ImageData } }] }] }; const apiKey = ""; const apiUrl = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${apiKey}`; try { const response = await fetch(apiUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); if (!response.ok) throw new Error(`API Error: ${response.statusText}`); const result = await response.json(); if (result.candidates?.length > 0) { setKeywords(result.candidates[0].content.parts[0].text.trim()); } else { throw new Error(t.errorOccurred); } } catch (err) { console.error(err); setError(err.message); } finally { setIsDescribing(false); } }; const handleDescribeFromUrl = async () => { if (!imageUrl.trim() || !isPremium) return; setIsDescribing(true); setError(''); try { const response = await fetch(`https://api.allorigins.win/raw?url=${encodeURIComponent(imageUrl)}`); if (!response.ok) throw new Error('Network response was not ok.'); const blob = await response.blob(); const reader = new FileReader(); reader.onloadend = () => { setUploadedImage(reader.result); generateDescriptionFromImage(reader.result.split(',')[1]); }; reader.readAsDataURL(blob); } catch (err) { console.error("CORS or fetch error:", err); setError(t.errorOccurred); setIsDescribing(false); } }; const handleGeneratePrompt = async (e) => { e.preventDefault(); if (!keywords.trim()) { setError(t.errorKeywords); return; } setIsLoading(true); setError(''); setGeneratedPrompts([]); const finalVariationCount = isPremium ? variationCount : Math.min(variationCount, 2); const detailsArray = []; if (visualStyle !== 'Default') detailsArray.push(`visual style: ${visualStyle}`); if (activeTab === 'image') { if (lighting !== 'Default') detailsArray.push(`lighting: ${lighting}`); if (composition !== 'Default') detailsArray.push(`composition: ${composition}`); } else { // video if (shotType !== 'Default') detailsArray.push(`shot type: ${shotType}`); if (mood !== 'Default') detailsArray.push(`mood: ${mood}`); if (duration !== 'Default') detailsArray.push(`duration: ${duration}`); if (frameRate !== 'Default') detailsArray.push(`frame rate: ${frameRate}`); } const promptDetails = detailsArray.join(', '); let premiumDetails = isPremium ? ` --ar ${aspectRatio.split(' ')[0]}` : ''; if (isPremium && negativePrompt) { premiumDetails += ` --no ${negativePrompt}`; } if (isPremium && chaos > 0) { premiumDetails += ` --chaos ${chaos}`; } const metaPrompt = `You are a professional prompt engineer. Your task is to generate ${finalVariationCount} distinct, highly detailed, and effective prompts for the AI generator "${provider}". Base the prompts on the description: "${keywords}". ${promptDetails ? `Incorporate these details: ${promptDetails}.` : ''} ${isPremium && premiumDetails ? `Also add these advanced parameters: "${premiumDetails}".` : ''} Your response MUST ONLY contain the prompt text. Do not add any extra words, titles, or explanations. Each prompt should be on a new line.`; const payload = { contents: [{ role: "user", parts: [{ text: metaPrompt }] }]}; const apiKey = ""; const apiUrl = `https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=${apiKey}`; try { const response = await fetch(apiUrl, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); if (!response.ok) throw new Error(`API Error: ${response.statusText}`); const result = await response.json(); if (result.candidates?.length > 0) { const text = result.candidates[0].content.parts[0].text; const prompts = text.split('\n').filter(p => p.trim() !== '').map(p => cleanPrompt(p)); setGeneratedPrompts(prompts); } else { throw new Error(t.errorOccurred); } } catch (err) { console.error(err); setError(err.message); } finally { setIsLoading(false); } }; return (
} isActive={activeTab === 'image'} onClick={() => setActiveTab('image')} /> } isActive={activeTab === 'video'} onClick={() => setActiveTab('video')} />
{/* Form Inputs */}
Submit
Submit
The form has been sent - thank you.
Please fill in all required fields!

You can find us on

A website created with in Indonesia