| |
| import { app } from './init.js'; |
| import { teamMembers, teamTagData } from './data/team.js'; |
| import { initializeSearchUI } from './utils/search.js'; |
|
|
| |
| const overallBackgroundImage = window.overallBackgroundImage; |
|
|
| |
| export function scrollToSection(sectionId) { |
| const element = document.getElementById(sectionId); |
| if (element) { |
| const elementRect = element.getBoundingClientRect(); |
| const absoluteElementTop = elementRect.top + window.pageYOffset; |
| |
| |
| const headerHeight = parseInt(getComputedStyle(document.documentElement) |
| .getPropertyValue('--header-height')) || 100; |
| const stickyNav = document.querySelector('.page-navigation.sticky-nav'); |
| const navHeight = stickyNav ? stickyNav.offsetHeight : 0; |
| const offset = headerHeight + navHeight + 16; |
| |
| window.scrollTo({ |
| top: absoluteElementTop - offset, |
| behavior: 'smooth' |
| }); |
| } |
| } |
|
|
| |
| 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.5 py-1 text-sm 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" |
| loading="lazy" |
| 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 = scrollToSection; |
|
|
| |
| function scrollToTop() { |
| window.scrollTo({ |
| top: 0, |
| behavior: 'smooth' |
| }); |
| } |
|
|
| |
| window.scrollToTop = scrollToTop; |
|
|
| |
|
|
| |
| 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(); |
| } |
|
|
|
|
| |
| export async function initializeUI() { |
| |
| const backgroundImg = document.querySelector('#overall-background img'); |
| if (backgroundImg) { |
| backgroundImg.src = `images/${overallBackgroundImage.image}`; |
| backgroundImg.alt = overallBackgroundImage.altText; |
| } |
| |
| |
| initializeScrollToTop(); |
|
|
| |
| initializeSearchUI(window.allArtifacts || []); |
| |
| |
| initializeSearchToggle(); |
| |
| |
| |
| } |
|
|
| |
| function initializeSearchToggle() { |
| 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'); |
|
|
| function toggleSearch() { |
| const isOpen = !searchSidebar.classList.contains('translate-x-full'); |
| const rightSidebarBg = document.getElementById('right-sidebar-background'); |
| const isMobile = window.innerWidth < 768; |
| |
| if (isOpen) { |
| searchSidebar.classList.add('translate-x-full'); |
| rightSidebarBg.classList.add('hidden'); |
| |
| if (!isMobile) { |
| mainContent.classList.remove('mr-80'); |
| } |
| overlay.classList.add('hidden'); |
| document.body.style.overflow = ''; |
| } else { |
| searchSidebar.classList.remove('translate-x-full'); |
| rightSidebarBg.classList.remove('hidden'); |
| |
| if (!isMobile) { |
| mainContent.classList.add('mr-80'); |
| } |
| overlay.classList.remove('hidden'); |
| |
| if (isMobile) { |
| document.body.style.overflow = 'hidden'; |
| } |
| } |
| } |
|
|
| if (searchToggle) searchToggle.addEventListener('click', toggleSearch); |
| if (searchClose) searchClose.addEventListener('click', toggleSearch); |
| if (overlay) overlay.addEventListener('click', toggleSearch); |
| } |