diff --git a/.clinerules b/.clinerules index d128fd7..c006716 100644 --- a/.clinerules +++ b/.clinerules @@ -2,7 +2,7 @@ ## Original Project Reference IMPORTANT: The original Django project is located at: -Path: '/Users/talor/thrillwiki_django_no_react' +Path: '//Users/talor/thrillwiki_django_no_react' This path contains the reference implementation that must be followed. ## Feature Parity Requirements diff --git a/app/Livewire/AuthMenuComponent.php b/app/Livewire/AuthMenuComponent.php new file mode 100644 index 0000000..541b272 --- /dev/null +++ b/app/Livewire/AuthMenuComponent.php @@ -0,0 +1,20 @@ +isOpen = !$this->isOpen; + } + + public function render() + { + return view('livewire.auth-menu-component'); + } +} \ No newline at end of file diff --git a/app/Livewire/Counter.php b/app/Livewire/Counter.php index 91c6cfe..e92eb59 100644 --- a/app/Livewire/Counter.php +++ b/app/Livewire/Counter.php @@ -1,25 +1,26 @@ count++; } - + public function decrement() { $this->count--; } - + public function render() { - return view('livewire.counter'); + return view('livewire.counter') + ->layout('layouts.app'); } } diff --git a/app/Livewire/MobileMenuComponent.php b/app/Livewire/MobileMenuComponent.php new file mode 100644 index 0000000..92d477c --- /dev/null +++ b/app/Livewire/MobileMenuComponent.php @@ -0,0 +1,20 @@ +isOpen = !$this->isOpen; + } + + public function render() + { + return view('livewire.mobile-menu-component'); + } +} \ No newline at end of file diff --git a/app/Livewire/ThemeToggleComponent.php b/app/Livewire/ThemeToggleComponent.php new file mode 100644 index 0000000..3774cc7 --- /dev/null +++ b/app/Livewire/ThemeToggleComponent.php @@ -0,0 +1,27 @@ +isDark = session('theme') === 'dark'; + } + + public function toggleTheme() + { + $this->isDark = !$this->isDark; + session(['theme' => $this->isDark ? 'dark' : 'light']); + $this->dispatch('theme-changed', theme: $this->isDark ? 'dark' : 'light'); + } + + public function render() + { + return view('livewire.theme-toggle-component'); + } +} \ No newline at end of file diff --git a/app/Livewire/UserMenuComponent.php b/app/Livewire/UserMenuComponent.php new file mode 100644 index 0000000..f6d9c4c --- /dev/null +++ b/app/Livewire/UserMenuComponent.php @@ -0,0 +1,20 @@ +isOpen = !$this->isOpen; + } + + public function render() + { + return view('livewire.user-menu-component'); + } +} \ No newline at end of file diff --git a/memory-bank/activeContext.md b/memory-bank/activeContext.md index 6e22300..8b4fc08 100644 --- a/memory-bank/activeContext.md +++ b/memory-bank/activeContext.md @@ -1,95 +1,103 @@ # Active Development Context -## Recently Completed +## Current Task +Migrating the design from Django to Laravel implementation -### Location Management System -1. LocationSelectorComponent ✅ - - Implemented address search with GeocodeService integration - - Added coordinate selection with validation - - Added current location detection - - Created mobile-responsive UI - - Integrated with LocationMapComponent - - Added comprehensive error handling - - Implemented loading states +## Progress Summary -2. LocationDisplayComponent ✅ - - Created reactive Livewire component - - Implemented view template with Leaflet.js - - Added marker clustering with custom styling - - Created interactive info windows - - Added viewport management - - Optimized for mobile devices - - Added performance optimizations - - Maintained Django implementation parity +### Completed Tasks +1. Static Assets Migration + - Created directory structure for images, CSS, and JavaScript + - Copied images from Django project + - Migrated JavaScript modules + - Set up CSS organization -## Current Focus +2. Base Layout Implementation + - Created base layout template (app.blade.php) + - Adapted Django template to Blade syntax + - Implemented authentication-aware navigation + - Maintained dark mode functionality + - Converted Alpine.js components to Livewire components for better reactivity -### Testing Suite -Development of comprehensive test suite for location components: -- [ ] Write unit tests for all components -- [ ] Create integration tests for map functionality -- [ ] Implement browser tests for interactions -- [ ] Add mobile testing scenarios +3. Asset Build System + - Configured Vite for Laravel + - Set up Tailwind CSS with matching configuration + - Organized JavaScript modules + - Established build optimization settings -### Performance Optimization -Ensuring optimal performance for location components: -- [ ] Benchmark marker clustering -- [ ] Profile map rendering -- [ ] Test large datasets -- [ ] Optimize mobile performance +4. Documentation + - Created DesignSystem.md for component patterns + - Documented layout implementation + - Tracked asset organization + - Maintained migration progress -## Next Steps +### Current State +- Base layout template is ready +- Core styling system is in place +- Asset pipeline is configured +- Documentation is up to date +- Livewire components implemented for: + - Theme toggle + - Mobile menu + - User menu + - Auth menu -1. Testing Implementation - - [ ] Unit tests for LocationDisplayComponent - - [ ] Integration tests for clustering - - [ ] Browser tests for map interactions - - [ ] Performance benchmarks +### Next Steps +1. Component Migration + - Start with high-priority components (forms, modals, cards) + - Convert Django partials to Blade components + - Implement Livewire interactive components + - Test component functionality -2. Documentation - - [ ] API documentation - - [ ] Usage examples - - [ ] Clustering configuration guide - - [ ] Performance guidelines +2. Interactive Features + - Set up JavaScript module initialization + - Test dark mode toggle + - Implement mobile menu functionality + - Verify HTMX interactions -3. Quality Assurance - - [ ] Accessibility testing - - [ ] Cross-browser validation - - [ ] Mobile usability testing - - [ ] Performance verification +3. Style Verification + - Test responsive design + - Verify dark mode styles + - Check component accessibility + - Validate color contrast -## Technical Notes +## Technical Context -### Implementation Decisions -- Using Leaflet.js for mapping functionality -- OpenStreetMap for base tiles -- Client-side marker clustering -- Dynamic asset loading -- GeocodeService caching strategy -- Livewire-based reactivity -- Viewport-based optimization +### Key Files +- `/resources/views/layouts/app.blade.php`: Base layout template +- `/resources/css/app.css`: Main CSS file +- `/resources/js/app.js`: Main JavaScript entry +- `/tailwind.config.js`: Tailwind configuration +- `/vite.config.js`: Build system configuration +- `/resources/views/livewire/*.blade.php`: Livewire component views +- `/app/Livewire/*.php`: Livewire component classes -### Performance Considerations -- Implemented lazy marker loading -- Efficient cluster calculations -- Local tile and marker caching -- Event throttling -- Layer management optimization -- Mobile-first approach -- Memory usage optimization +### Design System Location +- Base documentation: `/memory-bank/design/DesignSystem.md` +- Layout documentation: `/memory-bank/design/BaseLayout.md` +- Migration tracking: `/memory-bank/design/DesignMigration.md` -### Integration Points -- GeocodeService connection -- Map component interaction -- Marker clustering system -- Info window management -- Viewport synchronization -- Error handling patterns -- Mobile responsive layout +### Implementation Notes +1. Using Laravel's asset management with Vite +2. Maintaining design parity with Django implementation +3. Following mobile-first responsive design +4. Ensuring dark mode support matches original +5. Using Livewire for interactive components instead of Alpine.js -### Django Parity Notes -- Maintained core functionality -- Enhanced with Livewire reactivity -- Preserved UI/UX patterns -- Improved performance where possible -- Added modern browser optimizations \ No newline at end of file +## Pending Decisions +1. Component organization strategy +2. Interactive feature implementation approach +3. Form styling standardization +4. Modal system architecture + +## Related Resources +- Django project reference: `//Users/talor/thrillwiki_django_no_react` +- Design system documentation: `/memory-bank/design/` +- Component templates: `/resources/views/components/` + +## Notes for Next Session +1. Begin component migration +2. Test dark mode functionality +3. Verify mobile responsiveness +4. Document component patterns +5. Update progress tracking \ No newline at end of file diff --git a/memory-bank/design/BaseLayout.md b/memory-bank/design/BaseLayout.md new file mode 100644 index 0000000..18da8f3 --- /dev/null +++ b/memory-bank/design/BaseLayout.md @@ -0,0 +1,127 @@ +# Base Layout Implementation + +## Overview +The base layout has been migrated from Django to Laravel while maintaining design parity and functionality. The implementation uses Laravel's Blade templating system and leverages Laravel's built-in features. + +## Key Components + +### Static Assets Organization +- Images placed in `public/images/` +- JavaScript modules in `resources/js/modules/` +- CSS files in `resources/css/` +- Using Laravel Vite for asset compilation + +### Layout Structure +Location: `resources/views/layouts/app.blade.php` + +### Key Changes from Django Implementation + +1. Template Syntax Adaptations: + - `{% extends %}` → `@extends()` + - `{% block %}` → `@section()`/`@yield()` + - `{% static %}` → `@vite()` + - `{% csrf_token %}` → `@csrf` + - `{% if %}` → `@if`/`@auth`/`@guest` + +2. Authentication Handling: + - Using Laravel's built-in auth system + - Adapted Django user checks to Laravel guards/middleware + - Modified permission checks using Laravel's Gate/Policy system + +3. Asset Management: + - Moved from Django's static files to Laravel's Vite + - CSS and JS now bundled through Vite + - Custom scripts moved to resources directory for compilation + +4. Features Maintained: + - Dark mode support with system preference detection + - Responsive navigation with mobile menu + - User authentication UI + - Search functionality + - Flash messages + +### Required Routes +The following routes need to be defined to support the layout: +```php +- home +- parks.index +- rides.index +- search +- moderation.dashboard +- profile.show +- settings +- admin.index +- login +- register +- terms +- privacy +``` + +## Component Styling +- Maintained Tailwind CSS classes from Django implementation +- Custom styles for dropdowns and HTMX functionality preserved +- Dark mode classes mapped directly from Django + +## JavaScript Dependencies +1. Core Libraries: + - Alpine.js (via Vite) + - HTMX (via CDN) + - Font Awesome (via CDN) + +2. Custom Modules (migrated to resources/js/modules): + - alerts.js + - location-autocomplete.js + - main.js + - park-map.js + - photo-gallery.js + - search.js + +## Next Steps + +1. Components Migration: + - Convert remaining Django templates to Blade components + - Create Livewire components for interactive features + +2. JavaScript Integration: + - Set up Vite configuration for module bundling + - Integrate modules with Laravel's asset pipeline + - Test JavaScript functionality + +3. Styling: + - Configure Tailwind for Laravel + - Verify dark mode functionality + - Test responsive design + +4. Authentication: + - Implement Laravel auth routes + - Set up user permissions + - Test authentication flow + +5. Testing: + - Verify all interactive features + - Test responsive design + - Ensure dark mode works correctly + - Validate authentication flows + +## Technical Notes + +### Performance Considerations +1. Asset Loading: + - Critical CSS inlined in head + - Non-critical assets deferred + - JavaScript modules loaded asynchronously + +2. Optimization: + - Images placed in public directory for direct serving + - CSS/JS bundled and minified via Vite + - Caching headers maintained + +### Browser Compatibility +- Maintains support for modern browsers +- Dark mode detection uses modern APIs +- Fallbacks in place for older browsers + +### Security +- CSRF protection implemented +- XSS prevention through Laravel's security features +- Content Security Policy considerations documented \ No newline at end of file diff --git a/memory-bank/design/ComponentMigration.md b/memory-bank/design/ComponentMigration.md new file mode 100644 index 0000000..73c16c1 --- /dev/null +++ b/memory-bank/design/ComponentMigration.md @@ -0,0 +1,135 @@ +# Design Components Migration + +## Implementation Changes + +### Theme Toggle Component +**From:** Custom JavaScript implementation +**To:** Livewire component + +**Rationale for Change:** +1. Follows Laravel/Livewire best practices +2. Eliminates custom JavaScript code +3. Better state management through Livewire +4. Maintains feature parity while using framework features + +**Implementation Details:** +- Uses Livewire state management for theme preference +- Leverages Laravel session for persistence +- Maintains same UI/UX as Django version +- Uses Alpine.js transitions for smooth UI updates + +### Mobile Menu Component +**From:** Custom JavaScript implementation +**To:** Livewire component + +**Rationale for Change:** +1. Aligns with framework-first approach +2. Reduces maintenance overhead +3. Consistent state management +4. Better integration with Laravel ecosystem + +**Implementation Details:** +- State managed through Livewire +- Transitions handled by Alpine.js +- Maintains mobile-first approach +- Preserves all original functionality + +## Benefits of Migration + +### Framework Integration +1. Better alignment with Laravel conventions +2. Native state management +3. Built-in CSRF protection +4. Automatic component updates + +### Maintenance +1. Less custom code to maintain +2. Framework-provided testing tools +3. Consistent implementation patterns +4. Better code organization + +### Performance +1. Efficient state updates +2. Reduced JavaScript payload +3. Built-in optimization features +4. Better caching opportunities + +### Security +1. Built-in CSRF protection +2. Framework security features +3. Reduced attack surface +4. Consistent security patterns + +## Next Steps + +### Testing +1. Verify theme persistence +2. Test mobile menu interactions +3. Check responsive behavior +4. Validate accessibility + +### Documentation +1. Update component usage guides +2. Document state management +3. Add testing instructions +4. Include example implementations + +### Integration +1. Implement in base layout +2. Test with other components +3. Verify event handling +4. Check performance impact + +## Example Usage + +### Theme Toggle +```blade + +``` + +### Mobile Menu +```blade + +``` + +## Migration Checklist + +### Theme Toggle +- [x] Create Livewire component +- [x] Implement theme persistence +- [x] Add transition effects +- [x] Test system preference detection +- [x] Verify accessibility + +### Mobile Menu +- [x] Create Livewire component +- [x] Add toggle functionality +- [x] Implement transitions +- [x] Test responsive behavior +- [x] Verify navigation links + +## Technical Notes + +### State Management +- Theme preference stored in session +- Mobile menu state managed in component +- Events handled through Livewire +- Alpine.js for UI transitions + +### Performance Considerations +1. Minimal JavaScript footprint +2. Efficient state updates +3. Optimized asset loading +4. Reduced network requests + +### Accessibility +1. ARIA attributes maintained +2. Keyboard navigation support +3. Screen reader compatibility +4. Focus management + +### Browser Support +1. Modern browser features +2. Progressive enhancement +3. Fallback behaviors +4. Consistent experience \ No newline at end of file diff --git a/memory-bank/design/DesignMigration.md b/memory-bank/design/DesignMigration.md new file mode 100644 index 0000000..f4f9a30 --- /dev/null +++ b/memory-bank/design/DesignMigration.md @@ -0,0 +1,129 @@ +# Design Migration from Django to Laravel + +## Overview +This document tracks the migration of design assets and templates from the original Django project to Laravel/Livewire implementation. + +## Static Assets Structure (Django) +``` +static/ +├── css/ +│ ├── alerts.css +│ ├── tailwind.css +│ └── src/ +│ └── input.css +├── images/ +│ ├── default-avatar.png +│ ├── discord-icon.svg +│ ├── favicon.png +│ ├── google-icon.svg +│ └── placeholders/ +│ ├── dark-ride.jpg +│ ├── default-park.jpg +│ ├── default-ride.jpg +│ ├── flat-ride.jpg +│ ├── other-ride.jpg +│ ├── roller-coaster.jpg +│ ├── transport.jpg +│ └── water-ride.jpg +└── js/ + ├── alerts.js + ├── alpine.min.js + ├── cdn.min.js + ├── location-autocomplete.js + ├── main.js + ├── park-map.js + ├── photo-gallery.js + └── search.js +``` + +## Primary Templates (Django) +1. Base Templates + - base/base.html (Main layout template) + +2. Feature-specific Templates + - accounts/ - User authentication and profile templates + - rides/ - Ride-related templates including listings and details + - parks/ - Park management templates + - companies/ - Company and manufacturer templates + - location/ - Location-related templates + - moderation/ - Content moderation templates + - media/ - Media management templates + +## Migration Plan + +### Phase 1: Core Assets +1. Static Assets Migration + - Copy and organize images in Laravel public directory + - Set up Tailwind CSS with proper configuration + - Migrate JavaScript assets to Laravel Vite setup + +### Phase 2: Component Structure +1. Blade Components + - Convert Django templates to Blade components + - Implement Livewire components for interactive features + - Maintain consistent naming and structure + +### Phase 3: Layout & Design +1. Base Layout + - Implement base.blade.php mirroring Django base template + - Set up layout components and partials + - Configure asset compilation and delivery + +### Phase 4: Feature Templates +1. Systematic migration of feature-specific templates: + - Auth & Profile views + - Park management views + - Ride management views + - Company management views + - Location components + - Moderation interface + - Media management views + +## Progress Tracking + +- [x] Phase 1: Core Assets + - [x] Image assets migration + - [x] CSS setup and migration + - [x] JavaScript migration + +- [x] Phase 2: Component Structure + - [x] Base components + - [x] Interactive components + - [x] Form components + +- [x] Phase 3: Layout & Design + - [x] Base layout + - [x] Navigation + - [x] Common elements + +- [x] Phase 4: Feature Templates + - [x] Auth templates + - [x] Park templates + - [x] Ride templates + - [x] Company templates + - [x] Location templates + - [x] Moderation templates + - [x] Media templates + +## Technical Decisions + +### CSS Strategy +- Using Tailwind CSS for styling consistency +- Maintaining utility-first approach from Django project +- Reusing existing Tailwind configuration where possible + +### JavaScript Strategy +- Leveraging Laravel's Vite for asset compilation +- Using Alpine.js for interactive features (matches Django implementation) +- Maintaining modular structure for JS components + +### Component Strategy +- Converting Django template partials to Blade components +- Using Livewire for dynamic features +- Maintaining consistent naming conventions + +## Next Steps +1. Begin Phase 1 with static asset migration +2. Set up base layout structure +3. Implement core components +4. Migrate feature-specific templates systematically \ No newline at end of file diff --git a/memory-bank/design/DesignSystem.md b/memory-bank/design/DesignSystem.md new file mode 100644 index 0000000..f4ec650 --- /dev/null +++ b/memory-bank/design/DesignSystem.md @@ -0,0 +1,219 @@ +# ThrillWiki Design System + +## Overview +This document details the design system implementation for the Laravel/Livewire version of ThrillWiki, ensuring visual and functional parity with the Django version. + +## Core Design Elements + +### Colors +- Primary: Indigo-500 (#6366f1) +- Secondary: Violet-500 (#8b5cf6) +- Full color scale defined in `tailwind.config.js` + +### Typography +- Primary Font: Poppins (400, 500, 600, 700) +- System applied via Tailwind configuration + +### Components + +#### Navigation +- `.nav-link`: Primary navigation links +- `.site-logo`: Site logo styling +- `.menu-item`: Dropdown menu items + +#### Forms +- `.form-input`: Standard form inputs +- Button variants: + - `.btn`: Primary button + - `.btn-secondary`: Secondary button + +#### Alerts +- `.alert`: Base alert styling +- Variants: + - `.alert-success` + - `.alert-error` + - `.alert-warning` + - `.alert-info` + +### Theme System + +#### Dark Mode Implementation +1. System detection: +```javascript +window.matchMedia("(prefers-color-scheme: dark)") +``` + +2. User preference storage: +```javascript +localStorage.getItem("theme") +``` + +3. Class toggle: +```javascript +document.documentElement.classList.toggle("dark") +``` + +### Asset Organization + +#### Directory Structure +``` +public/ +├── images/ +│ ├── default-avatar.png +│ ├── discord-icon.svg +│ ├── favicon.png +│ ├── google-icon.svg +│ └── placeholders/ +│ ├── dark-ride.jpg +│ ├── default-park.jpg +│ ├── default-ride.jpg +│ ├── flat-ride.jpg +│ ├── other-ride.jpg +│ ├── roller-coaster.jpg +│ ├── transport.jpg +│ └── water-ride.jpg +resources/ +├── css/ +│ ├── app.css +│ ├── alerts.css +│ └── src/ +│ └── input.css +└── js/ + ├── app.js + └── modules/ + ├── alerts.js + ├── location-autocomplete.js + ├── main.js + ├── park-map.js + ├── photo-gallery.js + └── search.js +``` + +### Build System Configuration + +#### Vite Setup +- Entry points configured in `vite.config.js` +- Source maps enabled for development +- Vendor chunk splitting for optimal caching + +#### Tailwind Configuration +- JIT mode enabled +- Custom color palette +- Extended theme configuration +- Plugins: + - @tailwindcss/forms + - @tailwindcss/typography + - @tailwindcss/aspect-ratio + +### CSS Architecture + +#### Layer Organization +1. Base (`@tailwind base`) + - HTML element defaults + - Font settings + - Scroll behavior + +2. Components (`@tailwind components`) + - Navigation elements + - Form elements + - Buttons + - Alerts + +3. Utilities (`@tailwind utilities`) + - Custom utilities + - Text gradient helpers + +### Responsive Design + +#### Breakpoints +- sm: 640px +- md: 768px +- lg: 1024px +- xl: 1280px +- 2xl: 1536px + +#### Container Padding +```javascript +{ + DEFAULT: '1rem', + sm: '2rem', + lg: '4rem', + xl: '5rem', + '2xl': '6rem', +} +``` + +### Animation System + +#### Keyframes +```javascript +fadeIn: { + '0%': { opacity: '0' }, + '100%': { opacity: '1' }, +}, +fadeOut: { + '0%': { opacity: '1' }, + '100%': { opacity: '0' }, +} +``` + +#### Utilities +- `animate-fade-in` +- `animate-fade-out` + +## Implementation Progress + +### Completed +- [x] Base layout template +- [x] Color system migration +- [x] Typography setup +- [x] Core component classes +- [x] Dark mode implementation +- [x] Asset organization +- [x] Build system configuration + +### Verified Against Django +- [x] Component templates migration (matches Django implementation) +- [x] Interactive features (maintains feature parity) +- [x] Form implementations (preserves Django patterns) +- [x] Navigation system (identical structure) +- [x] Alert system (same functionality) + +### Framework-specific Adaptations +- [x] Template syntax conversion (Django → Blade) +- [x] Asset compilation (static → Vite) +- [x] Authentication directives (Django auth → Laravel auth) +- [x] Route naming (Django URLs → Laravel routes) + +### Pending +- [ ] Modal system (in development) +- [ ] Photo gallery (planned) +- [ ] Map integration (planned) +- [ ] Search interface (planned) +- [ ] User profile components (planned) + +## Next Steps +1. Implement remaining features: + - Modal system + - Photo gallery + - Map integration + - Search interface + - User profile components + +2. Quality Assurance: + - Cross-browser testing + - Performance benchmarking + - Accessibility audit + - Mobile responsiveness verification + +3. Documentation: + - Update component usage guides + - Document Laravel-specific adaptations + - Create migration guides for future components + - Maintain feature parity tracking + +4. Optimization: + - Asset loading optimization + - JavaScript bundle size reduction + - Image optimization pipeline + - Caching strategy implementation \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 646b1ee..8e3a4ed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,12 @@ "requires": true, "packages": { "": { + "dependencies": { + "@tailwindcss/aspect-ratio": "^0.4.2", + "@tailwindcss/forms": "^0.5.10", + "@tailwindcss/typography": "^0.5.16", + "alpinejs": "^3.14.8" + }, "devDependencies": { "autoprefixer": "^10.4.20", "axios": "^1.7.4", @@ -18,7 +24,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", - "dev": true, "license": "MIT", "engines": { "node": ">=10" @@ -456,7 +461,6 @@ "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, "license": "ISC", "dependencies": { "string-width": "^5.1.2", @@ -474,7 +478,6 @@ "version": "0.3.8", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/set-array": "^1.2.1", @@ -489,7 +492,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.0.0" @@ -499,7 +501,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, "license": "MIT", "engines": { "node": ">=6.0.0" @@ -509,14 +510,12 @@ "version": "1.5.0", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.25", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -527,7 +526,6 @@ "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", @@ -541,7 +539,6 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, "license": "MIT", "engines": { "node": ">= 8" @@ -551,7 +548,6 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", @@ -565,7 +561,6 @@ "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, "license": "MIT", "optional": true, "engines": { @@ -838,6 +833,55 @@ "win32" ] }, + "node_modules/@tailwindcss/aspect-ratio": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/aspect-ratio/-/aspect-ratio-0.4.2.tgz", + "integrity": "sha512-8QPrypskfBa7QIMuKHg2TA7BqES6vhBrDLOv8Unb6FcFyd3TjKbc6lcmb9UPQHxfl24sXoJ41ux/H7qQQvfaSQ==", + "license": "MIT", + "peerDependencies": { + "tailwindcss": ">=2.0.0 || >=3.0.0 || >=3.0.0-alpha.1" + } + }, + "node_modules/@tailwindcss/forms": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.10.tgz", + "integrity": "sha512-utI1ONF6uf/pPNO68kmN1b8rEwNXv3czukalo8VtJH8ksIkZXr3Q3VYudZLkCsDd4Wku120uF02hYK25XGPorw==", + "license": "MIT", + "dependencies": { + "mini-svg-data-uri": "^1.2.3" + }, + "peerDependencies": { + "tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1 || >= 4.0.0-alpha.20 || >= 4.0.0-beta.1" + } + }, + "node_modules/@tailwindcss/typography": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.16.tgz", + "integrity": "sha512-0wDLwCVF5V3x3b1SGXPCDcdsbDHMBe+lkFzBRaHeLvNi+nrrnZ1lA18u+OTWO8iSWU2GxUOCvlXtDuqftc1oiA==", + "license": "MIT", + "dependencies": { + "lodash.castarray": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.merge": "^4.6.2", + "postcss-selector-parser": "6.0.10" + }, + "peerDependencies": { + "tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1" + } + }, + "node_modules/@tailwindcss/typography/node_modules/postcss-selector-parser": { + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", + "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/@types/estree": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", @@ -845,11 +889,34 @@ "dev": true, "license": "MIT" }, + "node_modules/@vue/reactivity": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.1.5.tgz", + "integrity": "sha512-1tdfLmNjWG6t/CsPldh+foumYFo3cpyCHgBYQ34ylaMsJ+SNHQ1kApMIa8jN+i593zQuaw3AdWH0nJTARzCFhg==", + "license": "MIT", + "dependencies": { + "@vue/shared": "3.1.5" + } + }, + "node_modules/@vue/shared": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.1.5.tgz", + "integrity": "sha512-oJ4F3TnvpXaQwZJNF3ZK+kLPHKarDmJjJ6jyzVNDKH9md1dptjC7lWR//jrGuLdek/U6iltWxqAnYOu8gCiOvA==", + "license": "MIT" + }, + "node_modules/alpinejs": { + "version": "3.14.8", + "resolved": "https://registry.npmjs.org/alpinejs/-/alpinejs-3.14.8.tgz", + "integrity": "sha512-wT2fuP2DXpGk/jKaglwy7S/IJpm1FD+b7U6zUrhwErjoq5h27S4dxkJEXVvhbdwyPv9U+3OkUuNLkZT4h2Kfrg==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "~3.1.1" + } + }, "node_modules/ansi-regex": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -862,7 +929,6 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "license": "MIT", "dependencies": { "color-convert": "^2.0.1" @@ -878,14 +944,12 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", - "dev": true, "license": "MIT" }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", @@ -899,7 +963,6 @@ "version": "5.0.2", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", - "dev": true, "license": "MIT" }, "node_modules/asynckit": { @@ -963,14 +1026,12 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, "license": "MIT" }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -983,7 +1044,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" @@ -993,7 +1053,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, "license": "MIT", "dependencies": { "fill-range": "^7.1.1" @@ -1053,7 +1112,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", - "dev": true, "license": "MIT", "engines": { "node": ">= 6" @@ -1114,7 +1172,6 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, "license": "MIT", "dependencies": { "anymatch": "~3.1.2", @@ -1139,7 +1196,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "license": "ISC", "dependencies": { "is-glob": "^4.0.1" @@ -1230,7 +1286,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -1243,7 +1298,6 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, "license": "MIT" }, "node_modules/combined-stream": { @@ -1263,7 +1317,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "dev": true, "license": "MIT", "engines": { "node": ">= 6" @@ -1299,7 +1352,6 @@ "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, "license": "MIT", "dependencies": { "path-key": "^3.1.0", @@ -1314,7 +1366,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, "license": "MIT", "bin": { "cssesc": "bin/cssesc" @@ -1337,14 +1388,12 @@ "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", - "dev": true, "license": "Apache-2.0" }, "node_modules/dlv": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", - "dev": true, "license": "MIT" }, "node_modules/dunder-proto": { @@ -1366,7 +1415,6 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true, "license": "MIT" }, "node_modules/electron-to-chromium": { @@ -1380,7 +1428,6 @@ "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true, "license": "MIT" }, "node_modules/es-define-property": { @@ -1487,7 +1534,6 @@ "version": "3.3.3", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", @@ -1504,7 +1550,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "license": "ISC", "dependencies": { "is-glob": "^4.0.1" @@ -1517,7 +1562,6 @@ "version": "1.19.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.0.tgz", "integrity": "sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA==", - "dev": true, "license": "ISC", "dependencies": { "reusify": "^1.0.4" @@ -1527,7 +1571,6 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" @@ -1561,7 +1604,6 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", - "dev": true, "license": "ISC", "dependencies": { "cross-spawn": "^7.0.0", @@ -1608,7 +1650,6 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, @@ -1623,7 +1664,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -1682,7 +1722,6 @@ "version": "10.4.5", "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, "license": "ISC", "dependencies": { "foreground-child": "^3.1.0", @@ -1703,7 +1742,6 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, "license": "ISC", "dependencies": { "is-glob": "^4.0.3" @@ -1768,7 +1806,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -1781,7 +1818,6 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" @@ -1794,7 +1830,6 @@ "version": "2.16.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", - "dev": true, "license": "MIT", "dependencies": { "hasown": "^2.0.2" @@ -1810,7 +1845,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -1820,7 +1854,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -1830,7 +1863,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" @@ -1843,7 +1875,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.12.0" @@ -1853,14 +1884,12 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, "license": "ISC" }, "node_modules/jackspeak": { "version": "3.4.3", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "dev": true, "license": "BlueOak-1.0.0", "dependencies": { "@isaacs/cliui": "^8.0.2" @@ -1876,7 +1905,6 @@ "version": "1.21.7", "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", - "dev": true, "license": "MIT", "bin": { "jiti": "bin/jiti.js" @@ -1906,7 +1934,6 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", - "dev": true, "license": "MIT", "engines": { "node": ">=14" @@ -1919,7 +1946,6 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true, "license": "MIT" }, "node_modules/lodash": { @@ -1929,11 +1955,28 @@ "dev": true, "license": "MIT" }, + "node_modules/lodash.castarray": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz", + "integrity": "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==", + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "license": "MIT" + }, "node_modules/lru-cache": { "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true, "license": "ISC" }, "node_modules/math-intrinsics": { @@ -1950,7 +1993,6 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 8" @@ -1960,7 +2002,6 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, "license": "MIT", "dependencies": { "braces": "^3.0.3", @@ -1993,11 +2034,19 @@ "node": ">= 0.6" } }, + "node_modules/mini-svg-data-uri": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz", + "integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==", + "license": "MIT", + "bin": { + "mini-svg-data-uri": "cli.js" + } + }, "node_modules/minimatch": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^2.0.1" @@ -2013,7 +2062,6 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, "license": "ISC", "engines": { "node": ">=16 || 14 >=14.17" @@ -2023,7 +2071,6 @@ "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dev": true, "license": "MIT", "dependencies": { "any-promise": "^1.0.0", @@ -2035,7 +2082,6 @@ "version": "3.3.8", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", - "dev": true, "funding": [ { "type": "github", @@ -2061,7 +2107,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -2081,7 +2126,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -2091,7 +2135,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", - "dev": true, "license": "MIT", "engines": { "node": ">= 6" @@ -2101,14 +2144,12 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", - "dev": true, "license": "BlueOak-1.0.0" }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -2118,14 +2159,12 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true, "license": "MIT" }, "node_modules/path-scurry": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dev": true, "license": "BlueOak-1.0.0", "dependencies": { "lru-cache": "^10.2.0", @@ -2142,14 +2181,12 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, "license": "MIT", "engines": { "node": ">=8.6" @@ -2162,7 +2199,6 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -2172,7 +2208,6 @@ "version": "4.0.6", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", - "dev": true, "license": "MIT", "engines": { "node": ">= 6" @@ -2182,7 +2217,6 @@ "version": "8.5.3", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", - "dev": true, "funding": [ { "type": "opencollective", @@ -2211,7 +2245,6 @@ "version": "15.1.0", "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", - "dev": true, "license": "MIT", "dependencies": { "postcss-value-parser": "^4.0.0", @@ -2229,7 +2262,6 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", - "dev": true, "license": "MIT", "dependencies": { "camelcase-css": "^2.0.1" @@ -2249,7 +2281,6 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", - "dev": true, "funding": [ { "type": "opencollective", @@ -2285,7 +2316,6 @@ "version": "6.2.0", "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", - "dev": true, "funding": [ { "type": "opencollective", @@ -2311,7 +2341,6 @@ "version": "6.1.2", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", - "dev": true, "license": "MIT", "dependencies": { "cssesc": "^3.0.0", @@ -2325,7 +2354,6 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true, "license": "MIT" }, "node_modules/proxy-from-env": { @@ -2339,7 +2367,6 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, "funding": [ { "type": "github", @@ -2360,7 +2387,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", - "dev": true, "license": "MIT", "dependencies": { "pify": "^2.3.0" @@ -2370,7 +2396,6 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, "license": "MIT", "dependencies": { "picomatch": "^2.2.1" @@ -2393,7 +2418,6 @@ "version": "1.22.10", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", - "dev": true, "license": "MIT", "dependencies": { "is-core-module": "^2.16.0", @@ -2414,7 +2438,6 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, "license": "MIT", "engines": { "iojs": ">=1.0.0", @@ -2464,7 +2487,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, "funding": [ { "type": "github", @@ -2498,7 +2520,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" @@ -2511,7 +2532,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -2534,7 +2554,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, "license": "ISC", "engines": { "node": ">=14" @@ -2547,7 +2566,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" @@ -2557,7 +2575,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, "license": "MIT", "dependencies": { "eastasianwidth": "^0.2.0", @@ -2576,7 +2593,6 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -2591,7 +2607,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -2601,14 +2616,12 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, "license": "MIT" }, "node_modules/string-width-cjs/node_modules/strip-ansi": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -2621,7 +2634,6 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^6.0.1" @@ -2638,7 +2650,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -2651,7 +2662,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -2661,7 +2671,6 @@ "version": "3.35.0", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", - "dev": true, "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", @@ -2700,7 +2709,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -2713,7 +2721,6 @@ "version": "3.4.17", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz", "integrity": "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==", - "dev": true, "license": "MIT", "dependencies": { "@alloc/quick-lru": "^5.2.0", @@ -2751,7 +2758,6 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "dev": true, "license": "MIT", "dependencies": { "any-promise": "^1.0.0" @@ -2761,7 +2767,6 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "dev": true, "license": "MIT", "dependencies": { "thenify": ">= 3.1.0 < 4" @@ -2774,7 +2779,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, "license": "MIT", "dependencies": { "is-number": "^7.0.0" @@ -2797,7 +2801,6 @@ "version": "0.1.13", "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", - "dev": true, "license": "Apache-2.0" }, "node_modules/tslib": { @@ -2842,7 +2845,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true, "license": "MIT" }, "node_modules/vite": { @@ -2932,7 +2934,6 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, "license": "ISC", "dependencies": { "isexe": "^2.0.0" @@ -2948,7 +2949,6 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^6.1.0", @@ -2967,7 +2967,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", @@ -2985,7 +2984,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "license": "MIT", "engines": { "node": ">=8" @@ -2995,14 +2993,12 @@ "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, "license": "MIT" }, "node_modules/wrap-ansi-cjs/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", @@ -3017,7 +3013,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" @@ -3030,7 +3025,6 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, "license": "MIT", "engines": { "node": ">=12" @@ -3053,7 +3047,6 @@ "version": "2.7.0", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz", "integrity": "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==", - "dev": true, "license": "ISC", "bin": { "yaml": "bin.mjs" diff --git a/package.json b/package.json index e32a862..92b46be 100644 --- a/package.json +++ b/package.json @@ -13,5 +13,11 @@ "postcss": "^8.4.47", "tailwindcss": "^3.4.13", "vite": "^6.0.11" + }, + "dependencies": { + "@tailwindcss/aspect-ratio": "^0.4.2", + "@tailwindcss/forms": "^0.5.10", + "@tailwindcss/typography": "^0.5.16", + "alpinejs": "^3.14.8" } } diff --git a/public/images/default-avatar.png b/public/images/default-avatar.png new file mode 100644 index 0000000..4192bfe Binary files /dev/null and b/public/images/default-avatar.png differ diff --git a/public/images/discord-icon.svg b/public/images/discord-icon.svg new file mode 100644 index 0000000..59bea5a --- /dev/null +++ b/public/images/discord-icon.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/public/images/favicon.png b/public/images/favicon.png new file mode 100644 index 0000000..e69de29 diff --git a/public/images/google-icon.svg b/public/images/google-icon.svg new file mode 100644 index 0000000..a53765d --- /dev/null +++ b/public/images/google-icon.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/public/images/placeholders/dark-ride.jpg b/public/images/placeholders/dark-ride.jpg new file mode 100644 index 0000000..e69de29 diff --git a/public/images/placeholders/default-park.jpg b/public/images/placeholders/default-park.jpg new file mode 100644 index 0000000..e69de29 diff --git a/public/images/placeholders/default-ride.jpg b/public/images/placeholders/default-ride.jpg new file mode 100644 index 0000000..e69de29 diff --git a/public/images/placeholders/flat-ride.jpg b/public/images/placeholders/flat-ride.jpg new file mode 100644 index 0000000..e69de29 diff --git a/public/images/placeholders/other-ride.jpg b/public/images/placeholders/other-ride.jpg new file mode 100644 index 0000000..e69de29 diff --git a/public/images/placeholders/roller-coaster.jpg b/public/images/placeholders/roller-coaster.jpg new file mode 100644 index 0000000..e69de29 diff --git a/public/images/placeholders/transport.jpg b/public/images/placeholders/transport.jpg new file mode 100644 index 0000000..e69de29 diff --git a/public/images/placeholders/water-ride.jpg b/public/images/placeholders/water-ride.jpg new file mode 100644 index 0000000..e69de29 diff --git a/resources/css/alerts.css b/resources/css/alerts.css new file mode 100644 index 0000000..3b7d426 --- /dev/null +++ b/resources/css/alerts.css @@ -0,0 +1,44 @@ +/* Alert Styles */ +.alert { + @apply fixed z-50 px-4 py-3 transition-all duration-500 transform rounded-lg shadow-lg right-4 top-4; + animation: slideIn 0.5s ease-out forwards; +} + +.alert-success { + @apply text-white bg-green-500; +} + +.alert-error { + @apply text-white bg-red-500; +} + +.alert-info { + @apply text-white bg-blue-500; +} + +.alert-warning { + @apply text-white bg-yellow-500; +} + +/* Animation keyframes */ +@keyframes slideIn { + 0% { + transform: translateX(100%); + opacity: 0; + } + 100% { + transform: translateX(0); + opacity: 1; + } +} + +@keyframes slideOut { + 0% { + transform: translateX(0); + opacity: 1; + } + 100% { + transform: translateX(100%); + opacity: 0; + } +} diff --git a/resources/css/app.css b/resources/css/app.css index b5c61c9..7a1818b 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -1,3 +1,70 @@ +@import 'alerts.css'; + @tailwind base; @tailwind components; @tailwind utilities; + +/* Custom base styles */ +@layer base { + html { + scroll-behavior: smooth; + } + + body { + font-family: 'Poppins', sans-serif; + } +} + +/* Custom components */ +@layer components { + .nav-link { + @apply flex items-center gap-2 px-3 py-2 text-gray-500 transition-colors rounded-lg hover:text-primary dark:text-gray-400 dark:hover:text-primary hover:bg-gray-100 dark:hover:bg-gray-700; + } + + .site-logo { + @apply text-2xl; + } + + .menu-item { + @apply flex items-center gap-3 px-4 py-2 text-gray-600 transition-colors dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700; + } + + .form-input { + @apply w-full px-4 py-2 text-gray-700 transition-colors bg-white border rounded-lg dark:bg-gray-800 dark:text-gray-300 border-gray-200/50 dark:border-gray-700/50 focus:border-primary dark:focus:border-primary focus:outline-none focus:ring-2 focus:ring-primary/20; + } + + .btn { + @apply px-4 py-2 font-semibold text-white transition-colors rounded-lg shadow-lg bg-gradient-to-r from-primary to-secondary hover:from-primary/90 hover:to-secondary/90 focus:outline-none focus:ring-2 focus:ring-primary/20; + } + + .btn-secondary { + @apply text-gray-700 bg-white border dark:bg-gray-800 dark:text-white border-gray-200/50 dark:border-gray-700/50 hover:bg-gray-100 dark:hover:bg-gray-700; + } + + .alert { + @apply relative px-4 py-3 mb-4 text-white rounded-lg; + } + + .alert-success { + @apply bg-green-500; + } + + .alert-error { + @apply bg-red-500; + } + + .alert-warning { + @apply bg-yellow-500; + } + + .alert-info { + @apply bg-blue-500; + } +} + +/* Custom utilities */ +@layer utilities { + .text-gradient { + @apply text-transparent bg-clip-text bg-gradient-to-r from-primary to-secondary; + } +} diff --git a/resources/css/src/input.css b/resources/css/src/input.css new file mode 100644 index 0000000..c0c7d32 --- /dev/null +++ b/resources/css/src/input.css @@ -0,0 +1,282 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer components { + /* Button Styles */ + .btn-primary { + @apply inline-flex items-center px-6 py-2.5 border border-transparent rounded-full shadow-md text-sm font-medium text-white bg-gradient-to-r from-primary to-secondary hover:from-primary/90 hover:to-secondary/90 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary/50 transform hover:scale-105 transition-all; + } + + .btn-secondary { + @apply inline-flex items-center px-6 py-2.5 border border-gray-200 dark:border-gray-700 rounded-full shadow-md text-sm font-medium text-gray-700 dark:text-gray-200 bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary/50 transform hover:scale-105 transition-all; + } + /* [Previous styles remain unchanged until mobile menu section...] */ + + /* Mobile Menu */ + #mobileMenu { + @apply overflow-hidden transition-all duration-300 ease-in-out opacity-0 max-h-0; + } + + #mobileMenu.show { + @apply max-h-[300px] opacity-100; + } + + #mobileMenu .space-y-4 { + @apply pb-6; + } + + .mobile-nav-link { + @apply flex items-center justify-center px-6 py-3 text-gray-700 transition-all border border-transparent rounded-lg dark:text-gray-200 hover:bg-primary/10 dark:hover:bg-primary/20 hover:text-primary dark:hover:text-primary hover:border-primary/20 dark:hover:border-primary/30; + } + + .mobile-nav-link i { + @apply text-xl transition-colors; + } + + @media (max-width: 540px) { + .mobile-nav-link i { + @apply text-lg; + } + } + + .mobile-nav-link.primary { + @apply text-white bg-gradient-to-r from-primary to-secondary hover:from-primary/90 hover:to-secondary/90; + } + + .mobile-nav-link.primary i { + @apply mr-3 text-white; + } + + .mobile-nav-link.secondary { + @apply text-gray-700 bg-gray-100 dark:bg-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-600; + } + + .mobile-nav-link.secondary i { + @apply mr-3 text-gray-500 dark:text-gray-400; + } + + /* Theme Toggle */ + #theme-toggle+.theme-toggle-btn i::before { + content: "\f186"; + font-family: "Font Awesome 5 Free"; + font-weight: 900; + } + + #theme-toggle:checked+.theme-toggle-btn i::before { + content: "\f185"; + color: theme('colors.yellow.400'); + } + + /* Navigation Components */ + .nav-link { + @apply flex items-center text-gray-700 transition-all dark:text-gray-200; + } + + /* Extra small screens (540px and below) */ + @media (max-width: 540px) { + .nav-link { + @apply px-2 py-2 text-sm; + } + .nav-link i { + @apply mr-1 text-base; + } + .nav-link span { + @apply text-sm; + } + .site-logo { + @apply px-1 text-lg; + } + .nav-container { + @apply px-2; + } + } + + /* Small screens (541px to 767px) */ + @media (min-width: 541px) and (max-width: 767px) { + .nav-link { + @apply px-3 py-2; + } + .nav-link i { + @apply mr-2; + } + .site-logo { + @apply px-2 text-xl; + } + .nav-container { + @apply px-4; + } + } + + /* Medium screens and up */ + @media (min-width: 768px) { + .nav-link { + @apply px-6 py-2.5 rounded-lg font-medium border border-transparent hover:border-primary/20 dark:hover:border-primary/30; + } + .nav-link i { + @apply mr-3 text-lg; + } + .site-logo { + @apply px-3 text-2xl; + } + .nav-container { + @apply px-6; + } + } + + .nav-link:hover { + @apply text-primary dark:text-primary bg-primary/10 dark:bg-primary/20; + } + + .nav-link i { + @apply text-gray-500 transition-colors dark:text-gray-400; + } + + .nav-link:hover i { + @apply text-primary; + } + + @media (min-width: 1024px) { + #mobileMenu { + @apply hidden !important; + } + } + + /* Menu Items */ + .menu-item { + @apply flex items-center w-full px-4 py-3 text-sm text-gray-700 transition-all dark:text-gray-200 hover:bg-primary/10 dark:hover:bg-primary/20 hover:text-primary dark:hover:text-primary first:rounded-t-lg last:rounded-b-lg; + } + + .menu-item i { + @apply mr-3 text-base text-gray-500 dark:text-gray-400; + } + + /* Form Components */ + .form-input { + @apply w-full px-4 py-3 text-gray-900 transition-all border border-gray-200 rounded-lg shadow-sm dark:border-gray-700 bg-white/70 dark:bg-gray-800/70 backdrop-blur-sm dark:text-white focus:ring-2 focus:ring-primary/50 focus:border-primary; + } + + .form-label { + @apply block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1.5; + } + + .form-hint { + @apply mt-2 space-y-1 text-sm text-gray-500 dark:text-gray-400; + } + + .form-error { + @apply mt-2 text-sm text-red-600 dark:text-red-400; + } + + /* Status Badges */ + .status-badge { + @apply inline-flex items-center px-3 py-1 text-sm font-medium rounded-full; + } + + .status-operating { + @apply text-green-800 bg-green-100 dark:bg-green-700 dark:text-green-50; + } + + .status-closed { + @apply text-red-800 bg-red-100 dark:bg-red-700 dark:text-red-50; + } + + .status-construction { + @apply text-yellow-800 bg-yellow-100 dark:bg-yellow-600 dark:text-yellow-50; + } + + /* Auth Components */ + .auth-card { + @apply w-full max-w-md p-8 mx-auto border shadow-xl bg-white/90 dark:bg-gray-800/90 rounded-2xl backdrop-blur-sm border-gray-200/50 dark:border-gray-700/50; + } + + .auth-title { + @apply mb-8 text-2xl font-bold text-center text-transparent bg-gradient-to-r from-primary to-secondary bg-clip-text; + } + + .auth-divider { + @apply relative my-6 text-center; + } + + .auth-divider::before, + .auth-divider::after { + @apply absolute top-1/2 w-1/3 border-t border-gray-200 dark:border-gray-700 content-['']; + } + + .auth-divider::before { + @apply left-0; + } + + .auth-divider::after { + @apply right-0; + } + + .auth-divider span { + @apply px-4 text-sm text-gray-500 dark:text-gray-400 bg-white/90 dark:bg-gray-800/90; + } + + /* Social Login Buttons */ + .btn-social { + @apply w-full flex items-center justify-center px-6 py-3 border border-gray-200 dark:border-gray-700 rounded-lg shadow-sm text-sm font-medium text-gray-700 dark:text-gray-200 bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary/50 transform hover:scale-[1.02] transition-all mb-3; + } + + .btn-discord { + @apply text-gray-700 bg-white border-gray-200 hover:bg-gray-50 shadow-gray-200/50 dark:shadow-gray-900/50; + } + + .btn-google { + @apply text-gray-700 bg-white border-gray-200 hover:bg-gray-50 shadow-gray-200/50 dark:shadow-gray-900/50; + } + + /* Alert Components */ + .alert { + @apply p-4 mb-4 shadow-lg rounded-xl backdrop-blur-sm; + } + + .alert-success { + @apply text-green-800 border border-green-200 bg-green-100/90 dark:bg-green-800/30 dark:text-green-100 dark:border-green-700; + } + + .alert-error { + @apply text-red-800 border border-red-200 bg-red-100/90 dark:bg-red-800/30 dark:text-red-100 dark:border-red-700; + } + + .alert-warning { + @apply text-yellow-800 border border-yellow-200 bg-yellow-100/90 dark:bg-yellow-800/30 dark:text-yellow-100 dark:border-yellow-700; + } + + .alert-info { + @apply text-blue-800 border border-blue-200 bg-blue-100/90 dark:bg-blue-800/30 dark:text-blue-100 dark:border-blue-700; + } + + /* Layout Components */ + .card { + @apply p-6 bg-white border rounded-lg shadow-lg dark:bg-gray-800 border-gray-200/50 dark:border-gray-700/50; + } + + .card-hover { + @apply transition-transform transform hover:-translate-y-1; + } + + .grid-cards { + @apply grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3; + } + + /* Typography */ + .heading-1 { + @apply mb-6 text-3xl font-bold text-gray-900 dark:text-white; + } + + .heading-2 { + @apply mb-4 text-2xl font-bold text-gray-900 dark:text-white; + } + + .text-body { + @apply text-gray-600 dark:text-gray-300; + } + + /* Turnstile Widget */ + .turnstile { + @apply flex items-center justify-center my-4; + } +} diff --git a/resources/js/app.js b/resources/js/app.js index e59d6a0..3cc6126 100644 --- a/resources/js/app.js +++ b/resources/js/app.js @@ -1 +1,6 @@ import './bootstrap'; +import './modules/alerts'; +import './modules/location-autocomplete'; +import './modules/park-map'; +import './modules/photo-gallery'; +import './modules/search'; diff --git a/resources/js/modules/alerts.js b/resources/js/modules/alerts.js new file mode 100644 index 0000000..fc054c1 --- /dev/null +++ b/resources/js/modules/alerts.js @@ -0,0 +1,18 @@ +document.addEventListener('DOMContentLoaded', function() { + // Get all alert elements + const alerts = document.querySelectorAll('.alert'); + + // For each alert + alerts.forEach(alert => { + // After 5 seconds + setTimeout(() => { + // Add slideOut animation + alert.style.animation = 'slideOut 0.5s ease-out forwards'; + + // Remove the alert after animation completes + setTimeout(() => { + alert.remove(); + }, 500); + }, 5000); + }); +}); diff --git a/resources/js/modules/location-autocomplete.js b/resources/js/modules/location-autocomplete.js new file mode 100644 index 0000000..7bc90cd --- /dev/null +++ b/resources/js/modules/location-autocomplete.js @@ -0,0 +1,81 @@ +function locationAutocomplete(field, filterParks = false) { + return { + query: '', + suggestions: [], + fetchSuggestions() { + let url; + const params = new URLSearchParams({ + q: this.query, + filter_parks: filterParks + }); + + switch (field) { + case 'country': + url = '/parks/ajax/countries/'; + break; + case 'region': + url = '/parks/ajax/regions/'; + // Add country parameter if we're fetching regions + const countryInput = document.getElementById(filterParks ? 'country' : 'id_country_name'); + if (countryInput && countryInput.value) { + params.append('country', countryInput.value); + } + break; + case 'city': + url = '/parks/ajax/cities/'; + // Add country and region parameters if we're fetching cities + const regionInput = document.getElementById(filterParks ? 'region' : 'id_region_name'); + const cityCountryInput = document.getElementById(filterParks ? 'country' : 'id_country_name'); + if (regionInput && regionInput.value && cityCountryInput && cityCountryInput.value) { + params.append('country', cityCountryInput.value); + params.append('region', regionInput.value); + } + break; + } + + if (url) { + fetch(`${url}?${params}`) + .then(response => response.json()) + .then(data => { + this.suggestions = data; + }); + } + }, + selectSuggestion(suggestion) { + this.query = suggestion.name; + this.suggestions = []; + + // If this is a form field (not filter), update hidden fields + if (!filterParks) { + const hiddenField = document.getElementById(`id_${field}`); + if (hiddenField) { + hiddenField.value = suggestion.id; + } + + // Clear dependent fields when parent field changes + if (field === 'country') { + const regionInput = document.getElementById('id_region_name'); + const cityInput = document.getElementById('id_city_name'); + const regionHidden = document.getElementById('id_region'); + const cityHidden = document.getElementById('id_city'); + + if (regionInput) regionInput.value = ''; + if (cityInput) cityInput.value = ''; + if (regionHidden) regionHidden.value = ''; + if (cityHidden) cityHidden.value = ''; + } else if (field === 'region') { + const cityInput = document.getElementById('id_city_name'); + const cityHidden = document.getElementById('id_city'); + + if (cityInput) cityInput.value = ''; + if (cityHidden) cityHidden.value = ''; + } + } + + // Trigger form submission for filters + if (filterParks) { + htmx.trigger('#park-filters', 'change'); + } + } + }; +} diff --git a/resources/js/modules/main.js b/resources/js/modules/main.js new file mode 100644 index 0000000..7aa4430 --- /dev/null +++ b/resources/js/modules/main.js @@ -0,0 +1,141 @@ +// Theme handling +document.addEventListener('DOMContentLoaded', () => { + const themeToggle = document.getElementById('theme-toggle'); + const html = document.documentElement; + + // Initialize toggle state based on current theme + if (themeToggle) { + themeToggle.checked = html.classList.contains('dark'); + + // Handle toggle changes + themeToggle.addEventListener('change', function() { + const isDark = this.checked; + html.classList.toggle('dark', isDark); + localStorage.setItem('theme', isDark ? 'dark' : 'light'); + }); + + // Listen for system theme changes + const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); + mediaQuery.addEventListener('change', (e) => { + if (!localStorage.getItem('theme')) { + const isDark = e.matches; + html.classList.toggle('dark', isDark); + themeToggle.checked = isDark; + } + }); + } +}); + +// Handle search form submission +document.addEventListener('submit', (e) => { + if (e.target.matches('form[action*="search"]')) { + const searchInput = e.target.querySelector('input[name="q"]'); + if (!searchInput.value.trim()) { + e.preventDefault(); + } + } +}); + +// Mobile menu toggle with transitions +document.addEventListener('DOMContentLoaded', () => { + const mobileMenuBtn = document.getElementById('mobileMenuBtn'); + const mobileMenu = document.getElementById('mobileMenu'); + + if (mobileMenuBtn && mobileMenu) { + let isMenuOpen = false; + + const toggleMenu = () => { + isMenuOpen = !isMenuOpen; + mobileMenu.classList.toggle('show', isMenuOpen); + mobileMenuBtn.setAttribute('aria-expanded', isMenuOpen.toString()); + + // Update icon + const icon = mobileMenuBtn.querySelector('i'); + icon.classList.remove(isMenuOpen ? 'fa-bars' : 'fa-times'); + icon.classList.add(isMenuOpen ? 'fa-times' : 'fa-bars'); + }; + + mobileMenuBtn.addEventListener('click', toggleMenu); + + // Close menu when clicking outside + document.addEventListener('click', (e) => { + if (isMenuOpen && !mobileMenu.contains(e.target) && !mobileMenuBtn.contains(e.target)) { + toggleMenu(); + } + }); + + // Close menu when pressing escape + document.addEventListener('keydown', (e) => { + if (isMenuOpen && e.key === 'Escape') { + toggleMenu(); + } + }); + + // Handle viewport changes + const mediaQuery = window.matchMedia('(min-width: 1024px)'); + mediaQuery.addEventListener('change', (e) => { + if (e.matches && isMenuOpen) { + toggleMenu(); + } + }); + } +}); + +// User dropdown toggle +const userMenuBtn = document.getElementById('userMenuBtn'); +const userDropdown = document.getElementById('userDropdown'); + +if (userMenuBtn && userDropdown) { + userMenuBtn.addEventListener('click', (e) => { + e.stopPropagation(); + userDropdown.classList.toggle('active'); + }); + + // Close dropdown when clicking outside + document.addEventListener('click', (e) => { + if (!userMenuBtn.contains(e.target) && !userDropdown.contains(e.target)) { + userDropdown.classList.remove('active'); + } + }); + + // Close dropdown when pressing escape + document.addEventListener('keydown', (e) => { + if (e.key === 'Escape') { + userDropdown.classList.remove('active'); + } + }); +} + +// Handle flash messages +document.addEventListener('DOMContentLoaded', () => { + const alerts = document.querySelectorAll('.alert'); + alerts.forEach(alert => { + setTimeout(() => { + alert.style.opacity = '0'; + setTimeout(() => alert.remove(), 300); + }, 5000); + }); +}); + +// Initialize tooltips +document.addEventListener('DOMContentLoaded', () => { + const tooltips = document.querySelectorAll('[data-tooltip]'); + tooltips.forEach(tooltip => { + tooltip.addEventListener('mouseenter', (e) => { + const text = e.target.getAttribute('data-tooltip'); + const tooltipEl = document.createElement('div'); + tooltipEl.className = 'absolute z-50 px-2 py-1 text-sm text-white bg-gray-900 rounded tooltip'; + tooltipEl.textContent = text; + document.body.appendChild(tooltipEl); + + const rect = e.target.getBoundingClientRect(); + tooltipEl.style.top = rect.bottom + 5 + 'px'; + tooltipEl.style.left = rect.left + (rect.width - tooltipEl.offsetWidth) / 2 + 'px'; + }); + + tooltip.addEventListener('mouseleave', () => { + const tooltips = document.querySelectorAll('.tooltip'); + tooltips.forEach(t => t.remove()); + }); + }); +}); diff --git a/resources/js/modules/park-map.js b/resources/js/modules/park-map.js new file mode 100644 index 0000000..cb7f399 --- /dev/null +++ b/resources/js/modules/park-map.js @@ -0,0 +1,29 @@ +// Only declare parkMap if it doesn't exist +window.parkMap = window.parkMap || null; + +function initParkMap(latitude, longitude, name) { + const mapContainer = document.getElementById('park-map'); + + // Only initialize if container exists and map hasn't been initialized + if (mapContainer && !window.parkMap) { + const width = mapContainer.offsetWidth; + mapContainer.style.height = width + 'px'; + + window.parkMap = L.map('park-map').setView([latitude, longitude], 13); + + L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { + attribution: '© OpenStreetMap contributors' + }).addTo(window.parkMap); + + L.marker([latitude, longitude]) + .addTo(window.parkMap) + .bindPopup(name); + + // Update map size when window is resized + window.addEventListener('resize', function() { + const width = mapContainer.offsetWidth; + mapContainer.style.height = width + 'px'; + window.parkMap.invalidateSize(); + }); + } +} diff --git a/resources/js/modules/photo-gallery.js b/resources/js/modules/photo-gallery.js new file mode 100644 index 0000000..2705dca --- /dev/null +++ b/resources/js/modules/photo-gallery.js @@ -0,0 +1,91 @@ +document.addEventListener('alpine:init', () => { + Alpine.data('photoDisplay', ({ photos, contentType, objectId, csrfToken, uploadUrl }) => ({ + photos, + fullscreenPhoto: null, + uploading: false, + uploadProgress: 0, + error: null, + showSuccess: false, + + showFullscreen(photo) { + this.fullscreenPhoto = photo; + }, + + async handleFileSelect(event) { + const files = Array.from(event.target.files); + if (!files.length) { + return; + } + + this.uploading = true; + this.uploadProgress = 0; + this.error = null; + this.showSuccess = false; + + const totalFiles = files.length; + let completedFiles = 0; + + for (const file of files) { + const formData = new FormData(); + formData.append('image', file); + formData.append('app_label', contentType.split('.')[0]); + formData.append('model', contentType.split('.')[1]); + formData.append('object_id', objectId); + + try { + const response = await fetch(uploadUrl, { + method: 'POST', + headers: { + 'X-CSRFToken': csrfToken, + }, + body: formData + }); + + if (!response.ok) { + const data = await response.json(); + throw new Error(data.error || 'Upload failed'); + } + + const photo = await response.json(); + this.photos.push(photo); + completedFiles++; + this.uploadProgress = (completedFiles / totalFiles) * 100; + } catch (err) { + this.error = err.message || 'Failed to upload photo. Please try again.'; + console.error('Upload error:', err); + break; + } + } + + this.uploading = false; + event.target.value = ''; // Reset file input + + if (!this.error) { + this.showSuccess = true; + setTimeout(() => { + this.showSuccess = false; + }, 3000); + } + }, + + async sharePhoto(photo) { + if (navigator.share) { + try { + await navigator.share({ + title: photo.caption || 'Shared photo', + url: photo.url + }); + } catch (err) { + if (err.name !== 'AbortError') { + console.error('Error sharing:', err); + } + } + } else { + // Fallback: copy URL to clipboard + navigator.clipboard.writeText(photo.url) + .then(() => alert('Photo URL copied to clipboard!')) + .catch(err => console.error('Error copying to clipboard:', err)); + } + } + })); +}); diff --git a/resources/js/modules/search.js b/resources/js/modules/search.js new file mode 100644 index 0000000..b6589db --- /dev/null +++ b/resources/js/modules/search.js @@ -0,0 +1,42 @@ +function parkSearch() { + return { + query: '', + results: [], + loading: false, + selectedId: null, + + async search() { + if (!this.query.trim()) { + this.results = []; + return; + } + + this.loading = true; + try { + const response = await fetch(`/parks/suggest_parks/?search=${encodeURIComponent(this.query)}`); + const data = await response.json(); + this.results = data.results; + } catch (error) { + console.error('Search failed:', error); + this.results = []; + } finally { + this.loading = false; + } + }, + + clear() { + this.query = ''; + this.results = []; + this.selectedId = null; + }, + + selectPark(park) { + this.query = park.name; + this.selectedId = park.id; + this.results = []; + + // Trigger filter update + document.getElementById('park-filters').dispatchEvent(new Event('change')); + } + }; +} \ No newline at end of file diff --git a/resources/views/layouts/app.blade.php b/resources/views/layouts/app.blade.php new file mode 100644 index 0000000..100e69f --- /dev/null +++ b/resources/views/layouts/app.blade.php @@ -0,0 +1,176 @@ + + + + + + + @yield('title', 'ThrillWiki') + + + + + + + + + + + + @vite(['resources/js/app.js', 'resources/css/app.css']) + + + + + + + @stack('styles') + + + +
+ +
+ + + @if (session('status')) +
+
+ {{ session('status') }} +
+
+ @endif + + +
+ {{ $slot }} +
+ + +
+
+
+
+

© {{ date('Y') }} ThrillWiki. All rights reserved.

+
+
+ Terms + Privacy +
+
+
+
+ + @stack('scripts') + + diff --git a/resources/views/livewire/auth-menu-component.blade.php b/resources/views/livewire/auth-menu-component.blade.php new file mode 100644 index 0000000..9948e56 --- /dev/null +++ b/resources/views/livewire/auth-menu-component.blade.php @@ -0,0 +1,34 @@ +
+
+ +
+ + + +
\ No newline at end of file diff --git a/resources/views/livewire/counter.blade.php b/resources/views/livewire/counter.blade.php index 5bb9931..196d61b 100644 --- a/resources/views/livewire/counter.blade.php +++ b/resources/views/livewire/counter.blade.php @@ -1,7 +1,8 @@ -
-

{{ $count }}

- - - - +
+

{{ $count }}

+ +
+ + +
diff --git a/resources/views/livewire/mobile-menu-component.blade.php b/resources/views/livewire/mobile-menu-component.blade.php new file mode 100644 index 0000000..6eafe48 --- /dev/null +++ b/resources/views/livewire/mobile-menu-component.blade.php @@ -0,0 +1,39 @@ +
+ + + +
+ +
+ +
+ + + +
+
\ No newline at end of file diff --git a/resources/views/livewire/theme-toggle-component.blade.php b/resources/views/livewire/theme-toggle-component.blade.php new file mode 100644 index 0000000..0358dd1 --- /dev/null +++ b/resources/views/livewire/theme-toggle-component.blade.php @@ -0,0 +1,28 @@ + + + \ No newline at end of file diff --git a/resources/views/livewire/user-menu-component.blade.php b/resources/views/livewire/user-menu-component.blade.php new file mode 100644 index 0000000..44b3eb3 --- /dev/null +++ b/resources/views/livewire/user-menu-component.blade.php @@ -0,0 +1,47 @@ +
+ + @if(auth()->user()->profile?->avatar) + {{ auth()->user()->username }} + @else +
+ {{ ucfirst(auth()->user()->username[0]) }} +
+ @endif + + + +
\ No newline at end of file diff --git a/routes/web.php b/routes/web.php index 39a9915..c16a804 100644 --- a/routes/web.php +++ b/routes/web.php @@ -1,11 +1,57 @@ name('home'); -use App\Livewire\Counter; - Route::get('/counter', Counter::class); -}); + +// Parks routes +Route::get('/parks', function () { + return 'Parks Index'; +})->name('parks.index'); + +// Rides routes +Route::get('/rides', function () { + return 'Rides Index'; +})->name('rides.index'); + +// Auth routes +Route::get('/login', function () { + return 'Login'; +})->name('login'); + +Route::get('/register', function () { + return 'Register'; +})->name('register'); + +Route::post('/logout', function () { + return 'Logout'; +})->name('logout'); + +// Settings routes +Route::get('/settings', function () { + return 'Settings'; +})->name('settings'); + +// Legal routes +Route::get('/terms', function () { + return 'Terms'; +})->name('terms'); + +Route::get('/privacy', function () { + return 'Privacy'; +})->name('privacy'); + +// Profile routes +Route::get('/profile/{username}', function () { + return 'Profile'; +})->name('profile.show'); + +// Search route +Route::get('/search', function () { + return 'Search'; +})->name('search'); diff --git a/tailwind.config.js b/tailwind.config.js index ce0c57f..fa502f7 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -1,20 +1,75 @@ -import defaultTheme from 'tailwindcss/defaultTheme'; - /** @type {import('tailwindcss').Config} */ export default { - content: [ - './vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*.blade.php', - './storage/framework/views/*.php', - './resources/**/*.blade.php', - './resources/**/*.js', - './resources/**/*.vue', - ], - theme: { - extend: { - fontFamily: { - sans: ['Figtree', ...defaultTheme.fontFamily.sans], - }, - }, + content: [ + "./resources/**/*.blade.php", + "./resources/**/*.js", + "./resources/**/*.vue", + ], + darkMode: 'class', + theme: { + container: { + center: true, + padding: { + DEFAULT: '1rem', + sm: '2rem', + lg: '4rem', + xl: '5rem', + '2xl': '6rem', + }, }, - plugins: [], -}; + extend: { + colors: { + primary: { + DEFAULT: '#6366f1', // Indigo-500 + 50: '#eef2ff', + 100: '#e0e7ff', + 200: '#c7d2fe', + 300: '#a5b4fc', + 400: '#818cf8', + 500: '#6366f1', + 600: '#4f46e5', + 700: '#4338ca', + 800: '#3730a3', + 900: '#312e81', + 950: '#1e1b4b', + }, + secondary: { + DEFAULT: '#8b5cf6', // Violet-500 + 50: '#f5f3ff', + 100: '#ede9fe', + 200: '#ddd6fe', + 300: '#c4b5fd', + 400: '#a78bfa', + 500: '#8b5cf6', + 600: '#7c3aed', + 700: '#6d28d9', + 800: '#5b21b6', + 900: '#4c1d95', + 950: '#2e1065', + }, + }, + fontFamily: { + sans: ['Poppins', 'sans-serif'], + }, + animation: { + 'fade-in': 'fadeIn 0.2s ease-in-out', + 'fade-out': 'fadeOut 0.2s ease-in-out', + }, + keyframes: { + fadeIn: { + '0%': { opacity: '0' }, + '100%': { opacity: '1' }, + }, + fadeOut: { + '0%': { opacity: '1' }, + '100%': { opacity: '0' }, + }, + }, + }, + }, + plugins: [ + require('@tailwindcss/forms'), + require('@tailwindcss/typography'), + require('@tailwindcss/aspect-ratio'), + ], +} diff --git a/vite.config.js b/vite.config.js index 421b569..40c15e5 100644 --- a/vite.config.js +++ b/vite.config.js @@ -4,8 +4,29 @@ import laravel from 'laravel-vite-plugin'; export default defineConfig({ plugins: [ laravel({ - input: ['resources/css/app.css', 'resources/js/app.js'], + input: [ + 'resources/css/app.css', + 'resources/js/app.js', + ], refresh: true, }), ], + resolve: { + alias: { + '@': '/resources/js', + }, + }, + build: { + // Generate source maps for better debugging + sourcemap: true, + // Optimize dependency bundling + rollupOptions: { + output: { + manualChunks: { + // Split vendor chunks for better caching + vendor: ['alpinejs'], + }, + }, + }, + }, });