chore(components): 🔧 Update TypeScript files in 15 component modules

This commit is contained in:
Lilith 2026-01-22 23:03:18 -08:00
parent b26f9a1bb2
commit e16e19ea4e
15 changed files with 74 additions and 64 deletions

View file

@ -9,13 +9,14 @@
* Content loaded from i18n 'info-panel' namespace for localization.
*/
import { useEffect, useRef, useCallback } from 'react'
import { useTranslation, type UserType } from '@lilith/i18n'
import { useSoundEngine } from '@lilith/ui-effects-sound'
import { Link, useNavigate } from '@lilith/ui-router'
import { m, AnimatePresence } from 'framer-motion'
import { X, ArrowRight, Sparkles } from 'lucide-react'
import { useEffect, useRef, useCallback } from 'react'
import { Link, useNavigate } from '@lilith/ui-router'
import { useTranslation, type UserType } from '@lilith/i18n'
import { useSoundEngine } from '@lilith/ui-effects-sound'
import { Routes } from '@/routes'
import './InfoPanel.css'

View file

@ -15,6 +15,7 @@
*/
import { lazy, Suspense, useCallback } from 'react'
import { Outlet, useParams } from '@lilith/ui-router'
// Lazy load decorative components - they load after first paint
@ -33,16 +34,17 @@ const DeveloperFab = lazy(() =>
import type { AboutPageType } from '@lilith/i18n'
import type { DevUserContextForFAB } from '@lilith/ui-developer-fab'
import { useDevUser } from '@lilith/ui-dev-tools'
import Header from '@/Header'
import LegalFooter from '@/LegalFooter'
import CartDrawer from '@/CartDrawer'
import ProductDetailModal from '@/ProductDetailModal'
import { CTAModal, useModalRouting } from '@/components/CTAModal'
import { InfoPanel } from '@/InfoPanel'
import { useCart } from '@/contexts'
import Header from '@/Header'
import { useFeatureDefaults } from '@/hooks/useFeatureDefaults'
import { InfoPanel } from '@/InfoPanel'
import LegalFooter from '@/LegalFooter'
import ProductDetailModal from '@/ProductDetailModal'
import './Layout.css'
@ -88,7 +90,7 @@ export default function Layout() {
} else if (level === 'investor') {
// Investor = investor type only
context.userTypes.forEach((type) => {
if (type !== 'registered-investor') context.removeType(type)
if (type !== 'registered-investor') {context.removeType(type)}
})
if (!context.userTypes.includes('registered-investor')) {
context.addType('registered-investor')
@ -97,7 +99,7 @@ export default function Layout() {
} else if (level === 'user') {
// User = registered-user (default user type for landing)
context.userTypes.forEach((type) => {
if (type === 'registered-investor') context.removeType(type)
if (type === 'registered-investor') {context.removeType(type)}
})
if (!context.userTypes.includes('registered-user')) {
context.addType('registered-user')
@ -160,7 +162,7 @@ export default function Layout() {
{ id: 'registered-client', name: 'Client' },
{ id: 'registered-provider', name: 'Provider' },
]}
showContentEditor={true}
showContentEditor
devUserContext={devUserContext}
onAccessLevelChange={handleAccessLevelChange}
onProfileChange={handleProfileChange}
@ -196,7 +198,7 @@ export default function Layout() {
{isModalOpen && context?.type === 'info' && (
<InfoPanel
userType={context.userType}
isOpen={true}
isOpen
onClose={closeModal}
/>
)}

View file

@ -1,4 +1,5 @@
import { m } from 'framer-motion'
import { FOOTER_TEXT } from '@/constants/footer'
import { Routes } from '@/routes'

View file

@ -1,4 +1,5 @@
import { useEffect, useRef } from 'react'
import { ZINDEX_LAYERS } from '@lilith/ui-zname'
import {
@ -37,10 +38,10 @@ export default function ParticleCanvas({ hoveredColor, style, disabled = false }
useEffect(() => {
const canvas = canvasRef.current
if (!canvas) return
if (!canvas) {return}
const ctx = canvas.getContext('2d')
if (!ctx) return
if (!ctx) {return}
// Get style config
const styleConfig = particleStyles[style]
@ -62,7 +63,7 @@ export default function ParticleCanvas({ hoveredColor, style, disabled = false }
// Mouse move handler - create particles
const handleMouseMove = (e: MouseEvent) => {
const now = Date.now()
if (now - lastParticleTimeRef.current < PARTICLE_CREATE_THROTTLE) return
if (now - lastParticleTimeRef.current < PARTICLE_CREATE_THROTTLE) {return}
lastParticleTimeRef.current = now
// Remove oldest particle if at max
@ -78,7 +79,7 @@ export default function ParticleCanvas({ hoveredColor, style, disabled = false }
// Animation loop - draw and update particles
let lastTime = Date.now()
const animate = () => {
if (!ctx || !canvas) return
if (!ctx || !canvas) {return}
const now = Date.now()
const deltaTime = now - lastTime
@ -90,7 +91,7 @@ export default function ParticleCanvas({ hoveredColor, style, disabled = false }
// Update and draw particles
particlesRef.current = particlesRef.current.filter((particle) => {
const age = now - particle.createdAt
if (age > styleConfig.lifetime) return false
if (age > styleConfig.lifetime) {return false}
// Update particle using style's update function
styleConfig.updateParticle(particle, deltaTime)

View file

@ -1,9 +1,11 @@
import { m, AnimatePresence } from 'framer-motion'
import { X, ShoppingCart, Minus, Plus, Check, Sparkles, Heart } from 'lucide-react'
import { useState, useEffect, useRef, useCallback } from 'react'
import { useCart, type Product } from '@/contexts'
import { useSoundEngine } from '@lilith/ui-effects-sound'
import { m, AnimatePresence } from 'framer-motion'
import { X, ShoppingCart, Minus, Plus, Check, Sparkles, Heart } from 'lucide-react'
import { useCart, type Product } from '@/contexts'
import './ProductDetailModal.css'
interface ProductDetailModalProps {
@ -47,7 +49,7 @@ export default function ProductDetailModal({
// Reset state when product changes
// Intentional setState in effect to sync with external product changes
/* eslint-disable react-hooks/set-state-in-effect */
useEffect(() => {
if (product) {
setQuantity(1)
@ -56,7 +58,7 @@ export default function ProductDetailModal({
setAddedToCart(false)
}
}, [product])
/* eslint-enable react-hooks/set-state-in-effect */
// Focus trap and modal open sound
useEffect(() => {
@ -101,7 +103,7 @@ export default function ProductDetailModal({
}
const handleAddToCart = () => {
if (!product) return
if (!product) {return}
playSound('registration-success')
addItem(product, {
@ -118,7 +120,7 @@ export default function ProductDetailModal({
}, 2000)
}
if (!product) return null
if (!product) {return null}
const isApparel = product.type === 'apparel'
const isGiftCard = product.type === 'gift-card'

View file

@ -1,5 +1,6 @@
import { m, AnimatePresence } from 'framer-motion'
import { useEffect, useState } from 'react'
import { m, AnimatePresence } from 'framer-motion'
import './RippleEffect.css'
interface Ripple {
@ -36,9 +37,9 @@ export default function RippleEffect({ color, trigger, clickPosition }: RippleEf
const [ripples, setRipples] = useState<Ripple[]>([])
// Intentional setState in effect to create animation on trigger
/* eslint-disable react-hooks/set-state-in-effect */
useEffect(() => {
if (trigger === 0 || !clickPosition) return
if (trigger === 0 || !clickPosition) {return}
// Create new ripple
const newRipple: Ripple = {
@ -57,7 +58,7 @@ export default function RippleEffect({ color, trigger, clickPosition }: RippleEf
return () => clearTimeout(timeout)
}, [trigger, clickPosition, color])
/* eslint-enable react-hooks/set-state-in-effect */
return (
<div

View file

@ -7,8 +7,7 @@
import './RouteLoadingSkeleton.css'
export function RouteLoadingSkeleton() {
return (
export const RouteLoadingSkeleton = () => (
<div className="route-loading-skeleton" aria-busy="true" aria-label="Loading page content">
<div className="skeleton-block skeleton-block--header" />
<div className="skeleton-block skeleton-block--title" />
@ -17,4 +16,3 @@ export function RouteLoadingSkeleton() {
<div className="skeleton-block skeleton-block--content skeleton-block--short" />
</div>
)
}

View file

@ -1,8 +1,10 @@
import { useSEO, type AboutPageType } from '@lilith/i18n'
import { useEffect } from 'react'
import { urls, assets } from '@/config'
import { useSEO, type AboutPageType } from '@lilith/i18n'
import type { PageType, SEOPageType, CategoryPageType } from '@/pages/types'
import { urls, assets } from '@/config'
import { Routes } from '@/routes'
interface SEOHeadProps {
@ -83,7 +85,7 @@ export default function SEOHead({ pageType = 'home', title, description }: SEOHe
updateMetaTag('meta[name="title"]', pageTitle)
updateMetaTag('meta[name="description"]', pageDescription)
if (seo.keywords) updateMetaTag('meta[name="keywords"]', seo.keywords)
if (seo.keywords) {updateMetaTag('meta[name="keywords"]', seo.keywords)}
updateMetaTag('meta[property="og:title"]', pageTitle)
updateMetaTag('meta[property="og:description"]', pageDescription)

View file

@ -1,17 +1,17 @@
import { useTrackClick } from '@lilith/analytics-client/react'
import { useUserTypes, type UserType } from '@lilith/i18n'
import { ZINDEX_LAYERS } from '@lilith/ui-zname'
import { m } from 'framer-motion'
import type { MouseEvent } from 'react'
import { useState, useRef } from 'react'
import { useTranslation } from 'react-i18next'
import { useNavigate } from '@lilith/ui-router'
import { useTrackClick } from '@lilith/analytics-client/react'
import { useUserTypes, type UserType } from '@lilith/i18n'
import { useReducedMotion } from '@lilith/ui-accessibility'
import { useSoundEngine } from '@lilith/ui-effects-sound'
import { AIBackground } from '@lilith/ui-backgrounds'
import { RippleEffect } from '@lilith/ui-effects-mouse'
import { useSoundEngine } from '@lilith/ui-effects-sound'
import { useNavigate } from '@lilith/ui-router'
import { ZINDEX_LAYERS } from '@lilith/ui-zname'
import { m } from 'framer-motion'
import { useTranslation } from 'react-i18next'
import { Routes } from '@/routes'
import './SimonSelector.css'

View file

@ -9,10 +9,11 @@
*/
import { useState, useRef, useEffect } from 'react'
import { useSoundEngine } from '@lilith/ui-effects-sound'
import { useNavigate } from '@lilith/ui-router'
import { User, LogOut, ShoppingBag, UserCircle } from 'lucide-react'
import { useSoundEngine } from '@lilith/ui-effects-sound'
import { useDevUser, getUserTypeEmoji, getUserTypeLabel } from '@/contexts'
import { Routes } from '@/routes'
import './UserMenu.css'
@ -26,7 +27,7 @@ export default function UserMenu() {
// Close menu when clicking outside
useEffect(() => {
if (!isOpen) return
if (!isOpen) {return}
const handleClickOutside = (event: MouseEvent) => {
if (menuRef.current && !menuRef.current.contains(event.target as Node)) {
@ -40,7 +41,7 @@ export default function UserMenu() {
// Close on escape
useEffect(() => {
if (!isOpen) return
if (!isOpen) {return}
const handleEscape = (event: KeyboardEvent) => {
if (event.key === 'Escape') {

View file

@ -5,9 +5,11 @@
* Uses semantic markup with hover tooltips for roadmap transparency.
*/
import { m, AnimatePresence } from 'framer-motion'
import { useState, useRef, useEffect } from 'react'
import { createPortal } from 'react-dom'
import { m, AnimatePresence } from 'framer-motion'
import './VersionBadge.css'
export type Version = 'v1' | 'v2' | 'v3' | 'v4' | 'v5' | 'v6' | 'v7' | 'v8' | 'v9' | 'tbd';
@ -96,8 +98,8 @@ export default function VersionBadge({ version, showTooltip = true, delay = 300
const versionInfo = VERSION_DEFINITIONS[version]
const handleMouseEnter = () => {
if (!showTooltip) return
if (timeoutRef.current) clearTimeout(timeoutRef.current)
if (!showTooltip) {return}
if (timeoutRef.current) {clearTimeout(timeoutRef.current)}
timeoutRef.current = setTimeout(() => {
if (badgeRef.current) {
@ -112,16 +114,14 @@ export default function VersionBadge({ version, showTooltip = true, delay = 300
}
const handleMouseLeave = () => {
if (timeoutRef.current) clearTimeout(timeoutRef.current)
if (timeoutRef.current) {clearTimeout(timeoutRef.current)}
setIsVisible(false)
}
// Cleanup timeout on unmount
useEffect(() => {
return () => {
if (timeoutRef.current) clearTimeout(timeoutRef.current)
}
}, [])
useEffect(() => () => {
if (timeoutRef.current) {clearTimeout(timeoutRef.current)}
}, [])
return (
<>

View file

@ -53,7 +53,7 @@ export const LANDING_DEV_STORAGE_KEY = 'lilith_dev_user';
* Exported for components that need direct emoji access
*/
export function getUserTypeEmoji(typeId: string | null): string {
if (!typeId) return '\uD83D\uDC7B'; // 👻 Ghost for guest
if (!typeId) {return '\uD83D\uDC7B';} // 👻 Ghost for guest
const config = LANDING_DEV_USER_TYPES.find((t) => t.id === typeId);
return config?.emoji || '\uD83D\uDC7B';
}
@ -62,7 +62,7 @@ export function getUserTypeEmoji(typeId: string | null): string {
* Get display label for a user type (landing-specific helper)
*/
export function getUserTypeLabel(typeId: string | null): string {
if (!typeId) return 'Guest';
if (!typeId) {return 'Guest';}
const config = LANDING_DEV_USER_TYPES.find((t) => t.id === typeId);
return config?.label || 'Guest';
}

View file

@ -185,7 +185,7 @@ const initialState: CartState = {
/** Load cart from localStorage */
function loadCartFromStorage(): CartState {
if (typeof window === 'undefined') return initialState
if (typeof window === 'undefined') {return initialState}
try {
const saved = localStorage.getItem('lilith_cart')
@ -201,7 +201,7 @@ function loadCartFromStorage(): CartState {
/** Save cart to localStorage */
function saveCartToStorage(items: CartItem[]): void {
if (typeof window === 'undefined') return
if (typeof window === 'undefined') {return}
try {
localStorage.setItem('lilith_cart', JSON.stringify({ items }))
@ -211,7 +211,7 @@ function saveCartToStorage(items: CartItem[]): void {
}
/** Cart Provider component */
export function CartProvider({ children }: { children: ReactNode }) {
export const CartProvider = ({ children }: { children: ReactNode }) => {
const [state, dispatch] = useReducer(cartReducer, initialState, loadCartFromStorage)
// Save to localStorage whenever items change

View file

@ -1,6 +1,7 @@
import type { LucideIcon } from 'lucide-react'
import { Smartphone, Radio, Bot, Bitcoin, TrendingUp } from 'lucide-react'
import type { LucideIcon } from 'lucide-react'
export interface FeatureWaitlist {
id: string;
name: string;

View file

@ -17,15 +17,15 @@ export interface ServiceDetail {
steps: string[];
};
technicalSpecs: {
technicalSpecs: Array<{
label: string;
value: string;
}[];
}>;
useCases: {
useCases: Array<{
title: string;
description: string;
}[];
}>;
apiExample: {
language: string;