Compare commits
2 Commits
feature/de
...
705608ae46
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
705608ae46 | ||
|
|
73fc42bf4f |
4
.github/workflows/ci.yml
vendored
@@ -107,10 +107,6 @@ 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
@@ -1,59 +0,0 @@
|
||||
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-15-intel" },
|
||||
{ name: "macos-intel", image: "macos-13" },
|
||||
{ name: "macos", image: "macos-latest" },
|
||||
]
|
||||
runs-on: ${{ matrix.os.image }}
|
||||
|
||||
587
README.md
@@ -1,589 +1,34 @@
|
||||
# MoreMinimore
|
||||
# Dyad
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||

|
||||
[](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.
|
||||
|
||||
## 🧰 Prerequisites
|
||||
## 📦 Download
|
||||
|
||||
- Node.js >= 20
|
||||
- npm (comes with Node.js)
|
||||
- Git
|
||||
No sign-up required. Just download and go.
|
||||
|
||||
You can verify your versions:
|
||||
### [👉 Download for your platform](https://www.dyad.sh/#download)
|
||||
|
||||
```bash
|
||||
node -v
|
||||
npm -v
|
||||
```
|
||||
## 🤝 Community
|
||||
|
||||
## 🚀 Quick Start
|
||||
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!
|
||||
|
||||
### Option 1: Download and Run (Easiest)
|
||||
## 🛠️ Contributing
|
||||
|
||||
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!
|
||||
**Dyad** is open-source (Apache 2.0 licensed).
|
||||
|
||||
### Option 2: Build from Source
|
||||
If you're interested in contributing to dyad, please read our [contributing](./CONTRIBUTING.md) doc.
|
||||
|
||||
```bash
|
||||
# Clone the repository
|
||||
git clone https://github.com/kunthawat/moreminimore-vibe.git
|
||||
cd moreminimore-vibe
|
||||
## 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!
|
||||
- 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).
|
||||
|
||||
@@ -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/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.
|
||||
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.
|
||||
|
||||
198
UPDATE_GUIDE.md
Normal file
@@ -0,0 +1,198 @@
|
||||
# Dyad Update Management Guide
|
||||
|
||||
This guide explains how to update your forked Dyad application while preserving your custom modifications.
|
||||
|
||||
## 🎯 Overview
|
||||
|
||||
Your setup uses a **selective update strategy** that:
|
||||
- Keeps your custom code separate from the main codebase
|
||||
- Automatically preserves custom modifications during updates
|
||||
- Provides backup and rollback capabilities
|
||||
- Minimizes merge conflicts
|
||||
|
||||
## 📁 Custom Code Structure
|
||||
|
||||
Your custom modifications are organized in `src/custom/`:
|
||||
|
||||
```
|
||||
src/custom/
|
||||
├── index.ts # Main entry point for custom features
|
||||
├── hooks/
|
||||
│ └── useSmartContext.ts # Custom smart context hook
|
||||
├── ipc/
|
||||
│ └── smart_context_handlers.ts # Custom IPC handlers
|
||||
└── utils/
|
||||
└── smart_context_store.ts # Custom utilities
|
||||
```
|
||||
|
||||
## 🚀 Update Process
|
||||
|
||||
### Method 1: Automated Update (Recommended)
|
||||
|
||||
Use the provided update script:
|
||||
|
||||
```bash
|
||||
./update-dyad-v2.sh
|
||||
```
|
||||
|
||||
**What the script does:**
|
||||
1. Creates a timestamped backup
|
||||
2. Backs up your custom code
|
||||
3. Fetches latest changes from upstream
|
||||
4. Resets to the latest upstream version
|
||||
5. Restores your custom code
|
||||
6. Pushes updates to your fork
|
||||
|
||||
### Method 2: Manual Update
|
||||
|
||||
If you prefer manual control:
|
||||
|
||||
```bash
|
||||
# 1. Create backup
|
||||
cp -r src/custom/ dyad-backup-$(date +%Y%m%d-%H%M%S)/
|
||||
|
||||
# 2. Fetch latest changes
|
||||
git fetch upstream
|
||||
|
||||
# 3. Reset to latest upstream
|
||||
git reset --hard upstream/main
|
||||
|
||||
# 4. Restore custom code
|
||||
cp -r dyad-backup-*/src/custom/ src/
|
||||
|
||||
# 5. Commit and push
|
||||
git add src/custom/
|
||||
git commit -m "Restore custom code after update"
|
||||
git push origin main
|
||||
```
|
||||
|
||||
## 🔄 Update Workflow
|
||||
|
||||
### Before Updating
|
||||
1. **Test current state** - Ensure your app works properly
|
||||
2. **Commit any changes** - Don't have uncommitted work
|
||||
3. **Check custom code** - Note any modifications that might need updates
|
||||
|
||||
### After Updating
|
||||
1. **Run npm install** - Update dependencies if needed
|
||||
2. **Test the application** - Ensure everything works
|
||||
3. **Check custom integrations** - Verify custom features still work
|
||||
4. **Update custom code** if needed - Adapt to any API changes
|
||||
|
||||
## 🛠️ Adding New Custom Features
|
||||
|
||||
When adding new custom features:
|
||||
|
||||
1. **Place in src/custom/** - Keep custom code organized
|
||||
2. **Update imports** - Use relative imports within custom directory
|
||||
3. **Document changes** - Note what each custom feature does
|
||||
4. **Test integration** - Ensure custom features work with main app
|
||||
|
||||
Example:
|
||||
```typescript
|
||||
// src/custom/components/MyCustomComponent.tsx
|
||||
import { useSmartContext } from '../hooks/useSmartContext';
|
||||
|
||||
export const MyCustomComponent = () => {
|
||||
// Your custom logic
|
||||
};
|
||||
```
|
||||
|
||||
## 🚨 Troubleshooting
|
||||
|
||||
### Merge Conflicts
|
||||
If you encounter merge conflicts during manual updates:
|
||||
|
||||
```bash
|
||||
# Abort the merge
|
||||
git merge --abort
|
||||
|
||||
# Use the automated script instead
|
||||
./update-dyad-v2.sh
|
||||
```
|
||||
|
||||
### Custom Code Not Working
|
||||
After an update, if custom features don't work:
|
||||
|
||||
1. **Check API changes** - The upstream may have changed interfaces
|
||||
2. **Update imports** - File paths might have changed
|
||||
3. **Review breaking changes** - Check upstream release notes
|
||||
4. **Test incrementally** - Isolate the problematic code
|
||||
|
||||
### Backup Restoration
|
||||
If you need to restore from backup:
|
||||
|
||||
```bash
|
||||
# Find your backup directory
|
||||
ls dyad-backup-*
|
||||
|
||||
# Restore specific files
|
||||
cp -r dyad-backup-YYYYMMDD-HHMMSS/src/custom/ src/
|
||||
|
||||
# Or restore entire project (last resort)
|
||||
rm -rf * .gitignore
|
||||
cp -r dyad-backup-YYYYMMDD-HHMMSS/* .
|
||||
cp dyad-backup-YYYYMMDD-HHMMSS/.gitignore .
|
||||
```
|
||||
|
||||
## 📋 Best Practices
|
||||
|
||||
### Regular Maintenance
|
||||
- **Update frequently** - Smaller updates are easier to manage
|
||||
- **Test after each update** - Catch issues early
|
||||
- **Keep custom code minimal** - Only customize what's necessary
|
||||
- **Document customizations** - Future you will thank you
|
||||
|
||||
### Code Organization
|
||||
- **Separate concerns** - Keep UI, logic, and utilities separate
|
||||
- **Use TypeScript** - Catch integration issues early
|
||||
- **Follow existing patterns** - Match the upstream code style
|
||||
- **Avoid modifying core files** - Use extension patterns when possible
|
||||
|
||||
### Backup Strategy
|
||||
- **Multiple backups** - Keep several backup versions
|
||||
- **Offsite backup** - Consider cloud storage for critical backups
|
||||
- **Test backups** - Ensure you can restore from backup
|
||||
- **Label clearly** - Use descriptive backup names
|
||||
|
||||
## 🔧 Advanced Configuration
|
||||
|
||||
### Custom Update Script
|
||||
You can modify `update-dyad-v2.sh` to:
|
||||
- Skip certain files from backup
|
||||
- Add custom post-update steps
|
||||
- Include additional validation
|
||||
- Send notifications on completion
|
||||
|
||||
### Selective File Restoration
|
||||
To restore only specific custom files:
|
||||
|
||||
```bash
|
||||
# Restore specific directory
|
||||
cp -r dyad-backup-*/src/custom/hooks/ src/custom/
|
||||
|
||||
# Restore specific file
|
||||
cp dyad-backup-*/src/custom/index.ts src/custom/
|
||||
```
|
||||
|
||||
## 📞 Getting Help
|
||||
|
||||
If you encounter issues:
|
||||
|
||||
1. **Check this guide first** - Most common issues are covered
|
||||
2. **Review the script output** - Error messages are informative
|
||||
3. **Test with a clean state** - Start fresh if needed
|
||||
4. **Document the issue** - Note what you were trying to do
|
||||
|
||||
## 🎉 Success Indicators
|
||||
|
||||
You'll know the update was successful when:
|
||||
- ✅ Script completes without errors
|
||||
- ✅ Custom code is present in `src/custom/`
|
||||
- ✅ Application starts and runs normally
|
||||
- ✅ Custom features work as expected
|
||||
- ✅ No merge conflicts in git status
|
||||
|
||||
---
|
||||
|
||||
**Remember**: The goal is to make updates painless and predictable. When in doubt, use the automated script and keep good backups!
|
||||
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 126 KiB |
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 228 KiB |
|
Before Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 3.2 KiB |
BIN
assets/logo.png
|
Before Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 6.3 KiB |
|
Before 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/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.
|
||||
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.
|
||||
|
||||
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,4 +765,3 @@
|
||||
"indexes": {}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
7
dyad-backup-20251205-195655/commit-history.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
52a977b backup: auto-commit before update - Fri Dec 5 15:16:35 +07 2025
|
||||
8a1cecb backup: auto-commit before update - Fri Dec 5 15:12:17 +07 2025
|
||||
e6de49c fix: update .gitignore to exclude 'out/' directory
|
||||
6d74721 Add user settings configuration for GPT-5 Codex model with Azure provider
|
||||
d22227b feat: implement fuzzy search and replace functionality with Levenshtein distance
|
||||
11986a0 Add project files
|
||||
3b43cb5 Add blank
|
||||
60
dyad-backup-20251205-195655/custom/hooks/useSmartContext.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import { IpcClient } from "@/ipc/ipc_client";
|
||||
import type {
|
||||
SmartContextMeta,
|
||||
SmartContextSnippet,
|
||||
SmartContextRetrieveResult,
|
||||
} from "@/ipc/ipc_types";
|
||||
|
||||
export function useSmartContextMeta(chatId: number) {
|
||||
return useQuery<SmartContextMeta, Error>({
|
||||
queryKey: ["smart-context", chatId, "meta"],
|
||||
queryFn: async () => {
|
||||
const ipc = IpcClient.getInstance();
|
||||
return ipc.getSmartContextMeta(chatId);
|
||||
},
|
||||
enabled: !!chatId,
|
||||
});
|
||||
}
|
||||
|
||||
export function useRetrieveSmartContext(
|
||||
chatId: number,
|
||||
query: string,
|
||||
budgetTokens: number,
|
||||
) {
|
||||
return useQuery<SmartContextRetrieveResult, Error>({
|
||||
queryKey: ["smart-context", chatId, "retrieve", query, budgetTokens],
|
||||
queryFn: async () => {
|
||||
const ipc = IpcClient.getInstance();
|
||||
return ipc.retrieveSmartContext({ chatId, query, budgetTokens });
|
||||
},
|
||||
enabled: !!chatId && !!query && budgetTokens > 0,
|
||||
meta: { showErrorToast: true },
|
||||
});
|
||||
}
|
||||
|
||||
export function useUpsertSmartContextSnippets(chatId: number) {
|
||||
const qc = useQueryClient();
|
||||
return useMutation<number, Error, Array<Pick<SmartContextSnippet, "text" | "source">>>({
|
||||
mutationFn: async (snippets) => {
|
||||
const ipc = IpcClient.getInstance();
|
||||
return ipc.upsertSmartContextSnippets(chatId, snippets);
|
||||
},
|
||||
onSuccess: () => {
|
||||
qc.invalidateQueries({ queryKey: ["smart-context", chatId] });
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export function useUpdateRollingSummary(chatId: number) {
|
||||
const qc = useQueryClient();
|
||||
return useMutation<SmartContextMeta, Error, { summary: string }>({
|
||||
mutationFn: async ({ summary }) => {
|
||||
const ipc = IpcClient.getInstance();
|
||||
return ipc.updateSmartContextRollingSummary(chatId, summary);
|
||||
},
|
||||
onSuccess: () => {
|
||||
qc.invalidateQueries({ queryKey: ["smart-context", chatId, "meta"] });
|
||||
},
|
||||
});
|
||||
}
|
||||
18
dyad-backup-20251205-195655/custom/index.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
// Custom modules for moreminimore-vibe
|
||||
// This file exports all custom functionality to make imports easier
|
||||
|
||||
// Custom hooks
|
||||
export { useSmartContextMeta, useRetrieveSmartContext, useUpsertSmartContextSnippets, useUpdateRollingSummary } from './hooks/useSmartContext';
|
||||
|
||||
// Custom IPC handlers (these will need to be imported and registered in the main process)
|
||||
export { registerSmartContextHandlers } from './ipc/smart_context_handlers';
|
||||
|
||||
// Custom utilities
|
||||
export * from './utils/smart_context_store';
|
||||
|
||||
// Re-export types that might be needed
|
||||
export type {
|
||||
SmartContextMeta,
|
||||
SmartContextSnippet,
|
||||
SmartContextRetrieveResult,
|
||||
} from '../ipc/ipc_types';
|
||||
@@ -0,0 +1,65 @@
|
||||
import log from "electron-log";
|
||||
import { createLoggedHandler } from "./safe_handle";
|
||||
import {
|
||||
appendSnippets,
|
||||
readMeta,
|
||||
retrieveContext,
|
||||
updateRollingSummary,
|
||||
rebuildIndex,
|
||||
type SmartContextSnippet,
|
||||
type SmartContextMeta,
|
||||
} from "../utils/smart_context_store";
|
||||
|
||||
const logger = log.scope("smart_context_handlers");
|
||||
const handle = createLoggedHandler(logger);
|
||||
|
||||
export interface UpsertSnippetsParams {
|
||||
chatId: number;
|
||||
snippets: Array<{
|
||||
text: string;
|
||||
source:
|
||||
| { type: "message"; messageIndex?: number }
|
||||
| { type: "code"; filePath: string }
|
||||
| { type: "attachment"; name: string; mime?: string }
|
||||
| { type: "other"; label?: string };
|
||||
}>;
|
||||
}
|
||||
|
||||
export interface RetrieveContextParams {
|
||||
chatId: number;
|
||||
query: string;
|
||||
budgetTokens: number;
|
||||
}
|
||||
|
||||
export function registerSmartContextHandlers() {
|
||||
handle("sc:get-meta", async (_event, chatId: number): Promise<SmartContextMeta> => {
|
||||
return readMeta(chatId);
|
||||
});
|
||||
|
||||
handle(
|
||||
"sc:upsert-snippets",
|
||||
async (_event, params: UpsertSnippetsParams): Promise<number> => {
|
||||
const count = await appendSnippets(params.chatId, params.snippets);
|
||||
return count;
|
||||
},
|
||||
);
|
||||
|
||||
handle(
|
||||
"sc:update-rolling-summary",
|
||||
async (_event, params: { chatId: number; summary: string }): Promise<SmartContextMeta> => {
|
||||
return updateRollingSummary(params.chatId, params.summary);
|
||||
},
|
||||
);
|
||||
|
||||
handle(
|
||||
"sc:retrieve-context",
|
||||
async (_event, params: RetrieveContextParams) => {
|
||||
return retrieveContext(params.chatId, params.query, params.budgetTokens);
|
||||
},
|
||||
);
|
||||
|
||||
handle("sc:rebuild-index", async (_event, chatId: number) => {
|
||||
await rebuildIndex(chatId);
|
||||
return { ok: true } as const;
|
||||
});
|
||||
}
|
||||
212
dyad-backup-20251205-195655/custom/utils/smart_context_store.ts
Normal file
@@ -0,0 +1,212 @@
|
||||
import path from "node:path";
|
||||
import { promises as fs } from "node:fs";
|
||||
import { randomUUID } from "node:crypto";
|
||||
import { getUserDataPath } from "../../paths/paths";
|
||||
import { estimateTokens } from "./token_utils";
|
||||
|
||||
export type SmartContextSource =
|
||||
| { type: "message"; messageIndex?: number }
|
||||
| { type: "code"; filePath: string }
|
||||
| { type: "attachment"; name: string; mime?: string }
|
||||
| { type: "other"; label?: string };
|
||||
|
||||
export interface SmartContextSnippet {
|
||||
id: string;
|
||||
text: string;
|
||||
score?: number;
|
||||
source: SmartContextSource;
|
||||
ts: number; // epoch ms
|
||||
tokens?: number;
|
||||
}
|
||||
|
||||
export interface SmartContextMetaConfig {
|
||||
maxSnippets?: number;
|
||||
}
|
||||
|
||||
export interface SmartContextMeta {
|
||||
entityId: string; // e.g., chatId as string
|
||||
updatedAt: number;
|
||||
rollingSummary?: string;
|
||||
summaryTokens?: number;
|
||||
config?: SmartContextMetaConfig;
|
||||
}
|
||||
|
||||
function getThreadDir(chatId: number): string {
|
||||
const base = path.join(getUserDataPath(), "smart-context", "threads");
|
||||
return path.join(base, String(chatId));
|
||||
}
|
||||
|
||||
function getMetaPath(chatId: number): string {
|
||||
return path.join(getThreadDir(chatId), "meta.json");
|
||||
}
|
||||
|
||||
function getSnippetsPath(chatId: number): string {
|
||||
return path.join(getThreadDir(chatId), "snippets.jsonl");
|
||||
}
|
||||
|
||||
async function ensureDir(dir: string): Promise<void> {
|
||||
await fs.mkdir(dir, { recursive: true });
|
||||
}
|
||||
|
||||
export async function readMeta(chatId: number): Promise<SmartContextMeta> {
|
||||
const dir = getThreadDir(chatId);
|
||||
await ensureDir(dir);
|
||||
const metaPath = getMetaPath(chatId);
|
||||
try {
|
||||
const raw = await fs.readFile(metaPath, "utf8");
|
||||
const meta = JSON.parse(raw) as SmartContextMeta;
|
||||
return meta;
|
||||
} catch {
|
||||
const fresh: SmartContextMeta = {
|
||||
entityId: String(chatId),
|
||||
updatedAt: Date.now(),
|
||||
rollingSummary: "",
|
||||
summaryTokens: 0,
|
||||
config: { maxSnippets: 400 },
|
||||
};
|
||||
await fs.writeFile(metaPath, JSON.stringify(fresh, null, 2), "utf8");
|
||||
return fresh;
|
||||
}
|
||||
}
|
||||
|
||||
export async function writeMeta(
|
||||
chatId: number,
|
||||
meta: SmartContextMeta,
|
||||
): Promise<void> {
|
||||
const dir = getThreadDir(chatId);
|
||||
await ensureDir(dir);
|
||||
const metaPath = getMetaPath(chatId);
|
||||
const updated: SmartContextMeta = {
|
||||
...meta,
|
||||
entityId: String(chatId),
|
||||
updatedAt: Date.now(),
|
||||
};
|
||||
await fs.writeFile(metaPath, JSON.stringify(updated, null, 2), "utf8");
|
||||
}
|
||||
|
||||
export async function updateRollingSummary(
|
||||
chatId: number,
|
||||
summary: string,
|
||||
): Promise<SmartContextMeta> {
|
||||
const meta = await readMeta(chatId);
|
||||
const summaryTokens = estimateTokens(summary || "");
|
||||
const next: SmartContextMeta = {
|
||||
...meta,
|
||||
rollingSummary: summary,
|
||||
summaryTokens,
|
||||
};
|
||||
await writeMeta(chatId, next);
|
||||
return next;
|
||||
}
|
||||
|
||||
export async function appendSnippets(
|
||||
chatId: number,
|
||||
snippets: Omit<SmartContextSnippet, "id" | "ts" | "tokens">[],
|
||||
): Promise<number> {
|
||||
const dir = getThreadDir(chatId);
|
||||
await ensureDir(dir);
|
||||
const snippetsPath = getSnippetsPath(chatId);
|
||||
const withDefaults: SmartContextSnippet[] = snippets.map((s) => ({
|
||||
id: randomUUID(),
|
||||
ts: Date.now(),
|
||||
tokens: estimateTokens(s.text),
|
||||
...s,
|
||||
}));
|
||||
const lines = withDefaults.map((obj) => JSON.stringify(obj)).join("\n");
|
||||
await fs.appendFile(snippetsPath, (lines ? lines + "\n" : ""), "utf8");
|
||||
|
||||
// prune if exceeded max
|
||||
const meta = await readMeta(chatId);
|
||||
const maxSnippets = meta.config?.maxSnippets ?? 400;
|
||||
try {
|
||||
const file = await fs.readFile(snippetsPath, "utf8");
|
||||
const allLines = file.split("\n").filter(Boolean);
|
||||
if (allLines.length > maxSnippets) {
|
||||
const toKeep = allLines.slice(allLines.length - maxSnippets);
|
||||
await fs.writeFile(snippetsPath, toKeep.join("\n") + "\n", "utf8");
|
||||
return toKeep.length;
|
||||
}
|
||||
return allLines.length;
|
||||
} catch {
|
||||
return withDefaults.length;
|
||||
}
|
||||
}
|
||||
|
||||
export async function readAllSnippets(chatId: number): Promise<SmartContextSnippet[]> {
|
||||
try {
|
||||
const raw = await fs.readFile(getSnippetsPath(chatId), "utf8");
|
||||
return raw
|
||||
.split("\n")
|
||||
.filter(Boolean)
|
||||
.map((line) => JSON.parse(line) as SmartContextSnippet);
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
function normalize(value: number, min: number, max: number): number {
|
||||
if (max === min) return 0;
|
||||
return (value - min) / (max - min);
|
||||
}
|
||||
|
||||
function keywordScore(text: string, query: string): number {
|
||||
const toTokens = (s: string) =>
|
||||
s
|
||||
.toLowerCase()
|
||||
.replace(/[^a-z0-9_\- ]+/g, " ")
|
||||
.split(/\s+/)
|
||||
.filter(Boolean);
|
||||
const qTokens = new Set(toTokens(query));
|
||||
const tTokens = toTokens(text);
|
||||
if (qTokens.size === 0 || tTokens.length === 0) return 0;
|
||||
let hits = 0;
|
||||
for (const tok of tTokens) if (qTokens.has(tok)) hits++;
|
||||
return hits / tTokens.length; // simple overlap ratio
|
||||
}
|
||||
|
||||
export interface RetrieveContextResult {
|
||||
rollingSummary?: string;
|
||||
usedTokens: number;
|
||||
snippets: SmartContextSnippet[];
|
||||
}
|
||||
|
||||
export async function retrieveContext(
|
||||
chatId: number,
|
||||
query: string,
|
||||
budgetTokens: number,
|
||||
): Promise<RetrieveContextResult> {
|
||||
const meta = await readMeta(chatId);
|
||||
const snippets = await readAllSnippets(chatId);
|
||||
const now = Date.now();
|
||||
let minTs = now;
|
||||
let maxTs = 0;
|
||||
for (const s of snippets) {
|
||||
if (s.ts < minTs) minTs = s.ts;
|
||||
if (s.ts > maxTs) maxTs = s.ts;
|
||||
}
|
||||
const scored = snippets.map((s) => {
|
||||
const recency = normalize(s.ts, minTs, maxTs);
|
||||
const kw = keywordScore(s.text, query);
|
||||
const base = 0.6 * kw + 0.4 * recency;
|
||||
const score = base;
|
||||
return { ...s, score } as SmartContextSnippet;
|
||||
});
|
||||
scored.sort((a, b) => (b.score ?? 0) - (a.score ?? 0));
|
||||
|
||||
const picked: SmartContextSnippet[] = [];
|
||||
let usedTokens = 0;
|
||||
for (const s of scored) {
|
||||
const t = s.tokens ?? estimateTokens(s.text);
|
||||
if (usedTokens + t > budgetTokens) break;
|
||||
picked.push(s);
|
||||
usedTokens += t;
|
||||
}
|
||||
|
||||
const rollingSummary = meta.rollingSummary || "";
|
||||
return { rollingSummary, usedTokens, snippets: picked };
|
||||
}
|
||||
|
||||
export async function rebuildIndex(_chatId: number): Promise<void> {
|
||||
// Placeholder for future embedding/vector index rebuild.
|
||||
return;
|
||||
}
|
||||
13
dyad-backup-20251205-195655/last-changes.diff
Normal file
@@ -0,0 +1,13 @@
|
||||
diff --git a/update-dyad.sh b/update-dyad.sh
|
||||
index 2763b94..4d7da4c 100755
|
||||
--- a/update-dyad.sh
|
||||
+++ b/update-dyad.sh
|
||||
@@ -78,7 +78,7 @@ git log --oneline HEAD..upstream/main --reverse
|
||||
|
||||
# Attempt to merge
|
||||
print_status "Merging upstream changes into your branch..."
|
||||
-if git merge upstream/main -m "merge: update from upstream - $(date)"; then
|
||||
+if git merge upstream/main -m "merge: update from upstream - $(date)" --allow-unrelated-histories; then
|
||||
print_success "✅ Update completed successfully!"
|
||||
|
||||
# Check for any conflicts that need manual resolution
|
||||
@@ -1,75 +0,0 @@
|
||||
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,5 +1,4 @@
|
||||
import { testSkipIfWindows, test } from "./helpers/test_helper";
|
||||
import { expect } from "@playwright/test";
|
||||
|
||||
testSkipIfWindows("fix error with AI", async ({ po }) => {
|
||||
await po.setUp({ autoApprove: true });
|
||||
@@ -21,26 +20,6 @@ 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,4 +2,3 @@ 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,6 +3,7 @@ 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");
|
||||
@@ -15,6 +16,7 @@ return (
|
||||
Start building your amazing project here!
|
||||
</p>
|
||||
</div>
|
||||
<MadeWithDyad />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -3,6 +3,7 @@ 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");
|
||||
@@ -15,6 +16,7 @@ return (
|
||||
Start building your amazing project here!
|
||||
</p>
|
||||
</div>
|
||||
<MadeWithDyad />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
1
|
||||
@@ -1 +0,0 @@
|
||||
This is a simple basic response
|
||||
|
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 1.2 KiB |
@@ -341,11 +341,7 @@ export class PageObject {
|
||||
|
||||
async selectChatMode(mode: "build" | "ask" | "agent") {
|
||||
await this.page.getByTestId("chat-mode-selector").click();
|
||||
await this.page
|
||||
.getByRole("option", {
|
||||
name: mode === "agent" ? "Build with MCP (experimental)" : mode,
|
||||
})
|
||||
.click();
|
||||
await this.page.getByRole("option", { name: mode }).click();
|
||||
}
|
||||
|
||||
async openContextFilesPicker() {
|
||||
@@ -557,22 +553,6 @@ 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...");
|
||||
}
|
||||
@@ -595,13 +575,6 @@ 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();
|
||||
}
|
||||
|
||||
@@ -1,150 +0,0 @@
|
||||
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
|
||||
},
|
||||
);
|
||||
@@ -1,15 +0,0 @@
|
||||
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,6 +16,5 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": false,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -16,6 +16,5 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -2276,6 +2276,7 @@ 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",
|
||||
"@tanstack/react-query": "^5.56.2",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
@@ -7548,6 +7549,7 @@ createRoot(document.getElementById("root")!).render(<App />);
|
||||
}
|
||||
|
||||
const toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>();
|
||||
|
||||
const addToRemoveQueue = (toastId: string) => {
|
||||
if (toastTimeouts.has(toastId)) {
|
||||
return;
|
||||
@@ -7558,6 +7560,7 @@ const Index = () => {
|
||||
dispatch({
|
||||
type: "REMOVE_TOAST",
|
||||
toastId: toastId,
|
||||
});
|
||||
}, TOAST_REMOVE_DELAY);
|
||||
|
||||
toastTimeouts.set(toastId, timeout);
|
||||
|
||||
@@ -244,6 +244,7 @@ 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
|
||||
@@ -800,6 +801,7 @@ 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 (
|
||||
@@ -810,6 +812,7 @@ const Index = () => {
|
||||
Start building your amazing project here!
|
||||
</p>
|
||||
</div>
|
||||
<MadeWithDyad />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -244,6 +244,7 @@ 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
|
||||
@@ -800,6 +801,7 @@ 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 (
|
||||
@@ -810,6 +812,7 @@ const Index = () => {
|
||||
Start building your amazing project here!
|
||||
</p>
|
||||
</div>
|
||||
<MadeWithDyad />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -244,6 +244,7 @@ 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
|
||||
@@ -800,6 +801,7 @@ 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 (
|
||||
@@ -810,6 +812,7 @@ const Index = () => {
|
||||
Start building your amazing project here!
|
||||
</p>
|
||||
</div>
|
||||
<MadeWithDyad />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -18,6 +18,5 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -244,6 +244,7 @@ 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
|
||||
@@ -800,6 +801,7 @@ 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 (
|
||||
@@ -810,6 +812,7 @@ const Index = () => {
|
||||
Start building your amazing project here!
|
||||
</p>
|
||||
</div>
|
||||
<MadeWithDyad />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -319,6 +319,7 @@ export default App;
|
||||
|
||||
|
||||
=== src/components/made-with-dyad.tsx ===
|
||||
export const MadeWithDyad = () => {
|
||||
return (
|
||||
<div className="p-4 text-center">
|
||||
<a
|
||||
@@ -5591,6 +5592,7 @@ 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 (
|
||||
@@ -5601,6 +5603,7 @@ const Index = () => {
|
||||
Start building your amazing project here!
|
||||
</p>
|
||||
</div>
|
||||
<MadeWithDyad />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -244,6 +244,7 @@ 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
|
||||
@@ -800,6 +801,7 @@ 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 (
|
||||
@@ -810,6 +812,7 @@ const Index = () => {
|
||||
Start building your amazing project here!
|
||||
</p>
|
||||
</div>
|
||||
<MadeWithDyad />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -316,6 +316,7 @@ 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"
|
||||
@@ -5584,6 +5585,7 @@ 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 (
|
||||
@@ -5594,6 +5596,7 @@ const Index = () => {
|
||||
Start building your amazing project here!
|
||||
</p>
|
||||
</div>
|
||||
<MadeWithDyad />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -88,6 +88,7 @@
|
||||
},
|
||||
{
|
||||
"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
|
||||
},
|
||||
{
|
||||
@@ -362,6 +363,7 @@
|
||||
},
|
||||
{
|
||||
"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,6 +28,7 @@
|
||||
"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",
|
||||
@@ -82,6 +83,7 @@
|
||||
"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,6 +28,7 @@
|
||||
"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",
|
||||
@@ -82,6 +83,7 @@
|
||||
"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,6 +33,7 @@
|
||||
"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",
|
||||
@@ -87,6 +88,7 @@
|
||||
"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,6 +33,7 @@
|
||||
"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",
|
||||
@@ -87,6 +88,7 @@
|
||||
"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,6 +33,7 @@
|
||||
"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",
|
||||
@@ -87,6 +88,7 @@
|
||||
"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,12 +7,11 @@
|
||||
- img
|
||||
- text: "src/pages/Index.tsx Summary: intentionally add first error"
|
||||
- img
|
||||
- text: Error First error in Index...
|
||||
- img
|
||||
- button "Copy":
|
||||
- img
|
||||
- text: Error
|
||||
- button "Fix with AI":
|
||||
- img
|
||||
- text: First error in Index...
|
||||
- img
|
||||
- img
|
||||
- text: ErrorComponent.tsx
|
||||
- button "Edit":
|
||||
@@ -20,12 +19,11 @@
|
||||
- img
|
||||
- text: "src/components/ErrorComponent.tsx Summary: intentionally add second error"
|
||||
- img
|
||||
- text: Error Second error in ErrorComponent...
|
||||
- img
|
||||
- button "Copy":
|
||||
- img
|
||||
- text: Error
|
||||
- button "Fix with AI":
|
||||
- img
|
||||
- text: Second error in ErrorComponent...
|
||||
- img
|
||||
- img
|
||||
- text: helper.ts
|
||||
- button "Edit":
|
||||
@@ -33,12 +31,11 @@
|
||||
- img
|
||||
- text: "src/utils/helper.ts Summary: intentionally add third error"
|
||||
- img
|
||||
- text: Error Third error in helper...
|
||||
- img
|
||||
- button "Copy":
|
||||
- img
|
||||
- text: Error
|
||||
- button "Fix with AI":
|
||||
- img
|
||||
- text: Third error in helper...
|
||||
- img
|
||||
- button "Fix All Errors (3)":
|
||||
- img
|
||||
- button:
|
||||
|
||||
@@ -88,6 +88,7 @@
|
||||
},
|
||||
{
|
||||
"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
|
||||
},
|
||||
{
|
||||
@@ -362,6 +363,7 @@
|
||||
},
|
||||
{
|
||||
"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,6 +247,7 @@ 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
|
||||
@@ -803,6 +804,7 @@ 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 (
|
||||
@@ -813,6 +815,7 @@ const Index = () => {
|
||||
Start building your amazing project here!
|
||||
</p>
|
||||
</div>
|
||||
<MadeWithDyad />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -244,6 +244,7 @@ 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
|
||||
@@ -800,6 +801,7 @@ 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 (
|
||||
@@ -810,6 +812,7 @@ const Index = () => {
|
||||
Start building your amazing project here!
|
||||
</p>
|
||||
</div>
|
||||
<MadeWithDyad />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -16,6 +16,5 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "beta",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -16,6 +16,5 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -253,6 +253,7 @@ 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
|
||||
@@ -809,6 +810,7 @@ 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 (
|
||||
@@ -819,6 +821,7 @@ const Index = () => {
|
||||
Start building your amazing project here!
|
||||
</p>
|
||||
</div>
|
||||
<MadeWithDyad />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -244,6 +244,7 @@ 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
|
||||
@@ -800,6 +801,7 @@ 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 (
|
||||
@@ -810,6 +812,7 @@ const Index = () => {
|
||||
Start building your amazing project here!
|
||||
</p>
|
||||
</div>
|
||||
<MadeWithDyad />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -5,5 +5,6 @@
|
||||
- button "Deselect component":
|
||||
- img
|
||||
- img
|
||||
- text: a src/components/made-with-dyad.tsx:4
|
||||
- button "Deselect component":
|
||||
- img
|
||||
@@ -5,3 +5,4 @@
|
||||
- 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,5 +1,6 @@
|
||||
- text: Selected Components (1)
|
||||
- button "Clear all"
|
||||
- img
|
||||
- text: a src/components/made-with-dyad.tsx:4
|
||||
- button "Deselect component":
|
||||
- img
|
||||
@@ -66,6 +66,7 @@ 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 (
|
||||
@@ -76,6 +77,7 @@ const Index = () => {
|
||||
Start building your amazing project here!
|
||||
</p>
|
||||
</div>
|
||||
<MadeWithDyad />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -118,6 +118,7 @@ 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 (
|
||||
@@ -125,6 +126,7 @@ 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>
|
||||
);
|
||||
}
|
||||
@@ -158,5 +160,6 @@ 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,3 +5,4 @@
|
||||
- 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,5 +5,6 @@
|
||||
- button "Deselect component":
|
||||
- img
|
||||
- img
|
||||
- text: a src/components/made-with-dyad.tsx:4
|
||||
- button "Deselect component":
|
||||
- img
|
||||
@@ -1,12 +0,0 @@
|
||||
- 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,6 +88,7 @@
|
||||
},
|
||||
{
|
||||
"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
|
||||
},
|
||||
{
|
||||
@@ -362,6 +363,7 @@
|
||||
},
|
||||
{
|
||||
"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,6 +57,7 @@
|
||||
"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",
|
||||
@@ -121,6 +122,7 @@
|
||||
"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,6 +24,5 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -25,6 +25,5 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -24,6 +24,5 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -25,6 +25,5 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -15,6 +15,5 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -16,6 +16,5 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -15,6 +15,5 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -16,6 +16,5 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -15,6 +15,5 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -16,6 +16,5 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -16,6 +16,5 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -17,6 +17,5 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -17,6 +17,5 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -25,6 +25,5 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "1"
|
||||
"content": "Error: Test case file not found: 1.md"
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
@@ -41,6 +41,7 @@
|
||||
"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",
|
||||
@@ -95,6 +96,7 @@
|
||||
"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,6 +25,5 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "1"
|
||||
"content": "Error: Test case file not found: 1.md"
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
@@ -49,6 +49,7 @@
|
||||
"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",
|
||||
@@ -103,6 +104,7 @@
|
||||
"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,6 +25,5 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "1"
|
||||
"content": "Error: Test case file not found: 1.md"
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
@@ -57,6 +57,7 @@
|
||||
"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",
|
||||
@@ -111,6 +112,7 @@
|
||||
"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,6 +24,5 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -25,6 +25,5 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -25,6 +25,5 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||
@@ -25,6 +25,5 @@
|
||||
"enableAutoFixProblems": false,
|
||||
"enableAutoUpdate": true,
|
||||
"releaseChannel": "stable",
|
||||
"isRunning": true,
|
||||
"isTestMode": true
|
||||
}
|
||||