Compare commits
40 Commits
5325549fa7
...
feature/de
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
93206abf36 | ||
|
|
68189db3b3 | ||
|
|
29248688f3 | ||
|
|
6bb756fdd7 | ||
|
|
24c79defff | ||
|
|
756b405423 | ||
|
|
07bf4414cc | ||
|
|
4fd3b6ffe5 | ||
|
|
5660de49de | ||
|
|
32093a4cba | ||
|
|
656b6cb4a2 | ||
|
|
df785a8bd1 | ||
|
|
423be75dd6 | ||
|
|
2a5cd317e8 | ||
|
|
99b0cdf8ac | ||
|
|
7cf8317f55 | ||
|
|
2e31c508da | ||
|
|
3fd45ec253 | ||
|
|
47992f48dd | ||
|
|
91cf1e97c3 | ||
|
|
a6d6a4cdaf | ||
|
|
213def4a67 | ||
|
|
9d33f3757d | ||
|
|
a4ab1a7f84 | ||
|
|
86e4005795 | ||
|
|
70d4f5980e | ||
|
|
1ce399584e | ||
|
|
8d88460fe1 | ||
|
|
f2960a94b9 | ||
|
|
976e065fe5 | ||
|
|
5b789cb971 | ||
|
|
d3f3ac3ae1 | ||
|
|
a7bcec220a | ||
|
|
20866d5d8c | ||
|
|
352d4330ed | ||
|
|
c174778d5f | ||
|
|
4b17870049 | ||
|
|
1b678041ab | ||
|
|
6d66e13ea2 | ||
|
|
560cd1791d |
4
.github/workflows/ci.yml
vendored
@@ -107,6 +107,10 @@ jobs:
|
||||
# Merge reports after playwright-tests, even if some shards have failed
|
||||
if: ${{ !cancelled() }}
|
||||
needs: [test]
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
actions: read
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
59
.github/workflows/playwright-comment.yml
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
name: Playwright Report Comment
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ["CI"]
|
||||
types:
|
||||
- completed
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
issues: write
|
||||
actions: read
|
||||
|
||||
jobs:
|
||||
comment:
|
||||
if: ${{ github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.pull_requests[0].number }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.workflow_run.base_ref }}
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: lts/*
|
||||
|
||||
- name: Download Playwright HTML report
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: html-report--attempt-${{ github.event.workflow_run.run_attempt }}
|
||||
path: playwright-report
|
||||
github-token: ${{ github.token }}
|
||||
repository: ${{ github.event.workflow_run.repository.full_name }}
|
||||
run-id: ${{ github.event.workflow_run.id }}
|
||||
if-no-artifact-found: warn
|
||||
|
||||
- name: Download blob reports
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: all-blob-reports
|
||||
pattern: blob-report-*
|
||||
merge-multiple: true
|
||||
github-token: ${{ github.token }}
|
||||
repository: ${{ github.event.workflow_run.repository.full_name }}
|
||||
run-id: ${{ github.event.workflow_run.id }}
|
||||
if-no-artifact-found: warn
|
||||
|
||||
- name: Generate Playwright summary comment
|
||||
uses: actions/github-script@v7
|
||||
env:
|
||||
PR_NUMBER: ${{ github.event.workflow_run.pull_requests[0].number }}
|
||||
PLAYWRIGHT_RUN_ID: ${{ github.event.workflow_run.id }}
|
||||
with:
|
||||
script: |
|
||||
const { run } = require('./scripts/generate-playwright-summary.js');
|
||||
await run({ github, context, core });
|
||||
2
.github/workflows/release.yml
vendored
@@ -21,7 +21,7 @@ jobs:
|
||||
{ name: "windows", image: "windows-latest" },
|
||||
# See https://github.com/dyad-sh/dyad/issues/96
|
||||
{ name: "linux", image: "ubuntu-22.04" },
|
||||
{ name: "macos-intel", image: "macos-13" },
|
||||
{ name: "macos-intel", image: "macos-15-intel" },
|
||||
{ name: "macos", image: "macos-latest" },
|
||||
]
|
||||
runs-on: ${{ matrix.os.image }}
|
||||
|
||||
587
README.md
@@ -1,34 +1,589 @@
|
||||
# Dyad
|
||||
# MoreMinimore
|
||||
|
||||
Dyad is a local, open-source AI app builder. It's fast, private, and fully under your control — like Lovable, v0, or Bolt, but running right on your machine.
|
||||
MoreMinimore is a local, open-source AI app builder. It's fast, private, and fully under your control — like Lovable, v0, or Bolt, but running right on your machine.
|
||||
|
||||
[](https://dyad.sh/)
|
||||
|
||||
More info at: [https://dyad.sh/](https://dyad.sh/)
|
||||

|
||||
|
||||
## 🚀 Features
|
||||
|
||||
- ⚡️ **Local**: Fast, private and no lock-in.
|
||||
- 🛠 **Bring your own keys**: Use your own AI API keys — no vendor lock-in.
|
||||
- 🖥️ **Cross-platform**: Easy to run on Mac or Windows.
|
||||
- ✨ **Enhanced**: Smart context and unlimited usage with custom features.
|
||||
- 🎯 **No limitations**: All Pro features available to everyone.
|
||||
- 🔒 **Privacy-focused**: No external API calls to commercial services.
|
||||
|
||||
## 📦 Download
|
||||
## 🧰 Prerequisites
|
||||
|
||||
No sign-up required. Just download and go.
|
||||
- Node.js >= 20
|
||||
- npm (comes with Node.js)
|
||||
- Git
|
||||
|
||||
### [👉 Download for your platform](https://www.dyad.sh/#download)
|
||||
You can verify your versions:
|
||||
|
||||
## 🤝 Community
|
||||
```bash
|
||||
node -v
|
||||
npm -v
|
||||
```
|
||||
|
||||
Join our growing community of AI app builders on **Reddit**: [r/dyadbuilders](https://www.reddit.com/r/dyadbuilders/) - share your projects and get help from the community!
|
||||
## 🚀 Quick Start
|
||||
|
||||
## 🛠️ Contributing
|
||||
### Option 1: Download and Run (Easiest)
|
||||
|
||||
**Dyad** is open-source (Apache 2.0 licensed).
|
||||
1. **Download the latest release** from [GitHub Releases](https://github.com/kunthawat/moreminimore-vibe/releases)
|
||||
2. **Install the application** for your platform
|
||||
3. **Launch MoreMinimore** and start building!
|
||||
|
||||
If you're interested in contributing to dyad, please read our [contributing](./CONTRIBUTING.md) doc.
|
||||
### Option 2: Build from Source
|
||||
|
||||
## License
|
||||
```bash
|
||||
# Clone the repository
|
||||
git clone https://github.com/kunthawat/moreminimore-vibe.git
|
||||
cd moreminimore-vibe
|
||||
|
||||
- All the code in this repo outside of `src/pro` is open-source and licensed under Apache 2.0 - see [LICENSE](./LICENSE).
|
||||
- All the code in this repo within `src/pro` is fair-source and licensed under [Functional Source License 1.1 Apache 2.0](https://fsl.software/) - see [LICENSE](./src/pro/LICENSE).
|
||||
# Install dependencies
|
||||
npm install
|
||||
|
||||
# Apply custom features and debranding
|
||||
chmod +x scripts/update-and-debrand.sh
|
||||
./scripts/update-and-debrand.sh
|
||||
|
||||
# Start the application
|
||||
npm start
|
||||
```
|
||||
|
||||
## 📋 Essential Commands
|
||||
|
||||
This section contains all the commands you'll frequently need. Copy and paste these directly.
|
||||
|
||||
### 🏗️ Development Commands
|
||||
|
||||
```bash
|
||||
# Start development server
|
||||
npm start
|
||||
|
||||
# Check TypeScript compilation
|
||||
npm run ts
|
||||
|
||||
# Run tests
|
||||
npm test
|
||||
|
||||
# Run linting
|
||||
npm run lint
|
||||
|
||||
# Format code
|
||||
npm run prettier
|
||||
|
||||
# Clean build artifacts
|
||||
npm run clean
|
||||
```
|
||||
|
||||
### 🔨 Build Commands
|
||||
|
||||
```bash
|
||||
# Development build (no code signing)
|
||||
./scripts/build-moreminimore-app.sh
|
||||
|
||||
# Production build (requires code signing setup)
|
||||
./scripts/build-moreminimore-app.sh --production
|
||||
|
||||
# Clean build artifacts only
|
||||
./scripts/build-moreminimore-app.sh --clean-only
|
||||
|
||||
# Verbose build (for debugging)
|
||||
./scripts/build-moreminimore-app.sh --verbose
|
||||
|
||||
# Fast build (skip dependency install)
|
||||
./scripts/build-moreminimore-app.sh --skip-deps
|
||||
|
||||
# Create distributables
|
||||
npm run make
|
||||
```
|
||||
|
||||
### 🔄 Update Commands
|
||||
|
||||
```bash
|
||||
# Apply custom features and debranding
|
||||
./scripts/update-and-debrand.sh
|
||||
|
||||
# Integrate custom features after upstream update
|
||||
./scripts/integrate-custom-features.sh integrate
|
||||
|
||||
# Validate custom features integration
|
||||
./scripts/integrate-custom-features.sh validate
|
||||
|
||||
# Restore from backup (if needed)
|
||||
./scripts/integrate-custom-features.sh restore backup-YYYYMMDD-HHMMSS
|
||||
```
|
||||
|
||||
### 🧪 Testing Commands
|
||||
|
||||
```bash
|
||||
# Run unit tests
|
||||
npm test
|
||||
|
||||
# Run tests in watch mode
|
||||
npm run test:watch
|
||||
|
||||
# Run tests with UI
|
||||
npm run test:ui
|
||||
|
||||
# Run end-to-end tests
|
||||
npm run e2e
|
||||
|
||||
# Run E2E tests with sharding
|
||||
npm run e2e:shard
|
||||
```
|
||||
|
||||
## 🏗️ Complete Setup Guide
|
||||
|
||||
### Step 1: Clone and Install
|
||||
|
||||
```bash
|
||||
# Clone the repository
|
||||
git clone https://github.com/kunthawat/moreminimore-vibe.git
|
||||
cd moreminimore-vibe
|
||||
|
||||
# Install dependencies
|
||||
npm install
|
||||
|
||||
# Make scripts executable
|
||||
chmod +x scripts/*.sh
|
||||
```
|
||||
|
||||
### Step 2: Apply Custom Features
|
||||
|
||||
```bash
|
||||
# Run the debranding and custom features script
|
||||
./scripts/update-and-debrand.sh
|
||||
```
|
||||
|
||||
This script will:
|
||||
- ✅ Create automatic backup
|
||||
- ✅ Apply remove-limit feature
|
||||
- ✅ Enable smart context for all users
|
||||
- ✅ Remove Dyad branding and dependencies
|
||||
- ✅ Update all branding to MoreMinimore
|
||||
- ✅ Install dependencies and test compilation
|
||||
|
||||
### Step 3: Verify Installation
|
||||
|
||||
```bash
|
||||
# Check TypeScript compilation
|
||||
npm run ts
|
||||
|
||||
# Start the application
|
||||
npm start
|
||||
```
|
||||
|
||||
### Step 4: Test Build (Optional)
|
||||
|
||||
```bash
|
||||
# Test build process
|
||||
./scripts/build-moreminimore-app.sh
|
||||
```
|
||||
|
||||
## 📦 Building for Distribution
|
||||
|
||||
### Development Build (Recommended for Testing)
|
||||
|
||||
```bash
|
||||
./scripts/build-moreminimore-app.sh
|
||||
```
|
||||
|
||||
- **Output**: `out/make/zip/darwin/arm64/moreminimore-darwin-arm64-*.zip`
|
||||
- **Size**: ~180MB
|
||||
- **Code Signing**: Disabled (for development/testing)
|
||||
|
||||
### Production Build (Requires Code Signing)
|
||||
|
||||
```bash
|
||||
# Set up Apple Developer credentials first
|
||||
export APPLE_TEAM_ID="your-apple-developer-team-id"
|
||||
export APPLE_ID="your-apple-id@example.com"
|
||||
export APPLE_PASSWORD="your-app-specific-password"
|
||||
export SM_CODE_SIGNING_CERT_SHA1_HASH="your-certificate-sha1-hash"
|
||||
|
||||
# Build production version
|
||||
./scripts/build-moreminimore-app.sh --production
|
||||
```
|
||||
|
||||
### Build Options
|
||||
|
||||
```bash
|
||||
# Clean build artifacts only
|
||||
./scripts/build-moreminimore-app.sh --clean-only
|
||||
|
||||
# Verbose output for debugging
|
||||
./scripts/build-moreminimore-app.sh --verbose
|
||||
|
||||
# Skip dependency installation
|
||||
./scripts/build-moreminimore-app.sh --skip-deps
|
||||
|
||||
# Show help
|
||||
./scripts/build-moreminimore-app.sh --help
|
||||
```
|
||||
|
||||
## 🔄 Updating from Upstream
|
||||
|
||||
When you want to update MoreMinimore with new features from the original Dyad repository:
|
||||
|
||||
### Step 1: Fetch Latest Changes
|
||||
|
||||
```bash
|
||||
# Add upstream remote (if not already added)
|
||||
git remote add upstream https://github.com/dyad-sh/dyad.git
|
||||
|
||||
# Fetch latest changes
|
||||
git fetch upstream
|
||||
|
||||
# Merge upstream changes
|
||||
git merge upstream/main
|
||||
```
|
||||
|
||||
### Step 2: Re-apply Custom Features
|
||||
|
||||
```bash
|
||||
# Run the update script to re-apply all customizations
|
||||
./scripts/update-and-debrand.sh
|
||||
```
|
||||
|
||||
### Step 3: Integrate Custom Features
|
||||
|
||||
```bash
|
||||
# Integrate custom features with the new codebase
|
||||
./scripts/integrate-custom-features.sh integrate
|
||||
|
||||
# Validate the integration
|
||||
./scripts/integrate-custom-features.sh validate
|
||||
```
|
||||
|
||||
### Step 4: Test and Commit
|
||||
|
||||
```bash
|
||||
# Test the application
|
||||
npm start
|
||||
|
||||
# Test build process
|
||||
./scripts/build-moreminimore-app.sh
|
||||
|
||||
# Commit changes if everything works
|
||||
git add .
|
||||
git commit -m "Update upstream and re-apply custom features"
|
||||
```
|
||||
|
||||
## 🛠️ Custom Features
|
||||
|
||||
### Remove-Limit Feature
|
||||
- **Unlimited usage**: No message limits or restrictions
|
||||
- **Full feature access**: All Pro features available to everyone
|
||||
- **No upgrade prompts**: Clean interface without commercial restrictions
|
||||
|
||||
### Smart Context for All Users
|
||||
- **Advanced context management**: Intelligent handling of long conversations
|
||||
- **Rolling summaries**: Automatic summarization when context exceeds thresholds
|
||||
- **Context caching**: Efficient caching with TTL for better performance
|
||||
- **Snippet importance scoring**: Intelligent ranking of context snippets
|
||||
|
||||
### Enhanced UI/UX
|
||||
- **Clean interface**: No Pro banners or upgrade buttons
|
||||
- **Improved branding**: Complete MoreMinimore branding throughout
|
||||
- **Better organization**: Simplified controls and settings
|
||||
- **Context Settings**: Improved UI for context management
|
||||
|
||||
## 🔧 Configuration
|
||||
|
||||
### Environment Variables (Optional)
|
||||
|
||||
```bash
|
||||
# Set custom gateway URL
|
||||
MOREMINIMORE_GATEWAY_URL=http://localhost:8080/v1 npm start
|
||||
|
||||
# Development mode with debugging
|
||||
DEBUG=* npm start
|
||||
|
||||
# Production mode
|
||||
NODE_ENV=production npm start
|
||||
```
|
||||
|
||||
### Custom Feature Flags
|
||||
|
||||
Edit `src/custom/index.ts` to enable/disable features:
|
||||
|
||||
```typescript
|
||||
export const REMOVE_LIMIT_ENABLED = true;
|
||||
export const SMART_CONTEXT_ENABLED = true;
|
||||
export const ANNOTATOR_ENABLED = true;
|
||||
```
|
||||
|
||||
## 🐛 Troubleshooting
|
||||
|
||||
### Common Issues and Solutions
|
||||
|
||||
#### TypeScript Compilation Errors
|
||||
|
||||
```bash
|
||||
# Check TypeScript compilation
|
||||
npm run ts
|
||||
|
||||
# If errors occur, check specific files
|
||||
npm run ts:main # Main process
|
||||
npm run ts:workers # Worker processes
|
||||
```
|
||||
|
||||
#### Application Won't Start
|
||||
|
||||
```bash
|
||||
# Check dependencies
|
||||
npm install
|
||||
|
||||
# Clean and rebuild
|
||||
npm run clean
|
||||
npm install
|
||||
npm start
|
||||
|
||||
# Check logs for specific errors
|
||||
npm start 2>&1 | tee startup-errors.log
|
||||
```
|
||||
|
||||
#### Build Issues
|
||||
|
||||
```bash
|
||||
# Clean build artifacts
|
||||
./scripts/build-moreminimore-app.sh --clean-only
|
||||
|
||||
# Verbose build for debugging
|
||||
./scripts/build-moreminimore-app.sh --verbose
|
||||
|
||||
# Check Node.js and npm versions
|
||||
node -v
|
||||
npm -v
|
||||
```
|
||||
|
||||
#### Script Permission Issues
|
||||
|
||||
```bash
|
||||
# Make scripts executable
|
||||
chmod +x scripts/*.sh
|
||||
|
||||
# Check script permissions
|
||||
ls -la scripts/
|
||||
```
|
||||
|
||||
#### Integration Issues After Update
|
||||
|
||||
```bash
|
||||
# Validate current integration
|
||||
./scripts/integrate-custom-features.sh validate
|
||||
|
||||
# Restore from backup if needed
|
||||
ls backups/ # Find latest backup
|
||||
./scripts/integrate-custom-features.sh restore backup-YYYYMMDD-HHMMSS
|
||||
|
||||
# Re-run integration
|
||||
./scripts/integrate-custom-features.sh integrate
|
||||
```
|
||||
|
||||
### Recovery Procedures
|
||||
|
||||
#### Restore from Backup
|
||||
|
||||
```bash
|
||||
# Find available backups
|
||||
ls -la backups/
|
||||
|
||||
# Restore from specific backup
|
||||
./scripts/integrate-custom-features.sh restore backup-20231218-154512
|
||||
|
||||
# Verify restoration
|
||||
./scripts/integrate-custom-features.sh validate
|
||||
```
|
||||
|
||||
#### Reset to Clean State
|
||||
|
||||
```bash
|
||||
# Clean all build artifacts
|
||||
npm run clean
|
||||
rm -rf node_modules package-lock.json
|
||||
|
||||
# Reinstall dependencies
|
||||
npm install
|
||||
|
||||
# Re-apply custom features
|
||||
./scripts/update-and-debrand.sh
|
||||
```
|
||||
|
||||
## 📁 Project Structure
|
||||
|
||||
### Important Files and Directories
|
||||
|
||||
```
|
||||
moreminimore-vibe/
|
||||
├── src/ # Source code
|
||||
│ ├── components/ # React components
|
||||
│ ├── ipc/ # IPC handlers and utilities
|
||||
│ ├── pages/ # Application pages
|
||||
│ └── custom/ # Custom feature flags
|
||||
├── scripts/ # Build and utility scripts
|
||||
│ ├── update-and-debrand.sh # Main debranding script
|
||||
│ ├── build-moreminimore-app.sh # Build automation
|
||||
│ └── integrate-custom-features.sh # Feature integration
|
||||
├── assets/ # Static assets (logos, icons)
|
||||
├── out/ # Build output directory
|
||||
└── backups/ # Automatic backups (created as needed)
|
||||
```
|
||||
|
||||
### Key Scripts
|
||||
|
||||
- **`scripts/update-and-debrand.sh`** - Applies all custom features and debranding
|
||||
- **`scripts/build-moreminimore-app.sh`** - Comprehensive build automation
|
||||
- **`scripts/integrate-custom-features.sh`** - Manages custom feature integration
|
||||
|
||||
### Configuration Files
|
||||
|
||||
- **`package.json`** - Project configuration and dependencies
|
||||
- **`src/custom/index.ts`** - Custom feature flags
|
||||
- **`forge.config.ts`** - Electron Forge configuration
|
||||
|
||||
## 🎯 Development Workflow
|
||||
|
||||
### Daily Development
|
||||
|
||||
```bash
|
||||
# 1. Start development server
|
||||
npm start
|
||||
|
||||
# 2. Make changes to code
|
||||
|
||||
# 3. Check TypeScript compilation
|
||||
npm run ts
|
||||
|
||||
# 4. Run tests
|
||||
npm test
|
||||
|
||||
# 5. Format code
|
||||
npm run prettier
|
||||
|
||||
# 6. Test build
|
||||
./scripts/build-moreminimore-app.sh
|
||||
```
|
||||
|
||||
### Before Committing
|
||||
|
||||
```bash
|
||||
# Run all checks
|
||||
npm run presubmit
|
||||
|
||||
# Or run individually
|
||||
npm run prettier:check
|
||||
npm run lint
|
||||
npm run ts
|
||||
npm test
|
||||
```
|
||||
|
||||
### Release Preparation
|
||||
|
||||
```bash
|
||||
# 1. Update version in package.json
|
||||
# 2. Test thoroughly
|
||||
npm test
|
||||
./scripts/build-moreminimore-app.sh
|
||||
|
||||
# 3. Create production build
|
||||
./scripts/build-moreminimore-app.sh --production
|
||||
|
||||
# 4. Verify release assets
|
||||
npm run verify-release
|
||||
```
|
||||
|
||||
## 📚 Advanced Topics
|
||||
|
||||
### Code Signing Setup
|
||||
|
||||
For production builds, set up Apple Developer credentials:
|
||||
|
||||
```bash
|
||||
# Set environment variables
|
||||
export APPLE_TEAM_ID="your-apple-developer-team-id"
|
||||
export APPLE_ID="your-apple-id@example.com"
|
||||
export APPLE_PASSWORD="your-app-specific-password"
|
||||
export SM_CODE_SIGNING_CERT_SHA1_HASH="your-certificate-sha1-hash"
|
||||
|
||||
# Find your Team ID
|
||||
security find-identity -v -p codesigning
|
||||
|
||||
# Generate app-specific password
|
||||
# Visit: https://appleid.apple.com → Security → App-Specific Passwords
|
||||
```
|
||||
|
||||
### Custom Feature Development
|
||||
|
||||
1. **Add feature flag** to `src/custom/index.ts`
|
||||
2. **Implement feature** in appropriate files
|
||||
3. **Update scripts** to apply changes automatically
|
||||
4. **Test thoroughly** with `npm test` and `npm run ts`
|
||||
|
||||
### Database Operations
|
||||
|
||||
```bash
|
||||
# Generate database migrations
|
||||
npm run db:generate
|
||||
|
||||
# Push database changes
|
||||
npm run db:push
|
||||
|
||||
# Open database studio
|
||||
npm run db:studio
|
||||
```
|
||||
|
||||
## 🤝 Contributing
|
||||
|
||||
1. **Fork the repository**
|
||||
2. **Create a feature branch**: `git checkout -b feature-name`
|
||||
3. **Make your changes**
|
||||
4. **Run tests**: `npm test`
|
||||
5. **Check formatting**: `npm run prettier:check`
|
||||
6. **Commit changes**: `git commit -m "Add feature description"`
|
||||
7. **Push to fork**: `git push origin feature-name`
|
||||
8. **Create Pull Request**
|
||||
|
||||
### Contribution Guidelines
|
||||
|
||||
- Ensure no Dyad dependencies are added
|
||||
- Maintain custom features and branding
|
||||
- Update documentation as needed
|
||||
- Test thoroughly before submitting
|
||||
- Follow existing code style and patterns
|
||||
|
||||
## 📄 License
|
||||
|
||||
MIT License — see [LICENSE](./LICENSE).
|
||||
|
||||
## 🔗 Related Resources
|
||||
|
||||
- **GitHub Repository**: https://github.com/kunthawat/moreminimore-vibe
|
||||
- **Issues and Bug Reports**: https://github.com/kunthawat/moreminimore-vibe/issues
|
||||
- **Community**: Join our growing community of AI app builders
|
||||
|
||||
## 🆘 Support
|
||||
|
||||
If you encounter issues:
|
||||
|
||||
1. **Check this README** for troubleshooting steps
|
||||
2. **Review the logs** with `--verbose` flag on scripts
|
||||
3. **Search existing issues** on GitHub
|
||||
4. **Create a new issue** with detailed information
|
||||
5. **Test with clean environment** if needed
|
||||
|
||||
### Getting Help
|
||||
|
||||
For specific issues:
|
||||
|
||||
- **Build problems**: Run `./scripts/build-moreminimore-app.sh --verbose`
|
||||
- **Integration issues**: Run `./scripts/integrate-custom-features.sh validate`
|
||||
- **Application crashes**: Check console logs and `startup-errors.log`
|
||||
- **TypeScript errors**: Run `npm run ts` for specific error details
|
||||
|
||||
---
|
||||
|
||||
**MoreMinimore** is a fork of [Dyad](https://github.com/dyad-sh/dyad) with enhanced features, removed limitations, and complete independence from commercial services. Enjoy building AI applications with full control and no restrictions!
|
||||
|
||||
@@ -6,4 +6,4 @@ We will provide security fixes for the latest version of Dyad and encourage Dyad
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Please file security vulnerabilities by using [report a vulnerability](https://github.com/dyad-sh/dyad/security/advisories/new). Please do not file security vulnerabilities as a regular issue as the information could be used to exploit Dyad users.
|
||||
Please file security vulnerabilities by using [report a vulnerability](https://github.com/kunthawat/moreminimore-vibe/security/advisories/new). Please do not file security vulnerabilities as a regular issue as the information could be used to exploit Dyad users.
|
||||
|
||||
|
Before Width: | Height: | Size: 126 KiB After Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 228 KiB After Width: | Height: | Size: 23 KiB |
BIN
assets/icon/logo_1024x1024.png
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
assets/icon/logo_128x128.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
assets/icon/logo_16x16.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
assets/icon/logo_256x256.png
Normal file
|
After Width: | Height: | Size: 5.6 KiB |
BIN
assets/icon/logo_32x32.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
assets/icon/logo_48x48.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
assets/icon/logo_512x512.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
assets/icon/logo_64x64.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
assets/logo.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 31 KiB |
BIN
assets/moreminimorelogo.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
@@ -14,9 +14,9 @@ If you're not familiar with Electron apps, they are similar to a full-stack Java
|
||||
|
||||
The core workflow of Dyad is that a user sends a prompt to the AI which edits the code and is reflected in the preview. We'll break this down step-by-step.
|
||||
|
||||
1. **Constructing an LLM request** - the LLM request that Dyad sends consists of much more than the prompt (i.e. user input). It includes, by default, the entire codebase as well as a detailed [system prompt](https://github.com/dyad-sh/dyad/blob/main/src/prompts/system_prompt.ts) which gives the LLM instructions to respond in a specific XML-like format (e.g. `<dyad-write path="path/to/file.ts">console.log("hi")</dyad-write>`).
|
||||
2. **Stream the LLM response to the UI** - It's important to provide visual feedback to the user otherwise they're waiting for several minutes without knowing what's happening so we stream the LLM response and show the LLM response. We have a specialized [Markdown parser](https://github.com/dyad-sh/dyad/blob/main/src/components/chat/DyadMarkdownParser.tsx) which parses these `<dyad-*>` tags like the `<dyad-write>` tag shown earlier, so we can display the LLM output in a nice UI rather than just printing out raw XML-like text.
|
||||
3. **Process the LLM response** - Once the LLM response has finished, and the user has approved the changes, the [response processor](https://github.com/dyad-sh/dyad/blob/main/src/ipc/processors/response_processor.ts) in the main process applies these changes. Essentially each `<dyad-*>` tag described in the [system prompt](https://github.com/dyad-sh/dyad/blob/main/src/prompts/system_prompt.ts) maps to specific logic in the response processor, e.g. writing a file, deleting a file, adding a new NPM package, etc.
|
||||
1. **Constructing an LLM request** - the LLM request that Dyad sends consists of much more than the prompt (i.e. user input). It includes, by default, the entire codebase as well as a detailed [system prompt](https://github.com/kunthawat/moreminimore-vibe/blob/main/src/prompts/system_prompt.ts) which gives the LLM instructions to respond in a specific XML-like format (e.g. `<dyad-write path="path/to/file.ts">console.log("hi")</dyad-write>`).
|
||||
2. **Stream the LLM response to the UI** - It's important to provide visual feedback to the user otherwise they're waiting for several minutes without knowing what's happening so we stream the LLM response and show the LLM response. We have a specialized [Markdown parser](https://github.com/kunthawat/moreminimore-vibe/blob/main/src/components/chat/DyadMarkdownParser.tsx) which parses these `<dyad-*>` tags like the `<dyad-write>` tag shown earlier, so we can display the LLM output in a nice UI rather than just printing out raw XML-like text.
|
||||
3. **Process the LLM response** - Once the LLM response has finished, and the user has approved the changes, the [response processor](https://github.com/kunthawat/moreminimore-vibe/blob/main/src/ipc/processors/response_processor.ts) in the main process applies these changes. Essentially each `<dyad-*>` tag described in the [system prompt](https://github.com/kunthawat/moreminimore-vibe/blob/main/src/prompts/system_prompt.ts) maps to specific logic in the response processor, e.g. writing a file, deleting a file, adding a new NPM package, etc.
|
||||
|
||||
To recap, Dyad essentially tells the LLM about a bunch of tools like writing files using the `<dyad-*>` tags, the renderer process displays these Dyad tags in a nice UI and the main process executes these Dyad tags to apply the changes.
|
||||
|
||||
|
||||
@@ -765,3 +765,4 @@
|
||||
"indexes": {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
75
e2e-tests/annotator.spec.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
import { testSkipIfWindows } from "./helpers/test_helper";
|
||||
import { expect } from "@playwright/test";
|
||||
import fs from "fs";
|
||||
|
||||
testSkipIfWindows(
|
||||
"annotator - capture and submit screenshot",
|
||||
async ({ po }) => {
|
||||
await po.setUpDyadPro({ autoApprove: true });
|
||||
|
||||
// Create a basic app
|
||||
await po.sendPrompt("basic");
|
||||
|
||||
// Click the annotator button to activate annotator mode
|
||||
await po.clickPreviewAnnotatorButton();
|
||||
|
||||
// Wait for annotator mode to be active
|
||||
await po.waitForAnnotatorMode();
|
||||
|
||||
// Submit the screenshot to chat
|
||||
await po.clickAnnotatorSubmit();
|
||||
|
||||
await expect(po.getChatInput()).toContainText(
|
||||
"Please update the UI based on these screenshots",
|
||||
);
|
||||
|
||||
// Verify the screenshot was attached to chat context
|
||||
await po.sendPrompt("[dump]");
|
||||
|
||||
// Wait for the LLM response containing the dump path to appear in the UI
|
||||
// before attempting to extract it from the messages list
|
||||
await po.page.waitForSelector("text=/\\[\\[dyad-dump-path=.*\\]\\]/");
|
||||
|
||||
// Get the dump file path from the messages list
|
||||
const messagesListText = await po.page
|
||||
.getByTestId("messages-list")
|
||||
.textContent();
|
||||
const dumpPathMatch = messagesListText?.match(
|
||||
/\[\[dyad-dump-path=([^\]]+)\]\]/,
|
||||
);
|
||||
|
||||
if (!dumpPathMatch) {
|
||||
throw new Error("No dump path found in messages list");
|
||||
}
|
||||
|
||||
const dumpFilePath = dumpPathMatch[1];
|
||||
const dumpContent = fs.readFileSync(dumpFilePath, "utf-8");
|
||||
const parsedDump = JSON.parse(dumpContent);
|
||||
|
||||
// Get the last message from the dump
|
||||
const messages = parsedDump.body.messages;
|
||||
const lastMessage = messages[messages.length - 1];
|
||||
|
||||
expect(lastMessage).toBeTruthy();
|
||||
expect(lastMessage.content).toBeTruthy();
|
||||
|
||||
// The content is an array with text and image parts
|
||||
expect(Array.isArray(lastMessage.content)).toBe(true);
|
||||
|
||||
// Find the text part and verify it mentions the PNG attachment
|
||||
const textPart = lastMessage.content.find(
|
||||
(part: any) => part.type === "text",
|
||||
);
|
||||
expect(textPart).toBeTruthy();
|
||||
expect(textPart.text).toMatch(/annotated-screenshot-.*\.png/);
|
||||
expect(textPart.text).toMatch(/image\/png/);
|
||||
|
||||
// Find the image part and verify it has the correct structure
|
||||
const imagePart = lastMessage.content.find(
|
||||
(part: any) => part.type === "image_url",
|
||||
);
|
||||
expect(imagePart).toBeTruthy();
|
||||
expect(imagePart.image_url).toBeTruthy();
|
||||
expect(imagePart.image_url.url).toMatch(/^data:image\/png;base64,/);
|
||||
},
|
||||
);
|
||||
@@ -1,4 +1,5 @@
|
||||
import { testSkipIfWindows, test } from "./helpers/test_helper";
|
||||
import { expect } from "@playwright/test";
|
||||
|
||||
testSkipIfWindows("fix error with AI", async ({ po }) => {
|
||||
await po.setUp({ autoApprove: true });
|
||||
@@ -20,6 +21,26 @@ testSkipIfWindows("fix error with AI", async ({ po }) => {
|
||||
await po.snapshotPreview();
|
||||
});
|
||||
|
||||
testSkipIfWindows("copy error message from banner", async ({ po }) => {
|
||||
await po.setUp({ autoApprove: true });
|
||||
await po.sendPrompt("tc=create-error");
|
||||
|
||||
await po.page.getByText("Error Line 6 error", { exact: true }).waitFor({
|
||||
state: "visible",
|
||||
});
|
||||
|
||||
await po.clickCopyErrorMessage();
|
||||
|
||||
const clipboardText = await po.getClipboardText();
|
||||
expect(clipboardText).toContain("Error Line 6 error");
|
||||
expect(clipboardText.length).toBeGreaterThan(0);
|
||||
|
||||
await expect(po.page.getByRole("button", { name: "Copied" })).toBeVisible();
|
||||
|
||||
await expect(po.page.getByRole("button", { name: "Copied" })).toBeHidden({
|
||||
timeout: 3000,
|
||||
});
|
||||
});
|
||||
test("fix all errors button", async ({ po }) => {
|
||||
await po.setUp({ autoApprove: true });
|
||||
await po.sendPrompt("tc=create-multiple-errors");
|
||||
|
||||
@@ -2,3 +2,4 @@ Here is a simple response to test the context limit banner functionality.
|
||||
|
||||
This message simulates being close to the model's context window limit.
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ I will intentionally add an error
|
||||
<dyad-write path="src/pages/Index.tsx" description="intentionally add an error">
|
||||
// Update this page (the content is just a fallback if you fail to update the page)
|
||||
|
||||
import { MadeWithDyad } from "@/components/made-with-dyad";
|
||||
|
||||
const Index = () => {
|
||||
throw new Error("Line 6 error");
|
||||
@@ -16,7 +15,6 @@ return (
|
||||
Start building your amazing project here!
|
||||
</p>
|
||||
</div>
|
||||
<MadeWithDyad />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -3,7 +3,6 @@ I will intentionally add multiple errors to test the Fix All Errors button
|
||||
<dyad-write path="src/pages/Index.tsx" description="intentionally add first error">
|
||||
// Update this page (the content is just a fallback if you fail to update the page)
|
||||
|
||||
import { MadeWithDyad } from "@/components/made-with-dyad";
|
||||
|
||||
const Index = () => {
|
||||
throw new Error("First error in Index");
|
||||
@@ -16,7 +15,6 @@ return (
|
||||
Start building your amazing project here!
|
||||
</p>
|
||||
</div>
|
||||
<MadeWithDyad />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
1
e2e-tests/fixtures/engine/1.md
Normal file
@@ -0,0 +1 @@
|
||||
1
|
||||
1
e2e-tests/fixtures/engine/basic.md
Normal file
@@ -0,0 +1 @@
|
||||
This is a simple basic response
|
||||
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 23 KiB |
@@ -341,7 +341,11 @@ export class PageObject {
|
||||
|
||||
async selectChatMode(mode: "build" | "ask" | "agent") {
|
||||
await this.page.getByTestId("chat-mode-selector").click();
|
||||
await this.page.getByRole("option", { name: mode }).click();
|
||||
await this.page
|
||||
.getByRole("option", {
|
||||
name: mode === "agent" ? "Build with MCP (experimental)" : mode,
|
||||
})
|
||||
.click();
|
||||
}
|
||||
|
||||
async openContextFilesPicker() {
|
||||
@@ -553,6 +557,22 @@ export class PageObject {
|
||||
await this.page.getByTestId("preview-open-browser-button").click();
|
||||
}
|
||||
|
||||
async clickPreviewAnnotatorButton() {
|
||||
await this.page
|
||||
.getByTestId("preview-annotator-button")
|
||||
.click({ timeout: Timeout.EXTRA_LONG });
|
||||
}
|
||||
|
||||
async waitForAnnotatorMode() {
|
||||
// Wait for the annotator toolbar to be visible
|
||||
await expect(this.page.getByRole("button", { name: "Select" })).toBeVisible(
|
||||
{ timeout: Timeout.MEDIUM },
|
||||
);
|
||||
}
|
||||
|
||||
async clickAnnotatorSubmit() {
|
||||
await this.page.getByRole("button", { name: "Add to Chat" }).click();
|
||||
}
|
||||
locateLoadingAppPreview() {
|
||||
return this.page.getByText("Preparing app preview...");
|
||||
}
|
||||
@@ -575,6 +595,13 @@ export class PageObject {
|
||||
await this.page.getByRole("button", { name: "Fix error with AI" }).click();
|
||||
}
|
||||
|
||||
async clickCopyErrorMessage() {
|
||||
await this.page.getByRole("button", { name: /Copy/ }).click();
|
||||
}
|
||||
|
||||
async getClipboardText(): Promise<string> {
|
||||
return await this.page.evaluate(() => navigator.clipboard.readText());
|
||||
}
|
||||
async clickFixAllErrors() {
|
||||
await this.page.getByRole("button", { name: /Fix All Errors/ }).click();
|
||||
}
|
||||
|
||||
150
e2e-tests/performance_monitor.spec.ts
Normal file
@@ -0,0 +1,150 @@
|
||||
import { expect } from "@playwright/test";
|
||||
import { Timeout, testWithConfig } from "./helpers/test_helper";
|
||||
import * as fs from "node:fs";
|
||||
import * as path from "node:path";
|
||||
|
||||
testWithConfig({
|
||||
preLaunchHook: async ({ userDataDir }) => {
|
||||
// Set up a force-close scenario by creating settings with isRunning: true
|
||||
// and lastKnownPerformance data
|
||||
const settingsPath = path.join(userDataDir, "user-settings.json");
|
||||
const settings = {
|
||||
hasRunBefore: true,
|
||||
isRunning: true, // Simulate force-close
|
||||
enableAutoUpdate: false,
|
||||
releaseChannel: "stable",
|
||||
lastKnownPerformance: {
|
||||
timestamp: Date.now() - 5000, // 5 seconds ago
|
||||
memoryUsageMB: 256,
|
||||
cpuUsagePercent: 45.5,
|
||||
systemMemoryUsageMB: 8192,
|
||||
systemMemoryTotalMB: 16384,
|
||||
systemMemoryPercent: 50.0,
|
||||
systemCpuPercent: 35.2,
|
||||
},
|
||||
};
|
||||
|
||||
fs.mkdirSync(userDataDir, { recursive: true });
|
||||
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
|
||||
},
|
||||
})(
|
||||
"force-close detection shows dialog with performance data",
|
||||
async ({ po }) => {
|
||||
// Wait for the home page to be visible first
|
||||
await expect(po.getHomeChatInputContainer()).toBeVisible({
|
||||
timeout: Timeout.LONG,
|
||||
});
|
||||
|
||||
// Check if the force-close dialog is visible by looking for the heading
|
||||
await expect(
|
||||
po.page.getByRole("heading", { name: "Force Close Detected" }),
|
||||
).toBeVisible({ timeout: Timeout.MEDIUM });
|
||||
|
||||
// Verify the warning message
|
||||
await expect(
|
||||
po.page.getByText(
|
||||
"The app was not closed properly the last time it was running",
|
||||
),
|
||||
).toBeVisible();
|
||||
|
||||
// Verify performance data is displayed
|
||||
await expect(po.page.getByText("Last Known State:")).toBeVisible();
|
||||
|
||||
// Check Process Metrics section
|
||||
await expect(po.page.getByText("Process Metrics")).toBeVisible();
|
||||
await expect(po.page.getByText("256 MB")).toBeVisible();
|
||||
await expect(po.page.getByText("45.5%")).toBeVisible();
|
||||
|
||||
// Check System Metrics section
|
||||
await expect(po.page.getByText("System Metrics")).toBeVisible();
|
||||
await expect(po.page.getByText("8192 / 16384 MB")).toBeVisible();
|
||||
await expect(po.page.getByText("35.2%")).toBeVisible();
|
||||
|
||||
// Close the dialog
|
||||
await po.page.getByRole("button", { name: "OK" }).click();
|
||||
|
||||
// Verify dialog is closed by checking the heading is no longer visible
|
||||
await expect(
|
||||
po.page.getByRole("heading", { name: "Force Close Detected" }),
|
||||
).not.toBeVisible();
|
||||
},
|
||||
);
|
||||
|
||||
testWithConfig({
|
||||
preLaunchHook: async ({ userDataDir }) => {
|
||||
// Set up scenario without force-close (proper shutdown)
|
||||
const settingsPath = path.join(userDataDir, "user-settings.json");
|
||||
const settings = {
|
||||
hasRunBefore: true,
|
||||
isRunning: false, // Proper shutdown - no force-close
|
||||
enableAutoUpdate: false,
|
||||
releaseChannel: "stable",
|
||||
lastKnownPerformance: {
|
||||
timestamp: Date.now() - 5000,
|
||||
memoryUsageMB: 256,
|
||||
cpuUsagePercent: 45.5,
|
||||
systemMemoryUsageMB: 8192,
|
||||
systemMemoryTotalMB: 16384,
|
||||
systemMemoryPercent: 50.0,
|
||||
systemCpuPercent: 35.2,
|
||||
},
|
||||
};
|
||||
|
||||
fs.mkdirSync(userDataDir, { recursive: true });
|
||||
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
|
||||
},
|
||||
})("no force-close dialog when app was properly shut down", async ({ po }) => {
|
||||
// Verify the home page loaded normally
|
||||
await expect(po.getHomeChatInputContainer()).toBeVisible({
|
||||
timeout: Timeout.LONG,
|
||||
});
|
||||
|
||||
// Verify that the force-close dialog is NOT shown
|
||||
await expect(
|
||||
po.page.getByRole("heading", { name: "Force Close Detected" }),
|
||||
).not.toBeVisible();
|
||||
});
|
||||
|
||||
testWithConfig({})(
|
||||
"performance information is being captured during normal operation",
|
||||
async ({ po, electronApp }) => {
|
||||
// Wait for the app to load
|
||||
await expect(po.getHomeChatInputContainer()).toBeVisible({
|
||||
timeout: Timeout.LONG,
|
||||
});
|
||||
|
||||
// Get the user data directory
|
||||
const userDataDir = (electronApp as any).$dyadUserDataDir;
|
||||
const settingsPath = path.join(userDataDir, "user-settings.json");
|
||||
|
||||
// Wait a bit to allow performance monitoring to capture at least one data point
|
||||
// Performance monitoring runs every 30 seconds, but we'll wait 35 seconds to be safe
|
||||
await po.page.waitForTimeout(35000);
|
||||
|
||||
// Read the settings file
|
||||
const settingsContent = fs.readFileSync(settingsPath, "utf-8");
|
||||
const settings = JSON.parse(settingsContent);
|
||||
|
||||
// Verify that lastKnownPerformance exists and has all required fields
|
||||
expect(settings.lastKnownPerformance).toBeDefined();
|
||||
expect(settings.lastKnownPerformance.timestamp).toBeGreaterThan(0);
|
||||
expect(settings.lastKnownPerformance.memoryUsageMB).toBeGreaterThan(0);
|
||||
expect(
|
||||
settings.lastKnownPerformance.cpuUsagePercent,
|
||||
).toBeGreaterThanOrEqual(0);
|
||||
expect(settings.lastKnownPerformance.systemMemoryUsageMB).toBeGreaterThan(
|
||||
0,
|
||||
);
|
||||
expect(settings.lastKnownPerformance.systemMemoryTotalMB).toBeGreaterThan(
|
||||
0,
|
||||
);
|
||||
expect(
|
||||
settings.lastKnownPerformance.systemCpuPercent,
|
||||
).toBeGreaterThanOrEqual(0);
|
||||
|
||||
// Verify the timestamp is recent (within the last minute)
|
||||
const now = Date.now();
|
||||
const timeDiff = now - settings.lastKnownPerformance.timestamp;
|
||||
expect(timeDiff).toBeLessThan(60000); // Less than 1 minute old
|
||||
},
|
||||
);
|
||||
15
e2e-tests/smart_context_balanced.spec.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { testSkipIfWindows } from "./helpers/test_helper";
|
||||
|
||||
testSkipIfWindows("smart context balanced - simple", async ({ po }) => {
|
||||
await po.setUpDyadPro({ autoApprove: true });
|
||||
const proModesDialog = await po.openProModesDialog({
|
||||
location: "home-chat-input-container",
|
||||
});
|
||||
await proModesDialog.setSmartContextMode("balanced");
|
||||
await proModesDialog.close();
|
||||
|
||||
await po.sendPrompt("[dump]");
|
||||
|
||||
await po.snapshotServerDump("request");
|
||||
await po.snapshotMessages({ replaceDumpPath: true });
|
||||
});
|
||||
@@ -16,5 +16,6 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": false,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -16,5 +16,6 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -2276,7 +2276,6 @@ export default App;
|
||||
"@radix-ui/react-toast": "^1.2.1",
|
||||
"@radix-ui/react-toggle": "^1.1.0",
|
||||
"@radix-ui/react-toggle-group": "^1.1.0",
|
||||
"@radix-ui/react-tooltip": "^1.1.4",
|
||||
"@radix-ui/react-tooltip": "^1.1.4",
|
||||
"@tanstack/react-query": "^5.56.2",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
@@ -7549,7 +7548,6 @@ createRoot(document.getElementById("root")!).render(<App />);
|
||||
}
|
||||
|
||||
const toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>();
|
||||
|
||||
|
||||
const addToRemoveQueue = (toastId: string) => {
|
||||
if (toastTimeouts.has(toastId)) {
|
||||
@@ -7560,7 +7558,6 @@ const Index = () => {
|
||||
toastTimeouts.delete(toastId);
|
||||
dispatch({
|
||||
type: "REMOVE_TOAST",
|
||||
});
|
||||
toastId: toastId,
|
||||
});
|
||||
}, TOAST_REMOVE_DELAY);
|
||||
|
||||
@@ -244,7 +244,6 @@ export default App;
|
||||
</dyad-file>
|
||||
|
||||
<dyad-file path="src/components/made-with-dyad.tsx">
|
||||
export const MadeWithDyad = () => {
|
||||
return (
|
||||
<div className="p-4 text-center">
|
||||
<a
|
||||
@@ -801,7 +800,6 @@ createRoot(document.getElementById("root")!).render(<App />);
|
||||
<dyad-file path="src/pages/Index.tsx">
|
||||
// Update this page (the content is just a fallback if you fail to update the page)
|
||||
|
||||
import { MadeWithDyad } from "@/components/made-with-dyad";
|
||||
|
||||
const Index = () => {
|
||||
return (
|
||||
@@ -812,7 +810,6 @@ const Index = () => {
|
||||
Start building your amazing project here!
|
||||
</p>
|
||||
</div>
|
||||
<MadeWithDyad />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -244,7 +244,6 @@ export default App;
|
||||
</dyad-file>
|
||||
|
||||
<dyad-file path="src/components/made-with-dyad.tsx">
|
||||
export const MadeWithDyad = () => {
|
||||
return (
|
||||
<div className="p-4 text-center">
|
||||
<a
|
||||
@@ -801,7 +800,6 @@ createRoot(document.getElementById("root")!).render(<App />);
|
||||
<dyad-file path="src/pages/Index.tsx">
|
||||
// Update this page (the content is just a fallback if you fail to update the page)
|
||||
|
||||
import { MadeWithDyad } from "@/components/made-with-dyad";
|
||||
|
||||
const Index = () => {
|
||||
return (
|
||||
@@ -812,7 +810,6 @@ const Index = () => {
|
||||
Start building your amazing project here!
|
||||
</p>
|
||||
</div>
|
||||
<MadeWithDyad />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -244,7 +244,6 @@ export default App;
|
||||
</dyad-file>
|
||||
|
||||
<dyad-file path="src/components/made-with-dyad.tsx">
|
||||
export const MadeWithDyad = () => {
|
||||
return (
|
||||
<div className="p-4 text-center">
|
||||
<a
|
||||
@@ -801,7 +800,6 @@ createRoot(document.getElementById("root")!).render(<App />);
|
||||
<dyad-file path="src/pages/Index.tsx">
|
||||
// Update this page (the content is just a fallback if you fail to update the page)
|
||||
|
||||
import { MadeWithDyad } from "@/components/made-with-dyad";
|
||||
|
||||
const Index = () => {
|
||||
return (
|
||||
@@ -812,7 +810,6 @@ const Index = () => {
|
||||
Start building your amazing project here!
|
||||
</p>
|
||||
</div>
|
||||
<MadeWithDyad />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -18,5 +18,6 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -244,7 +244,6 @@ export default App;
|
||||
</dyad-file>
|
||||
|
||||
<dyad-file path="src/components/made-with-dyad.tsx">
|
||||
export const MadeWithDyad = () => {
|
||||
return (
|
||||
<div className="p-4 text-center">
|
||||
<a
|
||||
@@ -801,7 +800,6 @@ createRoot(document.getElementById("root")!).render(<App />);
|
||||
<dyad-file path="src/pages/Index.tsx">
|
||||
// Update this page (the content is just a fallback if you fail to update the page)
|
||||
|
||||
import { MadeWithDyad } from "@/components/made-with-dyad";
|
||||
|
||||
const Index = () => {
|
||||
return (
|
||||
@@ -812,7 +810,6 @@ const Index = () => {
|
||||
Start building your amazing project here!
|
||||
</p>
|
||||
</div>
|
||||
<MadeWithDyad />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -319,7 +319,6 @@ export default App;
|
||||
|
||||
|
||||
=== src/components/made-with-dyad.tsx ===
|
||||
export const MadeWithDyad = () => {
|
||||
return (
|
||||
<div className="p-4 text-center">
|
||||
<a
|
||||
@@ -5592,7 +5591,6 @@ createRoot(document.getElementById("root")!).render(<App />);
|
||||
=== src/pages/Index.tsx ===
|
||||
// Update this page (the content is just a fallback if you fail to update the page)
|
||||
|
||||
import { MadeWithDyad } from "@/components/made-with-dyad";
|
||||
|
||||
const Index = () => {
|
||||
return (
|
||||
@@ -5603,7 +5601,6 @@ const Index = () => {
|
||||
Start building your amazing project here!
|
||||
</p>
|
||||
</div>
|
||||
<MadeWithDyad />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -244,7 +244,6 @@ export default App;
|
||||
</dyad-file>
|
||||
|
||||
<dyad-file path="src/components/made-with-dyad.tsx">
|
||||
export const MadeWithDyad = () => {
|
||||
return (
|
||||
<div className="p-4 text-center">
|
||||
<a
|
||||
@@ -801,7 +800,6 @@ createRoot(document.getElementById("root")!).render(<App />);
|
||||
<dyad-file path="src/pages/Index.tsx">
|
||||
// Update this page (the content is just a fallback if you fail to update the page)
|
||||
|
||||
import { MadeWithDyad } from "@/components/made-with-dyad";
|
||||
|
||||
const Index = () => {
|
||||
return (
|
||||
@@ -812,7 +810,6 @@ const Index = () => {
|
||||
Start building your amazing project here!
|
||||
</p>
|
||||
</div>
|
||||
<MadeWithDyad />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -316,7 +316,6 @@ export default App;
|
||||
|
||||
|
||||
=== src/components/made-with-dyad.tsx ===
|
||||
export const MadeWithDyad = ; href="https://www.dyad.sh/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-sm text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200"
|
||||
@@ -5585,7 +5584,6 @@ createRoot(document.getElementById("root")!).render(<App />);
|
||||
=== src/pages/Index.tsx ===
|
||||
// Update this page (the content is just a fallback if you fail to update the page)
|
||||
|
||||
import { MadeWithDyad } from "@/components/made-with-dyad";
|
||||
|
||||
const Index = () => {
|
||||
return (
|
||||
@@ -5596,7 +5594,6 @@ const Index = () => {
|
||||
Start building your amazing project here!
|
||||
</p>
|
||||
</div>
|
||||
<MadeWithDyad />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -88,7 +88,6 @@
|
||||
},
|
||||
{
|
||||
"path": "src/components/made-with-dyad.tsx",
|
||||
"content": "export const MadeWithDyad = () => {\n return (\n <div className=\"p-4 text-center\">\n <a\n href=\"https://www.dyad.sh/\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-sm text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200\"\n >\n Made with Dyad\n </a>\n </div>\n );\n};\n",
|
||||
"force": false
|
||||
},
|
||||
{
|
||||
@@ -363,7 +362,6 @@
|
||||
},
|
||||
{
|
||||
"path": "src/pages/Index.tsx",
|
||||
"content": "// Update this page (the content is just a fallback if you fail to update the page)\n\nimport { MadeWithDyad } from \"@/components/made-with-dyad\";\n\nconst Index = () => {\n return (\n <div className=\"min-h-screen flex items-center justify-center bg-gray-100\">\n <div className=\"text-center\">\n <h1 className=\"text-4xl font-bold mb-4\">Welcome to Your Blank App</h1>\n <p className=\"text-xl text-gray-600\">\n Start building your amazing project here!\n </p>\n </div>\n <MadeWithDyad />\n </div>\n );\n};\n\nexport default Index;\n",
|
||||
"force": false
|
||||
},
|
||||
{
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
"5f1387ce504f44bce8e80b0f29e6aee60c3e8227c70db37231ad0dadb0117fe0": "# Welcome to your Dyad app\n",
|
||||
"a0715e0a09edbd0fbde65816a75e0fa0fc8b314c5260c0768c19bf3aac22621a": "#root {\n max-width: 1280px;\n margin: 0 auto;\n padding: 2rem;\n text-align: center;\n}\n\n.logo {\n height: 6em;\n padding: 1.5em;\n will-change: filter;\n transition: filter 300ms;\n}\n.logo:hover {\n filter: drop-shadow(0 0 2em #646cffaa);\n}\n.logo.react:hover {\n filter: drop-shadow(0 0 2em #61dafbaa);\n}\n\n@keyframes logo-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n\n@media (prefers-reduced-motion: no-preference) {\n a:nth-of-type(2) .logo {\n animation: logo-spin infinite 20s linear;\n }\n}\n\n.card {\n padding: 2em;\n}\n\n.read-the-docs {\n color: #888;\n}\n",
|
||||
"4e69ef9f71a824d0a6b0965300a4738f34e54a39d58433104162a61b6d072d49": "import { Toaster } from \"@/components/ui/toaster\";\nimport { Toaster as Sonner } from \"@/components/ui/sonner\";\nimport { TooltipProvider } from \"@/components/ui/tooltip\";\nimport { QueryClient, QueryClientProvider } from \"@tanstack/react-query\";\nimport { BrowserRouter, Routes, Route } from \"react-router-dom\";\nimport Index from \"./pages/Index\";\nimport NotFound from \"./pages/NotFound\";\n\nconst queryClient = new QueryClient();\n\nconst App = () => (\n <QueryClientProvider client={queryClient}>\n <TooltipProvider>\n <Toaster />\n <Sonner />\n <BrowserRouter>\n <Routes>\n <Route path=\"/\" element={<Index />} />\n {/* ADD ALL CUSTOM ROUTES ABOVE THE CATCH-ALL \"*\" ROUTE */}\n <Route path=\"*\" element={<NotFound />} />\n </Routes>\n </BrowserRouter>\n </TooltipProvider>\n </QueryClientProvider>\n);\n\nexport default App;\n",
|
||||
"b8d3ed0643f99b45851f98668e6ca4163004a878967abd283373393753c26666": "export const MadeWithDyad = () => {\n return (\n <div className=\"p-4 text-center\">\n <a\n href=\"https://www.dyad.sh/\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-sm text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200\"\n >\n Made with Dyad\n </a>\n </div>\n );\n};\n",
|
||||
"b728b30af5d9f770a34d5b4ae85ea720c90664fa55d83ad3d9835f48f20f5846": "import * as React from \"react\";\nimport * as AccordionPrimitive from \"@radix-ui/react-accordion\";\nimport { ChevronDown } from \"lucide-react\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst Accordion = AccordionPrimitive.Root;\n\nconst AccordionItem = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>\n>(({ className, ...props }, ref) => (\n <AccordionPrimitive.Item\n ref={ref}\n className={cn(\"border-b\", className)}\n {...props}\n />\n));\nAccordionItem.displayName = \"AccordionItem\";\n\nconst AccordionTrigger = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>\n>(({ className, children, ...props }, ref) => (\n <AccordionPrimitive.Header className=\"flex\">\n <AccordionPrimitive.Trigger\n ref={ref}\n className={cn(\n \"flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180\",\n className,\n )}\n {...props}\n >\n {children}\n <ChevronDown className=\"h-4 w-4 shrink-0 transition-transform duration-200\" />\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n));\nAccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;\n\nconst AccordionContent = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>\n>(({ className, children, ...props }, ref) => (\n <AccordionPrimitive.Content\n ref={ref}\n className=\"overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down\"\n {...props}\n >\n <div className={cn(\"pb-4 pt-0\", className)}>{children}</div>\n </AccordionPrimitive.Content>\n));\n\nAccordionContent.displayName = AccordionPrimitive.Content.displayName;\n\nexport { Accordion, AccordionItem, AccordionTrigger, AccordionContent };\n",
|
||||
"6f5d2b743e097cc0f38a8201fc9472bbcffa7ef80653eb09ac1733f470dd675c": "import * as React from \"react\";\nimport * as AlertDialogPrimitive from \"@radix-ui/react-alert-dialog\";\n\nimport { cn } from \"@/lib/utils\";\nimport { buttonVariants } from \"@/components/ui/button\";\n\nconst AlertDialog = AlertDialogPrimitive.Root;\n\nconst AlertDialogTrigger = AlertDialogPrimitive.Trigger;\n\nconst AlertDialogPortal = AlertDialogPrimitive.Portal;\n\nconst AlertDialogOverlay = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Overlay>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Overlay\n className={cn(\n \"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n className,\n )}\n {...props}\n ref={ref}\n />\n));\nAlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;\n\nconst AlertDialogContent = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content>\n>(({ className, ...props }, ref) => (\n <AlertDialogPortal>\n <AlertDialogOverlay />\n <AlertDialogPrimitive.Content\n ref={ref}\n className={cn(\n \"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg\",\n className,\n )}\n {...props}\n />\n </AlertDialogPortal>\n));\nAlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;\n\nconst AlertDialogHeader = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n \"flex flex-col space-y-2 text-center sm:text-left\",\n className,\n )}\n {...props}\n />\n);\nAlertDialogHeader.displayName = \"AlertDialogHeader\";\n\nconst AlertDialogFooter = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n \"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2\",\n className,\n )}\n {...props}\n />\n);\nAlertDialogFooter.displayName = \"AlertDialogFooter\";\n\nconst AlertDialogTitle = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Title>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Title\n ref={ref}\n className={cn(\"text-lg font-semibold\", className)}\n {...props}\n />\n));\nAlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;\n\nconst AlertDialogDescription = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Description>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Description\n ref={ref}\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n));\nAlertDialogDescription.displayName =\n AlertDialogPrimitive.Description.displayName;\n\nconst AlertDialogAction = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Action>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Action\n ref={ref}\n className={cn(buttonVariants(), className)}\n {...props}\n />\n));\nAlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName;\n\nconst AlertDialogCancel = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Cancel>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Cancel\n ref={ref}\n className={cn(\n buttonVariants({ variant: \"outline\" }),\n \"mt-2 sm:mt-0\",\n className,\n )}\n {...props}\n />\n));\nAlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName;\n\nexport {\n AlertDialog,\n AlertDialogPortal,\n AlertDialogOverlay,\n AlertDialogTrigger,\n AlertDialogContent,\n AlertDialogHeader,\n AlertDialogFooter,\n AlertDialogTitle,\n AlertDialogDescription,\n AlertDialogAction,\n AlertDialogCancel,\n};\n",
|
||||
"050c08a3ec850a8fae8579b2bdbb4c9b8aa64744b580f07e2b26f7e6fc17dac0": "import * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst alertVariants = cva(\n \"relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground\",\n {\n variants: {\n variant: {\n default: \"bg-background text-foreground\",\n destructive:\n \"border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n },\n);\n\nconst Alert = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>\n>(({ className, variant, ...props }, ref) => (\n <div\n ref={ref}\n role=\"alert\"\n className={cn(alertVariants({ variant }), className)}\n {...props}\n />\n));\nAlert.displayName = \"Alert\";\n\nconst AlertTitle = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLHeadingElement>\n>(({ className, ...props }, ref) => (\n <h5\n ref={ref}\n className={cn(\"mb-1 font-medium leading-none tracking-tight\", className)}\n {...props}\n />\n));\nAlertTitle.displayName = \"AlertTitle\";\n\nconst AlertDescription = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\"text-sm [&_p]:leading-relaxed\", className)}\n {...props}\n />\n));\nAlertDescription.displayName = \"AlertDescription\";\n\nexport { Alert, AlertTitle, AlertDescription };\n",
|
||||
@@ -83,7 +82,6 @@
|
||||
"4b70ac2ad6f1c640249bb43667f86d8447985c49be8bd0335897ad0ae7c70694": "import * as React from \"react\";\n\nimport type { ToastActionElement, ToastProps } from \"@/components/ui/toast\";\n\nconst TOAST_LIMIT = 1;\nconst TOAST_REMOVE_DELAY = 1000000;\n\ntype ToasterToast = ToastProps & {\n id: string;\n title?: React.ReactNode;\n description?: React.ReactNode;\n action?: ToastActionElement;\n};\n\nconst _actionTypes = {\n ADD_TOAST: \"ADD_TOAST\",\n UPDATE_TOAST: \"UPDATE_TOAST\",\n DISMISS_TOAST: \"DISMISS_TOAST\",\n REMOVE_TOAST: \"REMOVE_TOAST\",\n} as const;\n\nlet count = 0;\n\nfunction genId() {\n count = (count + 1) % Number.MAX_SAFE_INTEGER;\n return count.toString();\n}\n\ntype ActionType = typeof _actionTypes;\n\ntype Action =\n | {\n type: ActionType[\"ADD_TOAST\"];\n toast: ToasterToast;\n }\n | {\n type: ActionType[\"UPDATE_TOAST\"];\n toast: Partial<ToasterToast>;\n }\n | {\n type: ActionType[\"DISMISS_TOAST\"];\n toastId?: ToasterToast[\"id\"];\n }\n | {\n type: ActionType[\"REMOVE_TOAST\"];\n toastId?: ToasterToast[\"id\"];\n };\n\ninterface State {\n toasts: ToasterToast[];\n}\n\nconst toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>();\n\nconst addToRemoveQueue = (toastId: string) => {\n if (toastTimeouts.has(toastId)) {\n return;\n }\n\n const timeout = setTimeout(() => {\n toastTimeouts.delete(toastId);\n dispatch({\n type: \"REMOVE_TOAST\",\n toastId: toastId,\n });\n }, TOAST_REMOVE_DELAY);\n\n toastTimeouts.set(toastId, timeout);\n};\n\nexport const reducer = (state: State, action: Action): State => {\n switch (action.type) {\n case \"ADD_TOAST\":\n return {\n ...state,\n toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),\n };\n\n case \"UPDATE_TOAST\":\n return {\n ...state,\n toasts: state.toasts.map((t) =>\n t.id === action.toast.id ? { ...t, ...action.toast } : t,\n ),\n };\n\n case \"DISMISS_TOAST\": {\n const { toastId } = action;\n\n // ! Side effects ! - This could be extracted into a dismissToast() action,\n // but I'll keep it here for simplicity\n if (toastId) {\n addToRemoveQueue(toastId);\n } else {\n state.toasts.forEach((toast) => {\n addToRemoveQueue(toast.id);\n });\n }\n\n return {\n ...state,\n toasts: state.toasts.map((t) =>\n t.id === toastId || toastId === undefined\n ? {\n ...t,\n open: false,\n }\n : t,\n ),\n };\n }\n case \"REMOVE_TOAST\":\n if (action.toastId === undefined) {\n return {\n ...state,\n toasts: [],\n };\n }\n return {\n ...state,\n toasts: state.toasts.filter((t) => t.id !== action.toastId),\n };\n }\n};\n\nconst listeners: Array<(state: State) => void> = [];\n\nlet memoryState: State = { toasts: [] };\n\nfunction dispatch(action: Action) {\n memoryState = reducer(memoryState, action);\n listeners.forEach((listener) => {\n listener(memoryState);\n });\n}\n\ntype Toast = Omit<ToasterToast, \"id\">;\n\nfunction toast({ ...props }: Toast) {\n const id = genId();\n\n const update = (props: ToasterToast) =>\n dispatch({\n type: \"UPDATE_TOAST\",\n toast: { ...props, id },\n });\n const dismiss = () => dispatch({ type: \"DISMISS_TOAST\", toastId: id });\n\n dispatch({\n type: \"ADD_TOAST\",\n toast: {\n ...props,\n id,\n open: true,\n onOpenChange: (open) => {\n if (!open) dismiss();\n },\n },\n });\n\n return {\n id: id,\n dismiss,\n update,\n };\n}\n\nfunction useToast() {\n const [state, setState] = React.useState<State>(memoryState);\n\n React.useEffect(() => {\n listeners.push(setState);\n return () => {\n const index = listeners.indexOf(setState);\n if (index > -1) {\n listeners.splice(index, 1);\n }\n };\n }, [state]);\n\n return {\n ...state,\n toast,\n dismiss: (toastId?: string) => dispatch({ type: \"DISMISS_TOAST\", toastId }),\n };\n}\n\nexport { useToast, toast };\n",
|
||||
"d1f1e0d62cb8d8d1e04c26e14de842d8a151f75812d81b046c65b5d1fe8e4b27": "import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n",
|
||||
"5cbfd5e41e9218faa071fd97a799497ba5e31423f3a38d4d16adae98a11b80a4": "import { createRoot } from \"react-dom/client\";\nimport App from \"./App.tsx\";\nimport \"./globals.css\";\n\ncreateRoot(document.getElementById(\"root\")!).render(<App />);\n",
|
||||
"70618b5f415d91c92bef86039e35d5f282e959276bf49ed204c9f78f7490c99c": "// Update this page (the content is just a fallback if you fail to update the page)\n\nimport { MadeWithDyad } from \"@/components/made-with-dyad\";\n\nconst Index = () => {\n return (\n <div className=\"min-h-screen flex items-center justify-center bg-gray-100\">\n <div className=\"text-center\">\n <h1 className=\"text-4xl font-bold mb-4\">Welcome to Your Blank App</h1>\n <p className=\"text-xl text-gray-600\">\n Start building your amazing project here!\n </p>\n </div>\n <MadeWithDyad />\n </div>\n );\n};\n\nexport default Index;\n",
|
||||
"940578bf01ac3dbdcb16f52528bd59903b2cce7698c8b39064f2791022567b0e": "import { useLocation } from \"react-router-dom\";\nimport { useEffect } from \"react\";\n\nconst NotFound = () => {\n const location = useLocation();\n\n useEffect(() => {\n console.error(\n \"404 Error: User attempted to access non-existent route:\",\n location.pathname,\n );\n }, [location.pathname]);\n\n return (\n <div className=\"min-h-screen flex items-center justify-center bg-gray-100\">\n <div className=\"text-center\">\n <h1 className=\"text-4xl font-bold mb-4\">404</h1>\n <p className=\"text-xl text-gray-600 mb-4\">Oops! Page not found</p>\n <a href=\"/\" className=\"text-blue-500 hover:text-blue-700 underline\">\n Return to Home\n </a>\n </div>\n </div>\n );\n};\n\nexport default NotFound;\n",
|
||||
"328f94e9c711410b23188484a0a2f38886d7732d5c375cefcba442ab6195783f": "import { toast } from \"sonner\";\n\nexport const showSuccess = (message: string) => {\n toast.success(message);\n};\n\nexport const showError = (message: string) => {\n toast.error(message);\n};\n\nexport const showLoading = (message: string) => {\n return toast.loading(message);\n};\n\nexport const dismissToast = (toastId: string) => {\n toast.dismiss(toastId);\n};\n",
|
||||
"65996936fbb042915f7b74a200fcdde7e410f32a669b1ab9597cfaa4b0faddb5": "/// <reference types=\"vite/client\" />\n",
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
"5f1387ce504f44bce8e80b0f29e6aee60c3e8227c70db37231ad0dadb0117fe0": "# Welcome to your Dyad app\n",
|
||||
"a0715e0a09edbd0fbde65816a75e0fa0fc8b314c5260c0768c19bf3aac22621a": "#root {\n max-width: 1280px;\n margin: 0 auto;\n padding: 2rem;\n text-align: center;\n}\n\n.logo {\n height: 6em;\n padding: 1.5em;\n will-change: filter;\n transition: filter 300ms;\n}\n.logo:hover {\n filter: drop-shadow(0 0 2em #646cffaa);\n}\n.logo.react:hover {\n filter: drop-shadow(0 0 2em #61dafbaa);\n}\n\n@keyframes logo-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n\n@media (prefers-reduced-motion: no-preference) {\n a:nth-of-type(2) .logo {\n animation: logo-spin infinite 20s linear;\n }\n}\n\n.card {\n padding: 2em;\n}\n\n.read-the-docs {\n color: #888;\n}\n",
|
||||
"4e69ef9f71a824d0a6b0965300a4738f34e54a39d58433104162a61b6d072d49": "import { Toaster } from \"@/components/ui/toaster\";\nimport { Toaster as Sonner } from \"@/components/ui/sonner\";\nimport { TooltipProvider } from \"@/components/ui/tooltip\";\nimport { QueryClient, QueryClientProvider } from \"@tanstack/react-query\";\nimport { BrowserRouter, Routes, Route } from \"react-router-dom\";\nimport Index from \"./pages/Index\";\nimport NotFound from \"./pages/NotFound\";\n\nconst queryClient = new QueryClient();\n\nconst App = () => (\n <QueryClientProvider client={queryClient}>\n <TooltipProvider>\n <Toaster />\n <Sonner />\n <BrowserRouter>\n <Routes>\n <Route path=\"/\" element={<Index />} />\n {/* ADD ALL CUSTOM ROUTES ABOVE THE CATCH-ALL \"*\" ROUTE */}\n <Route path=\"*\" element={<NotFound />} />\n </Routes>\n </BrowserRouter>\n </TooltipProvider>\n </QueryClientProvider>\n);\n\nexport default App;\n",
|
||||
"b8d3ed0643f99b45851f98668e6ca4163004a878967abd283373393753c26666": "export const MadeWithDyad = () => {\n return (\n <div className=\"p-4 text-center\">\n <a\n href=\"https://www.dyad.sh/\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-sm text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200\"\n >\n Made with Dyad\n </a>\n </div>\n );\n};\n",
|
||||
"b728b30af5d9f770a34d5b4ae85ea720c90664fa55d83ad3d9835f48f20f5846": "import * as React from \"react\";\nimport * as AccordionPrimitive from \"@radix-ui/react-accordion\";\nimport { ChevronDown } from \"lucide-react\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst Accordion = AccordionPrimitive.Root;\n\nconst AccordionItem = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>\n>(({ className, ...props }, ref) => (\n <AccordionPrimitive.Item\n ref={ref}\n className={cn(\"border-b\", className)}\n {...props}\n />\n));\nAccordionItem.displayName = \"AccordionItem\";\n\nconst AccordionTrigger = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>\n>(({ className, children, ...props }, ref) => (\n <AccordionPrimitive.Header className=\"flex\">\n <AccordionPrimitive.Trigger\n ref={ref}\n className={cn(\n \"flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180\",\n className,\n )}\n {...props}\n >\n {children}\n <ChevronDown className=\"h-4 w-4 shrink-0 transition-transform duration-200\" />\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n));\nAccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;\n\nconst AccordionContent = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>\n>(({ className, children, ...props }, ref) => (\n <AccordionPrimitive.Content\n ref={ref}\n className=\"overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down\"\n {...props}\n >\n <div className={cn(\"pb-4 pt-0\", className)}>{children}</div>\n </AccordionPrimitive.Content>\n));\n\nAccordionContent.displayName = AccordionPrimitive.Content.displayName;\n\nexport { Accordion, AccordionItem, AccordionTrigger, AccordionContent };\n",
|
||||
"6f5d2b743e097cc0f38a8201fc9472bbcffa7ef80653eb09ac1733f470dd675c": "import * as React from \"react\";\nimport * as AlertDialogPrimitive from \"@radix-ui/react-alert-dialog\";\n\nimport { cn } from \"@/lib/utils\";\nimport { buttonVariants } from \"@/components/ui/button\";\n\nconst AlertDialog = AlertDialogPrimitive.Root;\n\nconst AlertDialogTrigger = AlertDialogPrimitive.Trigger;\n\nconst AlertDialogPortal = AlertDialogPrimitive.Portal;\n\nconst AlertDialogOverlay = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Overlay>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Overlay\n className={cn(\n \"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n className,\n )}\n {...props}\n ref={ref}\n />\n));\nAlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;\n\nconst AlertDialogContent = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content>\n>(({ className, ...props }, ref) => (\n <AlertDialogPortal>\n <AlertDialogOverlay />\n <AlertDialogPrimitive.Content\n ref={ref}\n className={cn(\n \"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg\",\n className,\n )}\n {...props}\n />\n </AlertDialogPortal>\n));\nAlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;\n\nconst AlertDialogHeader = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n \"flex flex-col space-y-2 text-center sm:text-left\",\n className,\n )}\n {...props}\n />\n);\nAlertDialogHeader.displayName = \"AlertDialogHeader\";\n\nconst AlertDialogFooter = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n \"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2\",\n className,\n )}\n {...props}\n />\n);\nAlertDialogFooter.displayName = \"AlertDialogFooter\";\n\nconst AlertDialogTitle = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Title>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Title\n ref={ref}\n className={cn(\"text-lg font-semibold\", className)}\n {...props}\n />\n));\nAlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;\n\nconst AlertDialogDescription = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Description>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Description\n ref={ref}\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n));\nAlertDialogDescription.displayName =\n AlertDialogPrimitive.Description.displayName;\n\nconst AlertDialogAction = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Action>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Action\n ref={ref}\n className={cn(buttonVariants(), className)}\n {...props}\n />\n));\nAlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName;\n\nconst AlertDialogCancel = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Cancel>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Cancel\n ref={ref}\n className={cn(\n buttonVariants({ variant: \"outline\" }),\n \"mt-2 sm:mt-0\",\n className,\n )}\n {...props}\n />\n));\nAlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName;\n\nexport {\n AlertDialog,\n AlertDialogPortal,\n AlertDialogOverlay,\n AlertDialogTrigger,\n AlertDialogContent,\n AlertDialogHeader,\n AlertDialogFooter,\n AlertDialogTitle,\n AlertDialogDescription,\n AlertDialogAction,\n AlertDialogCancel,\n};\n",
|
||||
"050c08a3ec850a8fae8579b2bdbb4c9b8aa64744b580f07e2b26f7e6fc17dac0": "import * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst alertVariants = cva(\n \"relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground\",\n {\n variants: {\n variant: {\n default: \"bg-background text-foreground\",\n destructive:\n \"border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n },\n);\n\nconst Alert = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>\n>(({ className, variant, ...props }, ref) => (\n <div\n ref={ref}\n role=\"alert\"\n className={cn(alertVariants({ variant }), className)}\n {...props}\n />\n));\nAlert.displayName = \"Alert\";\n\nconst AlertTitle = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLHeadingElement>\n>(({ className, ...props }, ref) => (\n <h5\n ref={ref}\n className={cn(\"mb-1 font-medium leading-none tracking-tight\", className)}\n {...props}\n />\n));\nAlertTitle.displayName = \"AlertTitle\";\n\nconst AlertDescription = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\"text-sm [&_p]:leading-relaxed\", className)}\n {...props}\n />\n));\nAlertDescription.displayName = \"AlertDescription\";\n\nexport { Alert, AlertTitle, AlertDescription };\n",
|
||||
@@ -83,7 +82,6 @@
|
||||
"4b70ac2ad6f1c640249bb43667f86d8447985c49be8bd0335897ad0ae7c70694": "import * as React from \"react\";\n\nimport type { ToastActionElement, ToastProps } from \"@/components/ui/toast\";\n\nconst TOAST_LIMIT = 1;\nconst TOAST_REMOVE_DELAY = 1000000;\n\ntype ToasterToast = ToastProps & {\n id: string;\n title?: React.ReactNode;\n description?: React.ReactNode;\n action?: ToastActionElement;\n};\n\nconst _actionTypes = {\n ADD_TOAST: \"ADD_TOAST\",\n UPDATE_TOAST: \"UPDATE_TOAST\",\n DISMISS_TOAST: \"DISMISS_TOAST\",\n REMOVE_TOAST: \"REMOVE_TOAST\",\n} as const;\n\nlet count = 0;\n\nfunction genId() {\n count = (count + 1) % Number.MAX_SAFE_INTEGER;\n return count.toString();\n}\n\ntype ActionType = typeof _actionTypes;\n\ntype Action =\n | {\n type: ActionType[\"ADD_TOAST\"];\n toast: ToasterToast;\n }\n | {\n type: ActionType[\"UPDATE_TOAST\"];\n toast: Partial<ToasterToast>;\n }\n | {\n type: ActionType[\"DISMISS_TOAST\"];\n toastId?: ToasterToast[\"id\"];\n }\n | {\n type: ActionType[\"REMOVE_TOAST\"];\n toastId?: ToasterToast[\"id\"];\n };\n\ninterface State {\n toasts: ToasterToast[];\n}\n\nconst toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>();\n\nconst addToRemoveQueue = (toastId: string) => {\n if (toastTimeouts.has(toastId)) {\n return;\n }\n\n const timeout = setTimeout(() => {\n toastTimeouts.delete(toastId);\n dispatch({\n type: \"REMOVE_TOAST\",\n toastId: toastId,\n });\n }, TOAST_REMOVE_DELAY);\n\n toastTimeouts.set(toastId, timeout);\n};\n\nexport const reducer = (state: State, action: Action): State => {\n switch (action.type) {\n case \"ADD_TOAST\":\n return {\n ...state,\n toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),\n };\n\n case \"UPDATE_TOAST\":\n return {\n ...state,\n toasts: state.toasts.map((t) =>\n t.id === action.toast.id ? { ...t, ...action.toast } : t,\n ),\n };\n\n case \"DISMISS_TOAST\": {\n const { toastId } = action;\n\n // ! Side effects ! - This could be extracted into a dismissToast() action,\n // but I'll keep it here for simplicity\n if (toastId) {\n addToRemoveQueue(toastId);\n } else {\n state.toasts.forEach((toast) => {\n addToRemoveQueue(toast.id);\n });\n }\n\n return {\n ...state,\n toasts: state.toasts.map((t) =>\n t.id === toastId || toastId === undefined\n ? {\n ...t,\n open: false,\n }\n : t,\n ),\n };\n }\n case \"REMOVE_TOAST\":\n if (action.toastId === undefined) {\n return {\n ...state,\n toasts: [],\n };\n }\n return {\n ...state,\n toasts: state.toasts.filter((t) => t.id !== action.toastId),\n };\n }\n};\n\nconst listeners: Array<(state: State) => void> = [];\n\nlet memoryState: State = { toasts: [] };\n\nfunction dispatch(action: Action) {\n memoryState = reducer(memoryState, action);\n listeners.forEach((listener) => {\n listener(memoryState);\n });\n}\n\ntype Toast = Omit<ToasterToast, \"id\">;\n\nfunction toast({ ...props }: Toast) {\n const id = genId();\n\n const update = (props: ToasterToast) =>\n dispatch({\n type: \"UPDATE_TOAST\",\n toast: { ...props, id },\n });\n const dismiss = () => dispatch({ type: \"DISMISS_TOAST\", toastId: id });\n\n dispatch({\n type: \"ADD_TOAST\",\n toast: {\n ...props,\n id,\n open: true,\n onOpenChange: (open) => {\n if (!open) dismiss();\n },\n },\n });\n\n return {\n id: id,\n dismiss,\n update,\n };\n}\n\nfunction useToast() {\n const [state, setState] = React.useState<State>(memoryState);\n\n React.useEffect(() => {\n listeners.push(setState);\n return () => {\n const index = listeners.indexOf(setState);\n if (index > -1) {\n listeners.splice(index, 1);\n }\n };\n }, [state]);\n\n return {\n ...state,\n toast,\n dismiss: (toastId?: string) => dispatch({ type: \"DISMISS_TOAST\", toastId }),\n };\n}\n\nexport { useToast, toast };\n",
|
||||
"d1f1e0d62cb8d8d1e04c26e14de842d8a151f75812d81b046c65b5d1fe8e4b27": "import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n",
|
||||
"5cbfd5e41e9218faa071fd97a799497ba5e31423f3a38d4d16adae98a11b80a4": "import { createRoot } from \"react-dom/client\";\nimport App from \"./App.tsx\";\nimport \"./globals.css\";\n\ncreateRoot(document.getElementById(\"root\")!).render(<App />);\n",
|
||||
"70618b5f415d91c92bef86039e35d5f282e959276bf49ed204c9f78f7490c99c": "// Update this page (the content is just a fallback if you fail to update the page)\n\nimport { MadeWithDyad } from \"@/components/made-with-dyad\";\n\nconst Index = () => {\n return (\n <div className=\"min-h-screen flex items-center justify-center bg-gray-100\">\n <div className=\"text-center\">\n <h1 className=\"text-4xl font-bold mb-4\">Welcome to Your Blank App</h1>\n <p className=\"text-xl text-gray-600\">\n Start building your amazing project here!\n </p>\n </div>\n <MadeWithDyad />\n </div>\n );\n};\n\nexport default Index;\n",
|
||||
"940578bf01ac3dbdcb16f52528bd59903b2cce7698c8b39064f2791022567b0e": "import { useLocation } from \"react-router-dom\";\nimport { useEffect } from \"react\";\n\nconst NotFound = () => {\n const location = useLocation();\n\n useEffect(() => {\n console.error(\n \"404 Error: User attempted to access non-existent route:\",\n location.pathname,\n );\n }, [location.pathname]);\n\n return (\n <div className=\"min-h-screen flex items-center justify-center bg-gray-100\">\n <div className=\"text-center\">\n <h1 className=\"text-4xl font-bold mb-4\">404</h1>\n <p className=\"text-xl text-gray-600 mb-4\">Oops! Page not found</p>\n <a href=\"/\" className=\"text-blue-500 hover:text-blue-700 underline\">\n Return to Home\n </a>\n </div>\n </div>\n );\n};\n\nexport default NotFound;\n",
|
||||
"328f94e9c711410b23188484a0a2f38886d7732d5c375cefcba442ab6195783f": "import { toast } from \"sonner\";\n\nexport const showSuccess = (message: string) => {\n toast.success(message);\n};\n\nexport const showError = (message: string) => {\n toast.error(message);\n};\n\nexport const showLoading = (message: string) => {\n return toast.loading(message);\n};\n\nexport const dismissToast = (toastId: string) => {\n toast.dismiss(toastId);\n};\n",
|
||||
"65996936fbb042915f7b74a200fcdde7e410f32a669b1ab9597cfaa4b0faddb5": "/// <reference types=\"vite/client\" />\n",
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
"5f1387ce504f44bce8e80b0f29e6aee60c3e8227c70db37231ad0dadb0117fe0": "# Welcome to your Dyad app\n",
|
||||
"a0715e0a09edbd0fbde65816a75e0fa0fc8b314c5260c0768c19bf3aac22621a": "#root {\n max-width: 1280px;\n margin: 0 auto;\n padding: 2rem;\n text-align: center;\n}\n\n.logo {\n height: 6em;\n padding: 1.5em;\n will-change: filter;\n transition: filter 300ms;\n}\n.logo:hover {\n filter: drop-shadow(0 0 2em #646cffaa);\n}\n.logo.react:hover {\n filter: drop-shadow(0 0 2em #61dafbaa);\n}\n\n@keyframes logo-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n\n@media (prefers-reduced-motion: no-preference) {\n a:nth-of-type(2) .logo {\n animation: logo-spin infinite 20s linear;\n }\n}\n\n.card {\n padding: 2em;\n}\n\n.read-the-docs {\n color: #888;\n}\n",
|
||||
"4e69ef9f71a824d0a6b0965300a4738f34e54a39d58433104162a61b6d072d49": "import { Toaster } from \"@/components/ui/toaster\";\nimport { Toaster as Sonner } from \"@/components/ui/sonner\";\nimport { TooltipProvider } from \"@/components/ui/tooltip\";\nimport { QueryClient, QueryClientProvider } from \"@tanstack/react-query\";\nimport { BrowserRouter, Routes, Route } from \"react-router-dom\";\nimport Index from \"./pages/Index\";\nimport NotFound from \"./pages/NotFound\";\n\nconst queryClient = new QueryClient();\n\nconst App = () => (\n <QueryClientProvider client={queryClient}>\n <TooltipProvider>\n <Toaster />\n <Sonner />\n <BrowserRouter>\n <Routes>\n <Route path=\"/\" element={<Index />} />\n {/* ADD ALL CUSTOM ROUTES ABOVE THE CATCH-ALL \"*\" ROUTE */}\n <Route path=\"*\" element={<NotFound />} />\n </Routes>\n </BrowserRouter>\n </TooltipProvider>\n </QueryClientProvider>\n);\n\nexport default App;\n",
|
||||
"b8d3ed0643f99b45851f98668e6ca4163004a878967abd283373393753c26666": "export const MadeWithDyad = () => {\n return (\n <div className=\"p-4 text-center\">\n <a\n href=\"https://www.dyad.sh/\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-sm text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200\"\n >\n Made with Dyad\n </a>\n </div>\n );\n};\n",
|
||||
"b728b30af5d9f770a34d5b4ae85ea720c90664fa55d83ad3d9835f48f20f5846": "import * as React from \"react\";\nimport * as AccordionPrimitive from \"@radix-ui/react-accordion\";\nimport { ChevronDown } from \"lucide-react\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst Accordion = AccordionPrimitive.Root;\n\nconst AccordionItem = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>\n>(({ className, ...props }, ref) => (\n <AccordionPrimitive.Item\n ref={ref}\n className={cn(\"border-b\", className)}\n {...props}\n />\n));\nAccordionItem.displayName = \"AccordionItem\";\n\nconst AccordionTrigger = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>\n>(({ className, children, ...props }, ref) => (\n <AccordionPrimitive.Header className=\"flex\">\n <AccordionPrimitive.Trigger\n ref={ref}\n className={cn(\n \"flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180\",\n className,\n )}\n {...props}\n >\n {children}\n <ChevronDown className=\"h-4 w-4 shrink-0 transition-transform duration-200\" />\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n));\nAccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;\n\nconst AccordionContent = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>\n>(({ className, children, ...props }, ref) => (\n <AccordionPrimitive.Content\n ref={ref}\n className=\"overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down\"\n {...props}\n >\n <div className={cn(\"pb-4 pt-0\", className)}>{children}</div>\n </AccordionPrimitive.Content>\n));\n\nAccordionContent.displayName = AccordionPrimitive.Content.displayName;\n\nexport { Accordion, AccordionItem, AccordionTrigger, AccordionContent };\n",
|
||||
"6f5d2b743e097cc0f38a8201fc9472bbcffa7ef80653eb09ac1733f470dd675c": "import * as React from \"react\";\nimport * as AlertDialogPrimitive from \"@radix-ui/react-alert-dialog\";\n\nimport { cn } from \"@/lib/utils\";\nimport { buttonVariants } from \"@/components/ui/button\";\n\nconst AlertDialog = AlertDialogPrimitive.Root;\n\nconst AlertDialogTrigger = AlertDialogPrimitive.Trigger;\n\nconst AlertDialogPortal = AlertDialogPrimitive.Portal;\n\nconst AlertDialogOverlay = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Overlay>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Overlay\n className={cn(\n \"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n className,\n )}\n {...props}\n ref={ref}\n />\n));\nAlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;\n\nconst AlertDialogContent = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content>\n>(({ className, ...props }, ref) => (\n <AlertDialogPortal>\n <AlertDialogOverlay />\n <AlertDialogPrimitive.Content\n ref={ref}\n className={cn(\n \"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg\",\n className,\n )}\n {...props}\n />\n </AlertDialogPortal>\n));\nAlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;\n\nconst AlertDialogHeader = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n \"flex flex-col space-y-2 text-center sm:text-left\",\n className,\n )}\n {...props}\n />\n);\nAlertDialogHeader.displayName = \"AlertDialogHeader\";\n\nconst AlertDialogFooter = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n \"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2\",\n className,\n )}\n {...props}\n />\n);\nAlertDialogFooter.displayName = \"AlertDialogFooter\";\n\nconst AlertDialogTitle = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Title>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Title\n ref={ref}\n className={cn(\"text-lg font-semibold\", className)}\n {...props}\n />\n));\nAlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;\n\nconst AlertDialogDescription = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Description>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Description\n ref={ref}\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n));\nAlertDialogDescription.displayName =\n AlertDialogPrimitive.Description.displayName;\n\nconst AlertDialogAction = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Action>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Action\n ref={ref}\n className={cn(buttonVariants(), className)}\n {...props}\n />\n));\nAlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName;\n\nconst AlertDialogCancel = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Cancel>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Cancel\n ref={ref}\n className={cn(\n buttonVariants({ variant: \"outline\" }),\n \"mt-2 sm:mt-0\",\n className,\n )}\n {...props}\n />\n));\nAlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName;\n\nexport {\n AlertDialog,\n AlertDialogPortal,\n AlertDialogOverlay,\n AlertDialogTrigger,\n AlertDialogContent,\n AlertDialogHeader,\n AlertDialogFooter,\n AlertDialogTitle,\n AlertDialogDescription,\n AlertDialogAction,\n AlertDialogCancel,\n};\n",
|
||||
"050c08a3ec850a8fae8579b2bdbb4c9b8aa64744b580f07e2b26f7e6fc17dac0": "import * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst alertVariants = cva(\n \"relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground\",\n {\n variants: {\n variant: {\n default: \"bg-background text-foreground\",\n destructive:\n \"border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n },\n);\n\nconst Alert = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>\n>(({ className, variant, ...props }, ref) => (\n <div\n ref={ref}\n role=\"alert\"\n className={cn(alertVariants({ variant }), className)}\n {...props}\n />\n));\nAlert.displayName = \"Alert\";\n\nconst AlertTitle = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLHeadingElement>\n>(({ className, ...props }, ref) => (\n <h5\n ref={ref}\n className={cn(\"mb-1 font-medium leading-none tracking-tight\", className)}\n {...props}\n />\n));\nAlertTitle.displayName = \"AlertTitle\";\n\nconst AlertDescription = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\"text-sm [&_p]:leading-relaxed\", className)}\n {...props}\n />\n));\nAlertDescription.displayName = \"AlertDescription\";\n\nexport { Alert, AlertTitle, AlertDescription };\n",
|
||||
@@ -88,7 +87,6 @@
|
||||
"4b70ac2ad6f1c640249bb43667f86d8447985c49be8bd0335897ad0ae7c70694": "import * as React from \"react\";\n\nimport type { ToastActionElement, ToastProps } from \"@/components/ui/toast\";\n\nconst TOAST_LIMIT = 1;\nconst TOAST_REMOVE_DELAY = 1000000;\n\ntype ToasterToast = ToastProps & {\n id: string;\n title?: React.ReactNode;\n description?: React.ReactNode;\n action?: ToastActionElement;\n};\n\nconst _actionTypes = {\n ADD_TOAST: \"ADD_TOAST\",\n UPDATE_TOAST: \"UPDATE_TOAST\",\n DISMISS_TOAST: \"DISMISS_TOAST\",\n REMOVE_TOAST: \"REMOVE_TOAST\",\n} as const;\n\nlet count = 0;\n\nfunction genId() {\n count = (count + 1) % Number.MAX_SAFE_INTEGER;\n return count.toString();\n}\n\ntype ActionType = typeof _actionTypes;\n\ntype Action =\n | {\n type: ActionType[\"ADD_TOAST\"];\n toast: ToasterToast;\n }\n | {\n type: ActionType[\"UPDATE_TOAST\"];\n toast: Partial<ToasterToast>;\n }\n | {\n type: ActionType[\"DISMISS_TOAST\"];\n toastId?: ToasterToast[\"id\"];\n }\n | {\n type: ActionType[\"REMOVE_TOAST\"];\n toastId?: ToasterToast[\"id\"];\n };\n\ninterface State {\n toasts: ToasterToast[];\n}\n\nconst toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>();\n\nconst addToRemoveQueue = (toastId: string) => {\n if (toastTimeouts.has(toastId)) {\n return;\n }\n\n const timeout = setTimeout(() => {\n toastTimeouts.delete(toastId);\n dispatch({\n type: \"REMOVE_TOAST\",\n toastId: toastId,\n });\n }, TOAST_REMOVE_DELAY);\n\n toastTimeouts.set(toastId, timeout);\n};\n\nexport const reducer = (state: State, action: Action): State => {\n switch (action.type) {\n case \"ADD_TOAST\":\n return {\n ...state,\n toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),\n };\n\n case \"UPDATE_TOAST\":\n return {\n ...state,\n toasts: state.toasts.map((t) =>\n t.id === action.toast.id ? { ...t, ...action.toast } : t,\n ),\n };\n\n case \"DISMISS_TOAST\": {\n const { toastId } = action;\n\n // ! Side effects ! - This could be extracted into a dismissToast() action,\n // but I'll keep it here for simplicity\n if (toastId) {\n addToRemoveQueue(toastId);\n } else {\n state.toasts.forEach((toast) => {\n addToRemoveQueue(toast.id);\n });\n }\n\n return {\n ...state,\n toasts: state.toasts.map((t) =>\n t.id === toastId || toastId === undefined\n ? {\n ...t,\n open: false,\n }\n : t,\n ),\n };\n }\n case \"REMOVE_TOAST\":\n if (action.toastId === undefined) {\n return {\n ...state,\n toasts: [],\n };\n }\n return {\n ...state,\n toasts: state.toasts.filter((t) => t.id !== action.toastId),\n };\n }\n};\n\nconst listeners: Array<(state: State) => void> = [];\n\nlet memoryState: State = { toasts: [] };\n\nfunction dispatch(action: Action) {\n memoryState = reducer(memoryState, action);\n listeners.forEach((listener) => {\n listener(memoryState);\n });\n}\n\ntype Toast = Omit<ToasterToast, \"id\">;\n\nfunction toast({ ...props }: Toast) {\n const id = genId();\n\n const update = (props: ToasterToast) =>\n dispatch({\n type: \"UPDATE_TOAST\",\n toast: { ...props, id },\n });\n const dismiss = () => dispatch({ type: \"DISMISS_TOAST\", toastId: id });\n\n dispatch({\n type: \"ADD_TOAST\",\n toast: {\n ...props,\n id,\n open: true,\n onOpenChange: (open) => {\n if (!open) dismiss();\n },\n },\n });\n\n return {\n id: id,\n dismiss,\n update,\n };\n}\n\nfunction useToast() {\n const [state, setState] = React.useState<State>(memoryState);\n\n React.useEffect(() => {\n listeners.push(setState);\n return () => {\n const index = listeners.indexOf(setState);\n if (index > -1) {\n listeners.splice(index, 1);\n }\n };\n }, [state]);\n\n return {\n ...state,\n toast,\n dismiss: (toastId?: string) => dispatch({ type: \"DISMISS_TOAST\", toastId }),\n };\n}\n\nexport { useToast, toast };\n",
|
||||
"d1f1e0d62cb8d8d1e04c26e14de842d8a151f75812d81b046c65b5d1fe8e4b27": "import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n",
|
||||
"5cbfd5e41e9218faa071fd97a799497ba5e31423f3a38d4d16adae98a11b80a4": "import { createRoot } from \"react-dom/client\";\nimport App from \"./App.tsx\";\nimport \"./globals.css\";\n\ncreateRoot(document.getElementById(\"root\")!).render(<App />);\n",
|
||||
"70618b5f415d91c92bef86039e35d5f282e959276bf49ed204c9f78f7490c99c": "// Update this page (the content is just a fallback if you fail to update the page)\n\nimport { MadeWithDyad } from \"@/components/made-with-dyad\";\n\nconst Index = () => {\n return (\n <div className=\"min-h-screen flex items-center justify-center bg-gray-100\">\n <div className=\"text-center\">\n <h1 className=\"text-4xl font-bold mb-4\">Welcome to Your Blank App</h1>\n <p className=\"text-xl text-gray-600\">\n Start building your amazing project here!\n </p>\n </div>\n <MadeWithDyad />\n </div>\n );\n};\n\nexport default Index;\n",
|
||||
"940578bf01ac3dbdcb16f52528bd59903b2cce7698c8b39064f2791022567b0e": "import { useLocation } from \"react-router-dom\";\nimport { useEffect } from \"react\";\n\nconst NotFound = () => {\n const location = useLocation();\n\n useEffect(() => {\n console.error(\n \"404 Error: User attempted to access non-existent route:\",\n location.pathname,\n );\n }, [location.pathname]);\n\n return (\n <div className=\"min-h-screen flex items-center justify-center bg-gray-100\">\n <div className=\"text-center\">\n <h1 className=\"text-4xl font-bold mb-4\">404</h1>\n <p className=\"text-xl text-gray-600 mb-4\">Oops! Page not found</p>\n <a href=\"/\" className=\"text-blue-500 hover:text-blue-700 underline\">\n Return to Home\n </a>\n </div>\n </div>\n );\n};\n\nexport default NotFound;\n",
|
||||
"328f94e9c711410b23188484a0a2f38886d7732d5c375cefcba442ab6195783f": "import { toast } from \"sonner\";\n\nexport const showSuccess = (message: string) => {\n toast.success(message);\n};\n\nexport const showError = (message: string) => {\n toast.error(message);\n};\n\nexport const showLoading = (message: string) => {\n return toast.loading(message);\n};\n\nexport const dismissToast = (toastId: string) => {\n toast.dismiss(toastId);\n};\n",
|
||||
"65996936fbb042915f7b74a200fcdde7e410f32a669b1ab9597cfaa4b0faddb5": "/// <reference types=\"vite/client\" />\n",
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
"5f1387ce504f44bce8e80b0f29e6aee60c3e8227c70db37231ad0dadb0117fe0": "# Welcome to your Dyad app\n",
|
||||
"a0715e0a09edbd0fbde65816a75e0fa0fc8b314c5260c0768c19bf3aac22621a": "#root {\n max-width: 1280px;\n margin: 0 auto;\n padding: 2rem;\n text-align: center;\n}\n\n.logo {\n height: 6em;\n padding: 1.5em;\n will-change: filter;\n transition: filter 300ms;\n}\n.logo:hover {\n filter: drop-shadow(0 0 2em #646cffaa);\n}\n.logo.react:hover {\n filter: drop-shadow(0 0 2em #61dafbaa);\n}\n\n@keyframes logo-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n\n@media (prefers-reduced-motion: no-preference) {\n a:nth-of-type(2) .logo {\n animation: logo-spin infinite 20s linear;\n }\n}\n\n.card {\n padding: 2em;\n}\n\n.read-the-docs {\n color: #888;\n}\n",
|
||||
"4e69ef9f71a824d0a6b0965300a4738f34e54a39d58433104162a61b6d072d49": "import { Toaster } from \"@/components/ui/toaster\";\nimport { Toaster as Sonner } from \"@/components/ui/sonner\";\nimport { TooltipProvider } from \"@/components/ui/tooltip\";\nimport { QueryClient, QueryClientProvider } from \"@tanstack/react-query\";\nimport { BrowserRouter, Routes, Route } from \"react-router-dom\";\nimport Index from \"./pages/Index\";\nimport NotFound from \"./pages/NotFound\";\n\nconst queryClient = new QueryClient();\n\nconst App = () => (\n <QueryClientProvider client={queryClient}>\n <TooltipProvider>\n <Toaster />\n <Sonner />\n <BrowserRouter>\n <Routes>\n <Route path=\"/\" element={<Index />} />\n {/* ADD ALL CUSTOM ROUTES ABOVE THE CATCH-ALL \"*\" ROUTE */}\n <Route path=\"*\" element={<NotFound />} />\n </Routes>\n </BrowserRouter>\n </TooltipProvider>\n </QueryClientProvider>\n);\n\nexport default App;\n",
|
||||
"b8d3ed0643f99b45851f98668e6ca4163004a878967abd283373393753c26666": "export const MadeWithDyad = () => {\n return (\n <div className=\"p-4 text-center\">\n <a\n href=\"https://www.dyad.sh/\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-sm text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200\"\n >\n Made with Dyad\n </a>\n </div>\n );\n};\n",
|
||||
"b728b30af5d9f770a34d5b4ae85ea720c90664fa55d83ad3d9835f48f20f5846": "import * as React from \"react\";\nimport * as AccordionPrimitive from \"@radix-ui/react-accordion\";\nimport { ChevronDown } from \"lucide-react\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst Accordion = AccordionPrimitive.Root;\n\nconst AccordionItem = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>\n>(({ className, ...props }, ref) => (\n <AccordionPrimitive.Item\n ref={ref}\n className={cn(\"border-b\", className)}\n {...props}\n />\n));\nAccordionItem.displayName = \"AccordionItem\";\n\nconst AccordionTrigger = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>\n>(({ className, children, ...props }, ref) => (\n <AccordionPrimitive.Header className=\"flex\">\n <AccordionPrimitive.Trigger\n ref={ref}\n className={cn(\n \"flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180\",\n className,\n )}\n {...props}\n >\n {children}\n <ChevronDown className=\"h-4 w-4 shrink-0 transition-transform duration-200\" />\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n));\nAccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;\n\nconst AccordionContent = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>\n>(({ className, children, ...props }, ref) => (\n <AccordionPrimitive.Content\n ref={ref}\n className=\"overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down\"\n {...props}\n >\n <div className={cn(\"pb-4 pt-0\", className)}>{children}</div>\n </AccordionPrimitive.Content>\n));\n\nAccordionContent.displayName = AccordionPrimitive.Content.displayName;\n\nexport { Accordion, AccordionItem, AccordionTrigger, AccordionContent };\n",
|
||||
"6f5d2b743e097cc0f38a8201fc9472bbcffa7ef80653eb09ac1733f470dd675c": "import * as React from \"react\";\nimport * as AlertDialogPrimitive from \"@radix-ui/react-alert-dialog\";\n\nimport { cn } from \"@/lib/utils\";\nimport { buttonVariants } from \"@/components/ui/button\";\n\nconst AlertDialog = AlertDialogPrimitive.Root;\n\nconst AlertDialogTrigger = AlertDialogPrimitive.Trigger;\n\nconst AlertDialogPortal = AlertDialogPrimitive.Portal;\n\nconst AlertDialogOverlay = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Overlay>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Overlay\n className={cn(\n \"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n className,\n )}\n {...props}\n ref={ref}\n />\n));\nAlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;\n\nconst AlertDialogContent = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content>\n>(({ className, ...props }, ref) => (\n <AlertDialogPortal>\n <AlertDialogOverlay />\n <AlertDialogPrimitive.Content\n ref={ref}\n className={cn(\n \"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg\",\n className,\n )}\n {...props}\n />\n </AlertDialogPortal>\n));\nAlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;\n\nconst AlertDialogHeader = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n \"flex flex-col space-y-2 text-center sm:text-left\",\n className,\n )}\n {...props}\n />\n);\nAlertDialogHeader.displayName = \"AlertDialogHeader\";\n\nconst AlertDialogFooter = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n \"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2\",\n className,\n )}\n {...props}\n />\n);\nAlertDialogFooter.displayName = \"AlertDialogFooter\";\n\nconst AlertDialogTitle = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Title>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Title\n ref={ref}\n className={cn(\"text-lg font-semibold\", className)}\n {...props}\n />\n));\nAlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;\n\nconst AlertDialogDescription = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Description>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Description\n ref={ref}\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n));\nAlertDialogDescription.displayName =\n AlertDialogPrimitive.Description.displayName;\n\nconst AlertDialogAction = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Action>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Action\n ref={ref}\n className={cn(buttonVariants(), className)}\n {...props}\n />\n));\nAlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName;\n\nconst AlertDialogCancel = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Cancel>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Cancel\n ref={ref}\n className={cn(\n buttonVariants({ variant: \"outline\" }),\n \"mt-2 sm:mt-0\",\n className,\n )}\n {...props}\n />\n));\nAlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName;\n\nexport {\n AlertDialog,\n AlertDialogPortal,\n AlertDialogOverlay,\n AlertDialogTrigger,\n AlertDialogContent,\n AlertDialogHeader,\n AlertDialogFooter,\n AlertDialogTitle,\n AlertDialogDescription,\n AlertDialogAction,\n AlertDialogCancel,\n};\n",
|
||||
"050c08a3ec850a8fae8579b2bdbb4c9b8aa64744b580f07e2b26f7e6fc17dac0": "import * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst alertVariants = cva(\n \"relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground\",\n {\n variants: {\n variant: {\n default: \"bg-background text-foreground\",\n destructive:\n \"border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n },\n);\n\nconst Alert = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>\n>(({ className, variant, ...props }, ref) => (\n <div\n ref={ref}\n role=\"alert\"\n className={cn(alertVariants({ variant }), className)}\n {...props}\n />\n));\nAlert.displayName = \"Alert\";\n\nconst AlertTitle = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLHeadingElement>\n>(({ className, ...props }, ref) => (\n <h5\n ref={ref}\n className={cn(\"mb-1 font-medium leading-none tracking-tight\", className)}\n {...props}\n />\n));\nAlertTitle.displayName = \"AlertTitle\";\n\nconst AlertDescription = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\"text-sm [&_p]:leading-relaxed\", className)}\n {...props}\n />\n));\nAlertDescription.displayName = \"AlertDescription\";\n\nexport { Alert, AlertTitle, AlertDescription };\n",
|
||||
@@ -88,7 +87,6 @@
|
||||
"4b70ac2ad6f1c640249bb43667f86d8447985c49be8bd0335897ad0ae7c70694": "import * as React from \"react\";\n\nimport type { ToastActionElement, ToastProps } from \"@/components/ui/toast\";\n\nconst TOAST_LIMIT = 1;\nconst TOAST_REMOVE_DELAY = 1000000;\n\ntype ToasterToast = ToastProps & {\n id: string;\n title?: React.ReactNode;\n description?: React.ReactNode;\n action?: ToastActionElement;\n};\n\nconst _actionTypes = {\n ADD_TOAST: \"ADD_TOAST\",\n UPDATE_TOAST: \"UPDATE_TOAST\",\n DISMISS_TOAST: \"DISMISS_TOAST\",\n REMOVE_TOAST: \"REMOVE_TOAST\",\n} as const;\n\nlet count = 0;\n\nfunction genId() {\n count = (count + 1) % Number.MAX_SAFE_INTEGER;\n return count.toString();\n}\n\ntype ActionType = typeof _actionTypes;\n\ntype Action =\n | {\n type: ActionType[\"ADD_TOAST\"];\n toast: ToasterToast;\n }\n | {\n type: ActionType[\"UPDATE_TOAST\"];\n toast: Partial<ToasterToast>;\n }\n | {\n type: ActionType[\"DISMISS_TOAST\"];\n toastId?: ToasterToast[\"id\"];\n }\n | {\n type: ActionType[\"REMOVE_TOAST\"];\n toastId?: ToasterToast[\"id\"];\n };\n\ninterface State {\n toasts: ToasterToast[];\n}\n\nconst toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>();\n\nconst addToRemoveQueue = (toastId: string) => {\n if (toastTimeouts.has(toastId)) {\n return;\n }\n\n const timeout = setTimeout(() => {\n toastTimeouts.delete(toastId);\n dispatch({\n type: \"REMOVE_TOAST\",\n toastId: toastId,\n });\n }, TOAST_REMOVE_DELAY);\n\n toastTimeouts.set(toastId, timeout);\n};\n\nexport const reducer = (state: State, action: Action): State => {\n switch (action.type) {\n case \"ADD_TOAST\":\n return {\n ...state,\n toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),\n };\n\n case \"UPDATE_TOAST\":\n return {\n ...state,\n toasts: state.toasts.map((t) =>\n t.id === action.toast.id ? { ...t, ...action.toast } : t,\n ),\n };\n\n case \"DISMISS_TOAST\": {\n const { toastId } = action;\n\n // ! Side effects ! - This could be extracted into a dismissToast() action,\n // but I'll keep it here for simplicity\n if (toastId) {\n addToRemoveQueue(toastId);\n } else {\n state.toasts.forEach((toast) => {\n addToRemoveQueue(toast.id);\n });\n }\n\n return {\n ...state,\n toasts: state.toasts.map((t) =>\n t.id === toastId || toastId === undefined\n ? {\n ...t,\n open: false,\n }\n : t,\n ),\n };\n }\n case \"REMOVE_TOAST\":\n if (action.toastId === undefined) {\n return {\n ...state,\n toasts: [],\n };\n }\n return {\n ...state,\n toasts: state.toasts.filter((t) => t.id !== action.toastId),\n };\n }\n};\n\nconst listeners: Array<(state: State) => void> = [];\n\nlet memoryState: State = { toasts: [] };\n\nfunction dispatch(action: Action) {\n memoryState = reducer(memoryState, action);\n listeners.forEach((listener) => {\n listener(memoryState);\n });\n}\n\ntype Toast = Omit<ToasterToast, \"id\">;\n\nfunction toast({ ...props }: Toast) {\n const id = genId();\n\n const update = (props: ToasterToast) =>\n dispatch({\n type: \"UPDATE_TOAST\",\n toast: { ...props, id },\n });\n const dismiss = () => dispatch({ type: \"DISMISS_TOAST\", toastId: id });\n\n dispatch({\n type: \"ADD_TOAST\",\n toast: {\n ...props,\n id,\n open: true,\n onOpenChange: (open) => {\n if (!open) dismiss();\n },\n },\n });\n\n return {\n id: id,\n dismiss,\n update,\n };\n}\n\nfunction useToast() {\n const [state, setState] = React.useState<State>(memoryState);\n\n React.useEffect(() => {\n listeners.push(setState);\n return () => {\n const index = listeners.indexOf(setState);\n if (index > -1) {\n listeners.splice(index, 1);\n }\n };\n }, [state]);\n\n return {\n ...state,\n toast,\n dismiss: (toastId?: string) => dispatch({ type: \"DISMISS_TOAST\", toastId }),\n };\n}\n\nexport { useToast, toast };\n",
|
||||
"d1f1e0d62cb8d8d1e04c26e14de842d8a151f75812d81b046c65b5d1fe8e4b27": "import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n",
|
||||
"5cbfd5e41e9218faa071fd97a799497ba5e31423f3a38d4d16adae98a11b80a4": "import { createRoot } from \"react-dom/client\";\nimport App from \"./App.tsx\";\nimport \"./globals.css\";\n\ncreateRoot(document.getElementById(\"root\")!).render(<App />);\n",
|
||||
"70618b5f415d91c92bef86039e35d5f282e959276bf49ed204c9f78f7490c99c": "// Update this page (the content is just a fallback if you fail to update the page)\n\nimport { MadeWithDyad } from \"@/components/made-with-dyad\";\n\nconst Index = () => {\n return (\n <div className=\"min-h-screen flex items-center justify-center bg-gray-100\">\n <div className=\"text-center\">\n <h1 className=\"text-4xl font-bold mb-4\">Welcome to Your Blank App</h1>\n <p className=\"text-xl text-gray-600\">\n Start building your amazing project here!\n </p>\n </div>\n <MadeWithDyad />\n </div>\n );\n};\n\nexport default Index;\n",
|
||||
"940578bf01ac3dbdcb16f52528bd59903b2cce7698c8b39064f2791022567b0e": "import { useLocation } from \"react-router-dom\";\nimport { useEffect } from \"react\";\n\nconst NotFound = () => {\n const location = useLocation();\n\n useEffect(() => {\n console.error(\n \"404 Error: User attempted to access non-existent route:\",\n location.pathname,\n );\n }, [location.pathname]);\n\n return (\n <div className=\"min-h-screen flex items-center justify-center bg-gray-100\">\n <div className=\"text-center\">\n <h1 className=\"text-4xl font-bold mb-4\">404</h1>\n <p className=\"text-xl text-gray-600 mb-4\">Oops! Page not found</p>\n <a href=\"/\" className=\"text-blue-500 hover:text-blue-700 underline\">\n Return to Home\n </a>\n </div>\n </div>\n );\n};\n\nexport default NotFound;\n",
|
||||
"328f94e9c711410b23188484a0a2f38886d7732d5c375cefcba442ab6195783f": "import { toast } from \"sonner\";\n\nexport const showSuccess = (message: string) => {\n toast.success(message);\n};\n\nexport const showError = (message: string) => {\n toast.error(message);\n};\n\nexport const showLoading = (message: string) => {\n return toast.loading(message);\n};\n\nexport const dismissToast = (toastId: string) => {\n toast.dismiss(toastId);\n};\n",
|
||||
"65996936fbb042915f7b74a200fcdde7e410f32a669b1ab9597cfaa4b0faddb5": "/// <reference types=\"vite/client\" />\n",
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
"5f1387ce504f44bce8e80b0f29e6aee60c3e8227c70db37231ad0dadb0117fe0": "# Welcome to your Dyad app\n",
|
||||
"a0715e0a09edbd0fbde65816a75e0fa0fc8b314c5260c0768c19bf3aac22621a": "#root {\n max-width: 1280px;\n margin: 0 auto;\n padding: 2rem;\n text-align: center;\n}\n\n.logo {\n height: 6em;\n padding: 1.5em;\n will-change: filter;\n transition: filter 300ms;\n}\n.logo:hover {\n filter: drop-shadow(0 0 2em #646cffaa);\n}\n.logo.react:hover {\n filter: drop-shadow(0 0 2em #61dafbaa);\n}\n\n@keyframes logo-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n\n@media (prefers-reduced-motion: no-preference) {\n a:nth-of-type(2) .logo {\n animation: logo-spin infinite 20s linear;\n }\n}\n\n.card {\n padding: 2em;\n}\n\n.read-the-docs {\n color: #888;\n}\n",
|
||||
"4e69ef9f71a824d0a6b0965300a4738f34e54a39d58433104162a61b6d072d49": "import { Toaster } from \"@/components/ui/toaster\";\nimport { Toaster as Sonner } from \"@/components/ui/sonner\";\nimport { TooltipProvider } from \"@/components/ui/tooltip\";\nimport { QueryClient, QueryClientProvider } from \"@tanstack/react-query\";\nimport { BrowserRouter, Routes, Route } from \"react-router-dom\";\nimport Index from \"./pages/Index\";\nimport NotFound from \"./pages/NotFound\";\n\nconst queryClient = new QueryClient();\n\nconst App = () => (\n <QueryClientProvider client={queryClient}>\n <TooltipProvider>\n <Toaster />\n <Sonner />\n <BrowserRouter>\n <Routes>\n <Route path=\"/\" element={<Index />} />\n {/* ADD ALL CUSTOM ROUTES ABOVE THE CATCH-ALL \"*\" ROUTE */}\n <Route path=\"*\" element={<NotFound />} />\n </Routes>\n </BrowserRouter>\n </TooltipProvider>\n </QueryClientProvider>\n);\n\nexport default App;\n",
|
||||
"b8d3ed0643f99b45851f98668e6ca4163004a878967abd283373393753c26666": "export const MadeWithDyad = () => {\n return (\n <div className=\"p-4 text-center\">\n <a\n href=\"https://www.dyad.sh/\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-sm text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200\"\n >\n Made with Dyad\n </a>\n </div>\n );\n};\n",
|
||||
"b728b30af5d9f770a34d5b4ae85ea720c90664fa55d83ad3d9835f48f20f5846": "import * as React from \"react\";\nimport * as AccordionPrimitive from \"@radix-ui/react-accordion\";\nimport { ChevronDown } from \"lucide-react\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst Accordion = AccordionPrimitive.Root;\n\nconst AccordionItem = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>\n>(({ className, ...props }, ref) => (\n <AccordionPrimitive.Item\n ref={ref}\n className={cn(\"border-b\", className)}\n {...props}\n />\n));\nAccordionItem.displayName = \"AccordionItem\";\n\nconst AccordionTrigger = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>\n>(({ className, children, ...props }, ref) => (\n <AccordionPrimitive.Header className=\"flex\">\n <AccordionPrimitive.Trigger\n ref={ref}\n className={cn(\n \"flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180\",\n className,\n )}\n {...props}\n >\n {children}\n <ChevronDown className=\"h-4 w-4 shrink-0 transition-transform duration-200\" />\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n));\nAccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;\n\nconst AccordionContent = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>\n>(({ className, children, ...props }, ref) => (\n <AccordionPrimitive.Content\n ref={ref}\n className=\"overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down\"\n {...props}\n >\n <div className={cn(\"pb-4 pt-0\", className)}>{children}</div>\n </AccordionPrimitive.Content>\n));\n\nAccordionContent.displayName = AccordionPrimitive.Content.displayName;\n\nexport { Accordion, AccordionItem, AccordionTrigger, AccordionContent };\n",
|
||||
"6f5d2b743e097cc0f38a8201fc9472bbcffa7ef80653eb09ac1733f470dd675c": "import * as React from \"react\";\nimport * as AlertDialogPrimitive from \"@radix-ui/react-alert-dialog\";\n\nimport { cn } from \"@/lib/utils\";\nimport { buttonVariants } from \"@/components/ui/button\";\n\nconst AlertDialog = AlertDialogPrimitive.Root;\n\nconst AlertDialogTrigger = AlertDialogPrimitive.Trigger;\n\nconst AlertDialogPortal = AlertDialogPrimitive.Portal;\n\nconst AlertDialogOverlay = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Overlay>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Overlay\n className={cn(\n \"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n className,\n )}\n {...props}\n ref={ref}\n />\n));\nAlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;\n\nconst AlertDialogContent = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content>\n>(({ className, ...props }, ref) => (\n <AlertDialogPortal>\n <AlertDialogOverlay />\n <AlertDialogPrimitive.Content\n ref={ref}\n className={cn(\n \"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg\",\n className,\n )}\n {...props}\n />\n </AlertDialogPortal>\n));\nAlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;\n\nconst AlertDialogHeader = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n \"flex flex-col space-y-2 text-center sm:text-left\",\n className,\n )}\n {...props}\n />\n);\nAlertDialogHeader.displayName = \"AlertDialogHeader\";\n\nconst AlertDialogFooter = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n \"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2\",\n className,\n )}\n {...props}\n />\n);\nAlertDialogFooter.displayName = \"AlertDialogFooter\";\n\nconst AlertDialogTitle = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Title>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Title\n ref={ref}\n className={cn(\"text-lg font-semibold\", className)}\n {...props}\n />\n));\nAlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;\n\nconst AlertDialogDescription = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Description>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Description\n ref={ref}\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n));\nAlertDialogDescription.displayName =\n AlertDialogPrimitive.Description.displayName;\n\nconst AlertDialogAction = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Action>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Action\n ref={ref}\n className={cn(buttonVariants(), className)}\n {...props}\n />\n));\nAlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName;\n\nconst AlertDialogCancel = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Cancel>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Cancel\n ref={ref}\n className={cn(\n buttonVariants({ variant: \"outline\" }),\n \"mt-2 sm:mt-0\",\n className,\n )}\n {...props}\n />\n));\nAlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName;\n\nexport {\n AlertDialog,\n AlertDialogPortal,\n AlertDialogOverlay,\n AlertDialogTrigger,\n AlertDialogContent,\n AlertDialogHeader,\n AlertDialogFooter,\n AlertDialogTitle,\n AlertDialogDescription,\n AlertDialogAction,\n AlertDialogCancel,\n};\n",
|
||||
"050c08a3ec850a8fae8579b2bdbb4c9b8aa64744b580f07e2b26f7e6fc17dac0": "import * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst alertVariants = cva(\n \"relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground\",\n {\n variants: {\n variant: {\n default: \"bg-background text-foreground\",\n destructive:\n \"border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n },\n);\n\nconst Alert = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>\n>(({ className, variant, ...props }, ref) => (\n <div\n ref={ref}\n role=\"alert\"\n className={cn(alertVariants({ variant }), className)}\n {...props}\n />\n));\nAlert.displayName = \"Alert\";\n\nconst AlertTitle = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLHeadingElement>\n>(({ className, ...props }, ref) => (\n <h5\n ref={ref}\n className={cn(\"mb-1 font-medium leading-none tracking-tight\", className)}\n {...props}\n />\n));\nAlertTitle.displayName = \"AlertTitle\";\n\nconst AlertDescription = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\"text-sm [&_p]:leading-relaxed\", className)}\n {...props}\n />\n));\nAlertDescription.displayName = \"AlertDescription\";\n\nexport { Alert, AlertTitle, AlertDescription };\n",
|
||||
@@ -88,7 +87,6 @@
|
||||
"4b70ac2ad6f1c640249bb43667f86d8447985c49be8bd0335897ad0ae7c70694": "import * as React from \"react\";\n\nimport type { ToastActionElement, ToastProps } from \"@/components/ui/toast\";\n\nconst TOAST_LIMIT = 1;\nconst TOAST_REMOVE_DELAY = 1000000;\n\ntype ToasterToast = ToastProps & {\n id: string;\n title?: React.ReactNode;\n description?: React.ReactNode;\n action?: ToastActionElement;\n};\n\nconst _actionTypes = {\n ADD_TOAST: \"ADD_TOAST\",\n UPDATE_TOAST: \"UPDATE_TOAST\",\n DISMISS_TOAST: \"DISMISS_TOAST\",\n REMOVE_TOAST: \"REMOVE_TOAST\",\n} as const;\n\nlet count = 0;\n\nfunction genId() {\n count = (count + 1) % Number.MAX_SAFE_INTEGER;\n return count.toString();\n}\n\ntype ActionType = typeof _actionTypes;\n\ntype Action =\n | {\n type: ActionType[\"ADD_TOAST\"];\n toast: ToasterToast;\n }\n | {\n type: ActionType[\"UPDATE_TOAST\"];\n toast: Partial<ToasterToast>;\n }\n | {\n type: ActionType[\"DISMISS_TOAST\"];\n toastId?: ToasterToast[\"id\"];\n }\n | {\n type: ActionType[\"REMOVE_TOAST\"];\n toastId?: ToasterToast[\"id\"];\n };\n\ninterface State {\n toasts: ToasterToast[];\n}\n\nconst toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>();\n\nconst addToRemoveQueue = (toastId: string) => {\n if (toastTimeouts.has(toastId)) {\n return;\n }\n\n const timeout = setTimeout(() => {\n toastTimeouts.delete(toastId);\n dispatch({\n type: \"REMOVE_TOAST\",\n toastId: toastId,\n });\n }, TOAST_REMOVE_DELAY);\n\n toastTimeouts.set(toastId, timeout);\n};\n\nexport const reducer = (state: State, action: Action): State => {\n switch (action.type) {\n case \"ADD_TOAST\":\n return {\n ...state,\n toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),\n };\n\n case \"UPDATE_TOAST\":\n return {\n ...state,\n toasts: state.toasts.map((t) =>\n t.id === action.toast.id ? { ...t, ...action.toast } : t,\n ),\n };\n\n case \"DISMISS_TOAST\": {\n const { toastId } = action;\n\n // ! Side effects ! - This could be extracted into a dismissToast() action,\n // but I'll keep it here for simplicity\n if (toastId) {\n addToRemoveQueue(toastId);\n } else {\n state.toasts.forEach((toast) => {\n addToRemoveQueue(toast.id);\n });\n }\n\n return {\n ...state,\n toasts: state.toasts.map((t) =>\n t.id === toastId || toastId === undefined\n ? {\n ...t,\n open: false,\n }\n : t,\n ),\n };\n }\n case \"REMOVE_TOAST\":\n if (action.toastId === undefined) {\n return {\n ...state,\n toasts: [],\n };\n }\n return {\n ...state,\n toasts: state.toasts.filter((t) => t.id !== action.toastId),\n };\n }\n};\n\nconst listeners: Array<(state: State) => void> = [];\n\nlet memoryState: State = { toasts: [] };\n\nfunction dispatch(action: Action) {\n memoryState = reducer(memoryState, action);\n listeners.forEach((listener) => {\n listener(memoryState);\n });\n}\n\ntype Toast = Omit<ToasterToast, \"id\">;\n\nfunction toast({ ...props }: Toast) {\n const id = genId();\n\n const update = (props: ToasterToast) =>\n dispatch({\n type: \"UPDATE_TOAST\",\n toast: { ...props, id },\n });\n const dismiss = () => dispatch({ type: \"DISMISS_TOAST\", toastId: id });\n\n dispatch({\n type: \"ADD_TOAST\",\n toast: {\n ...props,\n id,\n open: true,\n onOpenChange: (open) => {\n if (!open) dismiss();\n },\n },\n });\n\n return {\n id: id,\n dismiss,\n update,\n };\n}\n\nfunction useToast() {\n const [state, setState] = React.useState<State>(memoryState);\n\n React.useEffect(() => {\n listeners.push(setState);\n return () => {\n const index = listeners.indexOf(setState);\n if (index > -1) {\n listeners.splice(index, 1);\n }\n };\n }, [state]);\n\n return {\n ...state,\n toast,\n dismiss: (toastId?: string) => dispatch({ type: \"DISMISS_TOAST\", toastId }),\n };\n}\n\nexport { useToast, toast };\n",
|
||||
"d1f1e0d62cb8d8d1e04c26e14de842d8a151f75812d81b046c65b5d1fe8e4b27": "import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n",
|
||||
"5cbfd5e41e9218faa071fd97a799497ba5e31423f3a38d4d16adae98a11b80a4": "import { createRoot } from \"react-dom/client\";\nimport App from \"./App.tsx\";\nimport \"./globals.css\";\n\ncreateRoot(document.getElementById(\"root\")!).render(<App />);\n",
|
||||
"70618b5f415d91c92bef86039e35d5f282e959276bf49ed204c9f78f7490c99c": "// Update this page (the content is just a fallback if you fail to update the page)\n\nimport { MadeWithDyad } from \"@/components/made-with-dyad\";\n\nconst Index = () => {\n return (\n <div className=\"min-h-screen flex items-center justify-center bg-gray-100\">\n <div className=\"text-center\">\n <h1 className=\"text-4xl font-bold mb-4\">Welcome to Your Blank App</h1>\n <p className=\"text-xl text-gray-600\">\n Start building your amazing project here!\n </p>\n </div>\n <MadeWithDyad />\n </div>\n );\n};\n\nexport default Index;\n",
|
||||
"940578bf01ac3dbdcb16f52528bd59903b2cce7698c8b39064f2791022567b0e": "import { useLocation } from \"react-router-dom\";\nimport { useEffect } from \"react\";\n\nconst NotFound = () => {\n const location = useLocation();\n\n useEffect(() => {\n console.error(\n \"404 Error: User attempted to access non-existent route:\",\n location.pathname,\n );\n }, [location.pathname]);\n\n return (\n <div className=\"min-h-screen flex items-center justify-center bg-gray-100\">\n <div className=\"text-center\">\n <h1 className=\"text-4xl font-bold mb-4\">404</h1>\n <p className=\"text-xl text-gray-600 mb-4\">Oops! Page not found</p>\n <a href=\"/\" className=\"text-blue-500 hover:text-blue-700 underline\">\n Return to Home\n </a>\n </div>\n </div>\n );\n};\n\nexport default NotFound;\n",
|
||||
"328f94e9c711410b23188484a0a2f38886d7732d5c375cefcba442ab6195783f": "import { toast } from \"sonner\";\n\nexport const showSuccess = (message: string) => {\n toast.success(message);\n};\n\nexport const showError = (message: string) => {\n toast.error(message);\n};\n\nexport const showLoading = (message: string) => {\n return toast.loading(message);\n};\n\nexport const dismissToast = (toastId: string) => {\n toast.dismiss(toastId);\n};\n",
|
||||
"65996936fbb042915f7b74a200fcdde7e410f32a669b1ab9597cfaa4b0faddb5": "/// <reference types=\"vite/client\" />\n",
|
||||
|
||||
@@ -7,11 +7,12 @@
|
||||
- img
|
||||
- text: "src/pages/Index.tsx Summary: intentionally add first error"
|
||||
- img
|
||||
- text: Error
|
||||
- text: Error First error in Index...
|
||||
- img
|
||||
- button "Copy":
|
||||
- img
|
||||
- button "Fix with AI":
|
||||
- img
|
||||
- text: First error in Index...
|
||||
- img
|
||||
- img
|
||||
- text: ErrorComponent.tsx
|
||||
- button "Edit":
|
||||
@@ -19,11 +20,12 @@
|
||||
- img
|
||||
- text: "src/components/ErrorComponent.tsx Summary: intentionally add second error"
|
||||
- img
|
||||
- text: Error
|
||||
- text: Error Second error in ErrorComponent...
|
||||
- img
|
||||
- button "Copy":
|
||||
- img
|
||||
- button "Fix with AI":
|
||||
- img
|
||||
- text: Second error in ErrorComponent...
|
||||
- img
|
||||
- img
|
||||
- text: helper.ts
|
||||
- button "Edit":
|
||||
@@ -31,11 +33,12 @@
|
||||
- img
|
||||
- text: "src/utils/helper.ts Summary: intentionally add third error"
|
||||
- img
|
||||
- text: Error
|
||||
- text: Error Third error in helper...
|
||||
- img
|
||||
- button "Copy":
|
||||
- img
|
||||
- button "Fix with AI":
|
||||
- img
|
||||
- text: Third error in helper...
|
||||
- img
|
||||
- button "Fix All Errors (3)":
|
||||
- img
|
||||
- button:
|
||||
|
||||
@@ -88,7 +88,6 @@
|
||||
},
|
||||
{
|
||||
"path": "src/components/made-with-dyad.tsx",
|
||||
"content": "export const MadeWithDyad = () => {\n return (\n <div className=\"p-4 text-center\">\n <a\n href=\"https://www.dyad.sh/\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-sm text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200\"\n >\n Made with Dyad\n </a>\n </div>\n );\n};\n",
|
||||
"force": false
|
||||
},
|
||||
{
|
||||
@@ -363,7 +362,6 @@
|
||||
},
|
||||
{
|
||||
"path": "src/pages/Index.tsx",
|
||||
"content": "// Update this page (the content is just a fallback if you fail to update the page)\n\nimport { MadeWithDyad } from \"@/components/made-with-dyad\";\n\nconst Index = () => {\n return (\n <div className=\"min-h-screen flex items-center justify-center bg-gray-100\">\n <div className=\"text-center\">\n <h1 className=\"text-4xl font-bold mb-4\">Welcome to Your Blank App</h1>\n <p className=\"text-xl text-gray-600\">\n Start building your amazing project here!\n </p>\n </div>\n <MadeWithDyad />\n </div>\n );\n};\n\nexport default Index;\n",
|
||||
"force": false
|
||||
},
|
||||
{
|
||||
|
||||
@@ -247,7 +247,6 @@ export default App;
|
||||
</dyad-file>
|
||||
|
||||
<dyad-file path="src/components/made-with-dyad.tsx">
|
||||
export const MadeWithDyad = () => {
|
||||
return (
|
||||
<div className="p-4 text-center">
|
||||
<a
|
||||
@@ -804,7 +803,6 @@ createRoot(document.getElementById("root")!).render(<App />);
|
||||
<dyad-file path="src/pages/Index.tsx">
|
||||
// Update this page (the content is just a fallback if you fail to update the page)
|
||||
|
||||
import { MadeWithDyad } from "@/components/made-with-dyad";
|
||||
|
||||
const Index = () => {
|
||||
return (
|
||||
@@ -815,7 +813,6 @@ const Index = () => {
|
||||
Start building your amazing project here!
|
||||
</p>
|
||||
</div>
|
||||
<MadeWithDyad />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -244,7 +244,6 @@ export default App;
|
||||
</dyad-file>
|
||||
|
||||
<dyad-file path="src/components/made-with-dyad.tsx">
|
||||
export const MadeWithDyad = () => {
|
||||
return (
|
||||
<div className="p-4 text-center">
|
||||
<a
|
||||
@@ -801,7 +800,6 @@ createRoot(document.getElementById("root")!).render(<App />);
|
||||
<dyad-file path="src/pages/Index.tsx">
|
||||
// Update this page (the content is just a fallback if you fail to update the page)
|
||||
|
||||
import { MadeWithDyad } from "@/components/made-with-dyad";
|
||||
|
||||
const Index = () => {
|
||||
return (
|
||||
@@ -812,7 +810,6 @@ const Index = () => {
|
||||
Start building your amazing project here!
|
||||
</p>
|
||||
</div>
|
||||
<MadeWithDyad />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -16,5 +16,6 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "beta",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -16,5 +16,6 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -253,7 +253,6 @@ export default App;
|
||||
</dyad-file>
|
||||
|
||||
<dyad-file path="src/components/made-with-dyad.tsx">
|
||||
export const MadeWithDyad = () => {
|
||||
return (
|
||||
<div className="p-4 text-center">
|
||||
<a
|
||||
@@ -810,7 +809,6 @@ createRoot(document.getElementById("root")!).render(<App />);
|
||||
<dyad-file path="src/pages/Index.tsx">
|
||||
// Update this page (the content is just a fallback if you fail to update the page)
|
||||
|
||||
import { MadeWithDyad } from "@/components/made-with-dyad";
|
||||
|
||||
const Index = () => {
|
||||
return (
|
||||
@@ -821,7 +819,6 @@ const Index = () => {
|
||||
Start building your amazing project here!
|
||||
</p>
|
||||
</div>
|
||||
<MadeWithDyad />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -244,7 +244,6 @@ export default App;
|
||||
</dyad-file>
|
||||
|
||||
<dyad-file path="src/components/made-with-dyad.tsx">
|
||||
export const MadeWithDyad = () => {
|
||||
return (
|
||||
<div className="p-4 text-center">
|
||||
<a
|
||||
@@ -801,7 +800,6 @@ createRoot(document.getElementById("root")!).render(<App />);
|
||||
<dyad-file path="src/pages/Index.tsx">
|
||||
// Update this page (the content is just a fallback if you fail to update the page)
|
||||
|
||||
import { MadeWithDyad } from "@/components/made-with-dyad";
|
||||
|
||||
const Index = () => {
|
||||
return (
|
||||
@@ -812,7 +810,6 @@ const Index = () => {
|
||||
Start building your amazing project here!
|
||||
</p>
|
||||
</div>
|
||||
<MadeWithDyad />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -5,6 +5,5 @@
|
||||
- button "Deselect component":
|
||||
- img
|
||||
- img
|
||||
- text: a src/components/made-with-dyad.tsx:4
|
||||
- button "Deselect component":
|
||||
- img
|
||||
@@ -5,4 +5,3 @@
|
||||
- paragraph: Start building your amazing project here!
|
||||
- link "Made with Dyad":
|
||||
- /url: https://www.dyad.sh/
|
||||
- text: a src/components/made-with-dyad.tsx
|
||||
@@ -1,6 +1,5 @@
|
||||
- text: Selected Components (1)
|
||||
- button "Clear all"
|
||||
- img
|
||||
- text: a src/components/made-with-dyad.tsx:4
|
||||
- button "Deselect component":
|
||||
- img
|
||||
@@ -66,7 +66,6 @@ role: user
|
||||
message: This is my codebase. <dyad-file path="src/pages/Index.tsx">
|
||||
// Update this page (the content is just a fallback if you fail to update the page)
|
||||
|
||||
import { MadeWithDyad } from "@/components/made-with-dyad";
|
||||
|
||||
const Index = () => {
|
||||
return (
|
||||
@@ -77,7 +76,6 @@ const Index = () => {
|
||||
Start building your amazing project here!
|
||||
</p>
|
||||
</div>
|
||||
<MadeWithDyad />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -118,7 +118,6 @@ You need to first add Supabase to your app and then we can add auth.
|
||||
===
|
||||
role: user
|
||||
message: This is my codebase. <dyad-file path="src/app/page.tsx">
|
||||
import { MadeWithDyad } from "@/components/made-with-dyad";
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
@@ -126,7 +125,6 @@ export default function Home() {
|
||||
<main className="flex flex-col gap-8 row-start-1 items-center sm:items-start">
|
||||
<h1>Blank page</h1>
|
||||
</main>
|
||||
<MadeWithDyad />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -160,6 +158,5 @@ Snippet:
|
||||
<main className="flex flex-col gap-8 row-start-1 items-center sm:items-start">
|
||||
<h1>Blank page</h1> // <-- EDIT HERE
|
||||
</main>
|
||||
<MadeWithDyad />
|
||||
</div>
|
||||
```
|
||||
@@ -5,4 +5,3 @@
|
||||
- paragraph: Start building your amazing project here!
|
||||
- link "Made with Dyad":
|
||||
- /url: https://www.dyad.sh/
|
||||
- text: a src/components/made-with-dyad.tsx
|
||||
@@ -5,6 +5,5 @@
|
||||
- button "Deselect component":
|
||||
- img
|
||||
- img
|
||||
- text: a src/components/made-with-dyad.tsx:4
|
||||
- button "Deselect component":
|
||||
- img
|
||||
@@ -0,0 +1,12 @@
|
||||
- paragraph: "[dump]"
|
||||
- paragraph: "[[dyad-dump-path=*]]"
|
||||
- button:
|
||||
- img
|
||||
- img
|
||||
- text: Approved
|
||||
- img
|
||||
- text: less than a minute ago
|
||||
- button "Request ID":
|
||||
- img
|
||||
- button "Retry":
|
||||
- img
|
||||
@@ -88,7 +88,6 @@
|
||||
},
|
||||
{
|
||||
"path": "src/components/made-with-dyad.tsx",
|
||||
"content": "export const MadeWithDyad = () => {\n return (\n <div className=\"p-4 text-center\">\n <a\n href=\"https://www.dyad.sh/\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-sm text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200\"\n >\n Made with Dyad\n </a>\n </div>\n );\n};\n",
|
||||
"force": false
|
||||
},
|
||||
{
|
||||
@@ -363,7 +362,6 @@
|
||||
},
|
||||
{
|
||||
"path": "src/pages/Index.tsx",
|
||||
"content": "// Update this page (the content is just a fallback if you fail to update the page)\n\nimport { MadeWithDyad } from \"@/components/made-with-dyad\";\n\nconst Index = () => {\n return (\n <div className=\"min-h-screen flex items-center justify-center bg-gray-100\">\n <div className=\"text-center\">\n <h1 className=\"text-4xl font-bold mb-4\">Welcome to Your Blank App</h1>\n <p className=\"text-xl text-gray-600\">\n Start building your amazing project here!\n </p>\n </div>\n <MadeWithDyad />\n </div>\n );\n};\n\nexport default Index;\n",
|
||||
"force": false
|
||||
},
|
||||
{
|
||||
|
||||
@@ -57,7 +57,6 @@
|
||||
"5f1387ce504f44bce8e80b0f29e6aee60c3e8227c70db37231ad0dadb0117fe0": "# Welcome to your Dyad app\n",
|
||||
"a0715e0a09edbd0fbde65816a75e0fa0fc8b314c5260c0768c19bf3aac22621a": "#root {\n max-width: 1280px;\n margin: 0 auto;\n padding: 2rem;\n text-align: center;\n}\n\n.logo {\n height: 6em;\n padding: 1.5em;\n will-change: filter;\n transition: filter 300ms;\n}\n.logo:hover {\n filter: drop-shadow(0 0 2em #646cffaa);\n}\n.logo.react:hover {\n filter: drop-shadow(0 0 2em #61dafbaa);\n}\n\n@keyframes logo-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n\n@media (prefers-reduced-motion: no-preference) {\n a:nth-of-type(2) .logo {\n animation: logo-spin infinite 20s linear;\n }\n}\n\n.card {\n padding: 2em;\n}\n\n.read-the-docs {\n color: #888;\n}\n",
|
||||
"4e69ef9f71a824d0a6b0965300a4738f34e54a39d58433104162a61b6d072d49": "import { Toaster } from \"@/components/ui/toaster\";\nimport { Toaster as Sonner } from \"@/components/ui/sonner\";\nimport { TooltipProvider } from \"@/components/ui/tooltip\";\nimport { QueryClient, QueryClientProvider } from \"@tanstack/react-query\";\nimport { BrowserRouter, Routes, Route } from \"react-router-dom\";\nimport Index from \"./pages/Index\";\nimport NotFound from \"./pages/NotFound\";\n\nconst queryClient = new QueryClient();\n\nconst App = () => (\n <QueryClientProvider client={queryClient}>\n <TooltipProvider>\n <Toaster />\n <Sonner />\n <BrowserRouter>\n <Routes>\n <Route path=\"/\" element={<Index />} />\n {/* ADD ALL CUSTOM ROUTES ABOVE THE CATCH-ALL \"*\" ROUTE */}\n <Route path=\"*\" element={<NotFound />} />\n </Routes>\n </BrowserRouter>\n </TooltipProvider>\n </QueryClientProvider>\n);\n\nexport default App;\n",
|
||||
"b8d3ed0643f99b45851f98668e6ca4163004a878967abd283373393753c26666": "export const MadeWithDyad = () => {\n return (\n <div className=\"p-4 text-center\">\n <a\n href=\"https://www.dyad.sh/\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-sm text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200\"\n >\n Made with Dyad\n </a>\n </div>\n );\n};\n",
|
||||
"b728b30af5d9f770a34d5b4ae85ea720c90664fa55d83ad3d9835f48f20f5846": "import * as React from \"react\";\nimport * as AccordionPrimitive from \"@radix-ui/react-accordion\";\nimport { ChevronDown } from \"lucide-react\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst Accordion = AccordionPrimitive.Root;\n\nconst AccordionItem = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>\n>(({ className, ...props }, ref) => (\n <AccordionPrimitive.Item\n ref={ref}\n className={cn(\"border-b\", className)}\n {...props}\n />\n));\nAccordionItem.displayName = \"AccordionItem\";\n\nconst AccordionTrigger = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>\n>(({ className, children, ...props }, ref) => (\n <AccordionPrimitive.Header className=\"flex\">\n <AccordionPrimitive.Trigger\n ref={ref}\n className={cn(\n \"flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180\",\n className,\n )}\n {...props}\n >\n {children}\n <ChevronDown className=\"h-4 w-4 shrink-0 transition-transform duration-200\" />\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n));\nAccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;\n\nconst AccordionContent = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>\n>(({ className, children, ...props }, ref) => (\n <AccordionPrimitive.Content\n ref={ref}\n className=\"overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down\"\n {...props}\n >\n <div className={cn(\"pb-4 pt-0\", className)}>{children}</div>\n </AccordionPrimitive.Content>\n));\n\nAccordionContent.displayName = AccordionPrimitive.Content.displayName;\n\nexport { Accordion, AccordionItem, AccordionTrigger, AccordionContent };\n",
|
||||
"6f5d2b743e097cc0f38a8201fc9472bbcffa7ef80653eb09ac1733f470dd675c": "import * as React from \"react\";\nimport * as AlertDialogPrimitive from \"@radix-ui/react-alert-dialog\";\n\nimport { cn } from \"@/lib/utils\";\nimport { buttonVariants } from \"@/components/ui/button\";\n\nconst AlertDialog = AlertDialogPrimitive.Root;\n\nconst AlertDialogTrigger = AlertDialogPrimitive.Trigger;\n\nconst AlertDialogPortal = AlertDialogPrimitive.Portal;\n\nconst AlertDialogOverlay = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Overlay>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Overlay\n className={cn(\n \"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n className,\n )}\n {...props}\n ref={ref}\n />\n));\nAlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;\n\nconst AlertDialogContent = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content>\n>(({ className, ...props }, ref) => (\n <AlertDialogPortal>\n <AlertDialogOverlay />\n <AlertDialogPrimitive.Content\n ref={ref}\n className={cn(\n \"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg\",\n className,\n )}\n {...props}\n />\n </AlertDialogPortal>\n));\nAlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;\n\nconst AlertDialogHeader = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n \"flex flex-col space-y-2 text-center sm:text-left\",\n className,\n )}\n {...props}\n />\n);\nAlertDialogHeader.displayName = \"AlertDialogHeader\";\n\nconst AlertDialogFooter = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n \"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2\",\n className,\n )}\n {...props}\n />\n);\nAlertDialogFooter.displayName = \"AlertDialogFooter\";\n\nconst AlertDialogTitle = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Title>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Title\n ref={ref}\n className={cn(\"text-lg font-semibold\", className)}\n {...props}\n />\n));\nAlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;\n\nconst AlertDialogDescription = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Description>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Description\n ref={ref}\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n));\nAlertDialogDescription.displayName =\n AlertDialogPrimitive.Description.displayName;\n\nconst AlertDialogAction = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Action>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Action\n ref={ref}\n className={cn(buttonVariants(), className)}\n {...props}\n />\n));\nAlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName;\n\nconst AlertDialogCancel = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Cancel>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Cancel\n ref={ref}\n className={cn(\n buttonVariants({ variant: \"outline\" }),\n \"mt-2 sm:mt-0\",\n className,\n )}\n {...props}\n />\n));\nAlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName;\n\nexport {\n AlertDialog,\n AlertDialogPortal,\n AlertDialogOverlay,\n AlertDialogTrigger,\n AlertDialogContent,\n AlertDialogHeader,\n AlertDialogFooter,\n AlertDialogTitle,\n AlertDialogDescription,\n AlertDialogAction,\n AlertDialogCancel,\n};\n",
|
||||
"050c08a3ec850a8fae8579b2bdbb4c9b8aa64744b580f07e2b26f7e6fc17dac0": "import * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst alertVariants = cva(\n \"relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground\",\n {\n variants: {\n variant: {\n default: \"bg-background text-foreground\",\n destructive:\n \"border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n },\n);\n\nconst Alert = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>\n>(({ className, variant, ...props }, ref) => (\n <div\n ref={ref}\n role=\"alert\"\n className={cn(alertVariants({ variant }), className)}\n {...props}\n />\n));\nAlert.displayName = \"Alert\";\n\nconst AlertTitle = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLHeadingElement>\n>(({ className, ...props }, ref) => (\n <h5\n ref={ref}\n className={cn(\"mb-1 font-medium leading-none tracking-tight\", className)}\n {...props}\n />\n));\nAlertTitle.displayName = \"AlertTitle\";\n\nconst AlertDescription = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\"text-sm [&_p]:leading-relaxed\", className)}\n {...props}\n />\n));\nAlertDescription.displayName = \"AlertDescription\";\n\nexport { Alert, AlertTitle, AlertDescription };\n",
|
||||
@@ -122,7 +121,6 @@
|
||||
"a96b9ba5e40d95b92adf56431fdf9cbe25b5c2557621f0666615bff6889dfc50": "{\n \"compilerOptions\": {\n \"target\": \"ES2022\",\n \"lib\": [\"ES2023\"],\n \"module\": \"ESNext\",\n \"skipLibCheck\": true,\n\n /* Bundler mode */\n \"moduleResolution\": \"bundler\",\n \"allowImportingTsExtensions\": true,\n \"isolatedModules\": true,\n \"moduleDetection\": \"force\",\n \"noEmit\": true,\n\n /* Linting */\n \"strict\": true,\n \"noUnusedLocals\": false,\n \"noUnusedParameters\": false,\n \"noFallthroughCasesInSwitch\": true\n },\n \"include\": [\"vite.config.ts\"]\n}\n",
|
||||
"29afc6166ec968586a13e65e526754525abfbac1ef73ad5c6b9c75e2c16697f7": "{\n \"$schema\": \"https://openapi.vercel.sh/vercel.json\",\n \"rewrites\": [\n {\n \"source\": \"/(.*)\",\n \"destination\": \"/index.html\"\n }\n ]\n}\n",
|
||||
"92e6e1a0685f5d2cbe4e9f58d9fd2e8cb74d7ec6b0c93bfd25341edf47f3c130": "import { defineConfig } from \"vite\";\nimport dyadComponentTagger from \"@dyad-sh/react-vite-component-tagger\";\nimport react from \"@vitejs/plugin-react-swc\";\nimport path from \"path\";\n\nexport default defineConfig(() => ({\n server: {\n host: \"::\",\n port: 8080,\n },\n plugins: [dyadComponentTagger(), react()],\n resolve: {\n alias: {\n \"@\": path.resolve(__dirname, \"./src\"),\n },\n },\n}));\n",
|
||||
"70618b5f415d91c92bef86039e35d5f282e959276bf49ed204c9f78f7490c99c": "// Update this page (the content is just a fallback if you fail to update the page)\n\nimport { MadeWithDyad } from \"@/components/made-with-dyad\";\n\nconst Index = () => {\n return (\n <div className=\"min-h-screen flex items-center justify-center bg-gray-100\">\n <div className=\"text-center\">\n <h1 className=\"text-4xl font-bold mb-4\">Welcome to Your Blank App</h1>\n <p className=\"text-xl text-gray-600\">\n Start building your amazing project here!\n </p>\n </div>\n <MadeWithDyad />\n </div>\n );\n};\n\nexport default Index;\n"
|
||||
},
|
||||
"fileReferences": [
|
||||
{
|
||||
|
||||
@@ -24,5 +24,6 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -25,5 +25,6 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -24,5 +24,6 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -25,5 +25,6 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -15,5 +15,6 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -16,5 +16,6 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -15,5 +15,6 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -16,5 +16,6 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -15,5 +15,6 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -16,5 +16,6 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -16,5 +16,6 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -17,5 +17,6 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -17,5 +17,6 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -25,5 +25,6 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "Error: Test case file not found: 1.md"
|
||||
"content": "1"
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
@@ -41,7 +41,6 @@
|
||||
"5f1387ce504f44bce8e80b0f29e6aee60c3e8227c70db37231ad0dadb0117fe0": "# Welcome to your Dyad app\n",
|
||||
"a0715e0a09edbd0fbde65816a75e0fa0fc8b314c5260c0768c19bf3aac22621a": "#root {\n max-width: 1280px;\n margin: 0 auto;\n padding: 2rem;\n text-align: center;\n}\n\n.logo {\n height: 6em;\n padding: 1.5em;\n will-change: filter;\n transition: filter 300ms;\n}\n.logo:hover {\n filter: drop-shadow(0 0 2em #646cffaa);\n}\n.logo.react:hover {\n filter: drop-shadow(0 0 2em #61dafbaa);\n}\n\n@keyframes logo-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n\n@media (prefers-reduced-motion: no-preference) {\n a:nth-of-type(2) .logo {\n animation: logo-spin infinite 20s linear;\n }\n}\n\n.card {\n padding: 2em;\n}\n\n.read-the-docs {\n color: #888;\n}\n",
|
||||
"4e69ef9f71a824d0a6b0965300a4738f34e54a39d58433104162a61b6d072d49": "import { Toaster } from \"@/components/ui/toaster\";\nimport { Toaster as Sonner } from \"@/components/ui/sonner\";\nimport { TooltipProvider } from \"@/components/ui/tooltip\";\nimport { QueryClient, QueryClientProvider } from \"@tanstack/react-query\";\nimport { BrowserRouter, Routes, Route } from \"react-router-dom\";\nimport Index from \"./pages/Index\";\nimport NotFound from \"./pages/NotFound\";\n\nconst queryClient = new QueryClient();\n\nconst App = () => (\n <QueryClientProvider client={queryClient}>\n <TooltipProvider>\n <Toaster />\n <Sonner />\n <BrowserRouter>\n <Routes>\n <Route path=\"/\" element={<Index />} />\n {/* ADD ALL CUSTOM ROUTES ABOVE THE CATCH-ALL \"*\" ROUTE */}\n <Route path=\"*\" element={<NotFound />} />\n </Routes>\n </BrowserRouter>\n </TooltipProvider>\n </QueryClientProvider>\n);\n\nexport default App;\n",
|
||||
"b8d3ed0643f99b45851f98668e6ca4163004a878967abd283373393753c26666": "export const MadeWithDyad = () => {\n return (\n <div className=\"p-4 text-center\">\n <a\n href=\"https://www.dyad.sh/\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-sm text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200\"\n >\n Made with Dyad\n </a>\n </div>\n );\n};\n",
|
||||
"b728b30af5d9f770a34d5b4ae85ea720c90664fa55d83ad3d9835f48f20f5846": "import * as React from \"react\";\nimport * as AccordionPrimitive from \"@radix-ui/react-accordion\";\nimport { ChevronDown } from \"lucide-react\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst Accordion = AccordionPrimitive.Root;\n\nconst AccordionItem = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>\n>(({ className, ...props }, ref) => (\n <AccordionPrimitive.Item\n ref={ref}\n className={cn(\"border-b\", className)}\n {...props}\n />\n));\nAccordionItem.displayName = \"AccordionItem\";\n\nconst AccordionTrigger = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>\n>(({ className, children, ...props }, ref) => (\n <AccordionPrimitive.Header className=\"flex\">\n <AccordionPrimitive.Trigger\n ref={ref}\n className={cn(\n \"flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180\",\n className,\n )}\n {...props}\n >\n {children}\n <ChevronDown className=\"h-4 w-4 shrink-0 transition-transform duration-200\" />\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n));\nAccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;\n\nconst AccordionContent = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>\n>(({ className, children, ...props }, ref) => (\n <AccordionPrimitive.Content\n ref={ref}\n className=\"overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down\"\n {...props}\n >\n <div className={cn(\"pb-4 pt-0\", className)}>{children}</div>\n </AccordionPrimitive.Content>\n));\n\nAccordionContent.displayName = AccordionPrimitive.Content.displayName;\n\nexport { Accordion, AccordionItem, AccordionTrigger, AccordionContent };\n",
|
||||
"6f5d2b743e097cc0f38a8201fc9472bbcffa7ef80653eb09ac1733f470dd675c": "import * as React from \"react\";\nimport * as AlertDialogPrimitive from \"@radix-ui/react-alert-dialog\";\n\nimport { cn } from \"@/lib/utils\";\nimport { buttonVariants } from \"@/components/ui/button\";\n\nconst AlertDialog = AlertDialogPrimitive.Root;\n\nconst AlertDialogTrigger = AlertDialogPrimitive.Trigger;\n\nconst AlertDialogPortal = AlertDialogPrimitive.Portal;\n\nconst AlertDialogOverlay = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Overlay>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Overlay\n className={cn(\n \"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n className,\n )}\n {...props}\n ref={ref}\n />\n));\nAlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;\n\nconst AlertDialogContent = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content>\n>(({ className, ...props }, ref) => (\n <AlertDialogPortal>\n <AlertDialogOverlay />\n <AlertDialogPrimitive.Content\n ref={ref}\n className={cn(\n \"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg\",\n className,\n )}\n {...props}\n />\n </AlertDialogPortal>\n));\nAlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;\n\nconst AlertDialogHeader = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n \"flex flex-col space-y-2 text-center sm:text-left\",\n className,\n )}\n {...props}\n />\n);\nAlertDialogHeader.displayName = \"AlertDialogHeader\";\n\nconst AlertDialogFooter = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n \"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2\",\n className,\n )}\n {...props}\n />\n);\nAlertDialogFooter.displayName = \"AlertDialogFooter\";\n\nconst AlertDialogTitle = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Title>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Title\n ref={ref}\n className={cn(\"text-lg font-semibold\", className)}\n {...props}\n />\n));\nAlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;\n\nconst AlertDialogDescription = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Description>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Description\n ref={ref}\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n));\nAlertDialogDescription.displayName =\n AlertDialogPrimitive.Description.displayName;\n\nconst AlertDialogAction = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Action>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Action\n ref={ref}\n className={cn(buttonVariants(), className)}\n {...props}\n />\n));\nAlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName;\n\nconst AlertDialogCancel = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Cancel>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Cancel\n ref={ref}\n className={cn(\n buttonVariants({ variant: \"outline\" }),\n \"mt-2 sm:mt-0\",\n className,\n )}\n {...props}\n />\n));\nAlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName;\n\nexport {\n AlertDialog,\n AlertDialogPortal,\n AlertDialogOverlay,\n AlertDialogTrigger,\n AlertDialogContent,\n AlertDialogHeader,\n AlertDialogFooter,\n AlertDialogTitle,\n AlertDialogDescription,\n AlertDialogAction,\n AlertDialogCancel,\n};\n",
|
||||
"050c08a3ec850a8fae8579b2bdbb4c9b8aa64744b580f07e2b26f7e6fc17dac0": "import * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst alertVariants = cva(\n \"relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground\",\n {\n variants: {\n variant: {\n default: \"bg-background text-foreground\",\n destructive:\n \"border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n },\n);\n\nconst Alert = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>\n>(({ className, variant, ...props }, ref) => (\n <div\n ref={ref}\n role=\"alert\"\n className={cn(alertVariants({ variant }), className)}\n {...props}\n />\n));\nAlert.displayName = \"Alert\";\n\nconst AlertTitle = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLHeadingElement>\n>(({ className, ...props }, ref) => (\n <h5\n ref={ref}\n className={cn(\"mb-1 font-medium leading-none tracking-tight\", className)}\n {...props}\n />\n));\nAlertTitle.displayName = \"AlertTitle\";\n\nconst AlertDescription = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\"text-sm [&_p]:leading-relaxed\", className)}\n {...props}\n />\n));\nAlertDescription.displayName = \"AlertDescription\";\n\nexport { Alert, AlertTitle, AlertDescription };\n",
|
||||
@@ -96,7 +95,6 @@
|
||||
"4b70ac2ad6f1c640249bb43667f86d8447985c49be8bd0335897ad0ae7c70694": "import * as React from \"react\";\n\nimport type { ToastActionElement, ToastProps } from \"@/components/ui/toast\";\n\nconst TOAST_LIMIT = 1;\nconst TOAST_REMOVE_DELAY = 1000000;\n\ntype ToasterToast = ToastProps & {\n id: string;\n title?: React.ReactNode;\n description?: React.ReactNode;\n action?: ToastActionElement;\n};\n\nconst _actionTypes = {\n ADD_TOAST: \"ADD_TOAST\",\n UPDATE_TOAST: \"UPDATE_TOAST\",\n DISMISS_TOAST: \"DISMISS_TOAST\",\n REMOVE_TOAST: \"REMOVE_TOAST\",\n} as const;\n\nlet count = 0;\n\nfunction genId() {\n count = (count + 1) % Number.MAX_SAFE_INTEGER;\n return count.toString();\n}\n\ntype ActionType = typeof _actionTypes;\n\ntype Action =\n | {\n type: ActionType[\"ADD_TOAST\"];\n toast: ToasterToast;\n }\n | {\n type: ActionType[\"UPDATE_TOAST\"];\n toast: Partial<ToasterToast>;\n }\n | {\n type: ActionType[\"DISMISS_TOAST\"];\n toastId?: ToasterToast[\"id\"];\n }\n | {\n type: ActionType[\"REMOVE_TOAST\"];\n toastId?: ToasterToast[\"id\"];\n };\n\ninterface State {\n toasts: ToasterToast[];\n}\n\nconst toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>();\n\nconst addToRemoveQueue = (toastId: string) => {\n if (toastTimeouts.has(toastId)) {\n return;\n }\n\n const timeout = setTimeout(() => {\n toastTimeouts.delete(toastId);\n dispatch({\n type: \"REMOVE_TOAST\",\n toastId: toastId,\n });\n }, TOAST_REMOVE_DELAY);\n\n toastTimeouts.set(toastId, timeout);\n};\n\nexport const reducer = (state: State, action: Action): State => {\n switch (action.type) {\n case \"ADD_TOAST\":\n return {\n ...state,\n toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),\n };\n\n case \"UPDATE_TOAST\":\n return {\n ...state,\n toasts: state.toasts.map((t) =>\n t.id === action.toast.id ? { ...t, ...action.toast } : t,\n ),\n };\n\n case \"DISMISS_TOAST\": {\n const { toastId } = action;\n\n // ! Side effects ! - This could be extracted into a dismissToast() action,\n // but I'll keep it here for simplicity\n if (toastId) {\n addToRemoveQueue(toastId);\n } else {\n state.toasts.forEach((toast) => {\n addToRemoveQueue(toast.id);\n });\n }\n\n return {\n ...state,\n toasts: state.toasts.map((t) =>\n t.id === toastId || toastId === undefined\n ? {\n ...t,\n open: false,\n }\n : t,\n ),\n };\n }\n case \"REMOVE_TOAST\":\n if (action.toastId === undefined) {\n return {\n ...state,\n toasts: [],\n };\n }\n return {\n ...state,\n toasts: state.toasts.filter((t) => t.id !== action.toastId),\n };\n }\n};\n\nconst listeners: Array<(state: State) => void> = [];\n\nlet memoryState: State = { toasts: [] };\n\nfunction dispatch(action: Action) {\n memoryState = reducer(memoryState, action);\n listeners.forEach((listener) => {\n listener(memoryState);\n });\n}\n\ntype Toast = Omit<ToasterToast, \"id\">;\n\nfunction toast({ ...props }: Toast) {\n const id = genId();\n\n const update = (props: ToasterToast) =>\n dispatch({\n type: \"UPDATE_TOAST\",\n toast: { ...props, id },\n });\n const dismiss = () => dispatch({ type: \"DISMISS_TOAST\", toastId: id });\n\n dispatch({\n type: \"ADD_TOAST\",\n toast: {\n ...props,\n id,\n open: true,\n onOpenChange: (open) => {\n if (!open) dismiss();\n },\n },\n });\n\n return {\n id: id,\n dismiss,\n update,\n };\n}\n\nfunction useToast() {\n const [state, setState] = React.useState<State>(memoryState);\n\n React.useEffect(() => {\n listeners.push(setState);\n return () => {\n const index = listeners.indexOf(setState);\n if (index > -1) {\n listeners.splice(index, 1);\n }\n };\n }, [state]);\n\n return {\n ...state,\n toast,\n dismiss: (toastId?: string) => dispatch({ type: \"DISMISS_TOAST\", toastId }),\n };\n}\n\nexport { useToast, toast };\n",
|
||||
"d1f1e0d62cb8d8d1e04c26e14de842d8a151f75812d81b046c65b5d1fe8e4b27": "import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n",
|
||||
"5cbfd5e41e9218faa071fd97a799497ba5e31423f3a38d4d16adae98a11b80a4": "import { createRoot } from \"react-dom/client\";\nimport App from \"./App.tsx\";\nimport \"./globals.css\";\n\ncreateRoot(document.getElementById(\"root\")!).render(<App />);\n",
|
||||
"70618b5f415d91c92bef86039e35d5f282e959276bf49ed204c9f78f7490c99c": "// Update this page (the content is just a fallback if you fail to update the page)\n\nimport { MadeWithDyad } from \"@/components/made-with-dyad\";\n\nconst Index = () => {\n return (\n <div className=\"min-h-screen flex items-center justify-center bg-gray-100\">\n <div className=\"text-center\">\n <h1 className=\"text-4xl font-bold mb-4\">Welcome to Your Blank App</h1>\n <p className=\"text-xl text-gray-600\">\n Start building your amazing project here!\n </p>\n </div>\n <MadeWithDyad />\n </div>\n );\n};\n\nexport default Index;\n",
|
||||
"940578bf01ac3dbdcb16f52528bd59903b2cce7698c8b39064f2791022567b0e": "import { useLocation } from \"react-router-dom\";\nimport { useEffect } from \"react\";\n\nconst NotFound = () => {\n const location = useLocation();\n\n useEffect(() => {\n console.error(\n \"404 Error: User attempted to access non-existent route:\",\n location.pathname,\n );\n }, [location.pathname]);\n\n return (\n <div className=\"min-h-screen flex items-center justify-center bg-gray-100\">\n <div className=\"text-center\">\n <h1 className=\"text-4xl font-bold mb-4\">404</h1>\n <p className=\"text-xl text-gray-600 mb-4\">Oops! Page not found</p>\n <a href=\"/\" className=\"text-blue-500 hover:text-blue-700 underline\">\n Return to Home\n </a>\n </div>\n </div>\n );\n};\n\nexport default NotFound;\n",
|
||||
"328f94e9c711410b23188484a0a2f38886d7732d5c375cefcba442ab6195783f": "import { toast } from \"sonner\";\n\nexport const showSuccess = (message: string) => {\n toast.success(message);\n};\n\nexport const showError = (message: string) => {\n toast.error(message);\n};\n\nexport const showLoading = (message: string) => {\n return toast.loading(message);\n};\n\nexport const dismissToast = (toastId: string) => {\n toast.dismiss(toastId);\n};\n",
|
||||
"65996936fbb042915f7b74a200fcdde7e410f32a669b1ab9597cfaa4b0faddb5": "/// <reference types=\"vite/client\" />\n",
|
||||
|
||||
@@ -25,5 +25,6 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "Error: Test case file not found: 1.md"
|
||||
"content": "1"
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
@@ -49,7 +49,6 @@
|
||||
"5f1387ce504f44bce8e80b0f29e6aee60c3e8227c70db37231ad0dadb0117fe0": "# Welcome to your Dyad app\n",
|
||||
"a0715e0a09edbd0fbde65816a75e0fa0fc8b314c5260c0768c19bf3aac22621a": "#root {\n max-width: 1280px;\n margin: 0 auto;\n padding: 2rem;\n text-align: center;\n}\n\n.logo {\n height: 6em;\n padding: 1.5em;\n will-change: filter;\n transition: filter 300ms;\n}\n.logo:hover {\n filter: drop-shadow(0 0 2em #646cffaa);\n}\n.logo.react:hover {\n filter: drop-shadow(0 0 2em #61dafbaa);\n}\n\n@keyframes logo-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n\n@media (prefers-reduced-motion: no-preference) {\n a:nth-of-type(2) .logo {\n animation: logo-spin infinite 20s linear;\n }\n}\n\n.card {\n padding: 2em;\n}\n\n.read-the-docs {\n color: #888;\n}\n",
|
||||
"4e69ef9f71a824d0a6b0965300a4738f34e54a39d58433104162a61b6d072d49": "import { Toaster } from \"@/components/ui/toaster\";\nimport { Toaster as Sonner } from \"@/components/ui/sonner\";\nimport { TooltipProvider } from \"@/components/ui/tooltip\";\nimport { QueryClient, QueryClientProvider } from \"@tanstack/react-query\";\nimport { BrowserRouter, Routes, Route } from \"react-router-dom\";\nimport Index from \"./pages/Index\";\nimport NotFound from \"./pages/NotFound\";\n\nconst queryClient = new QueryClient();\n\nconst App = () => (\n <QueryClientProvider client={queryClient}>\n <TooltipProvider>\n <Toaster />\n <Sonner />\n <BrowserRouter>\n <Routes>\n <Route path=\"/\" element={<Index />} />\n {/* ADD ALL CUSTOM ROUTES ABOVE THE CATCH-ALL \"*\" ROUTE */}\n <Route path=\"*\" element={<NotFound />} />\n </Routes>\n </BrowserRouter>\n </TooltipProvider>\n </QueryClientProvider>\n);\n\nexport default App;\n",
|
||||
"b8d3ed0643f99b45851f98668e6ca4163004a878967abd283373393753c26666": "export const MadeWithDyad = () => {\n return (\n <div className=\"p-4 text-center\">\n <a\n href=\"https://www.dyad.sh/\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-sm text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200\"\n >\n Made with Dyad\n </a>\n </div>\n );\n};\n",
|
||||
"b728b30af5d9f770a34d5b4ae85ea720c90664fa55d83ad3d9835f48f20f5846": "import * as React from \"react\";\nimport * as AccordionPrimitive from \"@radix-ui/react-accordion\";\nimport { ChevronDown } from \"lucide-react\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst Accordion = AccordionPrimitive.Root;\n\nconst AccordionItem = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>\n>(({ className, ...props }, ref) => (\n <AccordionPrimitive.Item\n ref={ref}\n className={cn(\"border-b\", className)}\n {...props}\n />\n));\nAccordionItem.displayName = \"AccordionItem\";\n\nconst AccordionTrigger = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>\n>(({ className, children, ...props }, ref) => (\n <AccordionPrimitive.Header className=\"flex\">\n <AccordionPrimitive.Trigger\n ref={ref}\n className={cn(\n \"flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180\",\n className,\n )}\n {...props}\n >\n {children}\n <ChevronDown className=\"h-4 w-4 shrink-0 transition-transform duration-200\" />\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n));\nAccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;\n\nconst AccordionContent = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>\n>(({ className, children, ...props }, ref) => (\n <AccordionPrimitive.Content\n ref={ref}\n className=\"overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down\"\n {...props}\n >\n <div className={cn(\"pb-4 pt-0\", className)}>{children}</div>\n </AccordionPrimitive.Content>\n));\n\nAccordionContent.displayName = AccordionPrimitive.Content.displayName;\n\nexport { Accordion, AccordionItem, AccordionTrigger, AccordionContent };\n",
|
||||
"6f5d2b743e097cc0f38a8201fc9472bbcffa7ef80653eb09ac1733f470dd675c": "import * as React from \"react\";\nimport * as AlertDialogPrimitive from \"@radix-ui/react-alert-dialog\";\n\nimport { cn } from \"@/lib/utils\";\nimport { buttonVariants } from \"@/components/ui/button\";\n\nconst AlertDialog = AlertDialogPrimitive.Root;\n\nconst AlertDialogTrigger = AlertDialogPrimitive.Trigger;\n\nconst AlertDialogPortal = AlertDialogPrimitive.Portal;\n\nconst AlertDialogOverlay = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Overlay>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Overlay\n className={cn(\n \"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n className,\n )}\n {...props}\n ref={ref}\n />\n));\nAlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;\n\nconst AlertDialogContent = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content>\n>(({ className, ...props }, ref) => (\n <AlertDialogPortal>\n <AlertDialogOverlay />\n <AlertDialogPrimitive.Content\n ref={ref}\n className={cn(\n \"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg\",\n className,\n )}\n {...props}\n />\n </AlertDialogPortal>\n));\nAlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;\n\nconst AlertDialogHeader = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n \"flex flex-col space-y-2 text-center sm:text-left\",\n className,\n )}\n {...props}\n />\n);\nAlertDialogHeader.displayName = \"AlertDialogHeader\";\n\nconst AlertDialogFooter = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n \"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2\",\n className,\n )}\n {...props}\n />\n);\nAlertDialogFooter.displayName = \"AlertDialogFooter\";\n\nconst AlertDialogTitle = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Title>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Title\n ref={ref}\n className={cn(\"text-lg font-semibold\", className)}\n {...props}\n />\n));\nAlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;\n\nconst AlertDialogDescription = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Description>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Description\n ref={ref}\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n));\nAlertDialogDescription.displayName =\n AlertDialogPrimitive.Description.displayName;\n\nconst AlertDialogAction = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Action>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Action\n ref={ref}\n className={cn(buttonVariants(), className)}\n {...props}\n />\n));\nAlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName;\n\nconst AlertDialogCancel = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Cancel>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Cancel\n ref={ref}\n className={cn(\n buttonVariants({ variant: \"outline\" }),\n \"mt-2 sm:mt-0\",\n className,\n )}\n {...props}\n />\n));\nAlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName;\n\nexport {\n AlertDialog,\n AlertDialogPortal,\n AlertDialogOverlay,\n AlertDialogTrigger,\n AlertDialogContent,\n AlertDialogHeader,\n AlertDialogFooter,\n AlertDialogTitle,\n AlertDialogDescription,\n AlertDialogAction,\n AlertDialogCancel,\n};\n",
|
||||
"050c08a3ec850a8fae8579b2bdbb4c9b8aa64744b580f07e2b26f7e6fc17dac0": "import * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst alertVariants = cva(\n \"relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground\",\n {\n variants: {\n variant: {\n default: \"bg-background text-foreground\",\n destructive:\n \"border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n },\n);\n\nconst Alert = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>\n>(({ className, variant, ...props }, ref) => (\n <div\n ref={ref}\n role=\"alert\"\n className={cn(alertVariants({ variant }), className)}\n {...props}\n />\n));\nAlert.displayName = \"Alert\";\n\nconst AlertTitle = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLHeadingElement>\n>(({ className, ...props }, ref) => (\n <h5\n ref={ref}\n className={cn(\"mb-1 font-medium leading-none tracking-tight\", className)}\n {...props}\n />\n));\nAlertTitle.displayName = \"AlertTitle\";\n\nconst AlertDescription = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\"text-sm [&_p]:leading-relaxed\", className)}\n {...props}\n />\n));\nAlertDescription.displayName = \"AlertDescription\";\n\nexport { Alert, AlertTitle, AlertDescription };\n",
|
||||
@@ -104,7 +103,6 @@
|
||||
"4b70ac2ad6f1c640249bb43667f86d8447985c49be8bd0335897ad0ae7c70694": "import * as React from \"react\";\n\nimport type { ToastActionElement, ToastProps } from \"@/components/ui/toast\";\n\nconst TOAST_LIMIT = 1;\nconst TOAST_REMOVE_DELAY = 1000000;\n\ntype ToasterToast = ToastProps & {\n id: string;\n title?: React.ReactNode;\n description?: React.ReactNode;\n action?: ToastActionElement;\n};\n\nconst _actionTypes = {\n ADD_TOAST: \"ADD_TOAST\",\n UPDATE_TOAST: \"UPDATE_TOAST\",\n DISMISS_TOAST: \"DISMISS_TOAST\",\n REMOVE_TOAST: \"REMOVE_TOAST\",\n} as const;\n\nlet count = 0;\n\nfunction genId() {\n count = (count + 1) % Number.MAX_SAFE_INTEGER;\n return count.toString();\n}\n\ntype ActionType = typeof _actionTypes;\n\ntype Action =\n | {\n type: ActionType[\"ADD_TOAST\"];\n toast: ToasterToast;\n }\n | {\n type: ActionType[\"UPDATE_TOAST\"];\n toast: Partial<ToasterToast>;\n }\n | {\n type: ActionType[\"DISMISS_TOAST\"];\n toastId?: ToasterToast[\"id\"];\n }\n | {\n type: ActionType[\"REMOVE_TOAST\"];\n toastId?: ToasterToast[\"id\"];\n };\n\ninterface State {\n toasts: ToasterToast[];\n}\n\nconst toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>();\n\nconst addToRemoveQueue = (toastId: string) => {\n if (toastTimeouts.has(toastId)) {\n return;\n }\n\n const timeout = setTimeout(() => {\n toastTimeouts.delete(toastId);\n dispatch({\n type: \"REMOVE_TOAST\",\n toastId: toastId,\n });\n }, TOAST_REMOVE_DELAY);\n\n toastTimeouts.set(toastId, timeout);\n};\n\nexport const reducer = (state: State, action: Action): State => {\n switch (action.type) {\n case \"ADD_TOAST\":\n return {\n ...state,\n toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),\n };\n\n case \"UPDATE_TOAST\":\n return {\n ...state,\n toasts: state.toasts.map((t) =>\n t.id === action.toast.id ? { ...t, ...action.toast } : t,\n ),\n };\n\n case \"DISMISS_TOAST\": {\n const { toastId } = action;\n\n // ! Side effects ! - This could be extracted into a dismissToast() action,\n // but I'll keep it here for simplicity\n if (toastId) {\n addToRemoveQueue(toastId);\n } else {\n state.toasts.forEach((toast) => {\n addToRemoveQueue(toast.id);\n });\n }\n\n return {\n ...state,\n toasts: state.toasts.map((t) =>\n t.id === toastId || toastId === undefined\n ? {\n ...t,\n open: false,\n }\n : t,\n ),\n };\n }\n case \"REMOVE_TOAST\":\n if (action.toastId === undefined) {\n return {\n ...state,\n toasts: [],\n };\n }\n return {\n ...state,\n toasts: state.toasts.filter((t) => t.id !== action.toastId),\n };\n }\n};\n\nconst listeners: Array<(state: State) => void> = [];\n\nlet memoryState: State = { toasts: [] };\n\nfunction dispatch(action: Action) {\n memoryState = reducer(memoryState, action);\n listeners.forEach((listener) => {\n listener(memoryState);\n });\n}\n\ntype Toast = Omit<ToasterToast, \"id\">;\n\nfunction toast({ ...props }: Toast) {\n const id = genId();\n\n const update = (props: ToasterToast) =>\n dispatch({\n type: \"UPDATE_TOAST\",\n toast: { ...props, id },\n });\n const dismiss = () => dispatch({ type: \"DISMISS_TOAST\", toastId: id });\n\n dispatch({\n type: \"ADD_TOAST\",\n toast: {\n ...props,\n id,\n open: true,\n onOpenChange: (open) => {\n if (!open) dismiss();\n },\n },\n });\n\n return {\n id: id,\n dismiss,\n update,\n };\n}\n\nfunction useToast() {\n const [state, setState] = React.useState<State>(memoryState);\n\n React.useEffect(() => {\n listeners.push(setState);\n return () => {\n const index = listeners.indexOf(setState);\n if (index > -1) {\n listeners.splice(index, 1);\n }\n };\n }, [state]);\n\n return {\n ...state,\n toast,\n dismiss: (toastId?: string) => dispatch({ type: \"DISMISS_TOAST\", toastId }),\n };\n}\n\nexport { useToast, toast };\n",
|
||||
"d1f1e0d62cb8d8d1e04c26e14de842d8a151f75812d81b046c65b5d1fe8e4b27": "import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n",
|
||||
"5cbfd5e41e9218faa071fd97a799497ba5e31423f3a38d4d16adae98a11b80a4": "import { createRoot } from \"react-dom/client\";\nimport App from \"./App.tsx\";\nimport \"./globals.css\";\n\ncreateRoot(document.getElementById(\"root\")!).render(<App />);\n",
|
||||
"70618b5f415d91c92bef86039e35d5f282e959276bf49ed204c9f78f7490c99c": "// Update this page (the content is just a fallback if you fail to update the page)\n\nimport { MadeWithDyad } from \"@/components/made-with-dyad\";\n\nconst Index = () => {\n return (\n <div className=\"min-h-screen flex items-center justify-center bg-gray-100\">\n <div className=\"text-center\">\n <h1 className=\"text-4xl font-bold mb-4\">Welcome to Your Blank App</h1>\n <p className=\"text-xl text-gray-600\">\n Start building your amazing project here!\n </p>\n </div>\n <MadeWithDyad />\n </div>\n );\n};\n\nexport default Index;\n",
|
||||
"940578bf01ac3dbdcb16f52528bd59903b2cce7698c8b39064f2791022567b0e": "import { useLocation } from \"react-router-dom\";\nimport { useEffect } from \"react\";\n\nconst NotFound = () => {\n const location = useLocation();\n\n useEffect(() => {\n console.error(\n \"404 Error: User attempted to access non-existent route:\",\n location.pathname,\n );\n }, [location.pathname]);\n\n return (\n <div className=\"min-h-screen flex items-center justify-center bg-gray-100\">\n <div className=\"text-center\">\n <h1 className=\"text-4xl font-bold mb-4\">404</h1>\n <p className=\"text-xl text-gray-600 mb-4\">Oops! Page not found</p>\n <a href=\"/\" className=\"text-blue-500 hover:text-blue-700 underline\">\n Return to Home\n </a>\n </div>\n </div>\n );\n};\n\nexport default NotFound;\n",
|
||||
"328f94e9c711410b23188484a0a2f38886d7732d5c375cefcba442ab6195783f": "import { toast } from \"sonner\";\n\nexport const showSuccess = (message: string) => {\n toast.success(message);\n};\n\nexport const showError = (message: string) => {\n toast.error(message);\n};\n\nexport const showLoading = (message: string) => {\n return toast.loading(message);\n};\n\nexport const dismissToast = (toastId: string) => {\n toast.dismiss(toastId);\n};\n",
|
||||
"65996936fbb042915f7b74a200fcdde7e410f32a669b1ab9597cfaa4b0faddb5": "/// <reference types=\"vite/client\" />\n",
|
||||
|
||||
@@ -25,5 +25,6 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "Error: Test case file not found: 1.md"
|
||||
"content": "1"
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
@@ -57,7 +57,6 @@
|
||||
"5f1387ce504f44bce8e80b0f29e6aee60c3e8227c70db37231ad0dadb0117fe0": "# Welcome to your Dyad app\n",
|
||||
"a0715e0a09edbd0fbde65816a75e0fa0fc8b314c5260c0768c19bf3aac22621a": "#root {\n max-width: 1280px;\n margin: 0 auto;\n padding: 2rem;\n text-align: center;\n}\n\n.logo {\n height: 6em;\n padding: 1.5em;\n will-change: filter;\n transition: filter 300ms;\n}\n.logo:hover {\n filter: drop-shadow(0 0 2em #646cffaa);\n}\n.logo.react:hover {\n filter: drop-shadow(0 0 2em #61dafbaa);\n}\n\n@keyframes logo-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n\n@media (prefers-reduced-motion: no-preference) {\n a:nth-of-type(2) .logo {\n animation: logo-spin infinite 20s linear;\n }\n}\n\n.card {\n padding: 2em;\n}\n\n.read-the-docs {\n color: #888;\n}\n",
|
||||
"4e69ef9f71a824d0a6b0965300a4738f34e54a39d58433104162a61b6d072d49": "import { Toaster } from \"@/components/ui/toaster\";\nimport { Toaster as Sonner } from \"@/components/ui/sonner\";\nimport { TooltipProvider } from \"@/components/ui/tooltip\";\nimport { QueryClient, QueryClientProvider } from \"@tanstack/react-query\";\nimport { BrowserRouter, Routes, Route } from \"react-router-dom\";\nimport Index from \"./pages/Index\";\nimport NotFound from \"./pages/NotFound\";\n\nconst queryClient = new QueryClient();\n\nconst App = () => (\n <QueryClientProvider client={queryClient}>\n <TooltipProvider>\n <Toaster />\n <Sonner />\n <BrowserRouter>\n <Routes>\n <Route path=\"/\" element={<Index />} />\n {/* ADD ALL CUSTOM ROUTES ABOVE THE CATCH-ALL \"*\" ROUTE */}\n <Route path=\"*\" element={<NotFound />} />\n </Routes>\n </BrowserRouter>\n </TooltipProvider>\n </QueryClientProvider>\n);\n\nexport default App;\n",
|
||||
"b8d3ed0643f99b45851f98668e6ca4163004a878967abd283373393753c26666": "export const MadeWithDyad = () => {\n return (\n <div className=\"p-4 text-center\">\n <a\n href=\"https://www.dyad.sh/\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-sm text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200\"\n >\n Made with Dyad\n </a>\n </div>\n );\n};\n",
|
||||
"b728b30af5d9f770a34d5b4ae85ea720c90664fa55d83ad3d9835f48f20f5846": "import * as React from \"react\";\nimport * as AccordionPrimitive from \"@radix-ui/react-accordion\";\nimport { ChevronDown } from \"lucide-react\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst Accordion = AccordionPrimitive.Root;\n\nconst AccordionItem = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>\n>(({ className, ...props }, ref) => (\n <AccordionPrimitive.Item\n ref={ref}\n className={cn(\"border-b\", className)}\n {...props}\n />\n));\nAccordionItem.displayName = \"AccordionItem\";\n\nconst AccordionTrigger = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>\n>(({ className, children, ...props }, ref) => (\n <AccordionPrimitive.Header className=\"flex\">\n <AccordionPrimitive.Trigger\n ref={ref}\n className={cn(\n \"flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180\",\n className,\n )}\n {...props}\n >\n {children}\n <ChevronDown className=\"h-4 w-4 shrink-0 transition-transform duration-200\" />\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n));\nAccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;\n\nconst AccordionContent = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>\n>(({ className, children, ...props }, ref) => (\n <AccordionPrimitive.Content\n ref={ref}\n className=\"overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down\"\n {...props}\n >\n <div className={cn(\"pb-4 pt-0\", className)}>{children}</div>\n </AccordionPrimitive.Content>\n));\n\nAccordionContent.displayName = AccordionPrimitive.Content.displayName;\n\nexport { Accordion, AccordionItem, AccordionTrigger, AccordionContent };\n",
|
||||
"6f5d2b743e097cc0f38a8201fc9472bbcffa7ef80653eb09ac1733f470dd675c": "import * as React from \"react\";\nimport * as AlertDialogPrimitive from \"@radix-ui/react-alert-dialog\";\n\nimport { cn } from \"@/lib/utils\";\nimport { buttonVariants } from \"@/components/ui/button\";\n\nconst AlertDialog = AlertDialogPrimitive.Root;\n\nconst AlertDialogTrigger = AlertDialogPrimitive.Trigger;\n\nconst AlertDialogPortal = AlertDialogPrimitive.Portal;\n\nconst AlertDialogOverlay = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Overlay>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Overlay\n className={cn(\n \"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n className,\n )}\n {...props}\n ref={ref}\n />\n));\nAlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;\n\nconst AlertDialogContent = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content>\n>(({ className, ...props }, ref) => (\n <AlertDialogPortal>\n <AlertDialogOverlay />\n <AlertDialogPrimitive.Content\n ref={ref}\n className={cn(\n \"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg\",\n className,\n )}\n {...props}\n />\n </AlertDialogPortal>\n));\nAlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;\n\nconst AlertDialogHeader = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n \"flex flex-col space-y-2 text-center sm:text-left\",\n className,\n )}\n {...props}\n />\n);\nAlertDialogHeader.displayName = \"AlertDialogHeader\";\n\nconst AlertDialogFooter = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n \"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2\",\n className,\n )}\n {...props}\n />\n);\nAlertDialogFooter.displayName = \"AlertDialogFooter\";\n\nconst AlertDialogTitle = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Title>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Title\n ref={ref}\n className={cn(\"text-lg font-semibold\", className)}\n {...props}\n />\n));\nAlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;\n\nconst AlertDialogDescription = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Description>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Description\n ref={ref}\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n));\nAlertDialogDescription.displayName =\n AlertDialogPrimitive.Description.displayName;\n\nconst AlertDialogAction = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Action>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Action\n ref={ref}\n className={cn(buttonVariants(), className)}\n {...props}\n />\n));\nAlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName;\n\nconst AlertDialogCancel = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Cancel>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Cancel\n ref={ref}\n className={cn(\n buttonVariants({ variant: \"outline\" }),\n \"mt-2 sm:mt-0\",\n className,\n )}\n {...props}\n />\n));\nAlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName;\n\nexport {\n AlertDialog,\n AlertDialogPortal,\n AlertDialogOverlay,\n AlertDialogTrigger,\n AlertDialogContent,\n AlertDialogHeader,\n AlertDialogFooter,\n AlertDialogTitle,\n AlertDialogDescription,\n AlertDialogAction,\n AlertDialogCancel,\n};\n",
|
||||
"050c08a3ec850a8fae8579b2bdbb4c9b8aa64744b580f07e2b26f7e6fc17dac0": "import * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst alertVariants = cva(\n \"relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground\",\n {\n variants: {\n variant: {\n default: \"bg-background text-foreground\",\n destructive:\n \"border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n },\n);\n\nconst Alert = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>\n>(({ className, variant, ...props }, ref) => (\n <div\n ref={ref}\n role=\"alert\"\n className={cn(alertVariants({ variant }), className)}\n {...props}\n />\n));\nAlert.displayName = \"Alert\";\n\nconst AlertTitle = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLHeadingElement>\n>(({ className, ...props }, ref) => (\n <h5\n ref={ref}\n className={cn(\"mb-1 font-medium leading-none tracking-tight\", className)}\n {...props}\n />\n));\nAlertTitle.displayName = \"AlertTitle\";\n\nconst AlertDescription = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\"text-sm [&_p]:leading-relaxed\", className)}\n {...props}\n />\n));\nAlertDescription.displayName = \"AlertDescription\";\n\nexport { Alert, AlertTitle, AlertDescription };\n",
|
||||
@@ -112,7 +111,6 @@
|
||||
"4b70ac2ad6f1c640249bb43667f86d8447985c49be8bd0335897ad0ae7c70694": "import * as React from \"react\";\n\nimport type { ToastActionElement, ToastProps } from \"@/components/ui/toast\";\n\nconst TOAST_LIMIT = 1;\nconst TOAST_REMOVE_DELAY = 1000000;\n\ntype ToasterToast = ToastProps & {\n id: string;\n title?: React.ReactNode;\n description?: React.ReactNode;\n action?: ToastActionElement;\n};\n\nconst _actionTypes = {\n ADD_TOAST: \"ADD_TOAST\",\n UPDATE_TOAST: \"UPDATE_TOAST\",\n DISMISS_TOAST: \"DISMISS_TOAST\",\n REMOVE_TOAST: \"REMOVE_TOAST\",\n} as const;\n\nlet count = 0;\n\nfunction genId() {\n count = (count + 1) % Number.MAX_SAFE_INTEGER;\n return count.toString();\n}\n\ntype ActionType = typeof _actionTypes;\n\ntype Action =\n | {\n type: ActionType[\"ADD_TOAST\"];\n toast: ToasterToast;\n }\n | {\n type: ActionType[\"UPDATE_TOAST\"];\n toast: Partial<ToasterToast>;\n }\n | {\n type: ActionType[\"DISMISS_TOAST\"];\n toastId?: ToasterToast[\"id\"];\n }\n | {\n type: ActionType[\"REMOVE_TOAST\"];\n toastId?: ToasterToast[\"id\"];\n };\n\ninterface State {\n toasts: ToasterToast[];\n}\n\nconst toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>();\n\nconst addToRemoveQueue = (toastId: string) => {\n if (toastTimeouts.has(toastId)) {\n return;\n }\n\n const timeout = setTimeout(() => {\n toastTimeouts.delete(toastId);\n dispatch({\n type: \"REMOVE_TOAST\",\n toastId: toastId,\n });\n }, TOAST_REMOVE_DELAY);\n\n toastTimeouts.set(toastId, timeout);\n};\n\nexport const reducer = (state: State, action: Action): State => {\n switch (action.type) {\n case \"ADD_TOAST\":\n return {\n ...state,\n toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),\n };\n\n case \"UPDATE_TOAST\":\n return {\n ...state,\n toasts: state.toasts.map((t) =>\n t.id === action.toast.id ? { ...t, ...action.toast } : t,\n ),\n };\n\n case \"DISMISS_TOAST\": {\n const { toastId } = action;\n\n // ! Side effects ! - This could be extracted into a dismissToast() action,\n // but I'll keep it here for simplicity\n if (toastId) {\n addToRemoveQueue(toastId);\n } else {\n state.toasts.forEach((toast) => {\n addToRemoveQueue(toast.id);\n });\n }\n\n return {\n ...state,\n toasts: state.toasts.map((t) =>\n t.id === toastId || toastId === undefined\n ? {\n ...t,\n open: false,\n }\n : t,\n ),\n };\n }\n case \"REMOVE_TOAST\":\n if (action.toastId === undefined) {\n return {\n ...state,\n toasts: [],\n };\n }\n return {\n ...state,\n toasts: state.toasts.filter((t) => t.id !== action.toastId),\n };\n }\n};\n\nconst listeners: Array<(state: State) => void> = [];\n\nlet memoryState: State = { toasts: [] };\n\nfunction dispatch(action: Action) {\n memoryState = reducer(memoryState, action);\n listeners.forEach((listener) => {\n listener(memoryState);\n });\n}\n\ntype Toast = Omit<ToasterToast, \"id\">;\n\nfunction toast({ ...props }: Toast) {\n const id = genId();\n\n const update = (props: ToasterToast) =>\n dispatch({\n type: \"UPDATE_TOAST\",\n toast: { ...props, id },\n });\n const dismiss = () => dispatch({ type: \"DISMISS_TOAST\", toastId: id });\n\n dispatch({\n type: \"ADD_TOAST\",\n toast: {\n ...props,\n id,\n open: true,\n onOpenChange: (open) => {\n if (!open) dismiss();\n },\n },\n });\n\n return {\n id: id,\n dismiss,\n update,\n };\n}\n\nfunction useToast() {\n const [state, setState] = React.useState<State>(memoryState);\n\n React.useEffect(() => {\n listeners.push(setState);\n return () => {\n const index = listeners.indexOf(setState);\n if (index > -1) {\n listeners.splice(index, 1);\n }\n };\n }, [state]);\n\n return {\n ...state,\n toast,\n dismiss: (toastId?: string) => dispatch({ type: \"DISMISS_TOAST\", toastId }),\n };\n}\n\nexport { useToast, toast };\n",
|
||||
"d1f1e0d62cb8d8d1e04c26e14de842d8a151f75812d81b046c65b5d1fe8e4b27": "import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n",
|
||||
"5cbfd5e41e9218faa071fd97a799497ba5e31423f3a38d4d16adae98a11b80a4": "import { createRoot } from \"react-dom/client\";\nimport App from \"./App.tsx\";\nimport \"./globals.css\";\n\ncreateRoot(document.getElementById(\"root\")!).render(<App />);\n",
|
||||
"70618b5f415d91c92bef86039e35d5f282e959276bf49ed204c9f78f7490c99c": "// Update this page (the content is just a fallback if you fail to update the page)\n\nimport { MadeWithDyad } from \"@/components/made-with-dyad\";\n\nconst Index = () => {\n return (\n <div className=\"min-h-screen flex items-center justify-center bg-gray-100\">\n <div className=\"text-center\">\n <h1 className=\"text-4xl font-bold mb-4\">Welcome to Your Blank App</h1>\n <p className=\"text-xl text-gray-600\">\n Start building your amazing project here!\n </p>\n </div>\n <MadeWithDyad />\n </div>\n );\n};\n\nexport default Index;\n",
|
||||
"940578bf01ac3dbdcb16f52528bd59903b2cce7698c8b39064f2791022567b0e": "import { useLocation } from \"react-router-dom\";\nimport { useEffect } from \"react\";\n\nconst NotFound = () => {\n const location = useLocation();\n\n useEffect(() => {\n console.error(\n \"404 Error: User attempted to access non-existent route:\",\n location.pathname,\n );\n }, [location.pathname]);\n\n return (\n <div className=\"min-h-screen flex items-center justify-center bg-gray-100\">\n <div className=\"text-center\">\n <h1 className=\"text-4xl font-bold mb-4\">404</h1>\n <p className=\"text-xl text-gray-600 mb-4\">Oops! Page not found</p>\n <a href=\"/\" className=\"text-blue-500 hover:text-blue-700 underline\">\n Return to Home\n </a>\n </div>\n </div>\n );\n};\n\nexport default NotFound;\n",
|
||||
"328f94e9c711410b23188484a0a2f38886d7732d5c375cefcba442ab6195783f": "import { toast } from \"sonner\";\n\nexport const showSuccess = (message: string) => {\n toast.success(message);\n};\n\nexport const showError = (message: string) => {\n toast.error(message);\n};\n\nexport const showLoading = (message: string) => {\n return toast.loading(message);\n};\n\nexport const dismissToast = (toastId: string) => {\n toast.dismiss(toastId);\n};\n",
|
||||
"65996936fbb042915f7b74a200fcdde7e410f32a669b1ab9597cfaa4b0faddb5": "/// <reference types=\"vite/client\" />\n",
|
||||
|
||||
@@ -24,5 +24,6 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -25,5 +25,6 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -25,5 +25,6 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -25,5 +25,6 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
=== src/pages/Index.tsx ===
|
||||
// Update this page (the content is just a fallback if you fail to update the page)
|
||||
|
||||
import { MadeWithDyad } from "@/components/made-with-dyad";
|
||||
|
||||
const Index = () => {
|
||||
return (
|
||||
@@ -12,7 +11,6 @@ const Index = () => {
|
||||
Start building your amazing project here!
|
||||
</p>
|
||||
</div>
|
||||
<MadeWithDyad />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
"5f1387ce504f44bce8e80b0f29e6aee60c3e8227c70db37231ad0dadb0117fe0": "# Welcome to your Dyad app\n",
|
||||
"a0715e0a09edbd0fbde65816a75e0fa0fc8b314c5260c0768c19bf3aac22621a": "#root {\n max-width: 1280px;\n margin: 0 auto;\n padding: 2rem;\n text-align: center;\n}\n\n.logo {\n height: 6em;\n padding: 1.5em;\n will-change: filter;\n transition: filter 300ms;\n}\n.logo:hover {\n filter: drop-shadow(0 0 2em #646cffaa);\n}\n.logo.react:hover {\n filter: drop-shadow(0 0 2em #61dafbaa);\n}\n\n@keyframes logo-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n\n@media (prefers-reduced-motion: no-preference) {\n a:nth-of-type(2) .logo {\n animation: logo-spin infinite 20s linear;\n }\n}\n\n.card {\n padding: 2em;\n}\n\n.read-the-docs {\n color: #888;\n}\n",
|
||||
"4e69ef9f71a824d0a6b0965300a4738f34e54a39d58433104162a61b6d072d49": "import { Toaster } from \"@/components/ui/toaster\";\nimport { Toaster as Sonner } from \"@/components/ui/sonner\";\nimport { TooltipProvider } from \"@/components/ui/tooltip\";\nimport { QueryClient, QueryClientProvider } from \"@tanstack/react-query\";\nimport { BrowserRouter, Routes, Route } from \"react-router-dom\";\nimport Index from \"./pages/Index\";\nimport NotFound from \"./pages/NotFound\";\n\nconst queryClient = new QueryClient();\n\nconst App = () => (\n <QueryClientProvider client={queryClient}>\n <TooltipProvider>\n <Toaster />\n <Sonner />\n <BrowserRouter>\n <Routes>\n <Route path=\"/\" element={<Index />} />\n {/* ADD ALL CUSTOM ROUTES ABOVE THE CATCH-ALL \"*\" ROUTE */}\n <Route path=\"*\" element={<NotFound />} />\n </Routes>\n </BrowserRouter>\n </TooltipProvider>\n </QueryClientProvider>\n);\n\nexport default App;\n",
|
||||
"b8d3ed0643f99b45851f98668e6ca4163004a878967abd283373393753c26666": "export const MadeWithDyad = () => {\n return (\n <div className=\"p-4 text-center\">\n <a\n href=\"https://www.dyad.sh/\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-sm text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200\"\n >\n Made with Dyad\n </a>\n </div>\n );\n};\n",
|
||||
"b728b30af5d9f770a34d5b4ae85ea720c90664fa55d83ad3d9835f48f20f5846": "import * as React from \"react\";\nimport * as AccordionPrimitive from \"@radix-ui/react-accordion\";\nimport { ChevronDown } from \"lucide-react\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst Accordion = AccordionPrimitive.Root;\n\nconst AccordionItem = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>\n>(({ className, ...props }, ref) => (\n <AccordionPrimitive.Item\n ref={ref}\n className={cn(\"border-b\", className)}\n {...props}\n />\n));\nAccordionItem.displayName = \"AccordionItem\";\n\nconst AccordionTrigger = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>\n>(({ className, children, ...props }, ref) => (\n <AccordionPrimitive.Header className=\"flex\">\n <AccordionPrimitive.Trigger\n ref={ref}\n className={cn(\n \"flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180\",\n className,\n )}\n {...props}\n >\n {children}\n <ChevronDown className=\"h-4 w-4 shrink-0 transition-transform duration-200\" />\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n));\nAccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;\n\nconst AccordionContent = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>\n>(({ className, children, ...props }, ref) => (\n <AccordionPrimitive.Content\n ref={ref}\n className=\"overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down\"\n {...props}\n >\n <div className={cn(\"pb-4 pt-0\", className)}>{children}</div>\n </AccordionPrimitive.Content>\n));\n\nAccordionContent.displayName = AccordionPrimitive.Content.displayName;\n\nexport { Accordion, AccordionItem, AccordionTrigger, AccordionContent };\n",
|
||||
"6f5d2b743e097cc0f38a8201fc9472bbcffa7ef80653eb09ac1733f470dd675c": "import * as React from \"react\";\nimport * as AlertDialogPrimitive from \"@radix-ui/react-alert-dialog\";\n\nimport { cn } from \"@/lib/utils\";\nimport { buttonVariants } from \"@/components/ui/button\";\n\nconst AlertDialog = AlertDialogPrimitive.Root;\n\nconst AlertDialogTrigger = AlertDialogPrimitive.Trigger;\n\nconst AlertDialogPortal = AlertDialogPrimitive.Portal;\n\nconst AlertDialogOverlay = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Overlay>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Overlay\n className={cn(\n \"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n className,\n )}\n {...props}\n ref={ref}\n />\n));\nAlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;\n\nconst AlertDialogContent = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content>\n>(({ className, ...props }, ref) => (\n <AlertDialogPortal>\n <AlertDialogOverlay />\n <AlertDialogPrimitive.Content\n ref={ref}\n className={cn(\n \"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg\",\n className,\n )}\n {...props}\n />\n </AlertDialogPortal>\n));\nAlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;\n\nconst AlertDialogHeader = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n \"flex flex-col space-y-2 text-center sm:text-left\",\n className,\n )}\n {...props}\n />\n);\nAlertDialogHeader.displayName = \"AlertDialogHeader\";\n\nconst AlertDialogFooter = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n \"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2\",\n className,\n )}\n {...props}\n />\n);\nAlertDialogFooter.displayName = \"AlertDialogFooter\";\n\nconst AlertDialogTitle = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Title>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Title\n ref={ref}\n className={cn(\"text-lg font-semibold\", className)}\n {...props}\n />\n));\nAlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;\n\nconst AlertDialogDescription = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Description>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Description\n ref={ref}\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n));\nAlertDialogDescription.displayName =\n AlertDialogPrimitive.Description.displayName;\n\nconst AlertDialogAction = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Action>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Action\n ref={ref}\n className={cn(buttonVariants(), className)}\n {...props}\n />\n));\nAlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName;\n\nconst AlertDialogCancel = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Cancel>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Cancel\n ref={ref}\n className={cn(\n buttonVariants({ variant: \"outline\" }),\n \"mt-2 sm:mt-0\",\n className,\n )}\n {...props}\n />\n));\nAlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName;\n\nexport {\n AlertDialog,\n AlertDialogPortal,\n AlertDialogOverlay,\n AlertDialogTrigger,\n AlertDialogContent,\n AlertDialogHeader,\n AlertDialogFooter,\n AlertDialogTitle,\n AlertDialogDescription,\n AlertDialogAction,\n AlertDialogCancel,\n};\n",
|
||||
"050c08a3ec850a8fae8579b2bdbb4c9b8aa64744b580f07e2b26f7e6fc17dac0": "import * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst alertVariants = cva(\n \"relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground\",\n {\n variants: {\n variant: {\n default: \"bg-background text-foreground\",\n destructive:\n \"border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n },\n);\n\nconst Alert = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>\n>(({ className, variant, ...props }, ref) => (\n <div\n ref={ref}\n role=\"alert\"\n className={cn(alertVariants({ variant }), className)}\n {...props}\n />\n));\nAlert.displayName = \"Alert\";\n\nconst AlertTitle = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLHeadingElement>\n>(({ className, ...props }, ref) => (\n <h5\n ref={ref}\n className={cn(\"mb-1 font-medium leading-none tracking-tight\", className)}\n {...props}\n />\n));\nAlertTitle.displayName = \"AlertTitle\";\n\nconst AlertDescription = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\"text-sm [&_p]:leading-relaxed\", className)}\n {...props}\n />\n));\nAlertDescription.displayName = \"AlertDescription\";\n\nexport { Alert, AlertTitle, AlertDescription };\n",
|
||||
@@ -88,7 +87,6 @@
|
||||
"4b70ac2ad6f1c640249bb43667f86d8447985c49be8bd0335897ad0ae7c70694": "import * as React from \"react\";\n\nimport type { ToastActionElement, ToastProps } from \"@/components/ui/toast\";\n\nconst TOAST_LIMIT = 1;\nconst TOAST_REMOVE_DELAY = 1000000;\n\ntype ToasterToast = ToastProps & {\n id: string;\n title?: React.ReactNode;\n description?: React.ReactNode;\n action?: ToastActionElement;\n};\n\nconst _actionTypes = {\n ADD_TOAST: \"ADD_TOAST\",\n UPDATE_TOAST: \"UPDATE_TOAST\",\n DISMISS_TOAST: \"DISMISS_TOAST\",\n REMOVE_TOAST: \"REMOVE_TOAST\",\n} as const;\n\nlet count = 0;\n\nfunction genId() {\n count = (count + 1) % Number.MAX_SAFE_INTEGER;\n return count.toString();\n}\n\ntype ActionType = typeof _actionTypes;\n\ntype Action =\n | {\n type: ActionType[\"ADD_TOAST\"];\n toast: ToasterToast;\n }\n | {\n type: ActionType[\"UPDATE_TOAST\"];\n toast: Partial<ToasterToast>;\n }\n | {\n type: ActionType[\"DISMISS_TOAST\"];\n toastId?: ToasterToast[\"id\"];\n }\n | {\n type: ActionType[\"REMOVE_TOAST\"];\n toastId?: ToasterToast[\"id\"];\n };\n\ninterface State {\n toasts: ToasterToast[];\n}\n\nconst toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>();\n\nconst addToRemoveQueue = (toastId: string) => {\n if (toastTimeouts.has(toastId)) {\n return;\n }\n\n const timeout = setTimeout(() => {\n toastTimeouts.delete(toastId);\n dispatch({\n type: \"REMOVE_TOAST\",\n toastId: toastId,\n });\n }, TOAST_REMOVE_DELAY);\n\n toastTimeouts.set(toastId, timeout);\n};\n\nexport const reducer = (state: State, action: Action): State => {\n switch (action.type) {\n case \"ADD_TOAST\":\n return {\n ...state,\n toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),\n };\n\n case \"UPDATE_TOAST\":\n return {\n ...state,\n toasts: state.toasts.map((t) =>\n t.id === action.toast.id ? { ...t, ...action.toast } : t,\n ),\n };\n\n case \"DISMISS_TOAST\": {\n const { toastId } = action;\n\n // ! Side effects ! - This could be extracted into a dismissToast() action,\n // but I'll keep it here for simplicity\n if (toastId) {\n addToRemoveQueue(toastId);\n } else {\n state.toasts.forEach((toast) => {\n addToRemoveQueue(toast.id);\n });\n }\n\n return {\n ...state,\n toasts: state.toasts.map((t) =>\n t.id === toastId || toastId === undefined\n ? {\n ...t,\n open: false,\n }\n : t,\n ),\n };\n }\n case \"REMOVE_TOAST\":\n if (action.toastId === undefined) {\n return {\n ...state,\n toasts: [],\n };\n }\n return {\n ...state,\n toasts: state.toasts.filter((t) => t.id !== action.toastId),\n };\n }\n};\n\nconst listeners: Array<(state: State) => void> = [];\n\nlet memoryState: State = { toasts: [] };\n\nfunction dispatch(action: Action) {\n memoryState = reducer(memoryState, action);\n listeners.forEach((listener) => {\n listener(memoryState);\n });\n}\n\ntype Toast = Omit<ToasterToast, \"id\">;\n\nfunction toast({ ...props }: Toast) {\n const id = genId();\n\n const update = (props: ToasterToast) =>\n dispatch({\n type: \"UPDATE_TOAST\",\n toast: { ...props, id },\n });\n const dismiss = () => dispatch({ type: \"DISMISS_TOAST\", toastId: id });\n\n dispatch({\n type: \"ADD_TOAST\",\n toast: {\n ...props,\n id,\n open: true,\n onOpenChange: (open) => {\n if (!open) dismiss();\n },\n },\n });\n\n return {\n id: id,\n dismiss,\n update,\n };\n}\n\nfunction useToast() {\n const [state, setState] = React.useState<State>(memoryState);\n\n React.useEffect(() => {\n listeners.push(setState);\n return () => {\n const index = listeners.indexOf(setState);\n if (index > -1) {\n listeners.splice(index, 1);\n }\n };\n }, [state]);\n\n return {\n ...state,\n toast,\n dismiss: (toastId?: string) => dispatch({ type: \"DISMISS_TOAST\", toastId }),\n };\n}\n\nexport { useToast, toast };\n",
|
||||
"d1f1e0d62cb8d8d1e04c26e14de842d8a151f75812d81b046c65b5d1fe8e4b27": "import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n",
|
||||
"5cbfd5e41e9218faa071fd97a799497ba5e31423f3a38d4d16adae98a11b80a4": "import { createRoot } from \"react-dom/client\";\nimport App from \"./App.tsx\";\nimport \"./globals.css\";\n\ncreateRoot(document.getElementById(\"root\")!).render(<App />);\n",
|
||||
"70618b5f415d91c92bef86039e35d5f282e959276bf49ed204c9f78f7490c99c": "// Update this page (the content is just a fallback if you fail to update the page)\n\nimport { MadeWithDyad } from \"@/components/made-with-dyad\";\n\nconst Index = () => {\n return (\n <div className=\"min-h-screen flex items-center justify-center bg-gray-100\">\n <div className=\"text-center\">\n <h1 className=\"text-4xl font-bold mb-4\">Welcome to Your Blank App</h1>\n <p className=\"text-xl text-gray-600\">\n Start building your amazing project here!\n </p>\n </div>\n <MadeWithDyad />\n </div>\n );\n};\n\nexport default Index;\n",
|
||||
"940578bf01ac3dbdcb16f52528bd59903b2cce7698c8b39064f2791022567b0e": "import { useLocation } from \"react-router-dom\";\nimport { useEffect } from \"react\";\n\nconst NotFound = () => {\n const location = useLocation();\n\n useEffect(() => {\n console.error(\n \"404 Error: User attempted to access non-existent route:\",\n location.pathname,\n );\n }, [location.pathname]);\n\n return (\n <div className=\"min-h-screen flex items-center justify-center bg-gray-100\">\n <div className=\"text-center\">\n <h1 className=\"text-4xl font-bold mb-4\">404</h1>\n <p className=\"text-xl text-gray-600 mb-4\">Oops! Page not found</p>\n <a href=\"/\" className=\"text-blue-500 hover:text-blue-700 underline\">\n Return to Home\n </a>\n </div>\n </div>\n );\n};\n\nexport default NotFound;\n",
|
||||
"328f94e9c711410b23188484a0a2f38886d7732d5c375cefcba442ab6195783f": "import { toast } from \"sonner\";\n\nexport const showSuccess = (message: string) => {\n toast.success(message);\n};\n\nexport const showError = (message: string) => {\n toast.error(message);\n};\n\nexport const showLoading = (message: string) => {\n return toast.loading(message);\n};\n\nexport const dismissToast = (toastId: string) => {\n toast.dismiss(toastId);\n};\n",
|
||||
"65996936fbb042915f7b74a200fcdde7e410f32a669b1ab9597cfaa4b0faddb5": "/// <reference types=\"vite/client\" />\n",
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": "There was an issue with the following `dyad-search-replace` tags. Make sure you use `dyad-read` to read the latest version of the file and then trying to do search & replace again.\n \nFile path: src/pages/Index.tsx\nError: Unable to apply search-replace to file"
|
||||
"content": "There was an issue with the following `dyad-search-replace` tags. Make sure you use `dyad-read` to read the latest version of the file and then trying to do search & replace again.\n \nFile path: src/pages/Index.tsx\nError: Unable to apply search-replace to file because: Search block did not match any content in the target file. Best fuzzy match had similarity of 0.0% (threshold: 90.0%)"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
@@ -26,7 +26,7 @@
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": "There was an issue with the following `dyad-search-replace` tags. Please fix the errors by generating the code changes using `dyad-write` tags instead.\n \nFile path: src/pages/Index.tsx\nError: Unable to apply search-replace to file"
|
||||
"content": "There was an issue with the following `dyad-search-replace` tags. Please fix the errors by generating the code changes using `dyad-write` tags instead.\n \nFile path: src/pages/Index.tsx\nError: Unable to apply search-replace to file because: Search block did not match any content in the target file. Best fuzzy match had similarity of 0.0% (threshold: 90.0%)"
|
||||
}
|
||||
],
|
||||
"stream": true,
|
||||
@@ -49,7 +49,6 @@
|
||||
"5f1387ce504f44bce8e80b0f29e6aee60c3e8227c70db37231ad0dadb0117fe0": "# Welcome to your Dyad app\n",
|
||||
"a0715e0a09edbd0fbde65816a75e0fa0fc8b314c5260c0768c19bf3aac22621a": "#root {\n max-width: 1280px;\n margin: 0 auto;\n padding: 2rem;\n text-align: center;\n}\n\n.logo {\n height: 6em;\n padding: 1.5em;\n will-change: filter;\n transition: filter 300ms;\n}\n.logo:hover {\n filter: drop-shadow(0 0 2em #646cffaa);\n}\n.logo.react:hover {\n filter: drop-shadow(0 0 2em #61dafbaa);\n}\n\n@keyframes logo-spin {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(360deg);\n }\n}\n\n@media (prefers-reduced-motion: no-preference) {\n a:nth-of-type(2) .logo {\n animation: logo-spin infinite 20s linear;\n }\n}\n\n.card {\n padding: 2em;\n}\n\n.read-the-docs {\n color: #888;\n}\n",
|
||||
"4e69ef9f71a824d0a6b0965300a4738f34e54a39d58433104162a61b6d072d49": "import { Toaster } from \"@/components/ui/toaster\";\nimport { Toaster as Sonner } from \"@/components/ui/sonner\";\nimport { TooltipProvider } from \"@/components/ui/tooltip\";\nimport { QueryClient, QueryClientProvider } from \"@tanstack/react-query\";\nimport { BrowserRouter, Routes, Route } from \"react-router-dom\";\nimport Index from \"./pages/Index\";\nimport NotFound from \"./pages/NotFound\";\n\nconst queryClient = new QueryClient();\n\nconst App = () => (\n <QueryClientProvider client={queryClient}>\n <TooltipProvider>\n <Toaster />\n <Sonner />\n <BrowserRouter>\n <Routes>\n <Route path=\"/\" element={<Index />} />\n {/* ADD ALL CUSTOM ROUTES ABOVE THE CATCH-ALL \"*\" ROUTE */}\n <Route path=\"*\" element={<NotFound />} />\n </Routes>\n </BrowserRouter>\n </TooltipProvider>\n </QueryClientProvider>\n);\n\nexport default App;\n",
|
||||
"b8d3ed0643f99b45851f98668e6ca4163004a878967abd283373393753c26666": "export const MadeWithDyad = () => {\n return (\n <div className=\"p-4 text-center\">\n <a\n href=\"https://www.dyad.sh/\"\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-sm text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200\"\n >\n Made with Dyad\n </a>\n </div>\n );\n};\n",
|
||||
"b728b30af5d9f770a34d5b4ae85ea720c90664fa55d83ad3d9835f48f20f5846": "import * as React from \"react\";\nimport * as AccordionPrimitive from \"@radix-ui/react-accordion\";\nimport { ChevronDown } from \"lucide-react\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst Accordion = AccordionPrimitive.Root;\n\nconst AccordionItem = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>\n>(({ className, ...props }, ref) => (\n <AccordionPrimitive.Item\n ref={ref}\n className={cn(\"border-b\", className)}\n {...props}\n />\n));\nAccordionItem.displayName = \"AccordionItem\";\n\nconst AccordionTrigger = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Trigger>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>\n>(({ className, children, ...props }, ref) => (\n <AccordionPrimitive.Header className=\"flex\">\n <AccordionPrimitive.Trigger\n ref={ref}\n className={cn(\n \"flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180\",\n className,\n )}\n {...props}\n >\n {children}\n <ChevronDown className=\"h-4 w-4 shrink-0 transition-transform duration-200\" />\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n));\nAccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;\n\nconst AccordionContent = React.forwardRef<\n React.ElementRef<typeof AccordionPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>\n>(({ className, children, ...props }, ref) => (\n <AccordionPrimitive.Content\n ref={ref}\n className=\"overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down\"\n {...props}\n >\n <div className={cn(\"pb-4 pt-0\", className)}>{children}</div>\n </AccordionPrimitive.Content>\n));\n\nAccordionContent.displayName = AccordionPrimitive.Content.displayName;\n\nexport { Accordion, AccordionItem, AccordionTrigger, AccordionContent };\n",
|
||||
"6f5d2b743e097cc0f38a8201fc9472bbcffa7ef80653eb09ac1733f470dd675c": "import * as React from \"react\";\nimport * as AlertDialogPrimitive from \"@radix-ui/react-alert-dialog\";\n\nimport { cn } from \"@/lib/utils\";\nimport { buttonVariants } from \"@/components/ui/button\";\n\nconst AlertDialog = AlertDialogPrimitive.Root;\n\nconst AlertDialogTrigger = AlertDialogPrimitive.Trigger;\n\nconst AlertDialogPortal = AlertDialogPrimitive.Portal;\n\nconst AlertDialogOverlay = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Overlay>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Overlay\n className={cn(\n \"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0\",\n className,\n )}\n {...props}\n ref={ref}\n />\n));\nAlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;\n\nconst AlertDialogContent = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content>\n>(({ className, ...props }, ref) => (\n <AlertDialogPortal>\n <AlertDialogOverlay />\n <AlertDialogPrimitive.Content\n ref={ref}\n className={cn(\n \"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg\",\n className,\n )}\n {...props}\n />\n </AlertDialogPortal>\n));\nAlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;\n\nconst AlertDialogHeader = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n \"flex flex-col space-y-2 text-center sm:text-left\",\n className,\n )}\n {...props}\n />\n);\nAlertDialogHeader.displayName = \"AlertDialogHeader\";\n\nconst AlertDialogFooter = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) => (\n <div\n className={cn(\n \"flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2\",\n className,\n )}\n {...props}\n />\n);\nAlertDialogFooter.displayName = \"AlertDialogFooter\";\n\nconst AlertDialogTitle = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Title>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Title\n ref={ref}\n className={cn(\"text-lg font-semibold\", className)}\n {...props}\n />\n));\nAlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;\n\nconst AlertDialogDescription = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Description>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Description\n ref={ref}\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n));\nAlertDialogDescription.displayName =\n AlertDialogPrimitive.Description.displayName;\n\nconst AlertDialogAction = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Action>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Action\n ref={ref}\n className={cn(buttonVariants(), className)}\n {...props}\n />\n));\nAlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName;\n\nconst AlertDialogCancel = React.forwardRef<\n React.ElementRef<typeof AlertDialogPrimitive.Cancel>,\n React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>\n>(({ className, ...props }, ref) => (\n <AlertDialogPrimitive.Cancel\n ref={ref}\n className={cn(\n buttonVariants({ variant: \"outline\" }),\n \"mt-2 sm:mt-0\",\n className,\n )}\n {...props}\n />\n));\nAlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName;\n\nexport {\n AlertDialog,\n AlertDialogPortal,\n AlertDialogOverlay,\n AlertDialogTrigger,\n AlertDialogContent,\n AlertDialogHeader,\n AlertDialogFooter,\n AlertDialogTitle,\n AlertDialogDescription,\n AlertDialogAction,\n AlertDialogCancel,\n};\n",
|
||||
"050c08a3ec850a8fae8579b2bdbb4c9b8aa64744b580f07e2b26f7e6fc17dac0": "import * as React from \"react\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst alertVariants = cva(\n \"relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground\",\n {\n variants: {\n variant: {\n default: \"bg-background text-foreground\",\n destructive:\n \"border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n },\n);\n\nconst Alert = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants>\n>(({ className, variant, ...props }, ref) => (\n <div\n ref={ref}\n role=\"alert\"\n className={cn(alertVariants({ variant }), className)}\n {...props}\n />\n));\nAlert.displayName = \"Alert\";\n\nconst AlertTitle = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLHeadingElement>\n>(({ className, ...props }, ref) => (\n <h5\n ref={ref}\n className={cn(\"mb-1 font-medium leading-none tracking-tight\", className)}\n {...props}\n />\n));\nAlertTitle.displayName = \"AlertTitle\";\n\nconst AlertDescription = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\"text-sm [&_p]:leading-relaxed\", className)}\n {...props}\n />\n));\nAlertDescription.displayName = \"AlertDescription\";\n\nexport { Alert, AlertTitle, AlertDescription };\n",
|
||||
@@ -104,7 +103,6 @@
|
||||
"4b70ac2ad6f1c640249bb43667f86d8447985c49be8bd0335897ad0ae7c70694": "import * as React from \"react\";\n\nimport type { ToastActionElement, ToastProps } from \"@/components/ui/toast\";\n\nconst TOAST_LIMIT = 1;\nconst TOAST_REMOVE_DELAY = 1000000;\n\ntype ToasterToast = ToastProps & {\n id: string;\n title?: React.ReactNode;\n description?: React.ReactNode;\n action?: ToastActionElement;\n};\n\nconst _actionTypes = {\n ADD_TOAST: \"ADD_TOAST\",\n UPDATE_TOAST: \"UPDATE_TOAST\",\n DISMISS_TOAST: \"DISMISS_TOAST\",\n REMOVE_TOAST: \"REMOVE_TOAST\",\n} as const;\n\nlet count = 0;\n\nfunction genId() {\n count = (count + 1) % Number.MAX_SAFE_INTEGER;\n return count.toString();\n}\n\ntype ActionType = typeof _actionTypes;\n\ntype Action =\n | {\n type: ActionType[\"ADD_TOAST\"];\n toast: ToasterToast;\n }\n | {\n type: ActionType[\"UPDATE_TOAST\"];\n toast: Partial<ToasterToast>;\n }\n | {\n type: ActionType[\"DISMISS_TOAST\"];\n toastId?: ToasterToast[\"id\"];\n }\n | {\n type: ActionType[\"REMOVE_TOAST\"];\n toastId?: ToasterToast[\"id\"];\n };\n\ninterface State {\n toasts: ToasterToast[];\n}\n\nconst toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>();\n\nconst addToRemoveQueue = (toastId: string) => {\n if (toastTimeouts.has(toastId)) {\n return;\n }\n\n const timeout = setTimeout(() => {\n toastTimeouts.delete(toastId);\n dispatch({\n type: \"REMOVE_TOAST\",\n toastId: toastId,\n });\n }, TOAST_REMOVE_DELAY);\n\n toastTimeouts.set(toastId, timeout);\n};\n\nexport const reducer = (state: State, action: Action): State => {\n switch (action.type) {\n case \"ADD_TOAST\":\n return {\n ...state,\n toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),\n };\n\n case \"UPDATE_TOAST\":\n return {\n ...state,\n toasts: state.toasts.map((t) =>\n t.id === action.toast.id ? { ...t, ...action.toast } : t,\n ),\n };\n\n case \"DISMISS_TOAST\": {\n const { toastId } = action;\n\n // ! Side effects ! - This could be extracted into a dismissToast() action,\n // but I'll keep it here for simplicity\n if (toastId) {\n addToRemoveQueue(toastId);\n } else {\n state.toasts.forEach((toast) => {\n addToRemoveQueue(toast.id);\n });\n }\n\n return {\n ...state,\n toasts: state.toasts.map((t) =>\n t.id === toastId || toastId === undefined\n ? {\n ...t,\n open: false,\n }\n : t,\n ),\n };\n }\n case \"REMOVE_TOAST\":\n if (action.toastId === undefined) {\n return {\n ...state,\n toasts: [],\n };\n }\n return {\n ...state,\n toasts: state.toasts.filter((t) => t.id !== action.toastId),\n };\n }\n};\n\nconst listeners: Array<(state: State) => void> = [];\n\nlet memoryState: State = { toasts: [] };\n\nfunction dispatch(action: Action) {\n memoryState = reducer(memoryState, action);\n listeners.forEach((listener) => {\n listener(memoryState);\n });\n}\n\ntype Toast = Omit<ToasterToast, \"id\">;\n\nfunction toast({ ...props }: Toast) {\n const id = genId();\n\n const update = (props: ToasterToast) =>\n dispatch({\n type: \"UPDATE_TOAST\",\n toast: { ...props, id },\n });\n const dismiss = () => dispatch({ type: \"DISMISS_TOAST\", toastId: id });\n\n dispatch({\n type: \"ADD_TOAST\",\n toast: {\n ...props,\n id,\n open: true,\n onOpenChange: (open) => {\n if (!open) dismiss();\n },\n },\n });\n\n return {\n id: id,\n dismiss,\n update,\n };\n}\n\nfunction useToast() {\n const [state, setState] = React.useState<State>(memoryState);\n\n React.useEffect(() => {\n listeners.push(setState);\n return () => {\n const index = listeners.indexOf(setState);\n if (index > -1) {\n listeners.splice(index, 1);\n }\n };\n }, [state]);\n\n return {\n ...state,\n toast,\n dismiss: (toastId?: string) => dispatch({ type: \"DISMISS_TOAST\", toastId }),\n };\n}\n\nexport { useToast, toast };\n",
|
||||
"d1f1e0d62cb8d8d1e04c26e14de842d8a151f75812d81b046c65b5d1fe8e4b27": "import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n",
|
||||
"5cbfd5e41e9218faa071fd97a799497ba5e31423f3a38d4d16adae98a11b80a4": "import { createRoot } from \"react-dom/client\";\nimport App from \"./App.tsx\";\nimport \"./globals.css\";\n\ncreateRoot(document.getElementById(\"root\")!).render(<App />);\n",
|
||||
"70618b5f415d91c92bef86039e35d5f282e959276bf49ed204c9f78f7490c99c": "// Update this page (the content is just a fallback if you fail to update the page)\n\nimport { MadeWithDyad } from \"@/components/made-with-dyad\";\n\nconst Index = () => {\n return (\n <div className=\"min-h-screen flex items-center justify-center bg-gray-100\">\n <div className=\"text-center\">\n <h1 className=\"text-4xl font-bold mb-4\">Welcome to Your Blank App</h1>\n <p className=\"text-xl text-gray-600\">\n Start building your amazing project here!\n </p>\n </div>\n <MadeWithDyad />\n </div>\n );\n};\n\nexport default Index;\n",
|
||||
"940578bf01ac3dbdcb16f52528bd59903b2cce7698c8b39064f2791022567b0e": "import { useLocation } from \"react-router-dom\";\nimport { useEffect } from \"react\";\n\nconst NotFound = () => {\n const location = useLocation();\n\n useEffect(() => {\n console.error(\n \"404 Error: User attempted to access non-existent route:\",\n location.pathname,\n );\n }, [location.pathname]);\n\n return (\n <div className=\"min-h-screen flex items-center justify-center bg-gray-100\">\n <div className=\"text-center\">\n <h1 className=\"text-4xl font-bold mb-4\">404</h1>\n <p className=\"text-xl text-gray-600 mb-4\">Oops! Page not found</p>\n <a href=\"/\" className=\"text-blue-500 hover:text-blue-700 underline\">\n Return to Home\n </a>\n </div>\n </div>\n );\n};\n\nexport default NotFound;\n",
|
||||
"328f94e9c711410b23188484a0a2f38886d7732d5c375cefcba442ab6195783f": "import { toast } from \"sonner\";\n\nexport const showSuccess = (message: string) => {\n toast.success(message);\n};\n\nexport const showError = (message: string) => {\n toast.error(message);\n};\n\nexport const showLoading = (message: string) => {\n return toast.loading(message);\n};\n\nexport const dismissToast = (toastId: string) => {\n toast.dismiss(toastId);\n};\n",
|
||||
"65996936fbb042915f7b74a200fcdde7e410f32a669b1ab9597cfaa4b0faddb5": "/// <reference types=\"vite/client\" />\n",
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
=== src/pages/Index.tsx ===
|
||||
// Update this page (the content is just a fallback if you fail to update the page)
|
||||
|
||||
const Index = () => {
|
||||
return (
|
||||
<div className="min-h-screen flex items-center justify-center bg-gray-100">
|
||||
<div className="text-center">
|
||||
<h1 className="text-4xl font-bold mx-[20px] my-[10px]">Welcome to Your Blank App</h1>
|
||||
<p className="text-xl text-gray-600">Start building your amazing project here!
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Index;
|
||||
@@ -0,0 +1,16 @@
|
||||
=== src/pages/Index.tsx ===
|
||||
// Update this page (the content is just a fallback if you fail to update the page)
|
||||
|
||||
const Index = () => {
|
||||
return (
|
||||
<div className="min-h-screen flex items-center justify-center bg-gray-100">
|
||||
<div className="text-center">
|
||||
<h1 className="text-4xl font-bold mb-4">Hello from E2E Test</h1>
|
||||
<p className="text-xl text-gray-600">Start building your amazing project here!
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Index;
|
||||
@@ -1,8 +1,8 @@
|
||||
import { testSkipIfWindows, Timeout } from "./helpers/test_helper";
|
||||
import { PageObject, testSkipIfWindows, Timeout } from "./helpers/test_helper";
|
||||
import { expect } from "@playwright/test";
|
||||
|
||||
testSkipIfWindows("undo", async ({ po }) => {
|
||||
await po.setUp({ autoApprove: true });
|
||||
const runUndoTest = async (po: PageObject, nativeGit: boolean) => {
|
||||
await po.setUp({ autoApprove: true, nativeGit });
|
||||
await po.sendPrompt("tc=write-index");
|
||||
await po.sendPrompt("tc=write-index-2");
|
||||
|
||||
@@ -31,4 +31,12 @@ testSkipIfWindows("undo", async ({ po }) => {
|
||||
// Also, could be slow.
|
||||
timeout: Timeout.LONG,
|
||||
});
|
||||
};
|
||||
|
||||
testSkipIfWindows("undo", async ({ po }) => {
|
||||
await runUndoTest(po, false);
|
||||
});
|
||||
|
||||
testSkipIfWindows("undo with native git", async ({ po }) => {
|
||||
await runUndoTest(po, true);
|
||||
});
|
||||
|
||||
219
e2e-tests/visual_editing.spec.ts
Normal file
@@ -0,0 +1,219 @@
|
||||
import { expect } from "@playwright/test";
|
||||
import { testSkipIfWindows, Timeout } from "./helpers/test_helper";
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
testSkipIfWindows("edit style of one selected component", async ({ po }) => {
|
||||
await po.setUpDyadPro();
|
||||
await po.sendPrompt("tc=basic");
|
||||
await po.clickTogglePreviewPanel();
|
||||
await po.clickPreviewPickElement();
|
||||
|
||||
// Select a component
|
||||
await po
|
||||
.getPreviewIframeElement()
|
||||
.contentFrame()
|
||||
.getByRole("heading", { name: "Welcome to Your Blank App" })
|
||||
.click();
|
||||
|
||||
// Wait for the toolbar to appear (check for the Margin button which is always visible)
|
||||
const marginButton = po.page.getByRole("button", { name: "Margin" });
|
||||
await expect(marginButton).toBeVisible({
|
||||
timeout: Timeout.MEDIUM,
|
||||
});
|
||||
|
||||
// Ensure the toolbar has proper coordinates before clicking
|
||||
await expect(async () => {
|
||||
const box = await marginButton.boundingBox();
|
||||
expect(box).not.toBeNull();
|
||||
expect(box!.y).toBeGreaterThan(0);
|
||||
}).toPass({ timeout: Timeout.MEDIUM });
|
||||
|
||||
// Click on margin button to open the margin popover
|
||||
await marginButton.click();
|
||||
|
||||
// Wait for the popover to fully open by checking for the popover content container
|
||||
const marginDialog = po.page
|
||||
.locator('[role="dialog"]')
|
||||
.filter({ hasText: "Margin" });
|
||||
await expect(marginDialog).toBeVisible({
|
||||
timeout: Timeout.LONG,
|
||||
});
|
||||
|
||||
// Edit margin - set horizontal margin
|
||||
const marginXInput = po.page.getByLabel("Horizontal");
|
||||
await marginXInput.fill("20");
|
||||
|
||||
// Edit margin - set vertical margin
|
||||
const marginYInput = po.page.getByLabel("Vertical");
|
||||
await marginYInput.fill("10");
|
||||
|
||||
// Close the popover by clicking outside or pressing escape
|
||||
await po.page.keyboard.press("Escape");
|
||||
|
||||
// Check if the changes are applied to UI by verifying the visual changes dialog appears
|
||||
await expect(po.page.getByText(/\d+ component[s]? modified/)).toBeVisible({
|
||||
timeout: Timeout.MEDIUM,
|
||||
});
|
||||
|
||||
// Save the changes
|
||||
await po.page.getByRole("button", { name: "Save Changes" }).click();
|
||||
|
||||
// Wait for the success toast
|
||||
await po.waitForToastWithText("Visual changes saved to source files");
|
||||
|
||||
// Verify that the changes are applied to codebase
|
||||
await po.snapshotAppFiles({
|
||||
name: "visual-editing-single-component-margin",
|
||||
files: ["src/pages/Index.tsx"],
|
||||
});
|
||||
});
|
||||
|
||||
testSkipIfWindows("edit text of the selected component", async ({ po }) => {
|
||||
await po.setUpDyadPro();
|
||||
await po.sendPrompt("tc=basic");
|
||||
await po.clickTogglePreviewPanel();
|
||||
await po.clickPreviewPickElement();
|
||||
|
||||
// Click on component that contains static text
|
||||
await po
|
||||
.getPreviewIframeElement()
|
||||
.contentFrame()
|
||||
.getByRole("heading", { name: "Welcome to Your Blank App" })
|
||||
.click();
|
||||
|
||||
// Wait for the toolbar to appear (check for the Margin button which is always visible)
|
||||
await expect(po.page.getByRole("button", { name: "Margin" })).toBeVisible({
|
||||
timeout: Timeout.MEDIUM,
|
||||
});
|
||||
|
||||
// Get the iframe and access the content
|
||||
const iframe = po.getPreviewIframeElement();
|
||||
const frame = iframe.contentFrame();
|
||||
|
||||
// Find the heading element in the iframe
|
||||
const heading = frame.getByRole("heading", {
|
||||
name: "Welcome to Your Blank App",
|
||||
});
|
||||
|
||||
await heading.dblclick();
|
||||
|
||||
// Wait for contentEditable to be enabled
|
||||
await expect(async () => {
|
||||
const isEditable = await heading.evaluate(
|
||||
(el) => (el as HTMLElement).isContentEditable,
|
||||
);
|
||||
expect(isEditable).toBe(true);
|
||||
}).toPass({ timeout: Timeout.MEDIUM });
|
||||
|
||||
// Clear the existing text and type new text
|
||||
await heading.press("Meta+A");
|
||||
await heading.type("Hello from E2E Test");
|
||||
|
||||
// Click outside to finish editing
|
||||
await frame.locator("body").click({ position: { x: 10, y: 10 } });
|
||||
|
||||
// Verify the changes are applied in the UI
|
||||
await expect(frame.getByText("Hello from E2E Test")).toBeVisible({
|
||||
timeout: Timeout.MEDIUM,
|
||||
});
|
||||
|
||||
// Verify the visual changes dialog appears
|
||||
await expect(po.page.getByText(/\d+ component[s]? modified/)).toBeVisible({
|
||||
timeout: Timeout.MEDIUM,
|
||||
});
|
||||
|
||||
// Save the changes
|
||||
await po.page.getByRole("button", { name: "Save Changes" }).click();
|
||||
|
||||
// Wait for the success toast
|
||||
await po.waitForToastWithText("Visual changes saved to source files");
|
||||
|
||||
// Verify that the changes are applied to the codebase
|
||||
await po.snapshotAppFiles({
|
||||
name: "visual-editing-text-content",
|
||||
files: ["src/pages/Index.tsx"],
|
||||
});
|
||||
});
|
||||
|
||||
testSkipIfWindows("discard changes", async ({ po }) => {
|
||||
await po.setUpDyadPro();
|
||||
await po.sendPrompt("tc=basic");
|
||||
await po.clickTogglePreviewPanel();
|
||||
await po.clickPreviewPickElement();
|
||||
|
||||
// Select a component
|
||||
await po
|
||||
.getPreviewIframeElement()
|
||||
.contentFrame()
|
||||
.getByRole("heading", { name: "Welcome to Your Blank App" })
|
||||
.click();
|
||||
|
||||
// Wait for the toolbar to appear (check for the Margin button which is always visible)
|
||||
const marginButton = po.page.getByRole("button", { name: "Margin" });
|
||||
await expect(marginButton).toBeVisible({
|
||||
timeout: Timeout.MEDIUM,
|
||||
});
|
||||
|
||||
// Ensure the toolbar has proper coordinates before clicking
|
||||
await expect(async () => {
|
||||
const box = await marginButton.boundingBox();
|
||||
expect(box).not.toBeNull();
|
||||
expect(box!.y).toBeGreaterThan(0);
|
||||
}).toPass({ timeout: Timeout.MEDIUM });
|
||||
|
||||
// Click on margin button to open the margin popover
|
||||
await marginButton.click();
|
||||
|
||||
// Wait for the popover to fully open by checking for the popover content container
|
||||
const marginDialog = po.page
|
||||
.locator('[role="dialog"]')
|
||||
.filter({ hasText: "Margin" });
|
||||
await expect(marginDialog).toBeVisible({
|
||||
timeout: Timeout.LONG,
|
||||
});
|
||||
|
||||
// Edit margin
|
||||
const marginXInput = po.page.getByLabel("Horizontal");
|
||||
await marginXInput.fill("30");
|
||||
|
||||
const marginYInput = po.page.getByLabel("Vertical");
|
||||
await marginYInput.fill("30");
|
||||
|
||||
// Close the popover
|
||||
await po.page.keyboard.press("Escape");
|
||||
|
||||
// Wait for the popover to close
|
||||
await expect(marginDialog).not.toBeVisible({
|
||||
timeout: Timeout.MEDIUM,
|
||||
});
|
||||
|
||||
// Check if the changes are applied to UI
|
||||
await expect(po.page.getByText(/\d+ component[s]? modified/)).toBeVisible({
|
||||
timeout: Timeout.MEDIUM,
|
||||
});
|
||||
|
||||
// Take a snapshot of the app files before discarding
|
||||
const appPathBefore = await po.getCurrentAppPath();
|
||||
const appFileBefore = fs.readFileSync(
|
||||
path.join(appPathBefore, "src", "pages", "Index.tsx"),
|
||||
"utf-8",
|
||||
);
|
||||
|
||||
// Discard the changes
|
||||
await po.page.getByRole("button", { name: "Discard" }).click();
|
||||
|
||||
// Verify the visual changes dialog is gone
|
||||
await expect(po.page.getByText(/\d+ component[s]? modified/)).not.toBeVisible(
|
||||
{ timeout: Timeout.MEDIUM },
|
||||
);
|
||||
|
||||
// Verify that the changes are NOT applied to codebase
|
||||
const appFileAfter = fs.readFileSync(
|
||||
path.join(appPathBefore, "src", "pages", "Index.tsx"),
|
||||
"utf-8",
|
||||
);
|
||||
|
||||
// The file content should be the same as before
|
||||
expect(appFileAfter).toBe(appFileBefore);
|
||||
});
|
||||