|
|
|
|
|
import { createHomeAreaCard } from './cards/HomeAreaCard.js'; |
|
|
import { createArtifactSummaryCard, createArtifactCarousel } from './cards/ArtifactSummaryCard.js'; |
|
|
import { teamMembers, teamTagData } from './data/team.js'; |
|
|
import { router } from './router.js'; |
|
|
|
|
|
|
|
|
export function createTeamMember(name, role, hfUsername, tags) { |
|
|
|
|
|
const colors = ['blue', 'green', 'purple', 'orange', 'indigo', 'pink']; |
|
|
const colorIndex = name.length % colors.length; |
|
|
const color = colors[colorIndex]; |
|
|
|
|
|
const initials = name.split(' ').map(n => n[0]).join(''); |
|
|
|
|
|
const tagElements = tags.map(tag => { |
|
|
const tagInfo = teamTagData[tag]; |
|
|
return `<span class="inline-block px-2 py-0.5 text-xs bg-gray-100 text-gray-700 rounded-full hover:bg-blue-100 hover:text-blue-800 cursor-pointer transition-colors whitespace-nowrap" onclick="window.scrollToSection('${tagInfo.id}')">${tagInfo.name}</span>`; |
|
|
}).join(''); |
|
|
|
|
|
return ` |
|
|
<div class="flex items-start space-x-3 p-3 rounded-lg hover:bg-gray-50 transition-colors"> |
|
|
<div class="flex-shrink-0"> |
|
|
<div class="w-14 h-14 rounded-full overflow-hidden bg-gradient-to-br from-${color}-400 to-${color}-600 flex items-center justify-center relative"> |
|
|
<img |
|
|
src="images/${hfUsername}.jpeg" |
|
|
alt="${name}" |
|
|
class="w-full h-full object-cover" |
|
|
onerror="this.style.display='none'; this.nextElementSibling.style.display='flex';" |
|
|
/> |
|
|
<span class="text-white font-semibold text-base hidden w-full h-full items-center justify-center absolute">${initials}</span> |
|
|
</div> |
|
|
</div> |
|
|
<div class="flex-1 min-w-0"> |
|
|
<h4 class="font-semibold text-gray-900 text-base"> |
|
|
<a href="https://huggingface.co/${hfUsername}" class="hover:text-blue-600 transition-colors" target="_blank"> |
|
|
${name} |
|
|
</a> |
|
|
</h4> |
|
|
<p class="text-sm text-gray-600 mb-1.5">${role}</p> |
|
|
<div class="flex gap-1.5 overflow-x-auto scrollbar-hide"> |
|
|
${tagElements} |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
`; |
|
|
} |
|
|
|
|
|
|
|
|
window.scrollToSection = (sectionId) => { |
|
|
const element = document.getElementById(sectionId); |
|
|
if (element) { |
|
|
const elementRect = element.getBoundingClientRect(); |
|
|
const absoluteElementTop = elementRect.top + window.pageYOffset; |
|
|
const offset = 120; |
|
|
|
|
|
window.scrollTo({ |
|
|
top: absoluteElementTop - offset, |
|
|
behavior: 'smooth' |
|
|
}); |
|
|
} |
|
|
}; |
|
|
|
|
|
|
|
|
function scrollToTop() { |
|
|
window.scrollTo({ |
|
|
top: 0, |
|
|
behavior: 'smooth' |
|
|
}); |
|
|
} |
|
|
|
|
|
|
|
|
window.scrollToTop = scrollToTop; |
|
|
|
|
|
|
|
|
function initializeTeamMembers() { |
|
|
const teamContainer = document.getElementById('team-grid'); |
|
|
if (!teamContainer) return; |
|
|
|
|
|
teamContainer.innerHTML = teamMembers.map(member => |
|
|
createTeamMember(member.name, member.role, member.username, member.tags) |
|
|
).join(''); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function initializeScrollToTop() { |
|
|
const scrollToTopBtn = document.getElementById('scroll-to-top'); |
|
|
if (!scrollToTopBtn) return; |
|
|
|
|
|
|
|
|
scrollToTopBtn.addEventListener('click', scrollToTop); |
|
|
|
|
|
|
|
|
function toggleScrollToTopButton() { |
|
|
const scrollPosition = window.pageYOffset || document.documentElement.scrollTop; |
|
|
const showThreshold = 300; |
|
|
|
|
|
if (scrollPosition > showThreshold) { |
|
|
scrollToTopBtn.classList.remove('opacity-0', 'invisible'); |
|
|
scrollToTopBtn.classList.add('opacity-100', 'visible'); |
|
|
} else { |
|
|
scrollToTopBtn.classList.remove('opacity-100', 'visible'); |
|
|
scrollToTopBtn.classList.add('opacity-0', 'invisible'); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
window.addEventListener('scroll', toggleScrollToTopButton); |
|
|
|
|
|
|
|
|
toggleScrollToTopButton(); |
|
|
} |
|
|
|
|
|
|
|
|
document.addEventListener('DOMContentLoaded', function() { |
|
|
|
|
|
|
|
|
|
|
|
initializeScrollToTop(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const searchToggle = document.getElementById('search-toggle'); |
|
|
const searchSidebar = document.getElementById('search-sidebar'); |
|
|
const searchClose = document.getElementById('search-close'); |
|
|
const mainContent = document.getElementById('main-content'); |
|
|
const overlay = document.getElementById('sidebar-overlay'); |
|
|
|
|
|
const sidebarToggle = document.getElementById('sidebar-toggle'); |
|
|
const leftSidebar = document.getElementById('left-sidebar'); |
|
|
const mainContentEl = document.getElementById('main-content'); |
|
|
|
|
|
function toggleLeftSidebar() { |
|
|
const isOpen = !leftSidebar.classList.contains('-translate-x-full'); |
|
|
|
|
|
if (isOpen) { |
|
|
|
|
|
leftSidebar.classList.add('-translate-x-full'); |
|
|
mainContentEl.style.marginLeft = '0'; |
|
|
} else { |
|
|
|
|
|
leftSidebar.classList.remove('-translate-x-full'); |
|
|
mainContentEl.style.marginLeft = '256px'; |
|
|
} |
|
|
} |
|
|
|
|
|
if (sidebarToggle) sidebarToggle.addEventListener('click', toggleLeftSidebar) |
|
|
|
|
|
function toggleSearch() { |
|
|
const isOpen = !searchSidebar.classList.contains('translate-x-full'); |
|
|
const leftSidebarOpen = !leftSidebar.classList.contains('-translate-x-full'); |
|
|
|
|
|
if (isOpen) { |
|
|
searchSidebar.classList.add('translate-x-full'); |
|
|
if (leftSidebarOpen) { |
|
|
mainContent.style.marginLeft = '256px'; |
|
|
mainContent.classList.remove('mr-80'); |
|
|
} else { |
|
|
mainContent.style.marginLeft = '0'; |
|
|
mainContent.classList.remove('mr-80'); |
|
|
} |
|
|
overlay.classList.add('hidden'); |
|
|
} else { |
|
|
searchSidebar.classList.remove('translate-x-full'); |
|
|
if (leftSidebarOpen) { |
|
|
mainContent.style.marginLeft = '256px'; |
|
|
mainContent.classList.add('mr-80'); |
|
|
} else { |
|
|
mainContent.style.marginLeft = '0'; |
|
|
mainContent.classList.add('mr-80'); |
|
|
} |
|
|
overlay.classList.remove('hidden'); |
|
|
} |
|
|
} |
|
|
|
|
|
if (searchToggle) searchToggle.addEventListener('click', toggleSearch); |
|
|
if (searchClose) searchClose.addEventListener('click', toggleSearch); |
|
|
if (overlay) overlay.addEventListener('click', toggleSearch); |
|
|
|
|
|
|
|
|
const sections = document.querySelectorAll('section[id], div[id]'); |
|
|
const navLinks = document.querySelectorAll('.page-nav-link'); |
|
|
|
|
|
function updateActiveNavigation() { |
|
|
let current = ''; |
|
|
const scrollPos = window.scrollY + 150; |
|
|
|
|
|
sections.forEach(section => { |
|
|
const sectionTop = section.offsetTop; |
|
|
const sectionHeight = section.offsetHeight; |
|
|
|
|
|
if (scrollPos >= sectionTop && scrollPos < sectionTop + sectionHeight) { |
|
|
current = section.getAttribute('id'); |
|
|
} |
|
|
}); |
|
|
|
|
|
navLinks.forEach(link => { |
|
|
link.classList.remove('text-blue-600', 'bg-blue-50'); |
|
|
link.classList.add('text-gray-700'); |
|
|
|
|
|
if (link.getAttribute('href') === `#${current}`) { |
|
|
link.classList.remove('text-gray-700'); |
|
|
link.classList.add('text-blue-600', 'bg-blue-50'); |
|
|
} |
|
|
}); |
|
|
} |
|
|
|
|
|
window.addEventListener('scroll', updateActiveNavigation); |
|
|
updateActiveNavigation(); |
|
|
}); |