chore(components): 🔧 Update TypeScript files in 15 component modules
This commit is contained in:
parent
b26f9a1bb2
commit
e16e19ea4e
15 changed files with 74 additions and 64 deletions
|
|
@ -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'
|
||||
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
/>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { m } from 'framer-motion'
|
||||
|
||||
import { FOOTER_TEXT } from '@/constants/footer'
|
||||
import { Routes } from '@/routes'
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
|
|
|||
|
|
@ -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') {
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
<>
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue