diff --git a/image_selections.db.bak b/image_selections.db.bak
new file mode 100644
index 0000000..800af52
Binary files /dev/null and b/image_selections.db.bak differ
diff --git a/improved-styles.css b/improved-styles.css
new file mode 100644
index 0000000..4485d0d
--- /dev/null
+++ b/improved-styles.css
@@ -0,0 +1,786 @@
+:root {
+ --primary-color: #3498db;
+ --success-color: #2ecc71;
+ --danger-color: #e74c3c;
+ --warning-color: #f39c12;
+ --light-color: #f5f5f5;
+ --dark-color: #2c3e50;
+ --background-color: #ecf0f1;
+ --card-background: #ffffff;
+ --text-color: #2c3e50;
+ --border-radius: 16px;
+ --shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
+ --transition-speed: 0.3s;
+ --gradient-primary: linear-gradient(135deg, #3498db, #2980b9);
+ --gradient-success: linear-gradient(135deg, #2ecc71, #27ae60);
+ --gradient-danger: linear-gradient(135deg, #e74c3c, #c0392b);
+ --gradient-warning: linear-gradient(135deg, #f39c12, #d35400);
+
+ /* New variables */
+ --card-shadow: 0 15px 35px rgba(50, 50, 93, 0.1), 0 5px 15px rgba(0, 0, 0, 0.07);
+ --card-shadow-hover: 0 20px 40px rgba(50, 50, 93, 0.15), 0 10px 20px rgba(0, 0, 0, 0.1);
+ --card-border-radius: 20px;
+ --button-border-radius: 12px;
+}
+
+/* Enhanced Card Component */
+.swipe-container {
+ position: relative;
+ flex: 3;
+ min-height: 70vh;
+ perspective: 1200px;
+ border-radius: var(--card-border-radius);
+ background: var(--card-background);
+ box-shadow: var(--card-shadow);
+ overflow: hidden;
+ transition: box-shadow 0.4s ease, transform 0.4s ease;
+}
+
+.swipe-container:hover {
+ box-shadow: var(--card-shadow-hover);
+ transform: translateY(-5px);
+}
+
+.image-card {
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ border-radius: var(--card-border-radius);
+ overflow: hidden;
+ transition: transform 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275), opacity 0.5s ease-out;
+ transform-origin: center center;
+ background-color: var(--card-background);
+ touch-action: none;
+ cursor: grab;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ z-index: 5;
+ box-shadow: var(--card-shadow);
+}
+
+.image-card::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ background: linear-gradient(to bottom, transparent 70%, rgba(0,0,0,0.2));
+ pointer-events: none;
+ z-index: 1;
+ opacity: 0.7;
+ transition: opacity 0.3s ease;
+}
+
+.image-card:hover::before {
+ opacity: 0.5;
+}
+
+.image-card img {
+ width: 100%;
+ height: 100%;
+ object-fit: contain;
+ transition: transform 0.5s ease;
+ pointer-events: none;
+}
+
+.image-card:hover img {
+ transform: scale(1.02);
+}
+
+/* Enhanced Swipe Directions */
+.swipe-directions {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ z-index: 2;
+ pointer-events: none;
+ opacity: 0;
+ transition: opacity 0.4s;
+}
+
+.swipe-container:hover .swipe-directions {
+ opacity: 0.3;
+}
+
+.direction-arrow {
+ position: absolute;
+ width: 70px;
+ height: 70px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-size: 2.2rem;
+ color: white;
+ border-radius: 50%;
+ transition: transform 0.3s ease, box-shadow 0.3s ease;
+ box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
+}
+
+.arrow-left {
+ left: 20px;
+ top: 50%;
+ transform: translateY(-50%);
+ background: var(--gradient-danger);
+}
+
+.arrow-right {
+ right: 20px;
+ top: 50%;
+ transform: translateY(-50%);
+ background: var(--gradient-success);
+}
+
+.arrow-up {
+ top: 20px;
+ left: 50%;
+ transform: translateX(-50%);
+ background: var(--gradient-primary);
+}
+
+.arrow-down {
+ bottom: 20px;
+ left: 50%;
+ transform: translateX(-50%);
+ background: var(--gradient-warning);
+}
+
+/* Enhanced Action Hints */
+.action-hint {
+ position: absolute;
+ background-color: rgba(0, 0, 0, 0.85);
+ color: white;
+ padding: 12px 20px;
+ border-radius: 30px;
+ font-weight: bold;
+ opacity: 0;
+ transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
+ z-index: 10;
+ backdrop-filter: blur(8px);
+ box-shadow: 0 8px 20px rgba(0, 0, 0, 0.3);
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ transform: scale(0.9);
+ border-left: 4px solid;
+}
+
+.action-hint.visible {
+ opacity: 1;
+ transform: scale(1);
+}
+
+.left-hint {
+ left: 20px;
+ top: 50%;
+ transform: translateY(-50%);
+ border-color: var(--danger-color);
+}
+
+.right-hint {
+ right: 20px;
+ top: 50%;
+ transform: translateY(-50%);
+ border-color: var(--success-color);
+}
+
+.up-hint {
+ top: 20px;
+ left: 50%;
+ transform: translateX(-50%);
+ border-color: var(--primary-color);
+}
+
+.down-hint {
+ bottom: 20px;
+ left: 50%;
+ transform: translateX(-50%);
+ border-color: var(--warning-color);
+}
+
+/* Enhanced Swipe Animations */
+.image-card.swipe-left {
+ transform: translateX(-150%) rotate(-30deg);
+ opacity: 0;
+}
+
+.image-card.swipe-right {
+ transform: translateX(150%) rotate(30deg);
+ opacity: 0;
+}
+
+.image-card.swipe-up {
+ transform: translateY(-150%) rotate(10deg);
+ opacity: 0;
+}
+
+.image-card.swipe-down {
+ transform: translateY(150%) rotate(-10deg);
+ opacity: 0;
+}
+
+/* Enhanced Action Buttons */
+.action-buttons {
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+ transition: transform 0.3s ease;
+}
+
+.action-btn {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 12px;
+ padding: 16px;
+ border: none;
+ border-radius: var(--button-border-radius);
+ cursor: pointer;
+ font-weight: 600;
+ transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
+ font-size: 1rem;
+ color: white;
+ position: relative;
+ overflow: hidden;
+ z-index: 1;
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+}
+
+.action-btn::before {
+ content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background: rgba(255, 255, 255, 0.1);
+ transform: translateX(-100%);
+ transition: transform 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
+ z-index: -1;
+}
+
+.action-btn:hover::before {
+ transform: translateX(0);
+}
+
+.action-btn:hover {
+ transform: translateY(-5px) scale(1.03);
+ box-shadow: 0 8px 20px rgba(0, 0, 0, 0.15);
+}
+
+.action-btn:active {
+ transform: translateY(-2px) scale(0.98);
+}
+
+#btn-left {
+ background: var(--gradient-danger);
+ box-shadow: 0 4px 12px rgba(231, 76, 60, 0.3);
+}
+
+#btn-right {
+ background: var(--gradient-success);
+ box-shadow: 0 4px 12px rgba(46, 204, 113, 0.3);
+}
+
+#btn-up {
+ background: var(--gradient-primary);
+ box-shadow: 0 4px 12px rgba(52, 152, 219, 0.3);
+}
+
+#btn-down {
+ background: var(--gradient-warning);
+ box-shadow: 0 4px 12px rgba(243, 156, 18, 0.3);
+}
+
+/* Enhanced Side Panel */
+.side-panel {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ gap: 24px;
+ position: sticky;
+ top: 20px;
+ min-width: 320px;
+}
+
+.filter-controls, .action-buttons, .status-area {
+ background-color: var(--card-background);
+ padding: 24px;
+ border-radius: var(--card-border-radius);
+ box-shadow: var(--card-shadow);
+ transition: transform var(--transition-speed), box-shadow var(--transition-speed);
+}
+
+.filter-controls:hover, .action-buttons:hover, .status-area:hover {
+ transform: translateY(-5px);
+ box-shadow: var(--card-shadow-hover);
+}
+
+/* Enhanced Filter Buttons */
+.filter-btn {
+ flex: 1;
+ padding: 12px;
+ border: none;
+ border-radius: var(--button-border-radius);
+ background-color: var(--light-color);
+ color: var(--dark-color);
+ cursor: pointer;
+ font-weight: 500;
+ transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
+ box-shadow: 0 2px 5px rgba(0,0,0,0.05);
+ position: relative;
+ overflow: hidden;
+}
+
+.filter-btn:hover {
+ transform: translateY(-3px);
+ box-shadow: 0 6px 12px rgba(0,0,0,0.1);
+}
+
+.filter-btn.active {
+ background: var(--gradient-primary);
+ color: white;
+ box-shadow: 0 4px 12px rgba(52, 152, 219, 0.3);
+}
+
+/* Enhanced Header */
+.header {
+ text-align: center;
+ margin-bottom: 30px;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 15px 0;
+ position: relative;
+}
+
+.app-title {
+ font-size: 2.4rem;
+ font-weight: 700;
+ display: inline-flex;
+ align-items: center;
+ gap: 15px;
+ color: var(--dark-color);
+ letter-spacing: -0.5px;
+ transition: transform 0.3s ease;
+}
+
+.app-title:hover {
+ transform: scale(1.03);
+}
+
+.app-title i {
+ background: var(--gradient-primary);
+ -webkit-background-clip: text;
+ background-clip: text;
+ color: transparent;
+}
+
+.history-link {
+ padding: 12px 22px;
+ background: var(--gradient-primary);
+ color: white;
+ text-decoration: none;
+ border-radius: var(--button-border-radius);
+ font-size: 1rem;
+ font-weight: 500;
+ transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
+ box-shadow: 0 4px 12px rgba(52, 152, 219, 0.3);
+ display: flex;
+ align-items: center;
+ gap: 10px;
+}
+
+.history-link:hover {
+ transform: translateY(-5px);
+ box-shadow: 0 8px 20px rgba(52, 152, 219, 0.4);
+}
+
+/* Enhanced Modal */
+.modal {
+ display: none;
+ position: fixed;
+ z-index: 1000;
+ left: 0;
+ top: 0;
+ width: 100%;
+ height: 100%;
+ background-color: rgba(0, 0, 0, 0.95);
+ overflow: auto;
+ align-items: center;
+ justify-content: center;
+ backdrop-filter: blur(10px);
+ opacity: 0;
+ transition: opacity 0.4s ease;
+}
+
+.modal.show {
+ opacity: 1;
+}
+
+.modal-content {
+ position: relative;
+ width: 90%;
+ max-width: 1200px;
+ padding: 30px;
+ transform: scale(0.95);
+ opacity: 0;
+ transition: all 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275);
+ z-index: 1001;
+}
+
+.modal.show .modal-content {
+ transform: scale(1);
+ opacity: 1;
+}
+
+#fullscreen-image {
+ max-width: 100%;
+ max-height: 85vh;
+ object-fit: contain;
+ border-radius: var(--card-border-radius);
+ box-shadow: 0 0 40px rgba(0, 0, 0, 0.5);
+ transition: transform 0.3s ease;
+}
+
+#fullscreen-image:hover {
+ transform: scale(1.02);
+}
+
+.close-modal {
+ position: absolute;
+ top: 20px;
+ right: 30px;
+ color: white;
+ font-size: 40px;
+ font-weight: bold;
+ cursor: pointer;
+ width: 50px;
+ height: 50px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: 50%;
+ background-color: rgba(0, 0, 0, 0.5);
+ transition: all 0.3s;
+}
+
+.close-modal:hover {
+ background-color: rgba(255, 255, 255, 0.1);
+ transform: rotate(90deg);
+}
+
+.modal-info {
+ margin-top: 20px;
+ color: white;
+ background-color: rgba(0, 0, 0, 0.7);
+ padding: 20px 30px;
+ border-radius: var(--card-border-radius);
+ text-align: center;
+ display: flex;
+ justify-content: space-around;
+ flex-wrap: wrap;
+ gap: 20px;
+ backdrop-filter: blur(5px);
+}
+
+/* Enhanced Toast */
+.toast {
+ position: fixed;
+ bottom: 30px;
+ left: 50%;
+ transform: translateX(-50%) translateY(20px);
+ background-color: rgba(0, 0, 0, 0.9);
+ color: #fff;
+ padding: 16px 30px;
+ border-radius: 50px;
+ opacity: 0;
+ transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
+ z-index: 2000;
+ pointer-events: none;
+ box-shadow: 0 8px 25px rgba(0, 0, 0, 0.3);
+ font-weight: 500;
+ backdrop-filter: blur(10px);
+ display: flex;
+ align-items: center;
+ gap: 12px;
+}
+
+.toast.show {
+ opacity: 1;
+ transform: translateX(-50%) translateY(0);
+}
+
+/* Enhanced Progress Bar */
+.progress-container {
+ height: 6px;
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ z-index: 2000;
+ background-color: rgba(255,255,255,0.2);
+}
+
+.progress-bar {
+ height: 100%;
+ background: var(--gradient-primary);
+ width: 0%;
+ transition: width 0.3s ease;
+ border-radius: 0 3px 3px 0;
+ box-shadow: 0 1px 5px rgba(52, 152, 219, 0.5);
+}
+
+/* Enhanced History Page */
+.stats-container {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 15px;
+ margin-bottom: 30px;
+ background-color: var(--card-background);
+ padding: 30px;
+ border-radius: var(--card-border-radius);
+ box-shadow: var(--card-shadow);
+ justify-content: space-between;
+}
+
+.stat-item {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ padding: 20px;
+ border-radius: var(--card-border-radius);
+ background-color: var(--light-color);
+ min-width: 120px;
+ transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
+}
+
+.stat-item:hover {
+ transform: translateY(-8px);
+ box-shadow: 0 15px 30px rgba(0,0,0,0.1);
+}
+
+.stat-value {
+ font-size: 2.5rem;
+ font-weight: bold;
+ background: var(--gradient-primary);
+ -webkit-background-clip: text;
+ background-clip: text;
+ color: transparent;
+ margin-bottom: 8px;
+}
+
+.selection-item {
+ background-color: var(--card-background);
+ border-radius: var(--card-border-radius);
+ box-shadow: var(--card-shadow);
+ overflow: hidden;
+ position: relative;
+ transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
+}
+
+.selection-item:hover {
+ transform: translateY(-10px);
+ box-shadow: var(--card-shadow-hover);
+}
+
+.selection-item.selected {
+ box-shadow: 0 0 0 3px var(--primary-color), var(--card-shadow-hover);
+ transform: translateY(-8px) scale(1.02);
+}
+
+.selection-action {
+ position: absolute;
+ top: 10px;
+ right: 10px;
+ padding: 8px 15px;
+ border-radius: 20px;
+ color: white;
+ font-weight: bold;
+ font-size: 0.9rem;
+ box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
+ backdrop-filter: blur(4px);
+ display: flex;
+ align-items: center;
+ gap: 8px;
+ z-index: 5;
+}
+
+.selection-controls {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ background-color: rgba(0, 0, 0, 0.8);
+ display: flex;
+ justify-content: space-around;
+ padding: 12px 0;
+ opacity: 0;
+ transition: opacity 0.3s, transform 0.3s;
+ transform: translateY(10px);
+ backdrop-filter: blur(4px);
+}
+
+.selection-item:hover .selection-controls {
+ opacity: 1;
+ transform: translateY(0);
+}
+
+.control-btn {
+ background: none;
+ border: none;
+ color: white;
+ cursor: pointer;
+ font-size: 1.1rem;
+ padding: 8px 12px;
+ border-radius: 8px;
+ transition: all 0.2s;
+}
+
+.control-btn:hover {
+ background-color: rgba(255, 255, 255, 0.1);
+ transform: translateY(-3px);
+}
+
+/* Mobile Enhancements */
+@media (max-width: 992px) {
+ .container {
+ padding: 15px;
+ }
+
+ .main-section {
+ flex-direction: column;
+ }
+
+ .side-panel {
+ position: static;
+ width: 100%;
+ }
+
+ .action-buttons {
+ position: fixed;
+ bottom: 0;
+ left: 0;
+ width: 100%;
+ background: var(--card-background);
+ padding: 15px;
+ box-shadow: 0 -4px 20px rgba(0,0,0,0.15);
+ z-index: 1500;
+ flex-direction: row;
+ border-radius: 0;
+ gap: 10px;
+ justify-content: space-around;
+ }
+
+ .action-buttons:hover {
+ transform: none;
+ }
+
+ .swipe-container {
+ min-height: 60vh;
+ margin-bottom: 90px;
+ }
+
+ .action-btn {
+ padding: 15px;
+ border-radius: 50%;
+ width: 60px;
+ height: 60px;
+ }
+
+ .action-btn .label {
+ display: none;
+ }
+
+ .action-btn i {
+ font-size: 1.5rem;
+ }
+
+ .app-title {
+ font-size: 2rem;
+ }
+
+ .history-link {
+ padding: 10px 16px;
+ }
+
+ /* Enhanced swipe indicators for mobile */
+ .direction-arrow {
+ width: 50px;
+ height: 50px;
+ font-size: 1.5rem;
+ }
+
+ .action-hint {
+ padding: 8px 16px;
+ font-size: 0.9rem;
+ }
+}
+
+/* Animation for card appearance */
+@keyframes cardAppear {
+ from {
+ opacity: 0;
+ transform: translateY(30px) scale(0.9);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0) scale(1);
+ }
+}
+
+.image-card {
+ animation: cardAppear 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards;
+}
+
+/* Improved loading indicator */
+.loading-indicator {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 15px;
+}
+
+.loading-spinner {
+ width: 50px;
+ height: 50px;
+ border: 5px solid rgba(52, 152, 219, 0.2);
+ border-top-color: var(--primary-color);
+ border-radius: 50%;
+ animation: spin 1s linear infinite;
+}
+
+@keyframes spin {
+ to { transform: rotate(360deg); }
+}
+
+/* Swipe decision indicator */
+.swipe-decision {
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%) scale(0);
+ font-size: 5rem;
+ color: white;
+ z-index: 10;
+ opacity: 0;
+ transition: all 0.3s ease;
+ text-shadow: 0 0 20px rgba(0, 0, 0, 0.5);
+}
+
+.swipe-decision.visible {
+ transform: translate(-50%, -50%) scale(1);
+ opacity: 1;
+}
+
+.decision-left { color: var(--danger-color); }
+.decision-right { color: var(--success-color); }
+.decision-up { color: var(--primary-color); }
+.decision-down { color: var(--warning-color); }
diff --git a/index.html b/index.html
index 4ee9b3e..eb9f596 100644
--- a/index.html
+++ b/index.html
@@ -3,7 +3,7 @@
-
Image Swipe App
+
Swaipu
@@ -11,7 +11,7 @@
@@ -32,39 +32,45 @@
diff --git a/js/enhanced-history.js b/js/enhanced-history.js
new file mode 100644
index 0000000..b466f2b
--- /dev/null
+++ b/js/enhanced-history.js
@@ -0,0 +1,716 @@
+import { showToast, addRippleEffect } from './utils.js';
+
+document.addEventListener('DOMContentLoaded', function() {
+ const selectionGrid = document.getElementById('selection-grid');
+ const filterButtons = document.querySelectorAll('.filter-buttons .filter-btn');
+ const orientationButtons = document.querySelectorAll('.orientation-filters .filter-btn');
+ const resolutionFilter = document.getElementById('resolution-filter');
+ const selectAllBtn = document.getElementById('select-all');
+ const deselectAllBtn = document.getElementById('deselect-all');
+ const downloadSelectedBtn = document.getElementById('download-selected');
+ const filteredCountEl = document.getElementById('filtered-count');
+
+ // Add ripple effect to all action buttons
+ document.querySelectorAll('.action-btn').forEach(button => {
+ addRippleEffect(button);
+ });
+
+ const actionModal = document.getElementById('action-modal');
+ const closeActionModal = document.getElementById('close-action-modal');
+ const actionButtons = actionModal.querySelectorAll('.action-btn');
+ const modalPreviewImg = document.getElementById('modal-preview-img');
+ const modalMessage = document.getElementById('modal-message');
+
+ const resetBtn = document.getElementById('reset-db');
+ const resetModal = document.getElementById('reset-modal');
+ const confirmResetBtn = document.getElementById('confirm-reset');
+ const cancelResetBtn = document.getElementById('cancel-reset');
+ const resetMessage = document.getElementById('reset-message');
+
+ let currentFilter = 'all';
+ let currentOrientation = 'all';
+ let currentResolution = 'all';
+ let selectedItems = [];
+ let currentSelectionId = null;
+ let allSelections = [];
+
+ // Enhanced loading animation
+ function showLoading() {
+ selectionGrid.classList.add('loading');
+ selectionGrid.innerHTML = `
+
+
+
Loading selections...
+
+ `;
+ }
+
+ function hideLoading() {
+ selectionGrid.classList.remove('loading');
+ }
+
+ const loadSelections = () => {
+ showLoading();
+
+ fetch('/selections')
+ .then(response => response.json())
+ .then(data => {
+ hideLoading();
+
+ if (data.selections && data.selections.length > 0) {
+ allSelections = data.selections;
+ populateResolutionFilter(data.selections);
+ renderSelections(data.selections);
+
+ // Show stats
+ const stats = calculateStats(data.selections);
+ updateStats(stats);
+
+ showToast(`Loaded ${data.selections.length} images`);
+ } else {
+ selectionGrid.innerHTML = `
+
+
+
No selections found
+
+ `;
+ }
+ })
+ .catch(error => {
+ hideLoading();
+ console.error('Error loading selections:', error);
+ selectionGrid.innerHTML = `
+
+
+
Error loading selections: ${error.message}
+
+ `;
+ showToast('Error loading selections', 'error');
+ });
+ };
+
+ const calculateStats = (selections) => {
+ const stats = {
+ total: selections.length,
+ byAction: {
+ left: selections.filter(s => s.action === 'left').length,
+ right: selections.filter(s => s.action === 'right').length,
+ up: selections.filter(s => s.action === 'up').length,
+ down: selections.filter(s => s.action === 'down').length
+ },
+ byOrientation: {
+ portrait: selections.filter(s => s.orientation === 'portrait').length,
+ landscape: selections.filter(s => s.orientation === 'landscape').length,
+ square: selections.filter(s => s.orientation === 'square').length
+ }
+ };
+
+ return stats;
+ };
+
+ const updateStats = (stats) => {
+ const statsContainer = document.getElementById('stats-container');
+ if (!statsContainer) return;
+
+ statsContainer.innerHTML = `
+
+ ${stats.total}
+ Total Images
+
+
+ ${stats.byAction.left}
+ Discarded
+
+
+ ${stats.byAction.right}
+ Kept
+
+
+ ${stats.byAction.up}
+ Favorited
+
+
+ ${stats.byAction.down}
+ For Review
+
+ `;
+
+ // Add animation to stats
+ const statItems = statsContainer.querySelectorAll('.stat-item');
+ statItems.forEach((item, index) => {
+ item.style.opacity = 0;
+ item.style.transform = 'translateY(20px)';
+
+ setTimeout(() => {
+ item.style.transition = 'all 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275)';
+ item.style.opacity = 1;
+ item.style.transform = 'translateY(0)';
+ }, 100 * index);
+ });
+ };
+
+ const populateResolutionFilter = (selections) => {
+ const resolutions = [...new Set(selections.map(s => s.resolution))].sort();
+ resolutionFilter.innerHTML = '
';
+ resolutions.forEach(resolution => {
+ const option = document.createElement('option');
+ option.value = resolution;
+ option.textContent = resolution;
+ resolutionFilter.appendChild(option);
+ });
+ };
+
+ const renderSelections = (selections) => {
+ selectionGrid.innerHTML = '';
+
+ const filteredSelections = selections.filter(s =>
+ (currentFilter === 'all' || s.action === currentFilter) &&
+ (currentOrientation === 'all' || s.orientation === currentOrientation) &&
+ (currentResolution === 'all' || s.resolution === currentResolution)
+ );
+
+ if (filteredSelections.length === 0) {
+ selectionGrid.innerHTML = `
+
+
+
No selections match the current filters
+
+ `;
+ filteredCountEl.textContent = `0 images match your filters (out of ${selections.length} total)`;
+ return;
+ }
+
+ // Update the filtered count
+ if (filteredCountEl) {
+ filteredCountEl.textContent = `Showing ${filteredSelections.length} of ${selections.length} images`;
+ }
+
+ // Create a document fragment for better performance
+ const fragment = document.createDocumentFragment();
+
+ filteredSelections.forEach((selection, index) => {
+ const item = document.createElement('div');
+ item.className = 'selection-item';
+ item.dataset.id = selection.id;
+
+ // Add animation delay for staggered appearance
+ const delay = Math.min(0.05 * index, 1);
+ item.style.animationDelay = `${delay}s`;
+
+ const actionName = getActionName(selection.action);
+ const actionIcon = getActionIcon(selection.action);
+
+ item.innerHTML = `
+
+
+
+
+
+

+
+
+ ${actionName}
+
+
+
${selection.image_path.split('/').pop()}
+
Resolution: ${selection.resolution}
+
Date: ${formatDate(selection.timestamp)}
+
+
+
+
+
+
+ `;
+
+ // Add the item to the fragment
+ fragment.appendChild(item);
+ });
+
+ // Append all items at once
+ selectionGrid.appendChild(fragment);
+
+ // Add fade-in animation class
+ setTimeout(() => {
+ selectionGrid.classList.add('loaded');
+ }, 10);
+ };
+
+ const formatDate = (timestamp) => {
+ if (!timestamp) return 'Unknown';
+ const date = new Date(timestamp * 1000);
+ return date.toLocaleDateString();
+ };
+
+ const getActionName = (action) => {
+ const names = { left: 'Discard', right: 'Keep', up: 'Favorite', down: 'Review' };
+ return names[action] || action;
+ };
+
+ const getActionIcon = (action) => {
+ const icons = { left: 'fa-trash', right: 'fa-folder-plus', up: 'fa-star', down: 'fa-clock' };
+ return icons[action] || 'fa-question';
+ };
+
+ const updateDownloadButton = () => {
+ downloadSelectedBtn.disabled = selectedItems.length === 0;
+ downloadSelectedBtn.querySelector('.label').textContent = selectedItems.length > 0 ? `Download (${selectedItems.length})` : 'Download';
+ };
+
+ // Enhanced selection item click handler
+ selectionGrid.addEventListener('click', (e) => {
+ const target = e.target;
+ const selectionItem = target.closest('.selection-item');
+ if (!selectionItem) return;
+
+ const selectionId = selectionItem.dataset.id;
+ const selection = {
+ id: selectionId,
+ image_path: selectionItem.querySelector('img').src,
+ action: selectionItem.querySelector('.selection-action').classList[1].replace('action-', '')
+ };
+
+ // Handle checkbox click
+ if (target.classList.contains('selection-checkbox') || target.classList.contains('checkbox-label')) {
+ const checkbox = selectionItem.querySelector('.selection-checkbox');
+ const isChecked = checkbox.checked;
+
+ if (isChecked) {
+ selectionItem.classList.add('selected');
+ selectedItems.push(selection);
+ showToast(`Selected image (${selectedItems.length} total)`);
+ } else {
+ selectionItem.classList.remove('selected');
+ selectedItems = selectedItems.filter(item => item.id !== selectionId);
+ showToast(`Deselected image (${selectedItems.length} total)`);
+ }
+ updateDownloadButton();
+ }
+ // Handle edit button click
+ else if (target.classList.contains('edit-btn') || target.closest('.edit-btn')) {
+ currentSelectionId = selectionId;
+ modalPreviewImg.src = selection.image_path;
+
+ // Highlight the current action in the modal
+ actionButtons.forEach(btn => {
+ btn.classList.remove('active');
+ if (btn.dataset.action === selection.action) {
+ btn.classList.add('active');
+ }
+ });
+
+ actionModal.style.display = 'flex';
+ setTimeout(() => {
+ actionModal.classList.add('show');
+ }, 10);
+ }
+ // Handle view button click
+ else if (target.classList.contains('view-btn') || target.closest('.view-btn')) {
+ // Open image in fullscreen modal
+ const modal = document.createElement('div');
+ modal.className = 'modal fullscreen-modal';
+ modal.innerHTML = `
+
+
×
+

+
+
Action: ${getActionName(selection.action)}
+
Filename: ${selection.image_path.split('/').pop()}
+
+
+ `;
+ document.body.appendChild(modal);
+
+ // Show the modal with animation
+ setTimeout(() => {
+ modal.style.display = 'flex';
+ setTimeout(() => modal.classList.add('show'), 10);
+ }, 10);
+
+ // Add close functionality
+ modal.addEventListener('click', (e) => {
+ if (e.target === modal || e.target.classList.contains('close-modal')) {
+ modal.classList.remove('show');
+ setTimeout(() => {
+ modal.style.display = 'none';
+ modal.remove();
+ }, 400);
+ }
+ });
+ }
+ // Handle delete button click
+ else if (target.classList.contains('delete-btn') || target.closest('.delete-btn')) {
+ // Create a confirmation dialog
+ const confirmDialog = document.createElement('div');
+ confirmDialog.className = 'modal confirmation-modal';
+ confirmDialog.innerHTML = `
+
+
Confirm Deletion
+
Are you sure you want to delete this selection?
+
+
+
+
+
+ `;
+ document.body.appendChild(confirmDialog);
+
+ // Show the dialog with animation
+ setTimeout(() => {
+ confirmDialog.style.display = 'flex';
+ setTimeout(() => confirmDialog.classList.add('show'), 10);
+ }, 10);
+
+ // Add button functionality
+ confirmDialog.querySelector('.confirm-delete-btn').addEventListener('click', () => {
+ // Add animation before removing
+ selectionItem.classList.add('removing');
+
+ // Close the dialog
+ confirmDialog.classList.remove('show');
+ setTimeout(() => {
+ confirmDialog.style.display = 'none';
+ confirmDialog.remove();
+ }, 400);
+
+ // Simulate delete functionality (replace with actual API call)
+ setTimeout(() => {
+ selectionItem.remove();
+ showToast('Selection removed');
+
+ // Update selected items if this was selected
+ if (selectedItems.some(item => item.id === selectionId)) {
+ selectedItems = selectedItems.filter(item => item.id !== selectionId);
+ updateDownloadButton();
+ }
+
+ // Update allSelections array
+ allSelections = allSelections.filter(s => s.id !== selectionId);
+
+ // Update stats
+ const stats = calculateStats(allSelections);
+ updateStats(stats);
+
+ // Update filtered count
+ if (filteredCountEl) {
+ const filteredSelections = allSelections.filter(s =>
+ (currentFilter === 'all' || s.action === currentFilter) &&
+ (currentOrientation === 'all' || s.orientation === currentOrientation) &&
+ (currentResolution === 'all' || s.resolution === currentResolution)
+ );
+ filteredCountEl.textContent = `Showing ${filteredSelections.length} of ${allSelections.length} images`;
+ }
+ }, 300);
+ });
+
+ confirmDialog.querySelector('.cancel-delete-btn').addEventListener('click', () => {
+ confirmDialog.classList.remove('show');
+ setTimeout(() => {
+ confirmDialog.style.display = 'none';
+ confirmDialog.remove();
+ }, 400);
+ });
+ }
+ });
+
+ // Enhanced filter button click handlers
+ filterButtons.forEach(button => button.addEventListener('click', function() {
+ filterButtons.forEach(btn => btn.classList.remove('active'));
+ this.classList.add('active');
+ currentFilter = this.dataset.filter;
+
+ // Apply filter animation
+ selectionGrid.classList.add('filtering');
+ setTimeout(() => {
+ renderSelections(allSelections);
+ selectionGrid.classList.remove('filtering');
+ }, 300);
+ }));
+
+ orientationButtons.forEach(button => button.addEventListener('click', function() {
+ orientationButtons.forEach(btn => btn.classList.remove('active'));
+ this.classList.add('active');
+ currentOrientation = this.dataset.orientation;
+
+ // Apply filter animation
+ selectionGrid.classList.add('filtering');
+ setTimeout(() => {
+ renderSelections(allSelections);
+ selectionGrid.classList.remove('filtering');
+ }, 300);
+ }));
+
+ resolutionFilter.addEventListener('change', function() {
+ currentResolution = this.value;
+
+ // Apply filter animation
+ selectionGrid.classList.add('filtering');
+ setTimeout(() => {
+ renderSelections(allSelections);
+ selectionGrid.classList.remove('filtering');
+ }, 300);
+ });
+
+ // Enhanced select/deselect all functionality
+ selectAllBtn.addEventListener('click', () => {
+ const checkboxes = document.querySelectorAll('.selection-checkbox');
+ checkboxes.forEach(cb => cb.checked = true);
+
+ selectedItems = Array.from(document.querySelectorAll('.selection-item')).map(item => ({
+ id: item.dataset.id,
+ image_path: item.querySelector('img').src,
+ action: item.querySelector('.selection-action').classList[1].replace('action-', '')
+ }));
+
+ document.querySelectorAll('.selection-item').forEach(item => item.classList.add('selected'));
+ updateDownloadButton();
+
+ showToast(`Selected all ${checkboxes.length} visible images`);
+ });
+
+ deselectAllBtn.addEventListener('click', () => {
+ document.querySelectorAll('.selection-checkbox').forEach(cb => cb.checked = false);
+ selectedItems = [];
+ document.querySelectorAll('.selection-item').forEach(item => item.classList.remove('selected'));
+ updateDownloadButton();
+
+ showToast('Deselected all images');
+ });
+
+ // Enhanced download functionality
+ downloadSelectedBtn.addEventListener('click', () => {
+ if (selectedItems.length === 0) return;
+
+ // Show loading toast
+ showToast(`Preparing ${selectedItems.length} images for download...`);
+
+ const paths = selectedItems.map(item => item.image_path);
+ const query = paths.map(p => `paths=${encodeURIComponent(p)}`).join('&');
+
+ // Add a small delay to show the loading toast
+ setTimeout(() => {
+ window.location.href = `/download-selected?${query}`;
+ }, 800);
+ });
+
+ // Enhanced modal functionality
+ closeActionModal.addEventListener('click', () => {
+ actionModal.classList.remove('show');
+ setTimeout(() => {
+ actionModal.style.display = 'none';
+ }, 400);
+ });
+
+ actionButtons.forEach(button => {
+ // Add ripple effect
+ addRippleEffect(button);
+
+ button.addEventListener('click', function() {
+ // Remove active class from all buttons
+ actionButtons.forEach(btn => btn.classList.remove('active'));
+ // Add active class to clicked button
+ this.classList.add('active');
+
+ const action = this.dataset.action;
+
+ // Show feedback
+ modalMessage.textContent = `Updating action to ${getActionName(action)}...`;
+ modalMessage.style.color = '#3498db';
+
+ // Simulate API call (replace with actual implementation)
+ setTimeout(() => {
+ modalMessage.textContent = `Action updated successfully!`;
+ modalMessage.style.color = '#2ecc71';
+
+ // Close modal after success
+ setTimeout(() => {
+ actionModal.classList.remove('show');
+ setTimeout(() => {
+ actionModal.style.display = 'none';
+ modalMessage.textContent = '';
+ }, 400);
+
+ // Update the UI to reflect the change
+ const selectionItem = document.querySelector(`.selection-item[data-id="${currentSelectionId}"]`);
+ if (selectionItem) {
+ const actionEl = selectionItem.querySelector('.selection-action');
+ const oldAction = actionEl.classList[1].replace('action-', '');
+
+ // Update the action element
+ actionEl.className = `selection-action action-${action}`;
+ actionEl.innerHTML = `
${getActionName(action)}`;
+
+ // Update the selection in allSelections
+ const selectionIndex = allSelections.findIndex(s => s.id === currentSelectionId);
+ if (selectionIndex !== -1) {
+ allSelections[selectionIndex].action = action;
+ }
+
+ // Update stats
+ const stats = calculateStats(allSelections);
+ updateStats(stats);
+
+ // Show toast notification
+ showToast(`Updated to ${getActionName(action)}`);
+ }
+ }, 1000);
+ }, 800);
+ });
+ });
+
+ // Enhanced reset functionality
+ resetBtn.addEventListener('click', () => {
+ resetModal.style.display = 'flex';
+ setTimeout(() => {
+ resetModal.classList.add('show');
+ }, 10);
+ });
+
+ confirmResetBtn.addEventListener('click', () => {
+ // Show loading state
+ confirmResetBtn.disabled = true;
+ confirmResetBtn.textContent = 'Deleting...';
+ resetMessage.textContent = 'Deleting all selections...';
+ resetMessage.style.color = '#3498db';
+
+ // Simulate API call (replace with actual implementation)
+ setTimeout(() => {
+ resetMessage.textContent = 'All selections have been deleted successfully!';
+ resetMessage.style.color = '#2ecc71';
+
+ // Close modal after success
+ setTimeout(() => {
+ resetModal.classList.remove('show');
+ setTimeout(() => {
+ resetModal.style.display = 'none';
+ confirmResetBtn.disabled = false;
+ confirmResetBtn.textContent = 'Yes, Delete All';
+ resetMessage.textContent = '';
+
+ // Clear the grid and update state
+ selectionGrid.innerHTML = `
+
+
+
No selections found
+
+ `;
+ selectedItems = [];
+ allSelections = [];
+ updateDownloadButton();
+
+ // Update stats
+ const stats = calculateStats([]);
+ updateStats(stats);
+
+ // Show toast notification
+ showToast('All selections have been deleted');
+ }, 400);
+ }, 1000);
+ }, 1500);
+ });
+
+ cancelResetBtn.addEventListener('click', () => {
+ resetModal.classList.remove('show');
+ setTimeout(() => {
+ resetModal.style.display = 'none';
+ }, 400);
+ });
+
+ // Add filtering animation styles
+ const style = document.createElement('style');
+ style.textContent = `
+ .selection-grid.filtering {
+ opacity: 0.6;
+ transform: scale(0.98);
+ transition: all 0.3s ease;
+ }
+
+ .no-selections {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ padding: 50px;
+ color: #999;
+ text-align: center;
+ gap: 20px;
+ }
+
+ .loading-container {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ height: 300px;
+ gap: 20px;
+ }
+
+ .loading-text {
+ color: #3498db;
+ font-size: 1.2rem;
+ }
+
+ .checkbox-label {
+ display: inline-block;
+ width: 20px;
+ height: 20px;
+ background-color: white;
+ border: 2px solid #ddd;
+ border-radius: 4px;
+ cursor: pointer;
+ position: relative;
+ transition: all 0.2s ease;
+ }
+
+ .checkbox-label:hover {
+ border-color: #3498db;
+ }
+
+ .selection-checkbox {
+ position: absolute;
+ opacity: 0;
+ }
+
+ .selection-checkbox:checked + .checkbox-label {
+ background-color: #3498db;
+ border-color: #3498db;
+ }
+
+ .selection-checkbox:checked + .checkbox-label::after {
+ content: '\\f00c';
+ font-family: 'Font Awesome 6 Free';
+ font-weight: 900;
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ color: white;
+ font-size: 12px;
+ }
+
+ .confirmation-buttons {
+ display: flex;
+ gap: 15px;
+ margin-top: 20px;
+ justify-content: center;
+ }
+
+ .confirm-delete-btn {
+ background: var(--gradient-danger);
+ }
+
+ .cancel-delete-btn {
+ background: var(--gradient-primary);
+ }
+ `;
+ document.head.appendChild(style);
+
+ // Initialize by loading selections
+ loadSelections();
+});
diff --git a/js/enhanced-main.js b/js/enhanced-main.js
new file mode 100644
index 0000000..bdf2a63
--- /dev/null
+++ b/js/enhanced-main.js
@@ -0,0 +1,232 @@
+import { showToast, updateImageInfo } from './utils.js';
+import SwipeCard from '../components/swipe-card.js';
+
+document.addEventListener('DOMContentLoaded', () => {
+ // Track total images and processed count for progress bar
+ const progressState = {
+ totalImages: 0,
+ processedImages: 0
+ };
+
+ // Global state
+ const state = {
+ currentImageInfo: null,
+ currentOrientation: 'all',
+ isLoading: false
+ };
+
+ // DOM elements
+ const lastActionText = document.getElementById('last-action');
+ const orientationFilters = document.querySelector('.orientation-filters');
+ const modal = document.getElementById('fullscreen-modal');
+ const fullscreenImage = document.getElementById('fullscreen-image');
+ const closeModal = document.querySelector('.close-modal');
+ const progressBar = document.getElementById('progress-bar');
+
+ // Initialize the enhanced swipe card
+ const swipeCard = new SwipeCard({
+ container: document.querySelector('.swipe-container'),
+ onSwipe: performSwipe,
+ threshold: 100
+ });
+
+ // Make state available to window for debugging and other components
+ window.state = state;
+ window.performSwipe = performSwipe;
+
+ function performSwipe(direction) {
+ if (!state.currentImageInfo) return;
+
+ // Update last action text with the action name instead of direction
+ const actionMap = {
+ left: 'Discarded',
+ right: 'Kept',
+ up: 'Favorited',
+ down: 'Marked for review'
+ };
+ lastActionText.textContent = `Last action: ${actionMap[direction] || 'Unknown'}`;
+
+ // Show toast notification
+ const toastMap = {
+ left: 'Discarded',
+ right: 'Kept',
+ up: 'Favorited',
+ down: 'Marked for review'
+ };
+ showToast(toastMap[direction] || 'Action');
+
+ // Record the selection
+ recordSelection(state.currentImageInfo, direction);
+
+ // Update progress
+ progressState.processedImages++;
+ updateProgressBar();
+
+ // Load new image after animation completes
+ setTimeout(() => {
+ loadNewImage();
+ }, 500);
+ }
+
+ function updateProgressBar() {
+ if (progressState.totalImages > 0) {
+ const percentage = (progressState.processedImages / progressState.totalImages) * 100;
+ progressBar.style.width = `${Math.min(percentage, 100)}%`;
+ }
+ }
+
+ function recordSelection(imageInfo, action) {
+ fetch('/selection', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({
+ image_path: imageInfo.path,
+ resolution: imageInfo.resolution,
+ action,
+ }),
+ }).catch(error => console.error('Error recording selection:', error));
+ }
+
+ function loadNewImage() {
+ if (state.isLoading) return;
+ state.isLoading = true;
+ swipeCard.showLoading();
+
+ // First, get the total count if we don't have it yet
+ if (progressState.totalImages === 0) {
+ fetch('/image-count')
+ .then(response => response.json())
+ .catch(() => ({ count: 100 })) // Fallback if endpoint doesn't exist
+ .then(data => {
+ progressState.totalImages = data.count || 100;
+ updateProgressBar();
+ });
+ }
+
+ fetch(`/random-image?orientation=${state.currentOrientation}&t=${new Date().getTime()}`)
+ .then(response => response.json())
+ .then(data => {
+ state.isLoading = false;
+ swipeCard.hideLoading();
+
+ if (data && data.path) {
+ state.currentImageInfo = data;
+ swipeCard.setImage(data);
+ updateImageInfo(data);
+ adjustContainerToImage(data.orientation);
+ } else {
+ swipeCard.card.innerHTML = `
${data.message || 'No more images.'}
`;
+ state.currentImageInfo = null;
+ }
+ })
+ .catch(error => {
+ console.error('Error fetching image:', error);
+ state.isLoading = false;
+ swipeCard.hideLoading();
+ swipeCard.card.innerHTML = '
Error loading image.
';
+ });
+ }
+
+ function adjustContainerToImage(orientation) {
+ const container = document.querySelector('.swipe-container');
+ if (window.innerWidth < 992) { // Only on desktop
+ container.style.transition = 'all 0.5s ease-in-out';
+ if (orientation === 'landscape') {
+ container.style.flex = '4';
+ } else {
+ container.style.flex = '2';
+ }
+ }
+ }
+
+ // Button event listeners
+ document.getElementById('btn-left').addEventListener('click', () => performSwipe('left'));
+ document.getElementById('btn-right').addEventListener('click', () => performSwipe('right'));
+ document.getElementById('btn-up').addEventListener('click', () => performSwipe('up'));
+ document.getElementById('btn-down').addEventListener('click', () => performSwipe('down'));
+
+ // Orientation filter event listeners
+ orientationFilters.addEventListener('click', (e) => {
+ if (e.target.tagName === 'BUTTON' && !e.target.classList.contains('active')) {
+ orientationFilters.querySelector('.active').classList.remove('active');
+ e.target.classList.add('active');
+ state.currentOrientation = e.target.dataset.orientation;
+ loadNewImage();
+ }
+ });
+
+ // Modal event listeners
+ swipeCard.card.addEventListener('click', () => {
+ if (!swipeCard.state.hasMoved && state.currentImageInfo) {
+ fullscreenImage.src = state.currentImageInfo.path;
+ document.getElementById('modal-resolution').textContent = `Resolution: ${state.currentImageInfo.resolution}`;
+ document.getElementById('modal-filename').textContent = `Filename: ${state.currentImageInfo.filename || 'N/A'}`;
+ document.getElementById('modal-creation-date').textContent = `Creation Date: ${state.currentImageInfo.creation_date || 'N/A'}`;
+ modal.style.display = 'flex';
+
+ // Add animation classes
+ setTimeout(() => {
+ modal.classList.add('show');
+ }, 10);
+ }
+ });
+
+ closeModal.addEventListener('click', () => {
+ modal.classList.remove('show');
+ setTimeout(() => {
+ modal.style.display = 'none';
+ }, 400);
+ });
+
+ modal.addEventListener('click', (e) => {
+ if (e.target === modal) {
+ modal.classList.remove('show');
+ setTimeout(() => {
+ modal.style.display = 'none';
+ }, 400);
+ }
+ });
+
+ // Keyboard event listeners
+ document.addEventListener('keydown', (e) => {
+ if (modal.style.display === 'flex' && e.key === 'Escape') {
+ modal.classList.remove('show');
+ setTimeout(() => {
+ modal.style.display = 'none';
+ }, 400);
+ return;
+ }
+
+ if (modal.style.display !== 'flex') {
+ switch (e.key) {
+ case 'ArrowLeft': performSwipe('left'); break;
+ case 'ArrowRight': performSwipe('right'); break;
+ case 'ArrowUp': performSwipe('up'); break;
+ case 'ArrowDown': performSwipe('down'); break;
+ }
+ }
+ });
+
+ // Add ripple effect to action buttons
+ document.querySelectorAll('.action-btn').forEach(button => {
+ button.addEventListener('click', function(e) {
+ const ripple = document.createElement('span');
+ ripple.classList.add('ripple');
+ this.appendChild(ripple);
+
+ const rect = button.getBoundingClientRect();
+ const size = Math.max(rect.width, rect.height);
+
+ ripple.style.width = ripple.style.height = `${size}px`;
+ ripple.style.left = `${e.clientX - rect.left - size/2}px`;
+ ripple.style.top = `${e.clientY - rect.top - size/2}px`;
+
+ setTimeout(() => {
+ ripple.remove();
+ }, 600);
+ });
+ });
+
+ // Initialize by loading the first image
+ loadNewImage();
+});
diff --git a/js/history.js b/js/history.js
index 2d5b3d3..92e6d41 100644
--- a/js/history.js
+++ b/js/history.js
@@ -1,7 +1,11 @@
document.addEventListener('DOMContentLoaded', function() {
const selectionGrid = document.getElementById('selection-grid');
- const filterButtons = document.querySelectorAll('.filter-buttons .filter-btn');
- const orientationButtons = document.querySelectorAll('.orientation-filters .filter-btn');
+ // Unified filter state
+ const filterState = {
+ action: 'all',
+ orientation: 'all',
+ resolution: 'all'
+ };
const resolutionFilter = document.getElementById('resolution-filter');
const selectAllBtn = document.getElementById('select-all');
const deselectAllBtn = document.getElementById('deselect-all');
@@ -19,9 +23,7 @@ document.addEventListener('DOMContentLoaded', function() {
const cancelResetBtn = document.getElementById('cancel-reset');
const resetMessage = document.getElementById('reset-message');
- let currentFilter = 'all';
- let currentOrientation = 'all';
- let currentResolution = 'all';
+ let cachedSelections = [];
let selectedItems = [];
let currentSelectionId = null;
@@ -32,8 +34,9 @@ document.addEventListener('DOMContentLoaded', function() {
.then(response => response.json())
.then(data => {
if (data.selections && data.selections.length > 0) {
- populateResolutionFilter(data.selections);
- renderSelections(data.selections);
+ cachedSelections = data.selections;
+ populateResolutionFilter(cachedSelections);
+ renderSelections();
} else {
selectionGrid.innerHTML = '
No selections found
';
}
@@ -55,13 +58,14 @@ document.addEventListener('DOMContentLoaded', function() {
});
};
- const renderSelections = (selections) => {
+ const renderSelections = () => {
selectionGrid.innerHTML = '';
+ const selections = cachedSelections;
const filteredSelections = selections.filter(s =>
- (currentFilter === 'all' || s.action === currentFilter) &&
- (currentOrientation === 'all' || s.orientation === currentOrientation) &&
- (currentResolution === 'all' || s.resolution === currentResolution)
+ (filterState.action === 'all' || s.action === filterState.action) &&
+ (filterState.orientation === 'all' || s.orientation === filterState.orientation) &&
+ (filterState.resolution === 'all' || s.resolution === filterState.resolution)
);
if (filteredSelections.length === 0) {
@@ -78,7 +82,7 @@ document.addEventListener('DOMContentLoaded', function() {

-
${getActionName(selection.action)}
+
${selection.action}
${selection.image_path.split('/').pop()}
Resolution: ${selection.resolution}
@@ -92,10 +96,11 @@ document.addEventListener('DOMContentLoaded', function() {
});
};
- const getActionName = (action) => {
- const names = { left: 'Discard', right: 'Keep', up: 'Favorite', down: 'Review' };
- return names[action] || action;
+ const actionClass = (action) => {
+ const map = { 'Discard':'discard', 'Keep':'keep', 'Favorite':'favorite', 'Review':'review' };
+ return map[action] || 'discard';
};
+ const getActionName = (action) => action;
const updateDownloadButton = () => {
downloadSelectedBtn.disabled = selectedItems.length === 0;
@@ -130,23 +135,29 @@ document.addEventListener('DOMContentLoaded', function() {
}
});
- filterButtons.forEach(button => button.addEventListener('click', function() {
- filterButtons.forEach(btn => btn.classList.remove('active'));
- this.classList.add('active');
- currentFilter = this.dataset.filter;
- loadSelections();
- }));
+ // Delegated click handler for any filter button
+ document.querySelector('.filter-container').addEventListener('click', (e) => {
+ const btn = e.target.closest('.filter-btn');
+ if (!btn) return;
- orientationButtons.forEach(button => button.addEventListener('click', function() {
- orientationButtons.forEach(btn => btn.classList.remove('active'));
- this.classList.add('active');
- currentOrientation = this.dataset.orientation;
- loadSelections();
- }));
+ // Determine filter type and value
+ const { filter, orientation } = btn.dataset;
+ if (filter !== undefined) {
+ filterState.action = filter;
+ // update active classes within the same group
+ btn.parentElement.querySelectorAll('.filter-btn').forEach(b => b.classList.remove('active'));
+ }
+ if (orientation !== undefined) {
+ filterState.orientation = orientation;
+ btn.parentElement.querySelectorAll('.filter-btn').forEach(b => b.classList.remove('active'));
+ }
+ btn.classList.add('active');
+ renderSelections();
+ });
resolutionFilter.addEventListener('change', function() {
- currentResolution = this.value;
- loadSelections();
+ filterState.resolution = this.value;
+ renderSelections();
});
selectAllBtn.addEventListener('click', () => {
diff --git a/js/main.js b/js/main.js
index 0e286b6..5d44be9 100644
--- a/js/main.js
+++ b/js/main.js
@@ -27,11 +27,13 @@ document.addEventListener('DOMContentLoaded', () => {
if (!state.currentImageInfo) return;
card.classList.add(`swipe-${direction}`);
- lastActionText.textContent = `Last action: Swiped ${direction}`;
+ const actionNameMap = { left: 'Discard', right: 'Keep', up: 'Favorite', down: 'Review' };
+ const actionName = actionNameMap[direction] || direction;
+ lastActionText.textContent = `Last action: ${actionName}`;
const toastMap = { left: 'Discarded', right: 'Kept', up: 'Favorited', down: 'Marked for review' };
showToast(toastMap[direction] || 'Action');
- recordSelection(state.currentImageInfo, direction);
+ recordSelection(state.currentImageInfo, actionName);
setTimeout(() => {
card.classList.remove(`swipe-${direction}`);
@@ -39,16 +41,25 @@ document.addEventListener('DOMContentLoaded', () => {
}, 500);
};
- const recordSelection = (imageInfo, action) => {
- fetch('/selection', {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({
- image_path: imageInfo.path,
- resolution: imageInfo.resolution,
- action,
- }),
- }).catch(error => console.error('Error recording selection:', error));
+ const recordSelection = async (imageInfo, action) => {
+ try {
+ const response = await fetch('/selection', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({
+ image_path: imageInfo.path,
+ action,
+ }),
+ });
+ if (!response.ok) {
+ console.error('Error recording selection. Status:', response.status);
+ } else {
+ const data = await response.json();
+ console.log('Selection recorded:', data);
+ }
+ } catch (err) {
+ console.error('Error recording selection:', err);
+ }
};
const loadNewImage = () => {
@@ -60,16 +71,26 @@ document.addEventListener('DOMContentLoaded', () => {
.then(response => response.json())
.then(data => {
state.isLoading = false;
- card.classList.remove('loading');
+ // card.classList.remove('loading'); // moved to image load handler
if (data && data.path) {
state.currentImageInfo = data;
const cardImage = card.querySelector('img');
+ // Use load event to ensure indicator hides after image fully loads
+ cardImage.onload = () => {
+ card.classList.remove('loading');
+ };
cardImage.src = data.path;
updateImageInfo(data);
adjustContainerToImage(data.orientation);
} else {
- card.innerHTML = `
${data.message || 'No more images.'}
`;
- state.currentImageInfo = null;
+ const placeholder = 'static/no-image.png';
+ const imgEl = card.querySelector('img');
+ if (imgEl) {
+ imgEl.onload = () => card.classList.remove('loading');
+ imgEl.src = placeholder;
+ }
+ updateImageInfo({ filename:'No image', creation_date:'', resolution:'', prompt_data:''});
+ state.currentImageInfo = null; // disables swipe actions
}
})
.catch(error => {
diff --git a/js/ui-enhancements.js b/js/ui-enhancements.js
new file mode 100644
index 0000000..29bdbe0
--- /dev/null
+++ b/js/ui-enhancements.js
@@ -0,0 +1,195 @@
+/**
+ * UI Enhancements for the Swiper App
+ * Adds improved visual feedback and animations
+ */
+
+// Add swipe decision indicators
+function addSwipeDecisionIndicators() {
+ const swipeContainer = document.querySelector('.swipe-container');
+
+ // Create decision indicators for each direction
+ const directions = ['left', 'right', 'up', 'down'];
+ const icons = ['fa-trash', 'fa-folder-plus', 'fa-star', 'fa-clock'];
+
+ directions.forEach((direction, index) => {
+ const indicator = document.createElement('div');
+ indicator.className = `swipe-decision decision-${direction}`;
+ indicator.innerHTML = `
`;
+ swipeContainer.appendChild(indicator);
+ });
+}
+
+// Enhance loading indicator
+function enhanceLoadingIndicator() {
+ const loadingIndicator = document.querySelector('.loading-indicator');
+ if (loadingIndicator) {
+ loadingIndicator.innerHTML = `
+
+
Loading next image...
+ `;
+ }
+}
+
+// Add hover effects to direction arrows
+function enhanceDirectionArrows() {
+ const arrows = document.querySelectorAll('.direction-arrow');
+
+ arrows.forEach(arrow => {
+ arrow.addEventListener('mouseenter', function() {
+ this.style.transform = this.classList.contains('arrow-left') || this.classList.contains('arrow-right')
+ ? `translateY(-50%) scale(1.2)`
+ : `translateX(-50%) scale(1.2)`;
+ this.style.boxShadow = '0 10px 25px rgba(0, 0, 0, 0.2)';
+ });
+
+ arrow.addEventListener('mouseleave', function() {
+ this.style.transform = this.classList.contains('arrow-left') || this.classList.contains('arrow-right')
+ ? `translateY(-50%) scale(1)`
+ : `translateX(-50%) scale(1)`;
+ this.style.boxShadow = '0 5px 15px rgba(0, 0, 0, 0.1)';
+ });
+ });
+}
+
+// Show swipe decision indicator
+function showSwipeDecision(direction) {
+ const indicator = document.querySelector(`.decision-${direction}`);
+ if (indicator) {
+ indicator.classList.add('visible');
+
+ setTimeout(() => {
+ indicator.classList.remove('visible');
+ }, 800);
+ }
+}
+
+// Enhance the performSwipe function
+function enhancePerformSwipe() {
+ // Store the original performSwipe function
+ const originalPerformSwipe = window.performSwipe;
+
+ if (typeof originalPerformSwipe === 'function') {
+ // Override with enhanced version
+ window.performSwipe = function(direction) {
+ // Show the decision indicator
+ showSwipeDecision(direction);
+
+ // Call the original function
+ return originalPerformSwipe(direction);
+ };
+ }
+}
+
+// Add card tilt effect based on mouse position
+function addCardTiltEffect() {
+ const card = document.getElementById('current-card');
+ const container = document.querySelector('.swipe-container');
+
+ if (!card || !container) return;
+
+ container.addEventListener('mousemove', e => {
+ if (window.innerWidth < 992) return; // Skip on mobile
+
+ // Only apply when not dragging
+ if (window.state && window.state.isDragging) return;
+
+ const rect = container.getBoundingClientRect();
+ const x = e.clientX - rect.left;
+ const y = e.clientY - rect.top;
+
+ // Calculate rotation based on mouse position
+ const centerX = rect.width / 2;
+ const centerY = rect.height / 2;
+
+ const rotateY = ((x - centerX) / centerX) * 5; // Max 5 degrees
+ const rotateX = ((centerY - y) / centerY) * 5; // Max 5 degrees
+
+ // Apply the transform
+ card.style.transform = `perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`;
+ });
+
+ container.addEventListener('mouseleave', () => {
+ // Reset transform when mouse leaves
+ card.style.transform = '';
+ });
+}
+
+// Add pulse effect to action buttons
+function addButtonPulseEffect() {
+ const buttons = document.querySelectorAll('.action-btn');
+
+ buttons.forEach(button => {
+ button.addEventListener('mouseenter', function() {
+ this.classList.add('pulse');
+ });
+
+ button.addEventListener('mouseleave', function() {
+ this.classList.remove('pulse');
+ });
+ });
+
+ // Add the pulse animation to CSS
+ const style = document.createElement('style');
+ style.textContent = `
+ @keyframes pulse {
+ 0% { transform: scale(1); }
+ 50% { transform: scale(1.05); }
+ 100% { transform: scale(1); }
+ }
+
+ .action-btn.pulse {
+ animation: pulse 1s infinite;
+ }
+ `;
+ document.head.appendChild(style);
+}
+
+// Enhance the history page items
+function enhanceHistoryItems() {
+ if (!window.location.pathname.includes('history')) return;
+
+ // Add hover effect to selection items
+ const items = document.querySelectorAll('.selection-item');
+
+ items.forEach(item => {
+ // Add image zoom effect on hover
+ const img = item.querySelector('img');
+ if (img) {
+ img.style.transition = 'transform 0.3s ease';
+
+ item.addEventListener('mouseenter', () => {
+ img.style.transform = 'scale(1.1)';
+ });
+
+ item.addEventListener('mouseleave', () => {
+ img.style.transform = '';
+ });
+ }
+ });
+}
+
+// Initialize all UI enhancements
+function initUIEnhancements() {
+ // Add a small delay to ensure DOM is fully loaded
+ setTimeout(() => {
+ addSwipeDecisionIndicators();
+ enhanceLoadingIndicator();
+ enhanceDirectionArrows();
+ enhancePerformSwipe();
+ addCardTiltEffect();
+ addButtonPulseEffect();
+ enhanceHistoryItems();
+
+ console.log('UI enhancements initialized');
+ }, 500);
+}
+
+// Run when DOM is loaded
+document.addEventListener('DOMContentLoaded', initUIEnhancements);
+
+// Export functions for potential use in other modules
+export {
+ showSwipeDecision,
+ addSwipeDecisionIndicators,
+ enhanceLoadingIndicator
+};
diff --git a/js/utils.js b/js/utils.js
index bd27106..05df4a5 100644
--- a/js/utils.js
+++ b/js/utils.js
@@ -11,4 +11,21 @@ export function updateImageInfo(data) {
if (resolutionEl) {
resolutionEl.textContent = `Resolution: ${data.resolution || 'N/A'}`;
}
+ const filenameEl = document.getElementById('image-filename');
+ if (filenameEl) {
+ filenameEl.textContent = `Filename: ${data.filename || 'N/A'}`;
+ }
+ const creationEl = document.getElementById('image-creation-date');
+ if (creationEl) {
+ creationEl.textContent = `Created: ${data.creation_date || 'N/A'}`;
+ }
+ const promptEl = document.getElementById('image-prompt');
+ if (promptEl) {
+ // textarea uses value attribute
+ if (promptEl.tagName === 'TEXTAREA') {
+ promptEl.value = data.prompt_data || '';
+ } else {
+ promptEl.textContent = data.prompt_data || '';
+ }
+ }
}
diff --git a/node_modules/.package-lock.json b/node_modules/.package-lock.json
new file mode 100644
index 0000000..fee3130
--- /dev/null
+++ b/node_modules/.package-lock.json
@@ -0,0 +1,68 @@
+{
+ "name": "SWIPER",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "node_modules/framer-motion": {
+ "version": "12.18.1",
+ "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.18.1.tgz",
+ "integrity": "sha512-6o4EDuRPLk4LSZ1kRnnEOurbQ86MklVk+Y1rFBUKiF+d2pCdvMjWVu0ZkyMVCTwl5UyTH2n/zJEJx+jvTYuxow==",
+ "dependencies": {
+ "motion-dom": "^12.18.1",
+ "motion-utils": "^12.18.1",
+ "tslib": "^2.4.0"
+ },
+ "peerDependencies": {
+ "@emotion/is-prop-valid": "*",
+ "react": "^18.0.0 || ^19.0.0",
+ "react-dom": "^18.0.0 || ^19.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@emotion/is-prop-valid": {
+ "optional": true
+ },
+ "react": {
+ "optional": true
+ },
+ "react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/lucide-react": {
+ "version": "0.519.0",
+ "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.519.0.tgz",
+ "integrity": "sha512-cLJyjRKBJFzaZ/+1oIeQaH7XUdxKOYU3uANcGSrKdIZWElmNbRAm8RXKiTJS7AWLCBOS8b7A497Al/kCHozd+A==",
+ "peerDependencies": {
+ "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0"
+ }
+ },
+ "node_modules/motion-dom": {
+ "version": "12.18.1",
+ "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.18.1.tgz",
+ "integrity": "sha512-dR/4EYT23Snd+eUSLrde63Ws3oXQtJNw/krgautvTfwrN/2cHfCZMdu6CeTxVfRRWREW3Fy1f5vobRDiBb/q+w==",
+ "dependencies": {
+ "motion-utils": "^12.18.1"
+ }
+ },
+ "node_modules/motion-utils": {
+ "version": "12.18.1",
+ "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.18.1.tgz",
+ "integrity": "sha512-az26YDU4WoDP0ueAkUtABLk2BIxe28d8NH1qWT8jPGhPyf44XTdDUh8pDk9OPphaSrR9McgpcJlgwSOIw/sfkA=="
+ },
+ "node_modules/react": {
+ "version": "19.1.0",
+ "resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz",
+ "integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==",
+ "peer": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="
+ }
+ }
+}
diff --git a/node_modules/framer-motion/LICENSE.md b/node_modules/framer-motion/LICENSE.md
new file mode 100644
index 0000000..b5b8d6a
--- /dev/null
+++ b/node_modules/framer-motion/LICENSE.md
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2018 Framer B.V.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/node_modules/framer-motion/README.md b/node_modules/framer-motion/README.md
new file mode 100644
index 0000000..22e2ebc
--- /dev/null
+++ b/node_modules/framer-motion/README.md
@@ -0,0 +1,110 @@
+
+
+
+
Motion for React
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Motion for React is an open source, production-ready library that’s designed for all creative developers.
+
+It's the only animation library with a hybrid engine, combining the power of JavaScript animations with the performance of native browser APIs.
+
+It looks like this:
+
+```jsx
+
+```
+
+It does all this:
+
+- [Springs](https://motion.dev/docs/react-transitions#spring)
+- [Keyframes](https://motion.dev/docs/react-animation#keyframes)
+- [Layout animations](https://motion.dev/docs/react-layout-animations)
+- [Shared layout animations](https://motion.dev/docs/react-layout-animations#shared-layout-animations)
+- [Gestures (drag/tap/hover)](https://motion.dev/docs/react-gestures)
+- [Scroll animations](https://motion.dev/docs/react-scroll-animations)
+- [SVG paths](https://motion.dev/docs/react-animation#svg-line-drawing)
+- [Exit animations](https://motion.dev/docs/react-animation#exit-animations)
+- [Server-side rendering](https://motion.dev/docs/react-motion-component#server-side-rendering)
+- [Independent transforms](https://motion.dev/docs/react-motion-component#style)
+- [Orchestrate animations across components](https://motion.dev/docs/react-animation#orchestration)
+- [CSS variables](https://motion.dev/docs/react-animation#css-variables)
+
+...and a whole lot more.
+
+## Get started
+
+### 🐇 Quick start
+
+Install `motion` via your package manager:
+
+```
+npm install motion
+```
+
+Then import the `motion` component:
+
+```jsx
+import { motion } from "motion/react"
+
+export function Component({ isVisible }) {
+ return
+}
+```
+
+### 💎 Contribute
+
+- Want to contribute to Motion? Our [contributing guide](https://github.com/motiondivision/motion/blob/master/CONTRIBUTING.md) has you covered.
+
+### 👩🏻⚖️ License
+
+- Motion for React is MIT licensed.
+
+## ✨ Sponsors
+
+Motion is sustainable thanks to the kind support of its sponsors.
+
+### Partners
+
+#### Framer
+
+Motion powers Framer animations, the web builder for creative pros. Design and ship your dream site. Zero code, maximum speed.
+
+
+
+
+
+### Platinum
+
+

+
+### Gold
+
+

+
+### Silver
+
+

+
+### Personal
+
+- [OlegWock](https://sinja.io)
+- [Lambert Weller](https://github.com/l-mbert)
+- [Jake LeBoeuf](https://jklb.wf)
+- [Han Lee](https://github.com/hahnlee)
diff --git a/node_modules/framer-motion/client/README.md b/node_modules/framer-motion/client/README.md
new file mode 100644
index 0000000..00af8b4
--- /dev/null
+++ b/node_modules/framer-motion/client/README.md
@@ -0,0 +1 @@
+This directory is a fallback for `exports["./client"]` in the root `framer-motion` `package.json`.
diff --git a/node_modules/framer-motion/client/package.json b/node_modules/framer-motion/client/package.json
new file mode 100644
index 0000000..ed702d3
--- /dev/null
+++ b/node_modules/framer-motion/client/package.json
@@ -0,0 +1,6 @@
+{
+ "private": true,
+ "types": "../dist/types/client.d.ts",
+ "main": "../dist/cjs/client.js",
+ "module": "../dist/es/client.mjs"
+}
diff --git a/node_modules/framer-motion/dom/README.md b/node_modules/framer-motion/dom/README.md
new file mode 100644
index 0000000..9f4c437
--- /dev/null
+++ b/node_modules/framer-motion/dom/README.md
@@ -0,0 +1 @@
+This directory is a fallback for `exports["./dom"]` in the root `framer-motion` `package.json`.
diff --git a/node_modules/framer-motion/dom/mini/package.json b/node_modules/framer-motion/dom/mini/package.json
new file mode 100644
index 0000000..6d6ee8d
--- /dev/null
+++ b/node_modules/framer-motion/dom/mini/package.json
@@ -0,0 +1,6 @@
+{
+ "private": true,
+ "types": "../../dist/dom-mini.d.ts",
+ "main": "../../dist/cjs/dom-mini.js",
+ "module": "../../dist/es/dom-mini.mjs"
+}
diff --git a/node_modules/framer-motion/dom/package.json b/node_modules/framer-motion/dom/package.json
new file mode 100644
index 0000000..c08f91c
--- /dev/null
+++ b/node_modules/framer-motion/dom/package.json
@@ -0,0 +1,6 @@
+{
+ "private": true,
+ "types": "../dist/dom.d.ts",
+ "main": "../dist/cjs/dom.js",
+ "module": "../dist/es/dom.mjs"
+}
diff --git a/node_modules/framer-motion/m/package.json b/node_modules/framer-motion/m/package.json
new file mode 100644
index 0000000..5e76408
--- /dev/null
+++ b/node_modules/framer-motion/m/package.json
@@ -0,0 +1,6 @@
+{
+ "private": true,
+ "types": "../dist/m.d.ts",
+ "main": "../dist/cjs/m.js",
+ "module": "../dist/es/m.mjs"
+}
diff --git a/node_modules/framer-motion/mini/package.json b/node_modules/framer-motion/mini/package.json
new file mode 100644
index 0000000..1ed4407
--- /dev/null
+++ b/node_modules/framer-motion/mini/package.json
@@ -0,0 +1,6 @@
+{
+ "private": true,
+ "types": "../dist/mini.d.ts",
+ "main": "../dist/cjs/mini.js",
+ "module": "../dist/es/mini.mjs"
+}
diff --git a/node_modules/framer-motion/package.json b/node_modules/framer-motion/package.json
new file mode 100644
index 0000000..6dbad9c
--- /dev/null
+++ b/node_modules/framer-motion/package.json
@@ -0,0 +1,146 @@
+{
+ "name": "framer-motion",
+ "version": "12.18.1",
+ "description": "A simple and powerful JavaScript animation library",
+ "main": "dist/cjs/index.js",
+ "module": "dist/es/index.mjs",
+ "exports": {
+ ".": {
+ "types": "./dist/types/index.d.ts",
+ "require": "./dist/cjs/index.js",
+ "import": "./dist/es/index.mjs",
+ "default": "./dist/cjs/index.js"
+ },
+ "./debug": {
+ "types": "./dist/debug.d.ts",
+ "require": "./dist/cjs/debug.js",
+ "import": "./dist/es/debug.mjs",
+ "default": "./dist/cjs/debug.js"
+ },
+ "./dom/mini": {
+ "types": "./dist/dom-mini.d.ts",
+ "require": "./dist/cjs/dom-mini.js",
+ "import": "./dist/es/dom-mini.mjs",
+ "default": "./dist/cjs/dom-mini.js"
+ },
+ "./dom": {
+ "types": "./dist/dom.d.ts",
+ "require": "./dist/cjs/dom.js",
+ "import": "./dist/es/dom.mjs",
+ "default": "./dist/cjs/dom.js"
+ },
+ "./client": {
+ "types": "./dist/types/client.d.ts",
+ "require": "./dist/cjs/client.js",
+ "import": "./dist/es/client.mjs",
+ "default": "./dist/cjs/client.js"
+ },
+ "./m": {
+ "types": "./dist/m.d.ts",
+ "require": "./dist/cjs/m.js",
+ "import": "./dist/es/m.mjs",
+ "default": "./dist/cjs/m.js"
+ },
+ "./mini": {
+ "types": "./dist/mini.d.ts",
+ "require": "./dist/cjs/mini.js",
+ "import": "./dist/es/mini.mjs",
+ "default": "./dist/cjs/mini.js"
+ },
+ "./projection": {
+ "import": "./dist/es/projection.mjs",
+ "default": "./dist/es/projection.mjs"
+ },
+ "./package.json": "./package.json"
+ },
+ "types": "dist/types/index.d.ts",
+ "author": "Matt Perry",
+ "license": "MIT",
+ "repository": "https://github.com/motiondivision/motion/",
+ "sideEffects": false,
+ "keywords": [
+ "react animation",
+ "react",
+ "pose",
+ "react pose",
+ "animation",
+ "gestures",
+ "drag",
+ "spring",
+ "popmotion",
+ "framer",
+ "waapi"
+ ],
+ "scripts": {
+ "eslint": "yarn run lint",
+ "lint": "yarn eslint src/**/*.ts",
+ "build": "yarn clean && tsc --noEmitOnError -p . && rollup -c && node ./scripts/check-bundle.js",
+ "dev": "yarn watch",
+ "clean": "rm -rf types dist lib",
+ "test": "yarn test-server && yarn test-client",
+ "test-client": "jest --config jest.config.json --max-workers=2",
+ "test-server": "jest --config jest.config.ssr.json",
+ "prettier": "prettier ./src/* --write",
+ "watch": "concurrently -c blue,red -n tsc --noEmitOnError ,rollup --kill-others \"tsc --noEmitOnError --watch -p . --preserveWatchOutput\" \"rollup --config --watch --no-watch.clearScreen\"",
+ "prepack": "yarn build && yarn measure",
+ "postpublish": "git push --tags",
+ "measure": "rollup -c ./rollup.size.config.mjs"
+ },
+ "dependencies": {
+ "motion-dom": "^12.18.1",
+ "motion-utils": "^12.18.1",
+ "tslib": "^2.4.0"
+ },
+ "devDependencies": {
+ "@thednp/dommatrix": "^2.0.11",
+ "@types/three": "0.137.0",
+ "three": "0.137.0"
+ },
+ "peerDependencies": {
+ "@emotion/is-prop-valid": "*",
+ "react": "^18.0.0 || ^19.0.0",
+ "react-dom": "^18.0.0 || ^19.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@emotion/is-prop-valid": {
+ "optional": true
+ },
+ "react": {
+ "optional": true
+ },
+ "react-dom": {
+ "optional": true
+ }
+ },
+ "bundlesize": [
+ {
+ "path": "./dist/size-rollup-motion.js",
+ "maxSize": "34.9 kB"
+ },
+ {
+ "path": "./dist/size-rollup-m.js",
+ "maxSize": "6 kB"
+ },
+ {
+ "path": "./dist/size-rollup-dom-animation.js",
+ "maxSize": "17.85 kB"
+ },
+ {
+ "path": "./dist/size-rollup-dom-max.js",
+ "maxSize": "29.8 kB"
+ },
+ {
+ "path": "./dist/size-rollup-animate.js",
+ "maxSize": "19.1 kB"
+ },
+ {
+ "path": "./dist/size-rollup-scroll.js",
+ "maxSize": "5.2 kB"
+ },
+ {
+ "path": "./dist/size-rollup-waapi-animate.js",
+ "maxSize": "2.26 kB"
+ }
+ ],
+ "gitHead": "f3102d56a0a1a84aab20563f97e7976b6c8612df"
+}
diff --git a/node_modules/lucide-react/LICENSE b/node_modules/lucide-react/LICENSE
new file mode 100644
index 0000000..325e8ff
--- /dev/null
+++ b/node_modules/lucide-react/LICENSE
@@ -0,0 +1,15 @@
+ISC License
+
+Copyright (c) for portions of Lucide are held by Cole Bemis 2013-2022 as part of Feather (MIT). All other copyright (c) for Lucide are held by Lucide Contributors 2022.
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/node_modules/lucide-react/README.md b/node_modules/lucide-react/README.md
new file mode 100644
index 0000000..8d02efe
--- /dev/null
+++ b/node_modules/lucide-react/README.md
@@ -0,0 +1,73 @@
+
+
+
+
+
+
+
+Lucide icon library for React applications.
+
+
+
+
+ [](https://www.npmjs.com/package/lucide-react)
+ 
+ [](https://lucide.dev/license)
+
+
+
+ About
+ ·
+ Icons
+ ·
+ Documentation
+ ·
+ License
+
+
+# Lucide React
+
+Implementation of the lucide icon library for React applications.
+
+## Installation
+
+```sh
+pnpm add lucide-react
+```
+
+```sh
+npm install lucide-react
+```
+
+```sh
+yarn add lucide-react
+```
+
+```sh
+bun add lucide-react
+```
+
+## Documentation
+
+For full documentation, visit [lucide.dev](https://lucide.dev/guide/packages/lucide-react)
+
+## Community
+
+Join the [Discord server](https://discord.gg/EH6nSts) to chat with the maintainers and other users.
+
+## License
+
+Lucide is licensed under the ISC license. See [LICENSE](https://lucide.dev/license).
+
+## Sponsors
+
+
+
+
+
+

+
+### Awesome backers 🍺
+
+

+

diff --git a/node_modules/lucide-react/dynamic.d.ts b/node_modules/lucide-react/dynamic.d.ts
new file mode 100644
index 0000000..0db4d6e
--- /dev/null
+++ b/node_modules/lucide-react/dynamic.d.ts
@@ -0,0 +1,35576 @@
+import * as react from 'react';
+import { RefAttributes, SVGProps, ForwardRefExoticComponent } from 'react';
+
+/**
+ * A reduced version of `SVGElementType` from @types/react. This type was added
+ * with the release of React 19, and is included here in order to support usage
+ * with older versions.
+ */
+type SVGElementType = 'circle' | 'ellipse' | 'g' | 'line' | 'path' | 'polygon' | 'polyline' | 'rect';
+type IconNode = [elementName: SVGElementType, attrs: Record
][];
+type SVGAttributes = Partial>;
+type ElementAttributes = RefAttributes & SVGAttributes;
+interface LucideProps extends ElementAttributes {
+ size?: string | number;
+ absoluteStrokeWidth?: boolean;
+}
+type LucideIcon = ForwardRefExoticComponent & RefAttributes>;
+
+declare const __iconNode$p4: IconNode;
+/**
+ * @component @name ZoomOut
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/zoom-out
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const ZoomOut: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_zoom_out {
+ export {
+ __iconNode$p4 as __iconNode,
+ ZoomOut as default,
+ };
+}
+
+declare const __iconNode$p3: IconNode;
+/**
+ * @component @name ZoomIn
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/zoom-in
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const ZoomIn: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_zoom_in {
+ export {
+ __iconNode$p3 as __iconNode,
+ ZoomIn as default,
+ };
+}
+
+declare const __iconNode$p2: IconNode;
+/**
+ * @component @name Zap
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/zap
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Zap: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_zap {
+ export {
+ __iconNode$p2 as __iconNode,
+ Zap as default,
+ };
+}
+
+declare const __iconNode$p1: IconNode;
+/**
+ * @component @name ZapOff
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/zap-off
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const ZapOff: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_zap_off {
+ export {
+ __iconNode$p1 as __iconNode,
+ ZapOff as default,
+ };
+}
+
+declare const __iconNode$p0: IconNode;
+/**
+ * @component @name Youtube
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/youtube
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ * @deprecated Brand icons have been deprecated and are due to be removed, please refer to https://github.com/lucide-icons/lucide/issues/670. We recommend using https://simpleicons.org/?q=youtube instead. This icon will be removed in v1.0
+ */
+declare const Youtube: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_youtube {
+ export {
+ __iconNode$p0 as __iconNode,
+ Youtube as default,
+ };
+}
+
+declare const __iconNode$o$: IconNode;
+/**
+ * @component @name X
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/x
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const X: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_x {
+ export {
+ __iconNode$o$ as __iconNode,
+ X as default,
+ };
+}
+
+declare const __iconNode$o_: IconNode;
+/**
+ * @component @name Wrench
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/wrench
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Wrench: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_wrench {
+ export {
+ __iconNode$o_ as __iconNode,
+ Wrench as default,
+ };
+}
+
+declare const __iconNode$oZ: IconNode;
+/**
+ * @component @name WrapText
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/wrap-text
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const WrapText: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_wrap_text {
+ export {
+ __iconNode$oZ as __iconNode,
+ WrapText as default,
+ };
+}
+
+declare const __iconNode$oY: IconNode;
+/**
+ * @component @name Worm
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/worm
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Worm: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_worm {
+ export {
+ __iconNode$oY as __iconNode,
+ Worm as default,
+ };
+}
+
+declare const __iconNode$oX: IconNode;
+/**
+ * @component @name Workflow
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/workflow
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Workflow: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_workflow {
+ export {
+ __iconNode$oX as __iconNode,
+ Workflow as default,
+ };
+}
+
+declare const __iconNode$oW: IconNode;
+/**
+ * @component @name Wine
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/wine
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Wine: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_wine {
+ export {
+ __iconNode$oW as __iconNode,
+ Wine as default,
+ };
+}
+
+declare const __iconNode$oV: IconNode;
+/**
+ * @component @name WineOff
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/wine-off
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const WineOff: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_wine_off {
+ export {
+ __iconNode$oV as __iconNode,
+ WineOff as default,
+ };
+}
+
+declare const __iconNode$oU: IconNode;
+/**
+ * @component @name Wind
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/wind
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Wind: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_wind {
+ export {
+ __iconNode$oU as __iconNode,
+ Wind as default,
+ };
+}
+
+declare const __iconNode$oT: IconNode;
+/**
+ * @component @name WindArrowDown
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/wind-arrow-down
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const WindArrowDown: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_wind_arrow_down {
+ export {
+ __iconNode$oT as __iconNode,
+ WindArrowDown as default,
+ };
+}
+
+declare const __iconNode$oS: IconNode;
+/**
+ * @component @name Wifi
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/wifi
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Wifi: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_wifi {
+ export {
+ __iconNode$oS as __iconNode,
+ Wifi as default,
+ };
+}
+
+declare const __iconNode$oR: IconNode;
+/**
+ * @component @name WifiZero
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/wifi-zero
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const WifiZero: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_wifi_zero {
+ export {
+ __iconNode$oR as __iconNode,
+ WifiZero as default,
+ };
+}
+
+declare const __iconNode$oQ: IconNode;
+/**
+ * @component @name WifiPen
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/wifi-pen
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const WifiPen: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_wifi_pen {
+ export {
+ __iconNode$oQ as __iconNode,
+ WifiPen as default,
+ };
+}
+
+declare const __iconNode$oP: IconNode;
+/**
+ * @component @name WifiOff
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/wifi-off
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const WifiOff: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_wifi_off {
+ export {
+ __iconNode$oP as __iconNode,
+ WifiOff as default,
+ };
+}
+
+declare const __iconNode$oO: IconNode;
+/**
+ * @component @name WifiLow
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/wifi-low
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const WifiLow: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_wifi_low {
+ export {
+ __iconNode$oO as __iconNode,
+ WifiLow as default,
+ };
+}
+
+declare const __iconNode$oN: IconNode;
+/**
+ * @component @name WifiHigh
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/wifi-high
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const WifiHigh: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_wifi_high {
+ export {
+ __iconNode$oN as __iconNode,
+ WifiHigh as default,
+ };
+}
+
+declare const __iconNode$oM: IconNode;
+/**
+ * @component @name WifiCog
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/wifi-cog
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const WifiCog: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_wifi_cog {
+ export {
+ __iconNode$oM as __iconNode,
+ WifiCog as default,
+ };
+}
+
+declare const __iconNode$oL: IconNode;
+/**
+ * @component @name WholeWord
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/whole-word
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const WholeWord: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_whole_word {
+ export {
+ __iconNode$oL as __iconNode,
+ WholeWord as default,
+ };
+}
+
+declare const __iconNode$oK: IconNode;
+/**
+ * @component @name Wheat
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/wheat
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Wheat: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_wheat {
+ export {
+ __iconNode$oK as __iconNode,
+ Wheat as default,
+ };
+}
+
+declare const __iconNode$oJ: IconNode;
+/**
+ * @component @name WheatOff
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/wheat-off
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const WheatOff: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_wheat_off {
+ export {
+ __iconNode$oJ as __iconNode,
+ WheatOff as default,
+ };
+}
+
+declare const __iconNode$oI: IconNode;
+/**
+ * @component @name Weight
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/weight
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Weight: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_weight {
+ export {
+ __iconNode$oI as __iconNode,
+ Weight as default,
+ };
+}
+
+declare const __iconNode$oH: IconNode;
+/**
+ * @component @name Webhook
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/webhook
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Webhook: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_webhook {
+ export {
+ __iconNode$oH as __iconNode,
+ Webhook as default,
+ };
+}
+
+declare const __iconNode$oG: IconNode;
+/**
+ * @component @name WebhookOff
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/webhook-off
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const WebhookOff: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_webhook_off {
+ export {
+ __iconNode$oG as __iconNode,
+ WebhookOff as default,
+ };
+}
+
+declare const __iconNode$oF: IconNode;
+/**
+ * @component @name Webcam
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/webcam
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Webcam: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_webcam {
+ export {
+ __iconNode$oF as __iconNode,
+ Webcam as default,
+ };
+}
+
+declare const __iconNode$oE: IconNode;
+/**
+ * @component @name Waypoints
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/waypoints
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Waypoints: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_waypoints {
+ export {
+ __iconNode$oE as __iconNode,
+ Waypoints as default,
+ };
+}
+
+declare const __iconNode$oD: IconNode;
+/**
+ * @component @name Waves
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/waves
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Waves: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_waves {
+ export {
+ __iconNode$oD as __iconNode,
+ Waves as default,
+ };
+}
+
+declare const __iconNode$oC: IconNode;
+/**
+ * @component @name WavesLadder
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/waves-ladder
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const WavesLadder: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_waves_ladder {
+ export {
+ __iconNode$oC as __iconNode,
+ WavesLadder as default,
+ };
+}
+
+declare const __iconNode$oB: IconNode;
+/**
+ * @component @name Watch
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/watch
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Watch: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_watch {
+ export {
+ __iconNode$oB as __iconNode,
+ Watch as default,
+ };
+}
+
+declare const __iconNode$oA: IconNode;
+/**
+ * @component @name WashingMachine
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/washing-machine
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const WashingMachine: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_washing_machine {
+ export {
+ __iconNode$oA as __iconNode,
+ WashingMachine as default,
+ };
+}
+
+declare const __iconNode$oz: IconNode;
+/**
+ * @component @name Warehouse
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/warehouse
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Warehouse: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_warehouse {
+ export {
+ __iconNode$oz as __iconNode,
+ Warehouse as default,
+ };
+}
+
+declare const __iconNode$oy: IconNode;
+/**
+ * @component @name Wand
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/wand
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Wand: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_wand {
+ export {
+ __iconNode$oy as __iconNode,
+ Wand as default,
+ };
+}
+
+declare const __iconNode$ox: IconNode;
+/**
+ * @component @name WandSparkles
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/wand-sparkles
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const WandSparkles: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_wand_sparkles {
+ export {
+ __iconNode$ox as __iconNode,
+ WandSparkles as default,
+ };
+}
+
+declare const __iconNode$ow: IconNode;
+/**
+ * @component @name Wallpaper
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/wallpaper
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Wallpaper: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_wallpaper {
+ export {
+ __iconNode$ow as __iconNode,
+ Wallpaper as default,
+ };
+}
+
+declare const __iconNode$ov: IconNode;
+/**
+ * @component @name Wallet
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/wallet
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Wallet: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_wallet {
+ export {
+ __iconNode$ov as __iconNode,
+ Wallet as default,
+ };
+}
+
+declare const __iconNode$ou: IconNode;
+/**
+ * @component @name WalletMinimal
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/wallet-minimal
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const WalletMinimal: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_wallet_minimal {
+ export {
+ __iconNode$ou as __iconNode,
+ WalletMinimal as default,
+ };
+}
+
+declare const __iconNode$ot: IconNode;
+/**
+ * @component @name WalletCards
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/wallet-cards
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const WalletCards: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_wallet_cards {
+ export {
+ __iconNode$ot as __iconNode,
+ WalletCards as default,
+ };
+}
+
+declare const __iconNode$os: IconNode;
+/**
+ * @component @name Vote
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/vote
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Vote: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_vote {
+ export {
+ __iconNode$os as __iconNode,
+ Vote as default,
+ };
+}
+
+declare const __iconNode$or: IconNode;
+/**
+ * @component @name Volume
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/volume
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Volume: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_volume {
+ export {
+ __iconNode$or as __iconNode,
+ Volume as default,
+ };
+}
+
+declare const __iconNode$oq: IconNode;
+/**
+ * @component @name VolumeX
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/volume-x
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const VolumeX: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_volume_x {
+ export {
+ __iconNode$oq as __iconNode,
+ VolumeX as default,
+ };
+}
+
+declare const __iconNode$op: IconNode;
+/**
+ * @component @name VolumeOff
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/volume-off
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const VolumeOff: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_volume_off {
+ export {
+ __iconNode$op as __iconNode,
+ VolumeOff as default,
+ };
+}
+
+declare const __iconNode$oo: IconNode;
+/**
+ * @component @name Volume2
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/volume-2
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Volume2: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_volume_2 {
+ export {
+ __iconNode$oo as __iconNode,
+ Volume2 as default,
+ };
+}
+
+declare const __iconNode$on: IconNode;
+/**
+ * @component @name Volume1
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/volume-1
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Volume1: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_volume_1 {
+ export {
+ __iconNode$on as __iconNode,
+ Volume1 as default,
+ };
+}
+
+declare const __iconNode$om: IconNode;
+/**
+ * @component @name Volleyball
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/volleyball
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Volleyball: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_volleyball {
+ export {
+ __iconNode$om as __iconNode,
+ Volleyball as default,
+ };
+}
+
+declare const __iconNode$ol: IconNode;
+/**
+ * @component @name Voicemail
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/voicemail
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Voicemail: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_voicemail {
+ export {
+ __iconNode$ol as __iconNode,
+ Voicemail as default,
+ };
+}
+
+declare const __iconNode$ok: IconNode;
+/**
+ * @component @name View
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/view
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const View: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_view {
+ export {
+ __iconNode$ok as __iconNode,
+ View as default,
+ };
+}
+
+declare const __iconNode$oj: IconNode;
+/**
+ * @component @name Videotape
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/videotape
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Videotape: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_videotape {
+ export {
+ __iconNode$oj as __iconNode,
+ Videotape as default,
+ };
+}
+
+declare const __iconNode$oi: IconNode;
+/**
+ * @component @name Video
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/video
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Video: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_video {
+ export {
+ __iconNode$oi as __iconNode,
+ Video as default,
+ };
+}
+
+declare const __iconNode$oh: IconNode;
+/**
+ * @component @name VideoOff
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/video-off
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const VideoOff: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_video_off {
+ export {
+ __iconNode$oh as __iconNode,
+ VideoOff as default,
+ };
+}
+
+declare const __iconNode$og: IconNode;
+/**
+ * @component @name Vibrate
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/vibrate
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Vibrate: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_vibrate {
+ export {
+ __iconNode$og as __iconNode,
+ Vibrate as default,
+ };
+}
+
+declare const __iconNode$of: IconNode;
+/**
+ * @component @name VibrateOff
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/vibrate-off
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const VibrateOff: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_vibrate_off {
+ export {
+ __iconNode$of as __iconNode,
+ VibrateOff as default,
+ };
+}
+
+declare const __iconNode$oe: IconNode;
+/**
+ * @component @name Venus
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/venus
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Venus: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_venus {
+ export {
+ __iconNode$oe as __iconNode,
+ Venus as default,
+ };
+}
+
+declare const __iconNode$od: IconNode;
+/**
+ * @component @name VenusAndMars
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/venus-and-mars
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const VenusAndMars: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_venus_and_mars {
+ export {
+ __iconNode$od as __iconNode,
+ VenusAndMars as default,
+ };
+}
+
+declare const __iconNode$oc: IconNode;
+/**
+ * @component @name VenetianMask
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/venetian-mask
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const VenetianMask: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_venetian_mask {
+ export {
+ __iconNode$oc as __iconNode,
+ VenetianMask as default,
+ };
+}
+
+declare const __iconNode$ob: IconNode;
+/**
+ * @component @name Vegan
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/vegan
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Vegan: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_vegan {
+ export {
+ __iconNode$ob as __iconNode,
+ Vegan as default,
+ };
+}
+
+declare const __iconNode$oa: IconNode;
+/**
+ * @component @name Vault
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/vault
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Vault: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_vault {
+ export {
+ __iconNode$oa as __iconNode,
+ Vault as default,
+ };
+}
+
+declare const __iconNode$o9: IconNode;
+/**
+ * @component @name Variable
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/variable
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Variable: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_variable {
+ export {
+ __iconNode$o9 as __iconNode,
+ Variable as default,
+ };
+}
+
+declare const __iconNode$o8: IconNode;
+/**
+ * @component @name UtilityPole
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/utility-pole
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const UtilityPole: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_utility_pole {
+ export {
+ __iconNode$o8 as __iconNode,
+ UtilityPole as default,
+ };
+}
+
+declare const __iconNode$o7: IconNode;
+/**
+ * @component @name Utensils
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/utensils
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Utensils: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_utensils {
+ export {
+ __iconNode$o7 as __iconNode,
+ Utensils as default,
+ };
+}
+
+declare const __iconNode$o6: IconNode;
+/**
+ * @component @name UtensilsCrossed
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/utensils-crossed
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const UtensilsCrossed: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_utensils_crossed {
+ export {
+ __iconNode$o6 as __iconNode,
+ UtensilsCrossed as default,
+ };
+}
+
+declare const __iconNode$o5: IconNode;
+/**
+ * @component @name Users
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/users
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Users: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_users {
+ export {
+ __iconNode$o5 as __iconNode,
+ Users as default,
+ };
+}
+
+declare const __iconNode$o4: IconNode;
+/**
+ * @component @name UsersRound
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/users-round
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const UsersRound: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_users_round {
+ export {
+ __iconNode$o4 as __iconNode,
+ UsersRound as default,
+ };
+}
+
+declare const __iconNode$o3: IconNode;
+/**
+ * @component @name User
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/user
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const User: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_user {
+ export {
+ __iconNode$o3 as __iconNode,
+ User as default,
+ };
+}
+
+declare const __iconNode$o2: IconNode;
+/**
+ * @component @name UserX
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/user-x
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const UserX: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_user_x {
+ export {
+ __iconNode$o2 as __iconNode,
+ UserX as default,
+ };
+}
+
+declare const __iconNode$o1: IconNode;
+/**
+ * @component @name UserSearch
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/user-search
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const UserSearch: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_user_search {
+ export {
+ __iconNode$o1 as __iconNode,
+ UserSearch as default,
+ };
+}
+
+declare const __iconNode$o0: IconNode;
+/**
+ * @component @name UserRound
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/user-round
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const UserRound: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_user_round {
+ export {
+ __iconNode$o0 as __iconNode,
+ UserRound as default,
+ };
+}
+
+declare const __iconNode$n$: IconNode;
+/**
+ * @component @name UserRoundX
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/user-round-x
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const UserRoundX: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_user_round_x {
+ export {
+ __iconNode$n$ as __iconNode,
+ UserRoundX as default,
+ };
+}
+
+declare const __iconNode$n_: IconNode;
+/**
+ * @component @name UserRoundSearch
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/user-round-search
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const UserRoundSearch: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_user_round_search {
+ export {
+ __iconNode$n_ as __iconNode,
+ UserRoundSearch as default,
+ };
+}
+
+declare const __iconNode$nZ: IconNode;
+/**
+ * @component @name UserRoundPlus
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/user-round-plus
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const UserRoundPlus: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_user_round_plus {
+ export {
+ __iconNode$nZ as __iconNode,
+ UserRoundPlus as default,
+ };
+}
+
+declare const __iconNode$nY: IconNode;
+/**
+ * @component @name UserRoundPen
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/user-round-pen
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const UserRoundPen: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_user_round_pen {
+ export {
+ __iconNode$nY as __iconNode,
+ UserRoundPen as default,
+ };
+}
+
+declare const __iconNode$nX: IconNode;
+/**
+ * @component @name UserRoundMinus
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/user-round-minus
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const UserRoundMinus: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_user_round_minus {
+ export {
+ __iconNode$nX as __iconNode,
+ UserRoundMinus as default,
+ };
+}
+
+declare const __iconNode$nW: IconNode;
+/**
+ * @component @name UserRoundCog
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/user-round-cog
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const UserRoundCog: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_user_round_cog {
+ export {
+ __iconNode$nW as __iconNode,
+ UserRoundCog as default,
+ };
+}
+
+declare const __iconNode$nV: IconNode;
+/**
+ * @component @name UserRoundCheck
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/user-round-check
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const UserRoundCheck: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_user_round_check {
+ export {
+ __iconNode$nV as __iconNode,
+ UserRoundCheck as default,
+ };
+}
+
+declare const __iconNode$nU: IconNode;
+/**
+ * @component @name UserPlus
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/user-plus
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const UserPlus: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_user_plus {
+ export {
+ __iconNode$nU as __iconNode,
+ UserPlus as default,
+ };
+}
+
+declare const __iconNode$nT: IconNode;
+/**
+ * @component @name UserPen
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/user-pen
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const UserPen: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_user_pen {
+ export {
+ __iconNode$nT as __iconNode,
+ UserPen as default,
+ };
+}
+
+declare const __iconNode$nS: IconNode;
+/**
+ * @component @name UserMinus
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/user-minus
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const UserMinus: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_user_minus {
+ export {
+ __iconNode$nS as __iconNode,
+ UserMinus as default,
+ };
+}
+
+declare const __iconNode$nR: IconNode;
+/**
+ * @component @name UserLock
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/user-lock
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const UserLock: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_user_lock {
+ export {
+ __iconNode$nR as __iconNode,
+ UserLock as default,
+ };
+}
+
+declare const __iconNode$nQ: IconNode;
+/**
+ * @component @name UserCog
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/user-cog
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const UserCog: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_user_cog {
+ export {
+ __iconNode$nQ as __iconNode,
+ UserCog as default,
+ };
+}
+
+declare const __iconNode$nP: IconNode;
+/**
+ * @component @name UserCheck
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/user-check
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const UserCheck: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_user_check {
+ export {
+ __iconNode$nP as __iconNode,
+ UserCheck as default,
+ };
+}
+
+declare const __iconNode$nO: IconNode;
+/**
+ * @component @name Usb
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/usb
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Usb: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_usb {
+ export {
+ __iconNode$nO as __iconNode,
+ Usb as default,
+ };
+}
+
+declare const __iconNode$nN: IconNode;
+/**
+ * @component @name Upload
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/upload
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Upload: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_upload {
+ export {
+ __iconNode$nN as __iconNode,
+ Upload as default,
+ };
+}
+
+declare const __iconNode$nM: IconNode;
+/**
+ * @component @name Unplug
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/unplug
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Unplug: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_unplug {
+ export {
+ __iconNode$nM as __iconNode,
+ Unplug as default,
+ };
+}
+
+declare const __iconNode$nL: IconNode;
+/**
+ * @component @name Unlink
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/unlink
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Unlink: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_unlink {
+ export {
+ __iconNode$nL as __iconNode,
+ Unlink as default,
+ };
+}
+
+declare const __iconNode$nK: IconNode;
+/**
+ * @component @name Unlink2
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/unlink-2
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Unlink2: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_unlink_2 {
+ export {
+ __iconNode$nK as __iconNode,
+ Unlink2 as default,
+ };
+}
+
+declare const __iconNode$nJ: IconNode;
+/**
+ * @component @name University
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/university
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const University: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_university {
+ export {
+ __iconNode$nJ as __iconNode,
+ University as default,
+ };
+}
+
+declare const __iconNode$nI: IconNode;
+/**
+ * @component @name Ungroup
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/ungroup
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Ungroup: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_ungroup {
+ export {
+ __iconNode$nI as __iconNode,
+ Ungroup as default,
+ };
+}
+
+declare const __iconNode$nH: IconNode;
+/**
+ * @component @name UnfoldVertical
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/unfold-vertical
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const UnfoldVertical: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_unfold_vertical {
+ export {
+ __iconNode$nH as __iconNode,
+ UnfoldVertical as default,
+ };
+}
+
+declare const __iconNode$nG: IconNode;
+/**
+ * @component @name UnfoldHorizontal
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/unfold-horizontal
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const UnfoldHorizontal: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_unfold_horizontal {
+ export {
+ __iconNode$nG as __iconNode,
+ UnfoldHorizontal as default,
+ };
+}
+
+declare const __iconNode$nF: IconNode;
+/**
+ * @component @name Undo
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/undo
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Undo: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_undo {
+ export {
+ __iconNode$nF as __iconNode,
+ Undo as default,
+ };
+}
+
+declare const __iconNode$nE: IconNode;
+/**
+ * @component @name UndoDot
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/undo-dot
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const UndoDot: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_undo_dot {
+ export {
+ __iconNode$nE as __iconNode,
+ UndoDot as default,
+ };
+}
+
+declare const __iconNode$nD: IconNode;
+/**
+ * @component @name Undo2
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/undo-2
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Undo2: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_undo_2 {
+ export {
+ __iconNode$nD as __iconNode,
+ Undo2 as default,
+ };
+}
+
+declare const __iconNode$nC: IconNode;
+/**
+ * @component @name Underline
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/underline
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Underline: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_underline {
+ export {
+ __iconNode$nC as __iconNode,
+ Underline as default,
+ };
+}
+
+declare const __iconNode$nB: IconNode;
+/**
+ * @component @name Umbrella
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/umbrella
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Umbrella: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_umbrella {
+ export {
+ __iconNode$nB as __iconNode,
+ Umbrella as default,
+ };
+}
+
+declare const __iconNode$nA: IconNode;
+/**
+ * @component @name UmbrellaOff
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/umbrella-off
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const UmbrellaOff: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_umbrella_off {
+ export {
+ __iconNode$nA as __iconNode,
+ UmbrellaOff as default,
+ };
+}
+
+declare const __iconNode$nz: IconNode;
+/**
+ * @component @name Type
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/type
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Type: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_type {
+ export {
+ __iconNode$nz as __iconNode,
+ Type as default,
+ };
+}
+
+declare const __iconNode$ny: IconNode;
+/**
+ * @component @name TypeOutline
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/type-outline
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const TypeOutline: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_type_outline {
+ export {
+ __iconNode$ny as __iconNode,
+ TypeOutline as default,
+ };
+}
+
+declare const __iconNode$nx: IconNode;
+/**
+ * @component @name Twitter
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/twitter
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ * @deprecated Brand icons have been deprecated and are due to be removed, please refer to https://github.com/lucide-icons/lucide/issues/670. We recommend using https://simpleicons.org/?q=twitter instead. This icon will be removed in v1.0
+ */
+declare const Twitter: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_twitter {
+ export {
+ __iconNode$nx as __iconNode,
+ Twitter as default,
+ };
+}
+
+declare const __iconNode$nw: IconNode;
+/**
+ * @component @name Twitch
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/twitch
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ * @deprecated Brand icons have been deprecated and are due to be removed, please refer to https://github.com/lucide-icons/lucide/issues/670. We recommend using https://simpleicons.org/?q=twitch instead. This icon will be removed in v1.0
+ */
+declare const Twitch: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_twitch {
+ export {
+ __iconNode$nw as __iconNode,
+ Twitch as default,
+ };
+}
+
+declare const __iconNode$nv: IconNode;
+/**
+ * @component @name Tv
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/tv
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Tv: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_tv {
+ export {
+ __iconNode$nv as __iconNode,
+ Tv as default,
+ };
+}
+
+declare const __iconNode$nu: IconNode;
+/**
+ * @component @name TvMinimal
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/tv-minimal
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const TvMinimal: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_tv_minimal {
+ export {
+ __iconNode$nu as __iconNode,
+ TvMinimal as default,
+ };
+}
+
+declare const __iconNode$nt: IconNode;
+/**
+ * @component @name TvMinimalPlay
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/tv-minimal-play
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const TvMinimalPlay: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_tv_minimal_play {
+ export {
+ __iconNode$nt as __iconNode,
+ TvMinimalPlay as default,
+ };
+}
+
+declare const __iconNode$ns: IconNode;
+/**
+ * @component @name Turtle
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/turtle
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Turtle: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_turtle {
+ export {
+ __iconNode$ns as __iconNode,
+ Turtle as default,
+ };
+}
+
+declare const __iconNode$nr: IconNode;
+/**
+ * @component @name Truck
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/truck
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Truck: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_truck {
+ export {
+ __iconNode$nr as __iconNode,
+ Truck as default,
+ };
+}
+
+declare const __iconNode$nq: IconNode;
+/**
+ * @component @name TruckElectric
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/truck-electric
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const TruckElectric: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_truck_electric {
+ export {
+ __iconNode$nq as __iconNode,
+ TruckElectric as default,
+ };
+}
+
+declare const __iconNode$np: IconNode;
+/**
+ * @component @name Trophy
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/trophy
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Trophy: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_trophy {
+ export {
+ __iconNode$np as __iconNode,
+ Trophy as default,
+ };
+}
+
+declare const __iconNode$no: IconNode;
+/**
+ * @component @name Triangle
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/triangle
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Triangle: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_triangle {
+ export {
+ __iconNode$no as __iconNode,
+ Triangle as default,
+ };
+}
+
+declare const __iconNode$nn: IconNode;
+/**
+ * @component @name TriangleRight
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/triangle-right
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const TriangleRight: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_triangle_right {
+ export {
+ __iconNode$nn as __iconNode,
+ TriangleRight as default,
+ };
+}
+
+declare const __iconNode$nm: IconNode;
+/**
+ * @component @name TriangleDashed
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/triangle-dashed
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const TriangleDashed: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_triangle_dashed {
+ export {
+ __iconNode$nm as __iconNode,
+ TriangleDashed as default,
+ };
+}
+
+declare const __iconNode$nl: IconNode;
+/**
+ * @component @name TriangleAlert
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/triangle-alert
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const TriangleAlert: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_triangle_alert {
+ export {
+ __iconNode$nl as __iconNode,
+ TriangleAlert as default,
+ };
+}
+
+declare const __iconNode$nk: IconNode;
+/**
+ * @component @name TrendingUp
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/trending-up
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const TrendingUp: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_trending_up {
+ export {
+ __iconNode$nk as __iconNode,
+ TrendingUp as default,
+ };
+}
+
+declare const __iconNode$nj: IconNode;
+/**
+ * @component @name TrendingUpDown
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/trending-up-down
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const TrendingUpDown: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_trending_up_down {
+ export {
+ __iconNode$nj as __iconNode,
+ TrendingUpDown as default,
+ };
+}
+
+declare const __iconNode$ni: IconNode;
+/**
+ * @component @name TrendingDown
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/trending-down
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const TrendingDown: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_trending_down {
+ export {
+ __iconNode$ni as __iconNode,
+ TrendingDown as default,
+ };
+}
+
+declare const __iconNode$nh: IconNode;
+/**
+ * @component @name Trello
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/trello
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ * @deprecated Brand icons have been deprecated and are due to be removed, please refer to https://github.com/lucide-icons/lucide/issues/670. We recommend using https://simpleicons.org/?q=trello instead. This icon will be removed in v1.0
+ */
+declare const Trello: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_trello {
+ export {
+ __iconNode$nh as __iconNode,
+ Trello as default,
+ };
+}
+
+declare const __iconNode$ng: IconNode;
+/**
+ * @component @name Trees
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/trees
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Trees: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_trees {
+ export {
+ __iconNode$ng as __iconNode,
+ Trees as default,
+ };
+}
+
+declare const __iconNode$nf: IconNode;
+/**
+ * @component @name TreePine
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/tree-pine
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const TreePine: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_tree_pine {
+ export {
+ __iconNode$nf as __iconNode,
+ TreePine as default,
+ };
+}
+
+declare const __iconNode$ne: IconNode;
+/**
+ * @component @name TreePalm
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/tree-palm
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const TreePalm: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_tree_palm {
+ export {
+ __iconNode$ne as __iconNode,
+ TreePalm as default,
+ };
+}
+
+declare const __iconNode$nd: IconNode;
+/**
+ * @component @name TreeDeciduous
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/tree-deciduous
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const TreeDeciduous: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_tree_deciduous {
+ export {
+ __iconNode$nd as __iconNode,
+ TreeDeciduous as default,
+ };
+}
+
+declare const __iconNode$nc: IconNode;
+/**
+ * @component @name Trash
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/trash
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Trash: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_trash {
+ export {
+ __iconNode$nc as __iconNode,
+ Trash as default,
+ };
+}
+
+declare const __iconNode$nb: IconNode;
+/**
+ * @component @name Trash2
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/trash-2
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Trash2: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_trash_2 {
+ export {
+ __iconNode$nb as __iconNode,
+ Trash2 as default,
+ };
+}
+
+declare const __iconNode$na: IconNode;
+/**
+ * @component @name Transgender
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/transgender
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const Transgender: react.ForwardRefExoticComponent & react.RefAttributes>;
+
+declare namespace __icons_transgender {
+ export {
+ __iconNode$na as __iconNode,
+ Transgender as default,
+ };
+}
+
+declare const __iconNode$n9: IconNode;
+/**
+ * @component @name TramFront
+ * @description Lucide SVG icon component, renders SVG Element with children.
+ *
+ * @preview  - https://lucide.dev/icons/tram-front
+ * @see https://lucide.dev/guide/packages/lucide-react - Documentation
+ *
+ * @param {Object} props - Lucide icons props and any valid SVG attribute
+ * @returns {JSX.Element} JSX Element
+ *
+ */
+declare const TramFront: react.ForwardRefExoticComponent & react.RefAttributes