blacktrigram 0.7.44 → 0.7.45
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/audio/AudioManager.d.ts +26 -0
- package/lib/audio/AudioManager.d.ts.map +1 -1
- package/lib/audio/AudioManager.js +26 -0
- package/lib/audio/AudioManager.js.map +1 -1
- package/lib/audio/index.d.ts.map +1 -1
- package/lib/audio/index.js.map +1 -1
- package/lib/audio/types.d.ts +18 -2
- package/lib/audio/types.d.ts.map +1 -1
- package/lib/audio/types.js +1 -0
- package/lib/audio/types.js.map +1 -1
- package/lib/components/effects/WindParticles3D.d.ts.map +1 -1
- package/lib/components/index.d.ts.map +1 -1
- package/lib/components/index.js.map +1 -1
- package/lib/components/screens/combat/CombatScreen3D.d.ts.map +1 -1
- package/lib/components/screens/combat/CombatScreen3D.js.map +1 -1
- package/lib/components/screens/combat/components/controls/KeyboardHints.d.ts +0 -1
- package/lib/components/screens/combat/components/controls/KeyboardHints.d.ts.map +1 -1
- package/lib/components/screens/combat/components/controls/KeyboardHints.js +0 -1
- package/lib/components/screens/combat/components/controls/KeyboardHints.js.map +1 -1
- package/lib/components/screens/combat/components/controls/PauseMenu.d.ts.map +1 -1
- package/lib/components/screens/combat/components/controls/PauseMenu.js.map +1 -1
- package/lib/components/screens/combat/components/effects/ArterialSpray3D.d.ts.map +1 -1
- package/lib/components/screens/combat/components/effects/BloodDecals3D.d.ts.map +1 -1
- package/lib/components/screens/combat/components/effects/BloodDecals3D.js.map +1 -1
- package/lib/components/screens/combat/components/effects/BloodLossOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/combat/components/effects/BloodLossOverlayHtml.js.map +1 -1
- package/lib/components/screens/combat/components/effects/BloodParticles3D.d.ts.map +1 -1
- package/lib/components/screens/combat/components/effects/BloodParticles3D.js.map +1 -1
- package/lib/components/screens/combat/components/effects/BloodViscosity3D.d.ts.map +1 -1
- package/lib/components/screens/combat/components/effects/BloodViscosity3D.js.map +1 -1
- package/lib/components/screens/combat/components/effects/BoneCrackParticles3D.d.ts.map +1 -1
- package/lib/components/screens/combat/components/effects/CombatParticleEffects3D.d.ts.map +1 -1
- package/lib/components/screens/combat/components/effects/CombatParticleEffects3D.js.map +1 -1
- package/lib/components/screens/combat/components/effects/ConsciousnessBlur.d.ts.map +1 -1
- package/lib/components/screens/combat/components/effects/ConsciousnessBlur.js.map +1 -1
- package/lib/components/screens/combat/components/effects/DustClouds3D.d.ts.map +1 -1
- package/lib/components/screens/combat/components/effects/EarthCrackEffect3D.d.ts.map +1 -1
- package/lib/components/screens/combat/components/effects/EarthHealingEffect3D.d.ts.map +1 -1
- package/lib/components/screens/combat/components/effects/ImpactSparks3D.d.ts.map +1 -1
- package/lib/components/screens/combat/components/effects/InternalDamage3D.d.ts.map +1 -1
- package/lib/components/screens/combat/components/effects/InternalDamage3D.js.map +1 -1
- package/lib/components/screens/combat/components/effects/LiPrecisionTargetingOverlay.d.ts.map +1 -1
- package/lib/components/screens/combat/components/effects/NerveStrikeParticles3D.d.ts.map +1 -1
- package/lib/components/screens/combat/components/effects/PainVignette.d.ts.map +1 -1
- package/lib/components/screens/combat/components/effects/PainVignette.js.map +1 -1
- package/lib/components/screens/combat/components/effects/ParticleAudio3D.d.ts.map +1 -1
- package/lib/components/screens/combat/components/effects/ParticleAudio3D.js.map +1 -1
- package/lib/components/screens/combat/components/effects/TraumaOverlay3D.d.ts.map +1 -1
- package/lib/components/screens/combat/components/effects/TraumaOverlay3D.js.map +1 -1
- package/lib/components/screens/combat/components/effects/WaterRipple3D.d.ts.map +1 -1
- package/lib/components/screens/combat/components/effects/WaterWave3D.d.ts.map +1 -1
- package/lib/components/screens/combat/components/effects/index.d.ts.map +1 -1
- package/lib/components/screens/combat/components/feedback/MatchCountdown.d.ts.map +1 -1
- package/lib/components/screens/combat/components/feedback/MatchCountdown.js.map +1 -1
- package/lib/components/screens/combat/components/feedback/RoundAnnouncementOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/combat/components/feedback/RoundAnnouncementOverlayHtml.js.map +1 -1
- package/lib/components/screens/combat/components/feedback/RoundStartAnnouncementOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/combat/components/feedback/RoundStartAnnouncementOverlayHtml.js.map +1 -1
- package/lib/components/screens/combat/components/hud/CombatBottomHUD.d.ts.map +1 -1
- package/lib/components/screens/combat/components/hud/CombatBottomHUD.js.map +1 -1
- package/lib/components/screens/combat/components/hud/CombatLeftHUD.d.ts.map +1 -1
- package/lib/components/screens/combat/components/hud/CombatLeftHUD.js.map +1 -1
- package/lib/components/screens/combat/components/hud/CombatPortraitStatusStrip.d.ts.map +1 -1
- package/lib/components/screens/combat/components/hud/CombatPortraitStatusStrip.js.map +1 -1
- package/lib/components/screens/combat/components/hud/CombatRightHUD.d.ts.map +1 -1
- package/lib/components/screens/combat/components/hud/CombatRightHUD.js.map +1 -1
- package/lib/components/screens/combat/components/hud/CombatTopHUD.d.ts.map +1 -1
- package/lib/components/screens/combat/components/hud/CombatTopHUD.js.map +1 -1
- package/lib/components/screens/combat/components/hud/DifficultyIndicator.d.ts.map +1 -1
- package/lib/components/screens/combat/components/hud/DifficultyIndicator.js.map +1 -1
- package/lib/components/screens/combat/components/hud/FPSMonitor.d.ts.map +1 -1
- package/lib/components/screens/combat/components/hud/FPSMonitor.js.map +1 -1
- package/lib/components/screens/combat/components/hud/PlayerStateOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/combat/components/hud/PlayerStateOverlayHtml.js.map +1 -1
- package/lib/components/screens/combat/components/indicators/BalanceIndicator.d.ts.map +1 -1
- package/lib/components/screens/combat/components/indicators/BalanceIndicator.js.map +1 -1
- package/lib/components/screens/combat/components/indicators/InputBufferDisplay.d.ts +0 -1
- package/lib/components/screens/combat/components/indicators/InputBufferDisplay.d.ts.map +1 -1
- package/lib/components/screens/combat/components/indicators/InputBufferDisplay.js +0 -1
- package/lib/components/screens/combat/components/indicators/InputBufferDisplay.js.map +1 -1
- package/lib/components/screens/combat/components/indicators/StaminaWarning.d.ts.map +1 -1
- package/lib/components/screens/combat/components/indicators/StaminaWarning.js.map +1 -1
- package/lib/components/screens/combat/components/indicators/TechniqueNameDisplay.d.ts +0 -2
- package/lib/components/screens/combat/components/indicators/TechniqueNameDisplay.d.ts.map +1 -1
- package/lib/components/screens/combat/components/indicators/TechniqueNameDisplay.js +0 -1
- package/lib/components/screens/combat/components/indicators/TechniqueNameDisplay.js.map +1 -1
- package/lib/components/screens/combat/helpers/AnimationUpdater.d.ts.map +1 -1
- package/lib/components/screens/combat/helpers/AnimationUpdater.js.map +1 -1
- package/lib/components/screens/combat/helpers/combatHelpers.d.ts.map +1 -1
- package/lib/components/screens/combat/helpers/combatHelpers.js.map +1 -1
- package/lib/components/screens/combat/hooks/useAICombat.d.ts.map +1 -1
- package/lib/components/screens/combat/hooks/useAICombat.js.map +1 -1
- package/lib/components/screens/combat/hooks/useCombatActions.d.ts.map +1 -1
- package/lib/components/screens/combat/hooks/useCombatActions.js.map +1 -1
- package/lib/components/screens/combat/hooks/useCombatAttackMovement.d.ts.map +1 -1
- package/lib/components/screens/combat/hooks/useCombatAttackMovement.js.map +1 -1
- package/lib/components/screens/combat/hooks/useCombatAudio.d.ts.map +1 -1
- package/lib/components/screens/combat/hooks/useCombatAudio.js.map +1 -1
- package/lib/components/screens/combat/hooks/useCombatLayout.d.ts.map +1 -1
- package/lib/components/screens/combat/hooks/useCombatLayout.js.map +1 -1
- package/lib/components/screens/combat/hooks/useCombatState.d.ts.map +1 -1
- package/lib/components/screens/combat/hooks/useCombatState.js.map +1 -1
- package/lib/components/screens/combat/hooks/useGrapplingAudio.d.ts.map +1 -1
- package/lib/components/screens/combat/hooks/usePreloadCombatAudio.d.ts.map +1 -1
- package/lib/components/screens/controls/ControlsScreen3D.d.ts.map +1 -1
- package/lib/components/screens/controls/ControlsScreen3D.js.map +1 -1
- package/lib/components/screens/controls/components/ControlBindingsOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/controls/components/ControlBindingsOverlayHtml.js.map +1 -1
- package/lib/components/screens/controls/components/GamepadVisualization3D.d.ts.map +1 -1
- package/lib/components/screens/controls/components/GamepadVisualization3D.js.map +1 -1
- package/lib/components/screens/controls/components/InteractiveControlDemoOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/controls/components/InteractiveControlDemoOverlayHtml.js.map +1 -1
- package/lib/components/screens/controls/components/Key3D.d.ts.map +1 -1
- package/lib/components/screens/controls/components/Key3D.js.map +1 -1
- package/lib/components/screens/controls/components/VisualKeyboard3D.d.ts.map +1 -1
- package/lib/components/screens/controls/components/VisualKeyboard3D.js.map +1 -1
- package/lib/components/screens/controls/constants/ControlsConstants.d.ts.map +1 -1
- package/lib/components/screens/controls/constants/ControlsConstants.js.map +1 -1
- package/lib/components/screens/controls/hooks/useControlsState.d.ts.map +1 -1
- package/lib/components/screens/controls/hooks/useControlsState.js.map +1 -1
- package/lib/components/screens/endscreen/EndScreen3D.d.ts.map +1 -1
- package/lib/components/screens/endscreen/EndScreen3D.js.map +1 -1
- package/lib/components/screens/endscreen/components/DefeatAnimation3D.d.ts.map +1 -1
- package/lib/components/screens/endscreen/components/DefeatAnimation3D.js.map +1 -1
- package/lib/components/screens/endscreen/components/NavigationButtonsOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/endscreen/components/NavigationButtonsOverlayHtml.js.map +1 -1
- package/lib/components/screens/endscreen/components/PerformanceBreakdownOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/endscreen/components/PerformanceBreakdownOverlayHtml.js.map +1 -1
- package/lib/components/screens/endscreen/components/PerformanceRatingOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/endscreen/components/PerformanceRatingOverlayHtml.js.map +1 -1
- package/lib/components/screens/endscreen/components/VictoryAnimation3D.d.ts.map +1 -1
- package/lib/components/screens/endscreen/components/VictoryAnimation3D.js.map +1 -1
- package/lib/components/screens/endscreen/components/WinnerDisplayOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/endscreen/components/WinnerDisplayOverlayHtml.js.map +1 -1
- package/lib/components/screens/endscreen/components/index.d.ts.map +1 -1
- package/lib/components/screens/endscreen/index.d.ts.map +1 -1
- package/lib/components/screens/intro/IntroScreen3D.d.ts.map +1 -1
- package/lib/components/screens/intro/IntroScreen3D.js +1 -1
- package/lib/components/screens/intro/IntroScreen3D.js.map +1 -1
- package/lib/components/screens/intro/components/AbilityListOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/intro/components/AbilityListOverlayHtml.js.map +1 -1
- package/lib/components/screens/intro/components/ArchetypeCardGridOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/intro/components/ArchetypeCardGridOverlayHtml.js.map +1 -1
- package/lib/components/screens/intro/components/ArchetypeCardOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/intro/components/ArchetypeCardOverlayHtml.js.map +1 -1
- package/lib/components/screens/intro/components/ArchetypeDisplayOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/intro/components/ArchetypeDisplayOverlayHtml.js.map +1 -1
- package/lib/components/screens/intro/components/EnhancedArchetypeDisplayOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/intro/components/EnhancedArchetypeDisplayOverlayHtml.js.map +1 -1
- package/lib/components/screens/intro/components/MenuButtonsOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/intro/components/MenuButtonsOverlayHtml.js.map +1 -1
- package/lib/components/screens/intro/components/MenuSectionOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/intro/components/MenuSectionOverlayHtml.js.map +1 -1
- package/lib/components/screens/intro/components/StatBarOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/intro/components/StatBarOverlayHtml.js.map +1 -1
- package/lib/components/screens/philosophy/PhilosophyScreen3D.d.ts.map +1 -1
- package/lib/components/screens/philosophy/PhilosophyScreen3D.js.map +1 -1
- package/lib/components/screens/philosophy/components/InteractiveTrigramGridOverlayHtml.d.ts +0 -1
- package/lib/components/screens/philosophy/components/InteractiveTrigramGridOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/philosophy/components/PhilosophyNavigationOverlayHtml.d.ts +0 -1
- package/lib/components/screens/philosophy/components/PhilosophyNavigationOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/philosophy/components/PhilosophySectionOverlayHtml.d.ts +0 -1
- package/lib/components/screens/philosophy/components/PhilosophySectionOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/philosophy/components/PhilosophyTextOverlayHtml.d.ts +0 -1
- package/lib/components/screens/philosophy/components/PhilosophyTextOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/philosophy/components/TrigramSymbol3D.d.ts +0 -1
- package/lib/components/screens/philosophy/components/TrigramSymbol3D.d.ts.map +1 -1
- package/lib/components/screens/philosophy/components/TrigramVisualization3D.d.ts +0 -1
- package/lib/components/screens/philosophy/components/TrigramVisualization3D.d.ts.map +1 -1
- package/lib/components/screens/philosophy/hooks/usePhilosophyState.d.ts +0 -1
- package/lib/components/screens/philosophy/hooks/usePhilosophyState.d.ts.map +1 -1
- package/lib/components/screens/training/TrainingScreen3D.d.ts.map +1 -1
- package/lib/components/screens/training/TrainingScreen3D.js.map +1 -1
- package/lib/components/screens/training/components/AnatomyControlsOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/training/components/AnatomyControlsOverlayHtml.js.map +1 -1
- package/lib/components/screens/training/components/AnatomyOverlay3D.d.ts.map +1 -1
- package/lib/components/screens/training/components/AnatomyOverlay3D.js.map +1 -1
- package/lib/components/screens/training/components/DamageNumber3D.d.ts.map +1 -1
- package/lib/components/screens/training/components/FootPlacementMarkers3D.d.ts.map +1 -1
- package/lib/components/screens/training/components/FootPlacementMarkers3D.js.map +1 -1
- package/lib/components/screens/training/components/FootworkDrillsOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/training/components/FootworkDrillsOverlayHtml.js.map +1 -1
- package/lib/components/screens/training/components/HitFeedbackEffect3D.d.ts.map +1 -1
- package/lib/components/screens/training/components/HitFeedbackEffect3D.js.map +1 -1
- package/lib/components/screens/training/components/TrainingAICharacter3D.d.ts.map +1 -1
- package/lib/components/screens/training/components/TrainingArena3D.d.ts.map +1 -1
- package/lib/components/screens/training/components/TrainingControlsOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/training/components/TrainingControlsOverlayHtml.js.map +1 -1
- package/lib/components/screens/training/components/TrainingDummy3D.d.ts.map +1 -1
- package/lib/components/screens/training/components/TrainingDummy3D.js.map +1 -1
- package/lib/components/screens/training/components/TrainingFeedbackOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/training/components/TrainingFeedbackOverlayHtml.js.map +1 -1
- package/lib/components/screens/training/components/TrainingHitEffects3D.d.ts.map +1 -1
- package/lib/components/screens/training/components/TrainingModeSelectorOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/training/components/TrainingModeSelectorOverlayHtml.js.map +1 -1
- package/lib/components/screens/training/components/TrainingStatsOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/training/components/TrainingStatsOverlayHtml.js.map +1 -1
- package/lib/components/screens/training/components/VitalPointMarker3D.d.ts.map +1 -1
- package/lib/components/screens/training/components/VitalPointMarker3D.js.map +1 -1
- package/lib/components/screens/training/components/VitalPointTrainingOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/training/components/VitalPointTrainingOverlayHtml.js.map +1 -1
- package/lib/components/screens/training/components/hud/TrainingBottomHUD.d.ts.map +1 -1
- package/lib/components/screens/training/components/hud/TrainingBottomHUD.js.map +1 -1
- package/lib/components/screens/training/components/hud/TrainingLeftHUD.d.ts.map +1 -1
- package/lib/components/screens/training/components/hud/TrainingLeftHUD.js.map +1 -1
- package/lib/components/screens/training/components/hud/TrainingRightHUD.d.ts.map +1 -1
- package/lib/components/screens/training/components/hud/TrainingRightHUD.js.map +1 -1
- package/lib/components/screens/training/components/hud/TrainingTopHUD.d.ts.map +1 -1
- package/lib/components/screens/training/components/hud/TrainingTopHUD.js.map +1 -1
- package/lib/components/screens/training/components/index.d.ts.map +1 -1
- package/lib/components/screens/training/hooks/useAttackMovement.d.ts.map +1 -1
- package/lib/components/screens/training/hooks/useAttackMovement.js.map +1 -1
- package/lib/components/screens/training/hooks/useTrainingActions.d.ts.map +1 -1
- package/lib/components/screens/training/hooks/useTrainingActions.js.map +1 -1
- package/lib/components/screens/training/hooks/useTrainingLayout.d.ts.map +1 -1
- package/lib/components/screens/training/hooks/useTrainingLayout.js.map +1 -1
- package/lib/components/screens/training/hooks/useTrainingState.d.ts.map +1 -1
- package/lib/components/screens/training/hooks/useTrainingState.js.map +1 -1
- package/lib/components/shared/base/AccessibilityProvider.d.ts.map +1 -1
- package/lib/components/shared/base/BaseButton.d.ts.map +1 -1
- package/lib/components/shared/base/BaseButton.js.map +1 -1
- package/lib/components/shared/base/BaseButtonOverlayHtml.d.ts.map +1 -1
- package/lib/components/shared/base/BaseButtonOverlayHtml.js.map +1 -1
- package/lib/components/shared/base/BasePanel.d.ts.map +1 -1
- package/lib/components/shared/base/BasePanel.js.map +1 -1
- package/lib/components/shared/base/BaseText.d.ts.map +1 -1
- package/lib/components/shared/base/BaseText.js.map +1 -1
- package/lib/components/shared/base/ResponsiveContainer.d.ts.map +1 -1
- package/lib/components/shared/base/index.d.ts.map +1 -1
- package/lib/components/shared/base/useKoreanTheme.d.ts.map +1 -1
- package/lib/components/shared/base/useKoreanTheme.js.map +1 -1
- package/lib/components/shared/debug/PerformanceDebugOverlayHtml.d.ts.map +1 -1
- package/lib/components/shared/debug/PerformanceDebugOverlayHtml.js.map +1 -1
- package/lib/components/shared/effects/ScreenFlash.d.ts.map +1 -1
- package/lib/components/shared/mobile/ActionButtons.d.ts.map +1 -1
- package/lib/components/shared/mobile/ActionButtons.js +0 -1
- package/lib/components/shared/mobile/ActionButtons.js.map +1 -1
- package/lib/components/shared/mobile/GestureRecognizerPure.d.ts +0 -1
- package/lib/components/shared/mobile/GestureRecognizerPure.d.ts.map +1 -1
- package/lib/components/shared/mobile/GestureRecognizerPure.js +0 -1
- package/lib/components/shared/mobile/GestureRecognizerPure.js.map +1 -1
- package/lib/components/shared/mobile/HapticController.d.ts +0 -13
- package/lib/components/shared/mobile/HapticController.d.ts.map +1 -1
- package/lib/components/shared/mobile/HapticController.js +0 -10
- package/lib/components/shared/mobile/HapticController.js.map +1 -1
- package/lib/components/shared/mobile/MobileControlsPure.d.ts.map +1 -1
- package/lib/components/shared/mobile/MobileControlsPure.js.map +1 -1
- package/lib/components/shared/mobile/PerformanceMonitor.d.ts +0 -15
- package/lib/components/shared/mobile/PerformanceMonitor.d.ts.map +1 -1
- package/lib/components/shared/mobile/StanceWheelPure.d.ts +0 -1
- package/lib/components/shared/mobile/StanceWheelPure.d.ts.map +1 -1
- package/lib/components/shared/mobile/StanceWheelPure.js +0 -1
- package/lib/components/shared/mobile/StanceWheelPure.js.map +1 -1
- package/lib/components/shared/mobile/TouchOptimizer.d.ts +0 -4
- package/lib/components/shared/mobile/TouchOptimizer.d.ts.map +1 -1
- package/lib/components/shared/mobile/TouchOptimizer.js +0 -3
- package/lib/components/shared/mobile/TouchOptimizer.js.map +1 -1
- package/lib/components/shared/mobile/VirtualDPad.d.ts.map +1 -1
- package/lib/components/shared/mobile/VirtualDPad.js +0 -1
- package/lib/components/shared/mobile/VirtualDPad.js.map +1 -1
- package/lib/components/shared/mobile/index.d.ts.map +1 -1
- package/lib/components/shared/three/anatomy/BodySurface.d.ts.map +1 -1
- package/lib/components/shared/three/anatomy/BodySurface.js.map +1 -1
- package/lib/components/shared/three/anatomy/BoneAttachedMuscles.d.ts.map +1 -1
- package/lib/components/shared/three/anatomy/BoneAttachedMuscles.js.map +1 -1
- package/lib/components/shared/three/anatomy/BoneClothing.d.ts.map +1 -1
- package/lib/components/shared/three/anatomy/BoneClothing.js.map +1 -1
- package/lib/components/shared/three/anatomy/BoneRenderer.d.ts +0 -1
- package/lib/components/shared/three/anatomy/BoneRenderer.d.ts.map +1 -1
- package/lib/components/shared/three/anatomy/BoneRenderer.js.map +1 -1
- package/lib/components/shared/three/anatomy/Face3D.d.ts.map +1 -1
- package/lib/components/shared/three/anatomy/Face3D.js.map +1 -1
- package/lib/components/shared/three/anatomy/Foot3D.d.ts +0 -1
- package/lib/components/shared/three/anatomy/Foot3D.d.ts.map +1 -1
- package/lib/components/shared/three/anatomy/Foot3D.js.map +1 -1
- package/lib/components/shared/three/anatomy/Hand3D.d.ts +0 -1
- package/lib/components/shared/three/anatomy/Hand3D.d.ts.map +1 -1
- package/lib/components/shared/three/anatomy/Hand3D.js.map +1 -1
- package/lib/components/shared/three/effects/ActionFeedback.d.ts.map +1 -1
- package/lib/components/shared/three/effects/ActionFeedback.js.map +1 -1
- package/lib/components/shared/three/effects/DamageNumbers.d.ts.map +1 -1
- package/lib/components/shared/three/effects/DamageNumbers.js.map +1 -1
- package/lib/components/shared/three/effects/ExplosiveBurstEffect3D.d.ts.map +1 -1
- package/lib/components/shared/three/effects/GrapplingIndicator3D.d.ts.map +1 -1
- package/lib/components/shared/three/effects/HitEffects3D.d.ts.map +1 -1
- package/lib/components/shared/three/effects/HitEffects3D.js.map +1 -1
- package/lib/components/shared/three/effects/LimbExposureIndicator3D.d.ts.map +1 -1
- package/lib/components/shared/three/effects/NerveDisruptionEffect3D.d.ts.map +1 -1
- package/lib/components/shared/three/effects/PlayerStateIndicators.d.ts.map +1 -1
- package/lib/components/shared/three/effects/PlayerStateIndicators.js.map +1 -1
- package/lib/components/shared/three/effects/StanceSymbol3D.d.ts.map +1 -1
- package/lib/components/shared/three/effects/StanceSymbol3D.js.map +1 -1
- package/lib/components/shared/three/effects/StanceTransitionEffect.d.ts.map +1 -1
- package/lib/components/shared/three/effects/StanceTransitionEffect.js.map +1 -1
- package/lib/components/shared/three/effects/ThunderEffect3D.d.ts.map +1 -1
- package/lib/components/shared/three/effects/VitalPointMarkers3D.d.ts.map +1 -1
- package/lib/components/shared/three/effects/VitalPointMarkers3D.js.map +1 -1
- package/lib/components/shared/three/index.d.ts.map +1 -1
- package/lib/components/shared/three/indicators/ElementalColorSystem.d.ts +0 -6
- package/lib/components/shared/three/indicators/ElementalColorSystem.d.ts.map +1 -1
- package/lib/components/shared/three/indicators/ElementalColorSystem.js +0 -4
- package/lib/components/shared/three/indicators/ElementalColorSystem.js.map +1 -1
- package/lib/components/shared/three/indicators/GuardIndicator.d.ts +0 -1
- package/lib/components/shared/three/indicators/GuardIndicator.d.ts.map +1 -1
- package/lib/components/shared/three/indicators/GuardIndicator.js +0 -1
- package/lib/components/shared/three/indicators/GuardIndicator.js.map +1 -1
- package/lib/components/shared/three/indicators/HapticFeedback.d.ts +0 -7
- package/lib/components/shared/three/indicators/HapticFeedback.d.ts.map +1 -1
- package/lib/components/shared/three/indicators/HapticFeedback.js +0 -2
- package/lib/components/shared/three/indicators/HapticFeedback.js.map +1 -1
- package/lib/components/shared/three/indicators/StanceChangeIndicator.d.ts +0 -1
- package/lib/components/shared/three/indicators/StanceChangeIndicator.d.ts.map +1 -1
- package/lib/components/shared/three/indicators/StanceChangeIndicator.js +0 -1
- package/lib/components/shared/three/indicators/StanceChangeIndicator.js.map +1 -1
- package/lib/components/shared/three/indicators/TrigramSymbol3D.d.ts +0 -1
- package/lib/components/shared/three/indicators/TrigramSymbol3D.d.ts.map +1 -1
- package/lib/components/shared/three/models/Player3DWithTransitions.d.ts.map +1 -1
- package/lib/components/shared/three/models/Player3DWithTransitions.js.map +1 -1
- package/lib/components/shared/three/models/SkeletalPlayer3D.d.ts.map +1 -1
- package/lib/components/shared/three/models/SkeletalPlayer3D.js.map +1 -1
- package/lib/components/shared/three/optimization/AdaptiveQuality.d.ts.map +1 -1
- package/lib/components/shared/three/optimization/AdaptiveQuality.js.map +1 -1
- package/lib/components/shared/three/optimization/InstancedGeometry.d.ts.map +1 -1
- package/lib/components/shared/three/optimization/LODSystem.d.ts.map +1 -1
- package/lib/components/shared/three/scene/AtmosphericParticles3D.d.ts.map +1 -1
- package/lib/components/shared/three/scene/AtmosphericParticles3D.js.map +1 -1
- package/lib/components/shared/three/scene/BackgroundScene3D.d.ts.map +1 -1
- package/lib/components/shared/three/scene/BackgroundScene3D.js.map +1 -1
- package/lib/components/shared/three/scene/CombatArena3D.d.ts.map +1 -1
- package/lib/components/shared/three/scene/CombatArena3D.js.map +1 -1
- package/lib/components/shared/three/scene/DebugCollision.d.ts +0 -2
- package/lib/components/shared/three/scene/DebugCollision.d.ts.map +1 -1
- package/lib/components/shared/three/scene/KoreanSignage3D.d.ts.map +1 -1
- package/lib/components/shared/three/scene/KoreanSignage3D.js.map +1 -1
- package/lib/components/shared/three/ui/ArchetypeCard.d.ts.map +1 -1
- package/lib/components/shared/three/ui/ArchetypeCard.js.map +1 -1
- package/lib/components/shared/three/ui/BodyPartHealthDisplay.d.ts.map +1 -1
- package/lib/components/shared/three/ui/BodyPartHealthDisplay.js.map +1 -1
- package/lib/components/shared/three/ui/BreathingIndicator.d.ts.map +1 -1
- package/lib/components/shared/three/ui/BreathingIndicator2.js.map +1 -1
- package/lib/components/shared/three/ui/CombatReadinessBar.d.ts.map +1 -1
- package/lib/components/shared/three/ui/CombatReadinessBar.js.map +1 -1
- package/lib/components/shared/three/ui/ComboCounter.d.ts.map +1 -1
- package/lib/components/shared/three/ui/ComboCounter.js.map +1 -1
- package/lib/components/shared/three/ui/HealthBar.d.ts.map +1 -1
- package/lib/components/shared/three/ui/HealthBar.js.map +1 -1
- package/lib/components/shared/three/ui/KoreanButton.d.ts.map +1 -1
- package/lib/components/shared/three/ui/KoreanButton.js.map +1 -1
- package/lib/components/shared/three/ui/KoreanPanel.d.ts.map +1 -1
- package/lib/components/shared/three/ui/KoreanPanel.js.map +1 -1
- package/lib/components/shared/three/ui/KoreanText.d.ts.map +1 -1
- package/lib/components/shared/three/ui/KoreanText.js.map +1 -1
- package/lib/components/shared/three/ui/MenuList.d.ts.map +1 -1
- package/lib/components/shared/three/ui/MenuList.js.map +1 -1
- package/lib/components/shared/three/ui/PlayerHUD.d.ts.map +1 -1
- package/lib/components/shared/three/ui/PlayerHUD.js.map +1 -1
- package/lib/components/shared/three/ui/ProgressBar.d.ts.map +1 -1
- package/lib/components/shared/three/ui/ProgressBar.js.map +1 -1
- package/lib/components/shared/three/ui/SpeedIndicatorHUD.d.ts +0 -1
- package/lib/components/shared/three/ui/SpeedIndicatorHUD.d.ts.map +1 -1
- package/lib/components/shared/three/ui/SpeedIndicatorHUD.js +0 -1
- package/lib/components/shared/three/ui/SpeedIndicatorHUD.js.map +1 -1
- package/lib/components/shared/three/ui/StaminaBar.d.ts.map +1 -1
- package/lib/components/shared/three/ui/StaminaBar.js.map +1 -1
- package/lib/components/shared/three/ui/TechniqueBar.d.ts.map +1 -1
- package/lib/components/shared/three/ui/TechniqueBar.js.map +1 -1
- package/lib/components/shared/three/ui/TechniqueBarContainer.d.ts.map +1 -1
- package/lib/components/shared/three/ui/TechniqueCard.d.ts.map +1 -1
- package/lib/components/shared/three/ui/TechniqueCard.js.map +1 -1
- package/lib/components/shared/three/ui/VitalPointOverlayControlsHtml.d.ts.map +1 -1
- package/lib/components/shared/three/ui/VitalPointOverlayControlsHtml.js.map +1 -1
- package/lib/components/shared/three/ui/VulnerabilityWindowHUD.d.ts.map +1 -1
- package/lib/components/shared/ui/BaseHUDContainer.d.ts.map +1 -1
- package/lib/components/shared/ui/BaseHUDContainer.js.map +1 -1
- package/lib/components/shared/ui/CombatTimer.d.ts.map +1 -1
- package/lib/components/shared/ui/CombatTimer.js.map +1 -1
- package/lib/components/shared/ui/ErrorBoundary.d.ts.map +1 -1
- package/lib/components/shared/ui/ErrorModal.d.ts.map +1 -1
- package/lib/components/shared/ui/ErrorModal.js.map +1 -1
- package/lib/components/shared/ui/HUDSection.d.ts.map +1 -1
- package/lib/components/shared/ui/LoadingState.d.ts.map +1 -1
- package/lib/components/shared/ui/LoadingState.js.map +1 -1
- package/lib/components/shared/ui/MobileHUDLayout.d.ts +0 -1
- package/lib/components/shared/ui/MobileHUDLayout.d.ts.map +1 -1
- package/lib/components/shared/ui/ResponsiveContainer.d.ts +0 -1
- package/lib/components/shared/ui/ResponsiveContainer.d.ts.map +1 -1
- package/lib/components/shared/ui/SplashScreen.d.ts.map +1 -1
- package/lib/components/shared/ui/SplashScreen.js +2 -2
- package/lib/components/shared/ui/SplashScreen.js.map +1 -1
- package/lib/components/shared/ui/StyledHUDPanel.d.ts.map +1 -1
- package/lib/components/shared/ui/VitalPointOverlayControlsPure.d.ts.map +1 -1
- package/lib/components/shared/ui/VitalPointOverlayControlsPure.js.map +1 -1
- package/lib/components/shared/ui/VolumeControl.d.ts.map +1 -1
- package/lib/components/shared/ui/VolumeControl.js.map +1 -1
- package/lib/components/shared/ui/shared/ConfirmDialog.d.ts.map +1 -1
- package/lib/components/shared/ui/shared/ConfirmDialog.js.map +1 -1
- package/lib/components/test/Hello3D.d.ts.map +1 -1
- package/lib/components/ui/combat/BalanceIndicatorOverlayHtml.d.ts.map +1 -1
- package/lib/components/ui/combat/BalanceIndicatorOverlayHtml.js.map +1 -1
- package/lib/components/ui/combat/ComboCounter.d.ts.map +1 -1
- package/lib/components/ui/combat/PressureMeter.d.ts.map +1 -1
- package/lib/systems/CombatSystem.d.ts +0 -6
- package/lib/systems/CombatSystem.d.ts.map +1 -1
- package/lib/systems/CombatSystem.js +0 -6
- package/lib/systems/CombatSystem.js.map +1 -1
- package/lib/systems/EffectCalculator.d.ts +0 -7
- package/lib/systems/EffectCalculator.d.ts.map +1 -1
- package/lib/systems/EffectCalculator.js +0 -4
- package/lib/systems/EffectCalculator.js.map +1 -1
- package/lib/systems/LayoutSystem.d.ts +0 -1
- package/lib/systems/LayoutSystem.d.ts.map +1 -1
- package/lib/systems/LayoutSystem.js +0 -1
- package/lib/systems/LayoutSystem.js.map +1 -1
- package/lib/systems/PlayerEffectManager.d.ts +0 -10
- package/lib/systems/PlayerEffectManager.d.ts.map +1 -1
- package/lib/systems/PlayerEffectManager.js +0 -3
- package/lib/systems/PlayerEffectManager.js.map +1 -1
- package/lib/systems/ResponsiveScaling.d.ts +0 -12
- package/lib/systems/ResponsiveScaling.d.ts.map +1 -1
- package/lib/systems/ResponsiveScaling.js +0 -12
- package/lib/systems/ResponsiveScaling.js.map +1 -1
- package/lib/systems/TrigramSystem.d.ts +0 -13
- package/lib/systems/TrigramSystem.d.ts.map +1 -1
- package/lib/systems/TrigramSystem.js +0 -13
- package/lib/systems/TrigramSystem.js.map +1 -1
- package/lib/systems/VitalPointSystem.d.ts +0 -10
- package/lib/systems/VitalPointSystem.d.ts.map +1 -1
- package/lib/systems/VitalPointSystem.js +0 -10
- package/lib/systems/VitalPointSystem.js.map +1 -1
- package/lib/systems/animation/builders/KeyframeInterpolation.d.ts +0 -4
- package/lib/systems/animation/builders/KeyframeInterpolation.d.ts.map +1 -1
- package/lib/systems/animation/builders/KeyframeInterpolation.js +0 -1
- package/lib/systems/animation/builders/KeyframeInterpolation.js.map +1 -1
- package/lib/systems/animation/builders/SkeletonRig.d.ts +0 -4
- package/lib/systems/animation/builders/SkeletonRig.d.ts.map +1 -1
- package/lib/systems/animation/builders/SkeletonRig.js +0 -3
- package/lib/systems/animation/builders/SkeletonRig.js.map +1 -1
- package/lib/systems/animation/catalogs/RecoveryAnimations.d.ts +0 -5
- package/lib/systems/animation/catalogs/RecoveryAnimations.d.ts.map +1 -1
- package/lib/systems/animation/catalogs/RecoveryAnimations.js +0 -5
- package/lib/systems/animation/catalogs/RecoveryAnimations.js.map +1 -1
- package/lib/systems/animation/core/AnimationHitTiming.d.ts +0 -6
- package/lib/systems/animation/core/AnimationHitTiming.d.ts.map +1 -1
- package/lib/systems/animation/core/AnimationHitTiming.js +0 -4
- package/lib/systems/animation/core/AnimationHitTiming.js.map +1 -1
- package/lib/systems/animation/core/AnimationTransitions.d.ts +0 -3
- package/lib/systems/animation/core/AnimationTransitions.d.ts.map +1 -1
- package/lib/systems/animation/core/AnimationTransitions.js.map +1 -1
- package/lib/systems/animation/core/LateralityTransform.d.ts +0 -3
- package/lib/systems/animation/core/LateralityTransform.d.ts.map +1 -1
- package/lib/systems/animation/core/LateralityTransform.js +0 -1
- package/lib/systems/animation/core/LateralityTransform.js.map +1 -1
- package/lib/systems/animation/core/RecoveryPhaseEnhancer.d.ts +0 -1
- package/lib/systems/animation/core/RecoveryPhaseEnhancer.d.ts.map +1 -1
- package/lib/systems/animation/core/RecoveryPhaseEnhancer.js.map +1 -1
- package/lib/systems/animation/core/TechniqueAnimationMapper.d.ts +0 -10
- package/lib/systems/animation/core/TechniqueAnimationMapper.d.ts.map +1 -1
- package/lib/systems/animation/core/TechniqueAnimationMapper.js +0 -8
- package/lib/systems/animation/core/TechniqueAnimationMapper.js.map +1 -1
- package/lib/systems/animation/core/TrigramAnimationMapping.d.ts +0 -10
- package/lib/systems/animation/core/TrigramAnimationMapping.d.ts.map +1 -1
- package/lib/systems/animation/core/TrigramStanceTransitions.d.ts +0 -2
- package/lib/systems/animation/core/TrigramStanceTransitions.d.ts.map +1 -1
- package/lib/systems/animation/core/types.d.ts +0 -39
- package/lib/systems/animation/core/types.d.ts.map +1 -1
- package/lib/systems/animation/core/types.js +0 -9
- package/lib/systems/animation/core/types.js.map +1 -1
- package/lib/systems/animation/systems/AdvancedJointMovements.d.ts +0 -27
- package/lib/systems/animation/systems/AdvancedJointMovements.d.ts.map +1 -1
- package/lib/systems/animation/systems/AdvancedJointMovements.js +0 -1
- package/lib/systems/animation/systems/AdvancedJointMovements.js.map +1 -1
- package/lib/systems/animation/systems/BodyFacingSystem.d.ts +0 -19
- package/lib/systems/animation/systems/BodyFacingSystem.d.ts.map +1 -1
- package/lib/systems/animation/systems/BodyFacingSystem.js +0 -14
- package/lib/systems/animation/systems/BodyFacingSystem.js.map +1 -1
- package/lib/systems/animation/systems/FacialExpressions.d.ts +0 -10
- package/lib/systems/animation/systems/FacialExpressions.d.ts.map +1 -1
- package/lib/systems/animation/systems/FacialExpressions.js +0 -2
- package/lib/systems/animation/systems/FacialExpressions.js.map +1 -1
- package/lib/systems/animation/systems/FallAnimations.d.ts +0 -4
- package/lib/systems/animation/systems/FallAnimations.d.ts.map +1 -1
- package/lib/systems/animation/systems/FallAnimations.js +0 -2
- package/lib/systems/animation/systems/FallAnimations.js.map +1 -1
- package/lib/systems/animation/systems/HeadMovements.d.ts +0 -10
- package/lib/systems/animation/systems/HeadMovements.d.ts.map +1 -1
- package/lib/systems/bodypart/BodyPartDamageIntegration.d.ts +0 -7
- package/lib/systems/bodypart/BodyPartDamageIntegration.d.ts.map +1 -1
- package/lib/systems/bodypart/BodyPartDamageIntegration.js +0 -7
- package/lib/systems/bodypart/BodyPartDamageIntegration.js.map +1 -1
- package/lib/systems/bodypart/BodyPartHealthSystem.d.ts +0 -13
- package/lib/systems/bodypart/BodyPartHealthSystem.d.ts.map +1 -1
- package/lib/systems/bodypart/BodyPartHealthSystem.js +0 -13
- package/lib/systems/bodypart/BodyPartHealthSystem.js.map +1 -1
- package/lib/systems/bodypart/BodyPartPositionMapping.d.ts +0 -6
- package/lib/systems/bodypart/BodyPartPositionMapping.d.ts.map +1 -1
- package/lib/systems/bodypart/BodyPartPositionMapping.js +0 -6
- package/lib/systems/bodypart/BodyPartPositionMapping.js.map +1 -1
- package/lib/systems/bodypart/CombatInjuryIntegration.d.ts +0 -10
- package/lib/systems/bodypart/CombatInjuryIntegration.d.ts.map +1 -1
- package/lib/systems/bodypart/CombatInjuryIntegration.js +0 -8
- package/lib/systems/bodypart/CombatInjuryIntegration.js.map +1 -1
- package/lib/systems/bodypart/InjuryIntegration.d.ts +0 -2
- package/lib/systems/bodypart/InjuryIntegration.d.ts.map +1 -1
- package/lib/systems/bodypart/InjuryIntegration.js +0 -2
- package/lib/systems/bodypart/InjuryIntegration.js.map +1 -1
- package/lib/systems/bodypart/InjuryTracker.d.ts +0 -14
- package/lib/systems/bodypart/InjuryTracker.d.ts.map +1 -1
- package/lib/systems/bodypart/InjuryTracker.js +0 -12
- package/lib/systems/bodypart/InjuryTracker.js.map +1 -1
- package/lib/systems/bodypart/MovementPenaltySystem.d.ts +0 -8
- package/lib/systems/bodypart/MovementPenaltySystem.d.ts.map +1 -1
- package/lib/systems/bodypart/MovementPenaltySystem.js +0 -8
- package/lib/systems/bodypart/MovementPenaltySystem.js.map +1 -1
- package/lib/systems/bodypart/PlayerInjuryTrackingManager.d.ts +0 -8
- package/lib/systems/bodypart/PlayerInjuryTrackingManager.d.ts.map +1 -1
- package/lib/systems/bodypart/PlayerInjuryTrackingManager.js +0 -8
- package/lib/systems/bodypart/PlayerInjuryTrackingManager.js.map +1 -1
- package/lib/systems/bodypart/types.d.ts +0 -13
- package/lib/systems/bodypart/types.d.ts.map +1 -1
- package/lib/systems/bodypart/types.js +0 -5
- package/lib/systems/bodypart/types.js.map +1 -1
- package/lib/systems/breathing/BreathingDisruptionSystem.d.ts +0 -3
- package/lib/systems/breathing/BreathingDisruptionSystem.d.ts.map +1 -1
- package/lib/systems/breathing/BreathingDisruptionSystem.js +0 -2
- package/lib/systems/breathing/BreathingDisruptionSystem.js.map +1 -1
- package/lib/systems/combat/BalanceSystem.d.ts +0 -25
- package/lib/systems/combat/BalanceSystem.d.ts.map +1 -1
- package/lib/systems/combat/BalanceSystem.js +0 -25
- package/lib/systems/combat/BalanceSystem.js.map +1 -1
- package/lib/systems/combat/BreakingStatusEffects.d.ts +0 -4
- package/lib/systems/combat/BreakingStatusEffects.d.ts.map +1 -1
- package/lib/systems/combat/BreakingStatusEffects.js +0 -3
- package/lib/systems/combat/BreakingStatusEffects.js.map +1 -1
- package/lib/systems/combat/CombatStateSystem.d.ts +0 -9
- package/lib/systems/combat/CombatStateSystem.d.ts.map +1 -1
- package/lib/systems/combat/CombatStateSystem.js +0 -9
- package/lib/systems/combat/CombatStateSystem.js.map +1 -1
- package/lib/systems/combat/ConsciousnessSystem.d.ts +0 -16
- package/lib/systems/combat/ConsciousnessSystem.d.ts.map +1 -1
- package/lib/systems/combat/ConsciousnessSystem.js +0 -16
- package/lib/systems/combat/ConsciousnessSystem.js.map +1 -1
- package/lib/systems/combat/FallIntegration.d.ts +0 -3
- package/lib/systems/combat/FallIntegration.d.ts.map +1 -1
- package/lib/systems/combat/FallIntegration.js +0 -3
- package/lib/systems/combat/FallIntegration.js.map +1 -1
- package/lib/systems/combat/GrappleSystem.d.ts +0 -2
- package/lib/systems/combat/GrappleSystem.d.ts.map +1 -1
- package/lib/systems/combat/GrappleSystem.js +0 -2
- package/lib/systems/combat/GrappleSystem.js.map +1 -1
- package/lib/systems/combat/LimbExposureSystem.d.ts +0 -7
- package/lib/systems/combat/LimbExposureSystem.d.ts.map +1 -1
- package/lib/systems/combat/LimbExposureSystem.js +0 -7
- package/lib/systems/combat/LimbExposureSystem.js.map +1 -1
- package/lib/systems/combat/PainResponseSystem.d.ts +0 -11
- package/lib/systems/combat/PainResponseSystem.d.ts.map +1 -1
- package/lib/systems/combat/PainResponseSystem.js +0 -11
- package/lib/systems/combat/PainResponseSystem.js.map +1 -1
- package/lib/systems/combat/painConsciousnessUtils.d.ts +0 -7
- package/lib/systems/combat/painConsciousnessUtils.d.ts.map +1 -1
- package/lib/systems/combat/painConsciousnessUtils.js +0 -7
- package/lib/systems/combat/painConsciousnessUtils.js.map +1 -1
- package/lib/systems/effects.d.ts +11 -0
- package/lib/systems/effects.d.ts.map +1 -1
- package/lib/systems/effects.js +10 -0
- package/lib/systems/effects.js.map +1 -1
- package/lib/systems/game.d.ts +16 -0
- package/lib/systems/game.d.ts.map +1 -1
- package/lib/systems/game.js +1 -0
- package/lib/systems/game.js.map +1 -1
- package/lib/systems/index.d.ts +5 -1
- package/lib/systems/index.d.ts.map +1 -1
- package/lib/systems/index.js.map +1 -1
- package/lib/systems/movement/InjuryMovementModifier.d.ts +0 -10
- package/lib/systems/movement/InjuryMovementModifier.d.ts.map +1 -1
- package/lib/systems/movement/InjuryMovementModifier.js +0 -7
- package/lib/systems/movement/InjuryMovementModifier.js.map +1 -1
- package/lib/systems/movement/integration.d.ts +0 -3
- package/lib/systems/movement/integration.d.ts.map +1 -1
- package/lib/systems/movement/integration.js +0 -3
- package/lib/systems/movement/integration.js.map +1 -1
- package/lib/systems/physics/AttackMovementPhysics.d.ts +0 -9
- package/lib/systems/physics/AttackMovementPhysics.d.ts.map +1 -1
- package/lib/systems/physics/AttackMovementPhysics.js +0 -7
- package/lib/systems/physics/AttackMovementPhysics.js.map +1 -1
- package/lib/systems/physics/CollisionDetection.d.ts +0 -6
- package/lib/systems/physics/CollisionDetection.d.ts.map +1 -1
- package/lib/systems/physics/CollisionDetection.js +0 -6
- package/lib/systems/physics/CollisionDetection.js.map +1 -1
- package/lib/systems/physics/CoordinateMapper.d.ts +0 -1
- package/lib/systems/physics/CoordinateMapper.d.ts.map +1 -1
- package/lib/systems/physics/CoordinateMapper.js +0 -1
- package/lib/systems/physics/CoordinateMapper.js.map +1 -1
- package/lib/systems/physics/KnockbackPhysics.d.ts +0 -11
- package/lib/systems/physics/KnockbackPhysics.d.ts.map +1 -1
- package/lib/systems/physics/KnockbackPhysics.js +0 -8
- package/lib/systems/physics/KnockbackPhysics.js.map +1 -1
- package/lib/systems/physics/MovementPhysics.d.ts +0 -10
- package/lib/systems/physics/MovementPhysics.d.ts.map +1 -1
- package/lib/systems/physics/MovementPhysics.js +0 -8
- package/lib/systems/physics/MovementPhysics.js.map +1 -1
- package/lib/systems/physics/PhysicalReachCalculator.d.ts +0 -6
- package/lib/systems/physics/PhysicalReachCalculator.d.ts.map +1 -1
- package/lib/systems/physics/PhysicalReachCalculator.js +0 -5
- package/lib/systems/physics/PhysicalReachCalculator.js.map +1 -1
- package/lib/systems/physics/SpeedModifierSystem.d.ts +0 -5
- package/lib/systems/physics/SpeedModifierSystem.d.ts.map +1 -1
- package/lib/systems/physics/SpeedModifierSystem.js +0 -4
- package/lib/systems/physics/SpeedModifierSystem.js.map +1 -1
- package/lib/systems/player.d.ts +0 -5
- package/lib/systems/player.d.ts.map +1 -1
- package/lib/systems/trigram/TrigramCalculator.d.ts +0 -1
- package/lib/systems/trigram/TrigramCalculator.d.ts.map +1 -1
- package/lib/systems/trigram/TrigramCalculator.js +0 -1
- package/lib/systems/trigram/TrigramCalculator.js.map +1 -1
- package/lib/systems/trigram/types.d.ts +0 -4
- package/lib/systems/trigram/types.d.ts.map +1 -1
- package/lib/systems/trigram/types.js +0 -2
- package/lib/systems/trigram/types.js.map +1 -1
- package/lib/systems/types.d.ts +7 -2
- package/lib/systems/types.d.ts.map +1 -1
- package/lib/systems/types.js.map +1 -1
- package/lib/systems/vitalpoint/DamageCalculator.d.ts +0 -3
- package/lib/systems/vitalpoint/DamageCalculator.d.ts.map +1 -1
- package/lib/systems/vitalpoint/DamageCalculator.js +0 -3
- package/lib/systems/vitalpoint/DamageCalculator.js.map +1 -1
- package/lib/systems/vitalpoint/KoreanVitalPoints.d.ts +0 -8
- package/lib/systems/vitalpoint/KoreanVitalPoints.d.ts.map +1 -1
- package/lib/systems/vitalpoint/KoreanVitalPoints.js +0 -8
- package/lib/systems/vitalpoint/KoreanVitalPoints.js.map +1 -1
- package/lib/systems/vitalpoint/VitalPointsData.d.ts +0 -3
- package/lib/systems/vitalpoint/VitalPointsData.d.ts.map +1 -1
- package/lib/systems/vitalpoint/VitalPointsData.js +0 -1
- package/lib/systems/vitalpoint/VitalPointsData.js.map +1 -1
- package/lib/types/PhysicsTypes.d.ts +21 -78
- package/lib/types/PhysicsTypes.d.ts.map +1 -1
- package/lib/types/PhysicsTypes.js +17 -63
- package/lib/types/PhysicsTypes.js.map +1 -1
- package/lib/types/clothing.d.ts +0 -9
- package/lib/types/clothing.d.ts.map +1 -1
- package/lib/types/constants/animations.d.ts +35 -1
- package/lib/types/constants/animations.d.ts.map +1 -1
- package/lib/types/constants/animations.js +12 -1
- package/lib/types/constants/animations.js.map +1 -1
- package/lib/types/constants/colors.d.ts +28 -2
- package/lib/types/constants/colors.d.ts.map +1 -1
- package/lib/types/constants/colors.js +30 -4
- package/lib/types/constants/colors.js.map +1 -1
- package/lib/types/constants/index.d.ts +5 -1
- package/lib/types/constants/index.d.ts.map +1 -1
- package/lib/types/constants/index.js.map +1 -1
- package/lib/types/constants/performance.d.ts +0 -2
- package/lib/types/constants/performance.d.ts.map +1 -1
- package/lib/types/constants/performance.js +0 -2
- package/lib/types/constants/performance.js.map +1 -1
- package/lib/types/constants/typography.d.ts +40 -2
- package/lib/types/constants/typography.d.ts.map +1 -1
- package/lib/types/constants/typography.js +40 -2
- package/lib/types/constants/typography.js.map +1 -1
- package/lib/types/constants/ui.d.ts +89 -1
- package/lib/types/constants/ui.d.ts.map +1 -1
- package/lib/types/constants/ui.js +33 -1
- package/lib/types/constants/ui.js.map +1 -1
- package/lib/types/facial.d.ts +0 -15
- package/lib/types/facial.d.ts.map +1 -1
- package/lib/types/facial.js +0 -8
- package/lib/types/facial.js.map +1 -1
- package/lib/types/hand-animation.d.ts +34 -147
- package/lib/types/hand-animation.d.ts.map +1 -1
- package/lib/types/hand-animation.js +0 -2
- package/lib/types/hand-animation.js.map +1 -1
- package/lib/types/injury.d.ts +0 -2
- package/lib/types/injury.d.ts.map +1 -1
- package/lib/types/injury.js +0 -1
- package/lib/types/injury.js.map +1 -1
- package/lib/types/physics.d.ts +0 -21
- package/lib/types/physics.d.ts.map +1 -1
- package/lib/types/physics.js +0 -6
- package/lib/types/physics.js.map +1 -1
- package/lib/types/physicsConstants.d.ts +0 -12
- package/lib/types/physicsConstants.d.ts.map +1 -1
- package/lib/types/physicsConstants.js +0 -12
- package/lib/types/physicsConstants.js.map +1 -1
- package/lib/types/player-visual.d.ts +45 -189
- package/lib/types/player-visual.d.ts.map +1 -1
- package/lib/types/technique.d.ts +1 -5
- package/lib/types/technique.d.ts.map +1 -1
- package/lib/types/techniqueId.d.ts +0 -1
- package/lib/types/techniqueId.d.ts.map +1 -1
- package/lib/types/techniqueId.js +0 -1
- package/lib/types/techniqueId.js.map +1 -1
- package/lib/utils/arenaWorldDimensions.d.ts +0 -11
- package/lib/utils/arenaWorldDimensions.d.ts.map +1 -1
- package/lib/utils/arenaWorldDimensions.js +0 -6
- package/lib/utils/arenaWorldDimensions.js.map +1 -1
- package/lib/utils/controlMapping.d.ts +3 -4
- package/lib/utils/controlMapping.d.ts.map +1 -1
- package/lib/utils/controlMapping.js +1 -2
- package/lib/utils/controlMapping.js.map +1 -1
- package/lib/utils/deviceDetection.d.ts +0 -5
- package/lib/utils/deviceDetection.d.ts.map +1 -1
- package/lib/utils/deviceDetection.js +0 -5
- package/lib/utils/deviceDetection.js.map +1 -1
- package/lib/utils/hapticFeedback.d.ts +23 -95
- package/lib/utils/hapticFeedback.d.ts.map +1 -1
- package/lib/utils/hapticFeedback.js +9 -39
- package/lib/utils/hapticFeedback.js.map +1 -1
- package/lib/utils/haptics.d.ts +0 -3
- package/lib/utils/haptics.d.ts.map +1 -1
- package/lib/utils/haptics.js +0 -1
- package/lib/utils/haptics.js.map +1 -1
- package/lib/utils/math.d.ts +0 -3
- package/lib/utils/math.d.ts.map +1 -1
- package/lib/utils/math.js +0 -2
- package/lib/utils/math.js.map +1 -1
- package/lib/utils/mobileLayoutHelpers.d.ts +0 -3
- package/lib/utils/mobileLayoutHelpers.d.ts.map +1 -1
- package/lib/utils/mobileLayoutHelpers.js +0 -1
- package/lib/utils/mobileLayoutHelpers.js.map +1 -1
- package/lib/utils/mobileUIUtils.d.ts +5 -100
- package/lib/utils/mobileUIUtils.d.ts.map +1 -1
- package/lib/utils/mobileUIUtils.js +0 -9
- package/lib/utils/mobileUIUtils.js.map +1 -1
- package/lib/utils/physicalAttributeValidation.d.ts.map +1 -1
- package/lib/utils/player3DHelpers.d.ts.map +1 -1
- package/lib/utils/player3DHelpers.js.map +1 -1
- package/lib/utils/responsiveLayoutHelpers.d.ts +0 -65
- package/lib/utils/responsiveLayoutHelpers.d.ts.map +1 -1
- package/lib/utils/responsiveLayoutHelpers.js +0 -65
- package/lib/utils/responsiveLayoutHelpers.js.map +1 -1
- package/lib/utils/responsiveOrientationConstants.d.ts +0 -7
- package/lib/utils/responsiveOrientationConstants.d.ts.map +1 -1
- package/lib/utils/responsiveOrientationConstants.js +0 -7
- package/lib/utils/responsiveOrientationConstants.js.map +1 -1
- package/lib/utils/safeAreaUtils.d.ts +0 -6
- package/lib/utils/safeAreaUtils.d.ts.map +1 -1
- package/lib/utils/safeAreaUtils.js +0 -2
- package/lib/utils/safeAreaUtils.js.map +1 -1
- package/lib/utils/sharedPhysicsConfig.d.ts +0 -4
- package/lib/utils/sharedPhysicsConfig.d.ts.map +1 -1
- package/lib/utils/sharedPhysicsConfig.js +0 -2
- package/lib/utils/sharedPhysicsConfig.js.map +1 -1
- package/lib/utils/skeletonScaling.d.ts +0 -9
- package/lib/utils/skeletonScaling.d.ts.map +1 -1
- package/lib/utils/skeletonScaling.js +0 -1
- package/lib/utils/skeletonScaling.js.map +1 -1
- package/package.json +7 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MobileControlsPure.js","names":[],"sources":["../../../../src/components/shared/mobile/MobileControlsPure.tsx"],"sourcesContent":["/**\n * MobileControlsPure - Pure DOM mobile controls (no Three.js/drei dependency)\n *\n * These controls render OUTSIDE the Three.js Canvas for reliable touch event handling.\n * The key difference from VirtualDPad/ActionButtons is that these don't use drei's Html\n * component, which can intercept touch events on mobile devices.\n *\n * Visual style matches the existing Korean cyberpunk aesthetic.\n *\n * @module components/mobile/MobileControlsPure\n * @category Mobile Controls\n * @korean 순수 DOM 모바일 컨트롤\n */\n\nimport React, { useCallback, useMemo, useState } from \"react\";\nimport { KOREAN_COLORS, FONT_FAMILY } from \"@/types/constants\";\nimport { hexToRgbaString } from \"../../../utils/colorUtils\";\nimport { triggerHaptic } from \"../../../utils/haptics\";\n\n// Re-export types from VirtualDPad for compatibility\nexport type Direction =\n | \"up\"\n | \"up-right\"\n | \"right\"\n | \"down-right\"\n | \"down\"\n | \"down-left\"\n | \"left\"\n | \"up-left\";\n\nexport type DPadEventType = \"start\" | \"end\";\nexport type ButtonEventType = \"start\" | \"end\";\n\n/**\n * Props for the combined mobile controls overlay\n */\nexport interface MobileControlsOverlayProps {\n /** Callback when D-Pad direction changes */\n readonly onMove: (\n direction: Direction | null,\n eventType: DPadEventType,\n ) => void;\n /** Callback when attack is pressed */\n readonly onAttack: () => void;\n /** Callback when block is pressed/released */\n readonly onBlock: (eventType: ButtonEventType) => void;\n /** Whether controls are disabled */\n readonly disabled?: boolean;\n /** Bottom offset in pixels (default: 160 to clear BottomHUD) */\n readonly bottom?: number;\n /** Opacity (default: 0.85) */\n readonly opacity?: number;\n /** Viewport width for responsive control sizing */\n readonly viewportWidth?: number;\n /** Viewport height for responsive control sizing */\n readonly viewportHeight?: number;\n}\n\n/**\n * Direction configuration for D-Pad buttons\n */\ninterface DirectionConfig {\n readonly direction: Direction;\n readonly angle: number;\n readonly symbol: string;\n readonly keys: string[]; // Keys to dispatch\n}\n\nconst DIRECTIONS: readonly DirectionConfig[] = [\n { direction: \"up\", angle: 0, symbol: \"▲\", keys: [\"w\"] },\n { direction: \"up-right\", angle: 45, symbol: \"◥\", keys: [\"w\", \"d\"] },\n { direction: \"right\", angle: 90, symbol: \"▶\", keys: [\"d\"] },\n { direction: \"down-right\", angle: 135, symbol: \"◢\", keys: [\"s\", \"d\"] },\n { direction: \"down\", angle: 180, symbol: \"▼\", keys: [\"s\"] },\n { direction: \"down-left\", angle: 225, symbol: \"◣\", keys: [\"s\", \"a\"] },\n { direction: \"left\", angle: 270, symbol: \"◀\", keys: [\"a\"] },\n { direction: \"up-left\", angle: 315, symbol: \"◤\", keys: [\"w\", \"a\"] },\n] as const;\n\n/**\n * Fallback CSS-pixel viewport used only when a parent does not provide live\n * dimensions. 390×844 matches the common iPhone 13/14/15 CSS viewport class\n * and approximates many mid-size Android portrait viewports, avoiding oversized\n * controls on compact devices.\n */\nconst DEFAULT_MOBILE_VIEWPORT = {\n width: 390,\n height: 844,\n} as const;\n\n/**\n * D-Pad diameter target as a ratio of the shortest viewport side. 34% keeps the\n * full radial control reachable by thumb while each directional button remains\n * at or above the 44px WCAG touch target minimum after clamping.\n */\nconst DPAD_SHORTEST_SIDE_RATIO = 0.34;\n\n/**\n * MobileControlsOverlay - Floating mobile controls rendered outside Canvas\n *\n * Positions D-Pad on left, Action buttons on right, floating above BottomHUD.\n * Uses pure DOM events for reliable mobile touch handling.\n */\nexport const MobileControlsOverlay: React.FC<MobileControlsOverlayProps> =\n React.memo(\n ({\n onMove,\n onAttack,\n onBlock,\n disabled = false,\n bottom = 160,\n opacity = 0.85,\n viewportWidth = DEFAULT_MOBILE_VIEWPORT.width,\n viewportHeight = DEFAULT_MOBILE_VIEWPORT.height,\n }) => {\n const [activeDirection, setActiveDirection] = useState<Direction | null>(\n null,\n );\n const [attackPressed, setAttackPressed] = useState(false);\n const [blockPressed, setBlockPressed] = useState(false);\n\n // D-Pad/action sizing scales down on narrow mobile screens while\n // preserving WCAG touch target minimums.\n const controlLayout = useMemo(() => {\n const shortestSide = Math.min(viewportWidth, viewportHeight);\n const dpadSize = Math.round(\n Math.max(\n 112,\n Math.min(140, shortestSide * DPAD_SHORTEST_SIDE_RATIO),\n ),\n );\n const buttonSize = Math.max(44, Math.round(dpadSize * 0.34));\n const buttonPlacementRadius = dpadSize * 0.32;\n const attackSize = Math.round(\n Math.max(64, Math.min(80, dpadSize * 0.58)),\n );\n const blockSize = Math.round(\n Math.max(54, Math.min(65, dpadSize * 0.47)),\n );\n const sidePadding = Math.round(\n Math.max(12, Math.min(20, viewportWidth * 0.04)),\n );\n\n return {\n dpadSize,\n buttonSize,\n buttonPlacementRadius,\n attackSize,\n blockSize,\n sidePadding,\n overlayHeight: dpadSize + 32,\n actionGap: Math.max(8, Math.round(dpadSize * 0.08)),\n };\n }, [viewportHeight, viewportWidth]);\n\n // Handle D-Pad press\n const handleDPadStart = useCallback(\n (e: React.TouchEvent | React.MouseEvent, direction: Direction) => {\n if (disabled) return;\n e.preventDefault();\n e.stopPropagation();\n setActiveDirection(direction);\n triggerHaptic(\"light\");\n onMove(direction, \"start\");\n },\n [disabled, onMove],\n );\n\n // Handle D-Pad release\n const handleDPadEnd = useCallback(\n (e: React.TouchEvent | React.MouseEvent) => {\n if (disabled) return;\n e.preventDefault();\n e.stopPropagation();\n setActiveDirection(null);\n onMove(null, \"end\");\n },\n [disabled, onMove],\n );\n\n // Handle Attack press\n const handleAttackStart = useCallback(\n (e: React.TouchEvent | React.MouseEvent) => {\n if (disabled) return;\n e.preventDefault();\n e.stopPropagation();\n setAttackPressed(true);\n triggerHaptic(\"medium\");\n onAttack();\n },\n [disabled, onAttack],\n );\n\n const handleAttackEnd = useCallback(\n (e: React.TouchEvent | React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setAttackPressed(false);\n },\n [],\n );\n\n // Handle Block press/release\n const handleBlockStart = useCallback(\n (e: React.TouchEvent | React.MouseEvent) => {\n if (disabled) return;\n e.preventDefault();\n e.stopPropagation();\n setBlockPressed(true);\n triggerHaptic(\"light\");\n onBlock(\"start\");\n },\n [disabled, onBlock],\n );\n\n const handleBlockEnd = useCallback(\n (e: React.TouchEvent | React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setBlockPressed(false);\n onBlock(\"end\");\n },\n [onBlock],\n );\n\n // Common button styles\n const glowStyle = useMemo(\n () => ({\n boxShadow: `0 0 20px ${hexToRgbaString(KOREAN_COLORS.PRIMARY_CYAN, 0.4)}, inset 0 0 10px ${hexToRgbaString(KOREAN_COLORS.PRIMARY_CYAN, 0.2)}`,\n }),\n [],\n );\n\n return (\n <div\n style={{\n position: \"absolute\", // Changed from fixed to position relative to container\n bottom: `${bottom}px`,\n left: 0,\n right: 0,\n height: `${controlLayout.overlayHeight}px`,\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"flex-end\",\n padding: `0 ${controlLayout.sidePadding}px`,\n pointerEvents: \"none\",\n zIndex: 1000,\n opacity: disabled ? 0.4 : opacity,\n }}\n data-testid=\"mobile-controls-overlay\"\n >\n {/* D-Pad (Left Side) */}\n <div\n style={{\n position: \"relative\",\n width: `${controlLayout.dpadSize}px`,\n height: `${controlLayout.dpadSize}px`,\n pointerEvents: \"auto\",\n touchAction: \"none\",\n }}\n data-testid=\"mobile-dpad\"\n >\n {/* D-Pad Background Circle */}\n <div\n style={{\n position: \"absolute\",\n top: \"50%\",\n left: \"50%\",\n transform: \"translate(-50%, -50%)\",\n width: `${controlLayout.dpadSize * 0.9}px`,\n height: `${controlLayout.dpadSize * 0.9}px`,\n borderRadius: \"50%\",\n background: `radial-gradient(circle, ${hexToRgbaString(KOREAN_COLORS.UI_BACKGROUND_DARK, 0.8)} 0%, ${hexToRgbaString(KOREAN_COLORS.UI_BACKGROUND_DARK, 0.95)} 100%)`,\n border: `2px solid ${hexToRgbaString(KOREAN_COLORS.PRIMARY_CYAN, 0.5)}`,\n ...glowStyle,\n }}\n />\n\n {/* Direction Buttons */}\n {DIRECTIONS.map((config) => {\n const radian = (config.angle - 90) * (Math.PI / 180);\n const x = Math.cos(radian) * controlLayout.buttonPlacementRadius;\n const y = Math.sin(radian) * controlLayout.buttonPlacementRadius;\n const isActive = activeDirection === config.direction;\n\n return (\n <button\n key={config.direction}\n onTouchStart={(e) => handleDPadStart(e, config.direction)}\n onTouchEnd={handleDPadEnd}\n onTouchCancel={handleDPadEnd}\n onMouseDown={(e) => handleDPadStart(e, config.direction)}\n onMouseUp={handleDPadEnd}\n onMouseLeave={handleDPadEnd}\n style={{\n position: \"absolute\",\n left: `calc(50% + ${x}px - ${controlLayout.buttonSize / 2}px)`,\n top: `calc(50% + ${y}px - ${controlLayout.buttonSize / 2}px)`,\n width: `${controlLayout.buttonSize}px`,\n height: `${controlLayout.buttonSize}px`,\n borderRadius: \"50%\",\n background: isActive\n ? `radial-gradient(circle, ${hexToRgbaString(KOREAN_COLORS.ACCENT_GOLD, 1)} 0%, ${hexToRgbaString(KOREAN_COLORS.ACCENT_GOLD, 0.7)} 100%)`\n : `radial-gradient(circle, ${hexToRgbaString(KOREAN_COLORS.UI_BACKGROUND_MEDIUM, 0.9)} 0%, ${hexToRgbaString(KOREAN_COLORS.UI_BACKGROUND_DARK, 0.9)} 100%)`,\n border: `2px solid ${hexToRgbaString(isActive ? KOREAN_COLORS.ACCENT_GOLD : KOREAN_COLORS.PRIMARY_CYAN, isActive ? 1 : 0.7)}`,\n fontSize: \"14px\",\n color: isActive\n ? hexToRgbaString(KOREAN_COLORS.BLACK_SOLID, 1)\n : hexToRgbaString(KOREAN_COLORS.TEXT_PRIMARY, 1),\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n cursor: \"pointer\",\n touchAction: \"none\",\n transform: isActive ? \"scale(1.15)\" : \"scale(1)\",\n transition: \"transform 0.1s ease, background 0.1s ease\",\n boxShadow: isActive\n ? `0 0 15px ${hexToRgbaString(KOREAN_COLORS.ACCENT_GOLD, 0.8)}`\n : \"none\",\n outline: \"none\",\n WebkitTapHighlightColor: \"transparent\",\n }}\n aria-label={`이동 ${config.direction} | Move ${config.direction}`}\n data-testid={`mobile-dpad-${config.direction}`}\n >\n {config.symbol}\n </button>\n );\n })}\n\n {/* Center Indicator */}\n <div\n style={{\n position: \"absolute\",\n top: \"50%\",\n left: \"50%\",\n transform: \"translate(-50%, -50%)\",\n width: \"20px\",\n height: \"20px\",\n borderRadius: \"50%\",\n background: activeDirection\n ? hexToRgbaString(KOREAN_COLORS.ACCENT_GOLD, 0.9)\n : hexToRgbaString(KOREAN_COLORS.PRIMARY_CYAN, 0.6),\n border: `2px solid ${hexToRgbaString(KOREAN_COLORS.TEXT_PRIMARY, 0.8)}`,\n transition: \"background 0.15s ease\",\n }}\n />\n </div>\n\n {/* Action Buttons (Right Side) */}\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n gap: `${controlLayout.actionGap}px`,\n pointerEvents: \"auto\",\n touchAction: \"none\",\n }}\n data-testid=\"mobile-action-buttons\"\n >\n {/* Attack Button - Large Red */}\n <button\n onTouchStart={handleAttackStart}\n onTouchEnd={handleAttackEnd}\n onTouchCancel={handleAttackEnd}\n onMouseDown={handleAttackStart}\n onMouseUp={handleAttackEnd}\n onMouseLeave={handleAttackEnd}\n style={{\n width: `${controlLayout.attackSize}px`,\n height: `${controlLayout.attackSize}px`,\n borderRadius: \"50%\",\n background: attackPressed\n ? `radial-gradient(circle, ${hexToRgbaString(KOREAN_COLORS.PRIMARY_RED, 1)} 0%, ${hexToRgbaString(KOREAN_COLORS.PRIMARY_RED, 0.7)} 100%)`\n : `radial-gradient(circle, ${hexToRgbaString(KOREAN_COLORS.PRIMARY_RED, 0.9)} 0%, ${hexToRgbaString(KOREAN_COLORS.NEGATIVE_RED_DARK, 0.9)} 100%)`,\n border: `3px solid ${hexToRgbaString(KOREAN_COLORS.PRIMARY_RED, 1)}`,\n fontSize: \"28px\",\n color: hexToRgbaString(KOREAN_COLORS.TEXT_PRIMARY, 1),\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n cursor: \"pointer\",\n touchAction: \"none\",\n transform: attackPressed ? \"scale(0.92)\" : \"scale(1)\",\n transition: \"transform 0.1s ease\",\n boxShadow: attackPressed\n ? `0 0 25px ${hexToRgbaString(KOREAN_COLORS.PRIMARY_RED, 0.9)}`\n : `0 0 15px ${hexToRgbaString(KOREAN_COLORS.PRIMARY_RED, 0.5)}`,\n outline: \"none\",\n WebkitTapHighlightColor: \"transparent\",\n fontWeight: \"bold\",\n fontFamily: FONT_FAMILY.KOREAN,\n }}\n aria-label=\"공격 | Attack\"\n data-testid=\"mobile-attack-button\"\n >\n ⚡\n </button>\n\n {/* Block Button - Smaller Cyan */}\n <button\n onTouchStart={handleBlockStart}\n onTouchEnd={handleBlockEnd}\n onTouchCancel={handleBlockEnd}\n onMouseDown={handleBlockStart}\n onMouseUp={handleBlockEnd}\n onMouseLeave={handleBlockEnd}\n style={{\n width: `${controlLayout.blockSize}px`,\n height: `${controlLayout.blockSize}px`,\n borderRadius: \"50%\",\n marginLeft: \"auto\",\n background: blockPressed\n ? `radial-gradient(circle, ${hexToRgbaString(KOREAN_COLORS.PRIMARY_CYAN, 1)} 0%, ${hexToRgbaString(KOREAN_COLORS.PRIMARY_CYAN, 0.7)} 100%)`\n : `radial-gradient(circle, ${hexToRgbaString(KOREAN_COLORS.PRIMARY_CYAN, 0.8)} 0%, ${hexToRgbaString(KOREAN_COLORS.KI_LOW, 0.8)} 100%)`,\n border: `3px solid ${hexToRgbaString(KOREAN_COLORS.PRIMARY_CYAN, 1)}`,\n fontSize: \"22px\",\n color: hexToRgbaString(KOREAN_COLORS.TEXT_PRIMARY, 1),\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n cursor: \"pointer\",\n touchAction: \"none\",\n transform: blockPressed ? \"scale(0.92)\" : \"scale(1)\",\n transition: \"transform 0.1s ease\",\n boxShadow: blockPressed\n ? `0 0 20px ${hexToRgbaString(KOREAN_COLORS.PRIMARY_CYAN, 0.9)}`\n : `0 0 10px ${hexToRgbaString(KOREAN_COLORS.PRIMARY_CYAN, 0.4)}`,\n outline: \"none\",\n WebkitTapHighlightColor: \"transparent\",\n fontFamily: FONT_FAMILY.KOREAN,\n }}\n aria-label=\"방어 | Block\"\n data-testid=\"mobile-block-button\"\n >\n 🛡️\n </button>\n </div>\n </div>\n );\n },\n );\n\nMobileControlsOverlay.displayName = \"MobileControlsOverlay\";\n\nexport default MobileControlsOverlay;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MobileControlsPure.js","names":[],"sources":["../../../../src/components/shared/mobile/MobileControlsPure.tsx"],"sourcesContent":["/**\n * MobileControlsPure - Pure DOM mobile controls (no Three.js/drei dependency)\n *\n * These controls render OUTSIDE the Three.js Canvas for reliable touch event handling.\n * The key difference from VirtualDPad/ActionButtons is that these don't use drei's Html\n * component, which can intercept touch events on mobile devices.\n *\n * Visual style matches the existing Korean cyberpunk aesthetic.\n *\n * @module components/mobile/MobileControlsPure\n * @category Mobile Controls\n * @korean 순수 DOM 모바일 컨트롤\n */\n\nimport React, { useCallback, useMemo, useState } from \"react\";\nimport { KOREAN_COLORS, FONT_FAMILY } from \"@/types/constants\";\nimport { hexToRgbaString } from \"../../../utils/colorUtils\";\nimport { triggerHaptic } from \"../../../utils/haptics\";\n\nexport type Direction =\n | \"up\"\n | \"up-right\"\n | \"right\"\n | \"down-right\"\n | \"down\"\n | \"down-left\"\n | \"left\"\n | \"up-left\";\n\nexport type DPadEventType = \"start\" | \"end\";\nexport type ButtonEventType = \"start\" | \"end\";\n\n/**\n * Props for the combined mobile controls overlay\n */\nexport interface MobileControlsOverlayProps {\n /** Callback when D-Pad direction changes */\n readonly onMove: (\n direction: Direction | null,\n eventType: DPadEventType,\n ) => void;\n /** Callback when attack is pressed */\n readonly onAttack: () => void;\n /** Callback when block is pressed/released */\n readonly onBlock: (eventType: ButtonEventType) => void;\n /** Whether controls are disabled */\n readonly disabled?: boolean;\n /** Bottom offset in pixels (default: 160 to clear BottomHUD) */\n readonly bottom?: number;\n /** Opacity (default: 0.85) */\n readonly opacity?: number;\n /** Viewport width for responsive control sizing */\n readonly viewportWidth?: number;\n /** Viewport height for responsive control sizing */\n readonly viewportHeight?: number;\n}\n\n/**\n * Direction configuration for D-Pad buttons\n */\ninterface DirectionConfig {\n readonly direction: Direction;\n readonly angle: number;\n readonly symbol: string;\n readonly keys: string[]; // Keys to dispatch\n}\n\nconst DIRECTIONS: readonly DirectionConfig[] = [\n { direction: \"up\", angle: 0, symbol: \"▲\", keys: [\"w\"] },\n { direction: \"up-right\", angle: 45, symbol: \"◥\", keys: [\"w\", \"d\"] },\n { direction: \"right\", angle: 90, symbol: \"▶\", keys: [\"d\"] },\n { direction: \"down-right\", angle: 135, symbol: \"◢\", keys: [\"s\", \"d\"] },\n { direction: \"down\", angle: 180, symbol: \"▼\", keys: [\"s\"] },\n { direction: \"down-left\", angle: 225, symbol: \"◣\", keys: [\"s\", \"a\"] },\n { direction: \"left\", angle: 270, symbol: \"◀\", keys: [\"a\"] },\n { direction: \"up-left\", angle: 315, symbol: \"◤\", keys: [\"w\", \"a\"] },\n] as const;\n\n/**\n * Fallback CSS-pixel viewport used only when a parent does not provide live\n * dimensions. 390×844 matches the common iPhone 13/14/15 CSS viewport class\n * and approximates many mid-size Android portrait viewports, avoiding oversized\n * controls on compact devices.\n */\nconst DEFAULT_MOBILE_VIEWPORT = {\n width: 390,\n height: 844,\n} as const;\n\n/**\n * D-Pad diameter target as a ratio of the shortest viewport side. 34% keeps the\n * full radial control reachable by thumb while each directional button remains\n * at or above the 44px WCAG touch target minimum after clamping.\n */\nconst DPAD_SHORTEST_SIDE_RATIO = 0.34;\n\n/**\n * MobileControlsOverlay - Floating mobile controls rendered outside Canvas\n *\n * Positions D-Pad on left, Action buttons on right, floating above BottomHUD.\n * Uses pure DOM events for reliable mobile touch handling.\n */\nexport const MobileControlsOverlay: React.FC<MobileControlsOverlayProps> =\n React.memo(\n ({\n onMove,\n onAttack,\n onBlock,\n disabled = false,\n bottom = 160,\n opacity = 0.85,\n viewportWidth = DEFAULT_MOBILE_VIEWPORT.width,\n viewportHeight = DEFAULT_MOBILE_VIEWPORT.height,\n }) => {\n const [activeDirection, setActiveDirection] = useState<Direction | null>(\n null,\n );\n const [attackPressed, setAttackPressed] = useState(false);\n const [blockPressed, setBlockPressed] = useState(false);\n\n const controlLayout = useMemo(() => {\n const shortestSide = Math.min(viewportWidth, viewportHeight);\n const dpadSize = Math.round(\n Math.max(\n 112,\n Math.min(140, shortestSide * DPAD_SHORTEST_SIDE_RATIO),\n ),\n );\n const buttonSize = Math.max(44, Math.round(dpadSize * 0.34));\n const buttonPlacementRadius = dpadSize * 0.32;\n const attackSize = Math.round(\n Math.max(64, Math.min(80, dpadSize * 0.58)),\n );\n const blockSize = Math.round(\n Math.max(54, Math.min(65, dpadSize * 0.47)),\n );\n const sidePadding = Math.round(\n Math.max(12, Math.min(20, viewportWidth * 0.04)),\n );\n\n return {\n dpadSize,\n buttonSize,\n buttonPlacementRadius,\n attackSize,\n blockSize,\n sidePadding,\n overlayHeight: dpadSize + 32,\n actionGap: Math.max(8, Math.round(dpadSize * 0.08)),\n };\n }, [viewportHeight, viewportWidth]);\n\n const handleDPadStart = useCallback(\n (e: React.TouchEvent | React.MouseEvent, direction: Direction) => {\n if (disabled) return;\n e.preventDefault();\n e.stopPropagation();\n setActiveDirection(direction);\n triggerHaptic(\"light\");\n onMove(direction, \"start\");\n },\n [disabled, onMove],\n );\n\n const handleDPadEnd = useCallback(\n (e: React.TouchEvent | React.MouseEvent) => {\n if (disabled) return;\n e.preventDefault();\n e.stopPropagation();\n setActiveDirection(null);\n onMove(null, \"end\");\n },\n [disabled, onMove],\n );\n\n const handleAttackStart = useCallback(\n (e: React.TouchEvent | React.MouseEvent) => {\n if (disabled) return;\n e.preventDefault();\n e.stopPropagation();\n setAttackPressed(true);\n triggerHaptic(\"medium\");\n onAttack();\n },\n [disabled, onAttack],\n );\n\n const handleAttackEnd = useCallback(\n (e: React.TouchEvent | React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setAttackPressed(false);\n },\n [],\n );\n\n const handleBlockStart = useCallback(\n (e: React.TouchEvent | React.MouseEvent) => {\n if (disabled) return;\n e.preventDefault();\n e.stopPropagation();\n setBlockPressed(true);\n triggerHaptic(\"light\");\n onBlock(\"start\");\n },\n [disabled, onBlock],\n );\n\n const handleBlockEnd = useCallback(\n (e: React.TouchEvent | React.MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setBlockPressed(false);\n onBlock(\"end\");\n },\n [onBlock],\n );\n\n const glowStyle = useMemo(\n () => ({\n boxShadow: `0 0 20px ${hexToRgbaString(KOREAN_COLORS.PRIMARY_CYAN, 0.4)}, inset 0 0 10px ${hexToRgbaString(KOREAN_COLORS.PRIMARY_CYAN, 0.2)}`,\n }),\n [],\n );\n\n return (\n <div\n style={{\n position: \"absolute\", // Changed from fixed to position relative to container\n bottom: `${bottom}px`,\n left: 0,\n right: 0,\n height: `${controlLayout.overlayHeight}px`,\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"flex-end\",\n padding: `0 ${controlLayout.sidePadding}px`,\n pointerEvents: \"none\",\n zIndex: 1000,\n opacity: disabled ? 0.4 : opacity,\n }}\n data-testid=\"mobile-controls-overlay\"\n >\n {/* D-Pad (Left Side) */}\n <div\n style={{\n position: \"relative\",\n width: `${controlLayout.dpadSize}px`,\n height: `${controlLayout.dpadSize}px`,\n pointerEvents: \"auto\",\n touchAction: \"none\",\n }}\n data-testid=\"mobile-dpad\"\n >\n {/* D-Pad Background Circle */}\n <div\n style={{\n position: \"absolute\",\n top: \"50%\",\n left: \"50%\",\n transform: \"translate(-50%, -50%)\",\n width: `${controlLayout.dpadSize * 0.9}px`,\n height: `${controlLayout.dpadSize * 0.9}px`,\n borderRadius: \"50%\",\n background: `radial-gradient(circle, ${hexToRgbaString(KOREAN_COLORS.UI_BACKGROUND_DARK, 0.8)} 0%, ${hexToRgbaString(KOREAN_COLORS.UI_BACKGROUND_DARK, 0.95)} 100%)`,\n border: `2px solid ${hexToRgbaString(KOREAN_COLORS.PRIMARY_CYAN, 0.5)}`,\n ...glowStyle,\n }}\n />\n\n {/* Direction Buttons */}\n {DIRECTIONS.map((config) => {\n const radian = (config.angle - 90) * (Math.PI / 180);\n const x = Math.cos(radian) * controlLayout.buttonPlacementRadius;\n const y = Math.sin(radian) * controlLayout.buttonPlacementRadius;\n const isActive = activeDirection === config.direction;\n\n return (\n <button\n key={config.direction}\n onTouchStart={(e) => handleDPadStart(e, config.direction)}\n onTouchEnd={handleDPadEnd}\n onTouchCancel={handleDPadEnd}\n onMouseDown={(e) => handleDPadStart(e, config.direction)}\n onMouseUp={handleDPadEnd}\n onMouseLeave={handleDPadEnd}\n style={{\n position: \"absolute\",\n left: `calc(50% + ${x}px - ${controlLayout.buttonSize / 2}px)`,\n top: `calc(50% + ${y}px - ${controlLayout.buttonSize / 2}px)`,\n width: `${controlLayout.buttonSize}px`,\n height: `${controlLayout.buttonSize}px`,\n borderRadius: \"50%\",\n background: isActive\n ? `radial-gradient(circle, ${hexToRgbaString(KOREAN_COLORS.ACCENT_GOLD, 1)} 0%, ${hexToRgbaString(KOREAN_COLORS.ACCENT_GOLD, 0.7)} 100%)`\n : `radial-gradient(circle, ${hexToRgbaString(KOREAN_COLORS.UI_BACKGROUND_MEDIUM, 0.9)} 0%, ${hexToRgbaString(KOREAN_COLORS.UI_BACKGROUND_DARK, 0.9)} 100%)`,\n border: `2px solid ${hexToRgbaString(isActive ? KOREAN_COLORS.ACCENT_GOLD : KOREAN_COLORS.PRIMARY_CYAN, isActive ? 1 : 0.7)}`,\n fontSize: \"14px\",\n color: isActive\n ? hexToRgbaString(KOREAN_COLORS.BLACK_SOLID, 1)\n : hexToRgbaString(KOREAN_COLORS.TEXT_PRIMARY, 1),\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n cursor: \"pointer\",\n touchAction: \"none\",\n transform: isActive ? \"scale(1.15)\" : \"scale(1)\",\n transition: \"transform 0.1s ease, background 0.1s ease\",\n boxShadow: isActive\n ? `0 0 15px ${hexToRgbaString(KOREAN_COLORS.ACCENT_GOLD, 0.8)}`\n : \"none\",\n outline: \"none\",\n WebkitTapHighlightColor: \"transparent\",\n }}\n aria-label={`이동 ${config.direction} | Move ${config.direction}`}\n data-testid={`mobile-dpad-${config.direction}`}\n >\n {config.symbol}\n </button>\n );\n })}\n\n {/* Center Indicator */}\n <div\n style={{\n position: \"absolute\",\n top: \"50%\",\n left: \"50%\",\n transform: \"translate(-50%, -50%)\",\n width: \"20px\",\n height: \"20px\",\n borderRadius: \"50%\",\n background: activeDirection\n ? hexToRgbaString(KOREAN_COLORS.ACCENT_GOLD, 0.9)\n : hexToRgbaString(KOREAN_COLORS.PRIMARY_CYAN, 0.6),\n border: `2px solid ${hexToRgbaString(KOREAN_COLORS.TEXT_PRIMARY, 0.8)}`,\n transition: \"background 0.15s ease\",\n }}\n />\n </div>\n\n {/* Action Buttons (Right Side) */}\n <div\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n gap: `${controlLayout.actionGap}px`,\n pointerEvents: \"auto\",\n touchAction: \"none\",\n }}\n data-testid=\"mobile-action-buttons\"\n >\n {/* Attack Button - Large Red */}\n <button\n onTouchStart={handleAttackStart}\n onTouchEnd={handleAttackEnd}\n onTouchCancel={handleAttackEnd}\n onMouseDown={handleAttackStart}\n onMouseUp={handleAttackEnd}\n onMouseLeave={handleAttackEnd}\n style={{\n width: `${controlLayout.attackSize}px`,\n height: `${controlLayout.attackSize}px`,\n borderRadius: \"50%\",\n background: attackPressed\n ? `radial-gradient(circle, ${hexToRgbaString(KOREAN_COLORS.PRIMARY_RED, 1)} 0%, ${hexToRgbaString(KOREAN_COLORS.PRIMARY_RED, 0.7)} 100%)`\n : `radial-gradient(circle, ${hexToRgbaString(KOREAN_COLORS.PRIMARY_RED, 0.9)} 0%, ${hexToRgbaString(KOREAN_COLORS.NEGATIVE_RED_DARK, 0.9)} 100%)`,\n border: `3px solid ${hexToRgbaString(KOREAN_COLORS.PRIMARY_RED, 1)}`,\n fontSize: \"28px\",\n color: hexToRgbaString(KOREAN_COLORS.TEXT_PRIMARY, 1),\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n cursor: \"pointer\",\n touchAction: \"none\",\n transform: attackPressed ? \"scale(0.92)\" : \"scale(1)\",\n transition: \"transform 0.1s ease\",\n boxShadow: attackPressed\n ? `0 0 25px ${hexToRgbaString(KOREAN_COLORS.PRIMARY_RED, 0.9)}`\n : `0 0 15px ${hexToRgbaString(KOREAN_COLORS.PRIMARY_RED, 0.5)}`,\n outline: \"none\",\n WebkitTapHighlightColor: \"transparent\",\n fontWeight: \"bold\",\n fontFamily: FONT_FAMILY.KOREAN,\n }}\n aria-label=\"공격 | Attack\"\n data-testid=\"mobile-attack-button\"\n >\n ⚡\n </button>\n\n {/* Block Button - Smaller Cyan */}\n <button\n onTouchStart={handleBlockStart}\n onTouchEnd={handleBlockEnd}\n onTouchCancel={handleBlockEnd}\n onMouseDown={handleBlockStart}\n onMouseUp={handleBlockEnd}\n onMouseLeave={handleBlockEnd}\n style={{\n width: `${controlLayout.blockSize}px`,\n height: `${controlLayout.blockSize}px`,\n borderRadius: \"50%\",\n marginLeft: \"auto\",\n background: blockPressed\n ? `radial-gradient(circle, ${hexToRgbaString(KOREAN_COLORS.PRIMARY_CYAN, 1)} 0%, ${hexToRgbaString(KOREAN_COLORS.PRIMARY_CYAN, 0.7)} 100%)`\n : `radial-gradient(circle, ${hexToRgbaString(KOREAN_COLORS.PRIMARY_CYAN, 0.8)} 0%, ${hexToRgbaString(KOREAN_COLORS.KI_LOW, 0.8)} 100%)`,\n border: `3px solid ${hexToRgbaString(KOREAN_COLORS.PRIMARY_CYAN, 1)}`,\n fontSize: \"22px\",\n color: hexToRgbaString(KOREAN_COLORS.TEXT_PRIMARY, 1),\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n cursor: \"pointer\",\n touchAction: \"none\",\n transform: blockPressed ? \"scale(0.92)\" : \"scale(1)\",\n transition: \"transform 0.1s ease\",\n boxShadow: blockPressed\n ? `0 0 20px ${hexToRgbaString(KOREAN_COLORS.PRIMARY_CYAN, 0.9)}`\n : `0 0 10px ${hexToRgbaString(KOREAN_COLORS.PRIMARY_CYAN, 0.4)}`,\n outline: \"none\",\n WebkitTapHighlightColor: \"transparent\",\n fontFamily: FONT_FAMILY.KOREAN,\n }}\n aria-label=\"방어 | Block\"\n data-testid=\"mobile-block-button\"\n >\n 🛡️\n </button>\n </div>\n </div>\n );\n },\n );\n\nMobileControlsOverlay.displayName = \"MobileControlsOverlay\";\n\nexport default MobileControlsOverlay;\n"],"mappings":"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"}
|
|
@@ -53,7 +53,6 @@ export interface PerformanceMonitorOptions {
|
|
|
53
53
|
* PerformanceMonitor class
|
|
54
54
|
* Monitors device performance and provides adaptive recommendations
|
|
55
55
|
*
|
|
56
|
-
* @public
|
|
57
56
|
* @korean 성능모니터
|
|
58
57
|
*/
|
|
59
58
|
export declare class PerformanceMonitor {
|
|
@@ -109,14 +108,12 @@ export declare class PerformanceMonitor {
|
|
|
109
108
|
* Begins tracking FPS and frame times
|
|
110
109
|
*
|
|
111
110
|
* @korean 모니터링시작
|
|
112
|
-
* @public
|
|
113
111
|
*/
|
|
114
112
|
startMonitoring(): void;
|
|
115
113
|
/**
|
|
116
114
|
* Stop monitoring performance
|
|
117
115
|
*
|
|
118
116
|
* @korean 모니터링중지
|
|
119
|
-
* @public
|
|
120
117
|
*/
|
|
121
118
|
stopMonitoring(): void;
|
|
122
119
|
/**
|
|
@@ -143,7 +140,6 @@ export declare class PerformanceMonitor {
|
|
|
143
140
|
*
|
|
144
141
|
* @returns Current performance metrics
|
|
145
142
|
* @korean 메트릭가져오기
|
|
146
|
-
* @public
|
|
147
143
|
*/
|
|
148
144
|
getMetrics(): PerformanceMetrics;
|
|
149
145
|
/**
|
|
@@ -151,7 +147,6 @@ export declare class PerformanceMonitor {
|
|
|
151
147
|
*
|
|
152
148
|
* @returns Performance tier
|
|
153
149
|
* @korean 성능등급가져오기
|
|
154
|
-
* @public
|
|
155
150
|
*/
|
|
156
151
|
getPerformanceTier(): PerformanceTier;
|
|
157
152
|
/**
|
|
@@ -159,7 +154,6 @@ export declare class PerformanceMonitor {
|
|
|
159
154
|
*
|
|
160
155
|
* @returns True if 60fps is achievable
|
|
161
156
|
* @korean 60fps가능여부
|
|
162
|
-
* @public
|
|
163
157
|
*/
|
|
164
158
|
canHandle60Fps(): boolean;
|
|
165
159
|
/**
|
|
@@ -167,7 +161,6 @@ export declare class PerformanceMonitor {
|
|
|
167
161
|
*
|
|
168
162
|
* @returns Quality recommendations
|
|
169
163
|
* @korean 품질권장사항가져오기
|
|
170
|
-
* @public
|
|
171
164
|
*/
|
|
172
165
|
getQualityRecommendations(): {
|
|
173
166
|
enableHaptics: boolean;
|
|
@@ -181,7 +174,6 @@ export declare class PerformanceMonitor {
|
|
|
181
174
|
*
|
|
182
175
|
* @returns True if frame drops detected
|
|
183
176
|
* @korean 프레임드롭감지
|
|
184
|
-
* @public
|
|
185
177
|
*/
|
|
186
178
|
hasFrameDrops(): boolean;
|
|
187
179
|
/**
|
|
@@ -189,7 +181,6 @@ export declare class PerformanceMonitor {
|
|
|
189
181
|
*
|
|
190
182
|
* @returns Current FPS
|
|
191
183
|
* @korean FPS가져오기
|
|
192
|
-
* @public
|
|
193
184
|
*/
|
|
194
185
|
getCurrentFps(): number;
|
|
195
186
|
/**
|
|
@@ -197,14 +188,12 @@ export declare class PerformanceMonitor {
|
|
|
197
188
|
*
|
|
198
189
|
* @returns Average frame time in milliseconds
|
|
199
190
|
* @korean 평균프레임타임가져오기
|
|
200
|
-
* @public
|
|
201
191
|
*/
|
|
202
192
|
getAvgFrameTime(): number;
|
|
203
193
|
/**
|
|
204
194
|
* Reset performance metrics
|
|
205
195
|
*
|
|
206
196
|
* @korean 메트릭리셋
|
|
207
|
-
* @public
|
|
208
197
|
*/
|
|
209
198
|
reset(): void;
|
|
210
199
|
}
|
|
@@ -213,7 +202,6 @@ export declare class PerformanceMonitor {
|
|
|
213
202
|
*
|
|
214
203
|
* @returns PerformanceMonitor instance
|
|
215
204
|
* @korean 성능모니터가져오기
|
|
216
|
-
* @public
|
|
217
205
|
*/
|
|
218
206
|
export declare function getPerformanceMonitor(): PerformanceMonitor;
|
|
219
207
|
/**
|
|
@@ -221,7 +209,6 @@ export declare function getPerformanceMonitor(): PerformanceMonitor;
|
|
|
221
209
|
*
|
|
222
210
|
* @returns Performance tier
|
|
223
211
|
* @korean 성능등급가져오기
|
|
224
|
-
* @public
|
|
225
212
|
*/
|
|
226
213
|
export declare function getPerformanceTier(): PerformanceTier;
|
|
227
214
|
/**
|
|
@@ -229,7 +216,6 @@ export declare function getPerformanceTier(): PerformanceTier;
|
|
|
229
216
|
*
|
|
230
217
|
* @returns True if 60fps is achievable
|
|
231
218
|
* @korean 60fps가능여부
|
|
232
|
-
* @public
|
|
233
219
|
*/
|
|
234
220
|
export declare function canHandle60Fps(): boolean;
|
|
235
221
|
/**
|
|
@@ -237,7 +223,6 @@ export declare function canHandle60Fps(): boolean;
|
|
|
237
223
|
*
|
|
238
224
|
* @returns Quality recommendations
|
|
239
225
|
* @korean 품질권장사항가져오기
|
|
240
|
-
* @public
|
|
241
226
|
*/
|
|
242
227
|
export declare function getQualityRecommendations(): {
|
|
243
228
|
enableHaptics: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PerformanceMonitor.d.ts","sourceRoot":"","sources":["../../../../src/components/shared/mobile/PerformanceMonitor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;AAExD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,sCAAsC;IACtC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,yCAAyC;IACzC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,sCAAsC;IACtC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,wCAAwC;IACxC,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,8BAA8B;IAC9B,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAC/B,gCAAgC;IAChC,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;CAC9B;AAED;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,iDAAiD;IACjD,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,+BAA+B;IAC/B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,yDAAyD;IACzD,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IACrC,+CAA+C;IAC/C,QAAQ,CAAC,sBAAsB,CAAC,EAAE,OAAO,CAAC;CAC3C;AAED
|
|
1
|
+
{"version":3,"file":"PerformanceMonitor.d.ts","sourceRoot":"","sources":["../../../../src/components/shared/mobile/PerformanceMonitor.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StanceWheelPure.d.ts","sourceRoot":"","sources":["../../../../src/components/shared/mobile/StanceWheelPure.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAgC,MAAM,OAAO,CAAC;AAarD;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,iCAAiC;IACjC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,mCAAmC;IACnC,QAAQ,CAAC,cAAc,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IACvD,gCAAgC;IAChC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,mCAAmC;IACnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC;IAC9B,gCAAgC;IAChC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,mGAAmG;IACnG,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,sCAAsC;IACtC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AA+CD
|
|
1
|
+
{"version":3,"file":"StanceWheelPure.d.ts","sourceRoot":"","sources":["../../../../src/components/shared/mobile/StanceWheelPure.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAgC,MAAM,OAAO,CAAC;AAarD;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,iCAAiC;IACjC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,mCAAmC;IACnC,QAAQ,CAAC,cAAc,EAAE,CAAC,WAAW,EAAE,MAAM,KAAK,IAAI,CAAC;IACvD,gCAAgC;IAChC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,mCAAmC;IACnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,IAAI,CAAC;IAC9B,gCAAgC;IAChC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,mGAAmG;IACnG,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,sCAAsC;IACtC,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AA+CD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CA+U1D,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StanceWheelPure.js","names":[],"sources":["../../../../src/components/shared/mobile/StanceWheelPure.tsx"],"sourcesContent":["/**\n * StanceWheelPure Component - Pure DOM version (no Three.js/drei dependency)\n *\n * Circular 8-segment stance selector for mobile touch controls\n * Provides visual and tactile stance switching interface\n *\n * This is a pure DOM version that renders OUTSIDE the Three.js Canvas.\n * It does NOT use Html from @react-three/drei, making it compatible with\n * rendering outside Canvas contexts.\n *\n * WCAG 2.1 Level AA Compliance:\n * - ARIA labels for all 8 stance buttons\n * - Keyboard navigation (Tab, Enter, Arrow keys)\n * - Visible focus indicators (2px cyan border)\n * - aria-expanded state for wheel toggle\n * - role=\"radiogroup\" for stance selection\n * - 50x50px touch targets (exceeds 44x44px minimum)\n *\n * @module components/mobile/StanceWheelPure\n * @category Mobile Controls\n * @korean 자세 휠 (순수 DOM)\n */\n\nimport React, { useCallback, useState } from \"react\";\nimport { KOREAN_COLORS } from \"@/types/constants\";\nimport { TRIGRAM_STANCES_ORDER } from \"../../../systems/trigram/types\";\nimport { TrigramStance } from \"../../../types/common\";\nimport { triggerHaptic } from \"../../../utils/haptics\";\nimport { getColorRGB } from \"../../../utils/colorHelpers\";\nimport {\n handleKeyboardNav,\n getFocusStyle,\n announceToScreenReader,\n} from \"../../../utils/accessibility\";\nimport { createBilingualLabel } from \"../../../types/AccessibilityTypes\";\n\n/**\n * Props for StanceWheelPure component\n */\nexport interface StanceWheelPureProps {\n /** Current stance index (0-7) */\n readonly currentStance: number;\n /** Callback when stance changes */\n readonly onStanceChange: (stanceIndex: number) => void;\n /** Whether wheel is expanded */\n readonly expanded: boolean;\n /** Callback to toggle expansion */\n readonly onToggle: () => void;\n /** Whether wheel is disabled */\n readonly disabled?: boolean;\n /** Position from bottom in pixels (default: 34 when collapsed, 100 when expanded for safe area) */\n readonly bottom?: number;\n /** Opacity of wheel (default: 0.8) */\n readonly opacity?: number;\n}\n\n/**\n * Trigram symbols for each stance\n */\nconst TRIGRAM_SYMBOLS = [\n \"☰\",\n \"☱\",\n \"☲\",\n \"☳\",\n \"☴\",\n \"☵\",\n \"☶\",\n \"☷\",\n] as const;\n\n/**\n * Korean names for each stance\n */\nconst STANCE_KOREAN_NAMES = [\n \"건\", // Geon - Heaven\n \"태\", // Tae - Lake\n \"리\", // Li - Fire\n \"진\", // Jin - Thunder\n \"손\", // Son - Wind\n \"감\", // Gam - Water\n \"간\", // Gan - Mountain\n \"곤\", // Gon - Earth\n] as const;\n\n/**\n * Get color for a specific stance\n */\nconst getStanceColor = (stance: TrigramStance): number => {\n const stanceColors: Record<TrigramStance, number> = {\n geon: 0xffd700, // Gold - Heaven\n tae: 0x00ffff, // Cyan - Lake\n li: 0xff4444, // Red - Fire\n jin: 0xffaa00, // Orange - Thunder\n son: 0x88ff88, // Light Green - Wind\n gam: 0x0088ff, // Blue - Water\n gan: 0x8844ff, // Purple - Mountain\n gon: 0xaa6644, // Brown - Earth\n };\n return stanceColors[stance] ?? KOREAN_COLORS.PRIMARY_CYAN;\n};\n\n/**\n * StanceWheelPure Component\n *\n * Pure DOM circular stance selector with 8 segments for trigram stances\n * Features:\n * - Expandable/collapsible interface\n * - Visual stance indicator when collapsed (60x60px)\n * - 8 touch-optimized stance buttons when expanded (50x50px each)\n * - 200px wheel diameter with safe positioning\n * - Korean trigram symbols and names\n * - Color-coded by stance element\n * - Haptic feedback on selection\n * - 50x50px minimum touch targets\n *\n * Usage in Combat:\n * - Tap collapsed indicator to expand wheel\n * - Select from 8 trigram stances\n * - Current stance highlighted with gold accent\n * - Tap current stance to collapse wheel\n *\n * @example\n * ```tsx\n * <StanceWheelPure\n * currentStance={player.stance}\n * onStanceChange={(index) => handleStanceChange(index)}\n * expanded={wheelExpanded}\n * onToggle={() => setWheelExpanded(!wheelExpanded)}\n * disabled={isPaused}\n * />\n * ```\n *\n * @public\n * @korean 자세휠순수\n */\nexport const StanceWheelPure: React.FC<StanceWheelPureProps> = ({\n currentStance,\n onStanceChange,\n expanded,\n onToggle,\n disabled = false,\n bottom,\n opacity = 0.8,\n}) => {\n const [hoveredStance, setHoveredStance] = useState<number | null>(null);\n const [focusedStance, setFocusedStance] = useState<number | null>(null);\n\n /**\n * Handle stance selection (touch or mouse)\n */\n const handleStanceSelect = useCallback(\n (e: React.TouchEvent | React.MouseEvent, stanceIndex: number) => {\n if (disabled) return;\n e.preventDefault();\n e.stopPropagation();\n\n // Don't allow selecting the same stance\n if (stanceIndex === currentStance) {\n // Collapse wheel if tapping current stance\n onToggle();\n triggerHaptic(\"light\");\n return;\n }\n\n onStanceChange(stanceIndex);\n triggerHaptic(\"medium\");\n\n // Announce stance change to screen readers\n const stanceName = STANCE_KOREAN_NAMES[stanceIndex];\n const stanceSymbol = TRIGRAM_SYMBOLS[stanceIndex];\n announceToScreenReader({\n message: createBilingualLabel(\n `자세 변경: ${stanceName} ${stanceSymbol}`,\n `Stance changed to ${TRIGRAM_STANCES_ORDER[stanceIndex]}`,\n ).label,\n politeness: \"polite\",\n });\n\n // Auto-collapse after selection (optional)\n // onToggle();\n },\n [disabled, currentStance, onStanceChange, onToggle],\n );\n\n /**\n * Handle wheel toggle (touch or mouse)\n */\n const handleToggle = useCallback(\n (e: React.TouchEvent | React.MouseEvent) => {\n if (disabled) return;\n e.preventDefault();\n e.stopPropagation();\n\n onToggle();\n triggerHaptic(\"light\");\n\n // Announce state change to screen readers using the toggled value\n const nextExpanded = !expanded;\n announceToScreenReader({\n message: createBilingualLabel(\n nextExpanded ? \"자세 휠 열림\" : \"자세 휠 닫힘\",\n nextExpanded ? \"Stance wheel opened\" : \"Stance wheel closed\",\n ).label,\n politeness: \"polite\",\n });\n },\n [disabled, onToggle, expanded],\n );\n\n /**\n * Handle keyboard navigation for stance buttons\n */\n const handleStanceKeyDown = useCallback(\n (stanceIndex: number) => (e: React.KeyboardEvent) => {\n if (disabled) return;\n handleKeyboardNav(e.nativeEvent, {\n onActivate: () => {\n if (stanceIndex === currentStance) {\n onToggle();\n } else {\n onStanceChange(stanceIndex);\n }\n triggerHaptic(\"medium\");\n },\n onCancel: () => {\n onToggle();\n },\n onNavigate: (direction) => {\n // Navigate between stances with arrow keys\n let newIndex = stanceIndex;\n if (direction === \"left\" || direction === \"up\") {\n newIndex = (stanceIndex - 1 + 8) % 8;\n } else if (direction === \"right\" || direction === \"down\") {\n newIndex = (stanceIndex + 1) % 8;\n }\n setFocusedStance(newIndex);\n // Focus the new stance button on the next animation frame\n requestAnimationFrame(() => {\n const button = document.querySelector(\n `[data-testid=\"stance-button-pure-${newIndex}\"]`,\n ) as HTMLElement | null;\n button?.focus();\n });\n },\n });\n },\n [disabled, currentStance, onStanceChange, onToggle],\n );\n\n /**\n * Handle keyboard navigation for toggle button\n */\n const handleToggleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (disabled) return;\n handleKeyboardNav(e.nativeEvent, {\n onActivate: () => {\n onToggle();\n triggerHaptic(\"light\");\n },\n });\n },\n [disabled, onToggle],\n );\n\n // Dynamic bottom position with safe area consideration\n const dynamicBottom = bottom ?? (expanded ? 100 : 34);\n\n // Get RGB values for colors using shared utility\n const currentStanceColor = getColorRGB(\n getStanceColor(TRIGRAM_STANCES_ORDER[currentStance]),\n );\n const goldColor = getColorRGB(KOREAN_COLORS.ACCENT_GOLD);\n const primaryColor = getColorRGB(KOREAN_COLORS.PRIMARY_CYAN);\n\n if (expanded) {\n // Expanded: Show full 8-segment wheel\n const wheelSize = 200;\n const segmentAngle = 360 / 8;\n\n return (\n <div\n style={{\n position: \"absolute\", // Changed from fixed to position relative to container\n bottom: `${dynamicBottom}px`,\n left: \"50%\",\n transform: \"translateX(-50%)\",\n opacity: disabled ? 0.3 : opacity,\n pointerEvents: disabled ? \"none\" : \"auto\",\n transition: \"all 0.3s ease\",\n zIndex: 1000,\n }}\n data-testid=\"stance-wheel-pure-expanded\"\n role=\"radiogroup\"\n aria-label={\n createBilingualLabel(\n \"팔괘 자세 선택\",\n \"Eight Trigram Stance Selection\",\n ).label\n }\n aria-activedescendant={`stance-button-pure-${currentStance}`}\n >\n <div\n style={{\n width: `${wheelSize}px`,\n height: `${wheelSize}px`,\n position: \"relative\",\n }}\n >\n {/* Stance buttons arranged in circle */}\n {TRIGRAM_STANCES_ORDER.map((stance, index) => {\n const angle = index * segmentAngle;\n const radian = (angle - 90) * (Math.PI / 180); // -90 to start from top\n const x = Math.cos(radian) * 80 + 100;\n const y = Math.sin(radian) * 80 + 100;\n const isActive = index === currentStance;\n const isHovered = index === hoveredStance;\n const stanceColor = getColorRGB(getStanceColor(stance));\n\n return (\n <button\n key={stance}\n onTouchStart={(e) => handleStanceSelect(e, index)}\n onTouchEnd={(e) => {\n e.preventDefault();\n e.stopPropagation();\n setHoveredStance(null);\n }}\n onMouseDown={(e) => handleStanceSelect(e, index)}\n onMouseEnter={() => setHoveredStance(index)}\n onMouseLeave={() => setHoveredStance(null)}\n onKeyDown={handleStanceKeyDown(index)}\n onFocus={() => setFocusedStance(index)}\n onBlur={() => setFocusedStance(null)}\n style={{\n position: \"absolute\",\n left: `${x - 25}px`,\n top: `${y - 25}px`,\n width: \"50px\",\n height: \"50px\",\n borderRadius: \"50%\",\n background: isActive\n ? `rgba(${goldColor.r}, ${goldColor.g}, ${goldColor.b}, 0.95)`\n : `rgba(${stanceColor.r}, ${stanceColor.g}, ${stanceColor.b}, 0.8)`,\n border: `3px solid ${isActive ? \"#fff\" : `rgba(${stanceColor.r}, ${stanceColor.g}, ${stanceColor.b}, 1)`}`,\n fontSize: \"24px\",\n color: isActive ? \"#000\" : \"#fff\",\n fontWeight: \"bold\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n cursor: \"pointer\",\n userSelect: \"none\",\n touchAction: \"none\",\n transition: \"all 0.2s ease\",\n transform: isActive || isHovered ? \"scale(1.15)\" : \"scale(1)\",\n boxShadow: isActive\n ? `0 0 25px rgba(${goldColor.r}, ${goldColor.g}, ${goldColor.b}, 0.9)`\n : isHovered\n ? `0 0 15px rgba(${stanceColor.r}, ${stanceColor.g}, ${stanceColor.b}, 0.8)`\n : `0 4px 10px rgba(0, 0, 0, 0.5)`,\n ...getFocusStyle(focusedStance === index, {\n boxShadow: `0 0 0 4px rgba(${primaryColor.r}, ${primaryColor.g}, ${primaryColor.b}, 0.5), 0 0 25px rgba(${goldColor.r}, ${goldColor.g}, ${goldColor.b}, 0.9)`,\n outlineColor: KOREAN_COLORS.PRIMARY_CYAN,\n outlineWidth: 3,\n }),\n }}\n aria-label={\n createBilingualLabel(\n `${STANCE_KOREAN_NAMES[index]} ${TRIGRAM_SYMBOLS[index]}`,\n `${stance} stance`,\n ).label\n }\n aria-checked={isActive}\n role=\"radio\"\n tabIndex={0}\n disabled={disabled}\n id={`stance-button-pure-${index}`}\n data-testid={`stance-button-pure-${index}`}\n >\n <div style={{ fontSize: \"20px\", lineHeight: 1 }}>\n {TRIGRAM_SYMBOLS[index]}\n </div>\n <div style={{ fontSize: \"8px\", marginTop: \"2px\" }}>\n {STANCE_KOREAN_NAMES[index]}\n </div>\n </button>\n );\n })}\n\n {/* Center label */}\n <div\n style={{\n position: \"absolute\",\n top: \"50%\",\n left: \"50%\",\n transform: \"translate(-50%, -50%)\",\n fontSize: \"12px\",\n color: `rgba(${primaryColor.r}, ${primaryColor.g}, ${primaryColor.b}, 0.9)`,\n textShadow: \"0 1px 3px rgba(0, 0, 0, 0.8)\",\n fontWeight: \"bold\",\n textAlign: \"center\",\n pointerEvents: \"none\",\n }}\n >\n 자세 선택\n <br />\n <span style={{ fontSize: \"10px\" }}>Stance</span>\n </div>\n </div>\n </div>\n );\n }\n\n // Collapsed: Show current stance indicator\n return (\n <div\n style={{\n position: \"absolute\", // Changed from fixed to position relative to container\n bottom: `${dynamicBottom}px`,\n left: \"50%\",\n transform: \"translateX(-50%)\",\n opacity: disabled ? 0.3 : opacity,\n pointerEvents: disabled ? \"none\" : \"auto\",\n transition: \"all 0.3s ease\",\n zIndex: 1000,\n }}\n data-testid=\"stance-wheel-pure-collapsed\"\n >\n <button\n onTouchStart={handleToggle}\n onMouseDown={handleToggle}\n onKeyDown={handleToggleKeyDown}\n onFocus={() => setFocusedStance(currentStance)}\n onBlur={() => setFocusedStance(null)}\n style={{\n width: \"60px\",\n height: \"60px\",\n borderRadius: \"50%\",\n background: `rgba(${currentStanceColor.r}, ${currentStanceColor.g}, ${currentStanceColor.b}, 0.9)`,\n border: `3px solid rgba(${goldColor.r}, ${goldColor.g}, ${goldColor.b}, 0.9)`,\n fontSize: \"28px\",\n color: \"#fff\",\n fontWeight: \"bold\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n cursor: \"pointer\",\n userSelect: \"none\",\n touchAction: \"none\",\n transition: \"all 0.2s ease\",\n boxShadow: `0 4px 15px rgba(0, 0, 0, 0.6), 0 0 20px rgba(${currentStanceColor.r}, ${currentStanceColor.g}, ${currentStanceColor.b}, 0.6)`,\n ...getFocusStyle(focusedStance === currentStance, {\n boxShadow: `0 0 0 4px rgba(${primaryColor.r}, ${primaryColor.g}, ${primaryColor.b}, 0.5), 0 4px 15px rgba(0, 0, 0, 0.6), 0 0 20px rgba(${currentStanceColor.r}, ${currentStanceColor.g}, ${currentStanceColor.b}, 0.6)`,\n outlineColor: KOREAN_COLORS.PRIMARY_CYAN,\n outlineWidth: 3,\n }),\n }}\n disabled={disabled}\n aria-label={\n createBilingualLabel(\n `현재 자세: ${STANCE_KOREAN_NAMES[currentStance]} ${TRIGRAM_SYMBOLS[currentStance]}. 자세 휠 열기`,\n `Current stance: ${TRIGRAM_STANCES_ORDER[currentStance]}. Open stance wheel`,\n ).label\n }\n aria-expanded={expanded}\n aria-haspopup=\"menu\"\n role=\"button\"\n tabIndex={disabled ? -1 : 0}\n data-testid=\"stance-wheel-pure-toggle\"\n >\n <div style={{ fontSize: \"24px\", lineHeight: 1 }}>\n {TRIGRAM_SYMBOLS[currentStance]}\n </div>\n <div style={{ fontSize: \"10px\", marginTop: \"2px\" }}>\n {STANCE_KOREAN_NAMES[currentStance]}\n </div>\n </button>\n </div>\n );\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"StanceWheelPure.js","names":[],"sources":["../../../../src/components/shared/mobile/StanceWheelPure.tsx"],"sourcesContent":["/**\n * StanceWheelPure Component - Pure DOM version (no Three.js/drei dependency)\n *\n * Circular 8-segment stance selector for mobile touch controls\n * Provides visual and tactile stance switching interface\n *\n * This is a pure DOM version that renders OUTSIDE the Three.js Canvas.\n * It does NOT use Html from @react-three/drei, making it compatible with\n * rendering outside Canvas contexts.\n *\n * WCAG 2.1 Level AA Compliance:\n * - ARIA labels for all 8 stance buttons\n * - Keyboard navigation (Tab, Enter, Arrow keys)\n * - Visible focus indicators (2px cyan border)\n * - aria-expanded state for wheel toggle\n * - role=\"radiogroup\" for stance selection\n * - 50x50px touch targets (exceeds 44x44px minimum)\n *\n * @module components/mobile/StanceWheelPure\n * @category Mobile Controls\n * @korean 자세 휠 (순수 DOM)\n */\n\nimport React, { useCallback, useState } from \"react\";\nimport { KOREAN_COLORS } from \"@/types/constants\";\nimport { TRIGRAM_STANCES_ORDER } from \"../../../systems/trigram/types\";\nimport { TrigramStance } from \"../../../types/common\";\nimport { triggerHaptic } from \"../../../utils/haptics\";\nimport { getColorRGB } from \"../../../utils/colorHelpers\";\nimport {\n handleKeyboardNav,\n getFocusStyle,\n announceToScreenReader,\n} from \"../../../utils/accessibility\";\nimport { createBilingualLabel } from \"../../../types/AccessibilityTypes\";\n\n/**\n * Props for StanceWheelPure component\n */\nexport interface StanceWheelPureProps {\n /** Current stance index (0-7) */\n readonly currentStance: number;\n /** Callback when stance changes */\n readonly onStanceChange: (stanceIndex: number) => void;\n /** Whether wheel is expanded */\n readonly expanded: boolean;\n /** Callback to toggle expansion */\n readonly onToggle: () => void;\n /** Whether wheel is disabled */\n readonly disabled?: boolean;\n /** Position from bottom in pixels (default: 34 when collapsed, 100 when expanded for safe area) */\n readonly bottom?: number;\n /** Opacity of wheel (default: 0.8) */\n readonly opacity?: number;\n}\n\n/**\n * Trigram symbols for each stance\n */\nconst TRIGRAM_SYMBOLS = [\n \"☰\",\n \"☱\",\n \"☲\",\n \"☳\",\n \"☴\",\n \"☵\",\n \"☶\",\n \"☷\",\n] as const;\n\n/**\n * Korean names for each stance\n */\nconst STANCE_KOREAN_NAMES = [\n \"건\", // Geon - Heaven\n \"태\", // Tae - Lake\n \"리\", // Li - Fire\n \"진\", // Jin - Thunder\n \"손\", // Son - Wind\n \"감\", // Gam - Water\n \"간\", // Gan - Mountain\n \"곤\", // Gon - Earth\n] as const;\n\n/**\n * Get color for a specific stance\n */\nconst getStanceColor = (stance: TrigramStance): number => {\n const stanceColors: Record<TrigramStance, number> = {\n geon: 0xffd700, // Gold - Heaven\n tae: 0x00ffff, // Cyan - Lake\n li: 0xff4444, // Red - Fire\n jin: 0xffaa00, // Orange - Thunder\n son: 0x88ff88, // Light Green - Wind\n gam: 0x0088ff, // Blue - Water\n gan: 0x8844ff, // Purple - Mountain\n gon: 0xaa6644, // Brown - Earth\n };\n return stanceColors[stance] ?? KOREAN_COLORS.PRIMARY_CYAN;\n};\n\n/**\n * StanceWheelPure Component\n *\n * Pure DOM circular stance selector with 8 segments for trigram stances\n * Features:\n * - Expandable/collapsible interface\n * - Visual stance indicator when collapsed (60x60px)\n * - 8 touch-optimized stance buttons when expanded (50x50px each)\n * - 200px wheel diameter with safe positioning\n * - Korean trigram symbols and names\n * - Color-coded by stance element\n * - Haptic feedback on selection\n * - 50x50px minimum touch targets\n *\n * Usage in Combat:\n * - Tap collapsed indicator to expand wheel\n * - Select from 8 trigram stances\n * - Current stance highlighted with gold accent\n * - Tap current stance to collapse wheel\n *\n * @example\n * ```tsx\n * <StanceWheelPure\n * currentStance={player.stance}\n * onStanceChange={(index) => handleStanceChange(index)}\n * expanded={wheelExpanded}\n * onToggle={() => setWheelExpanded(!wheelExpanded)}\n * disabled={isPaused}\n * />\n * ```\n *\n * @korean 자세휠순수\n */\nexport const StanceWheelPure: React.FC<StanceWheelPureProps> = ({\n currentStance,\n onStanceChange,\n expanded,\n onToggle,\n disabled = false,\n bottom,\n opacity = 0.8,\n}) => {\n const [hoveredStance, setHoveredStance] = useState<number | null>(null);\n const [focusedStance, setFocusedStance] = useState<number | null>(null);\n\n /**\n * Handle stance selection (touch or mouse)\n */\n const handleStanceSelect = useCallback(\n (e: React.TouchEvent | React.MouseEvent, stanceIndex: number) => {\n if (disabled) return;\n e.preventDefault();\n e.stopPropagation();\n\n if (stanceIndex === currentStance) {\n onToggle();\n triggerHaptic(\"light\");\n return;\n }\n\n onStanceChange(stanceIndex);\n triggerHaptic(\"medium\");\n\n const stanceName = STANCE_KOREAN_NAMES[stanceIndex];\n const stanceSymbol = TRIGRAM_SYMBOLS[stanceIndex];\n announceToScreenReader({\n message: createBilingualLabel(\n `자세 변경: ${stanceName} ${stanceSymbol}`,\n `Stance changed to ${TRIGRAM_STANCES_ORDER[stanceIndex]}`,\n ).label,\n politeness: \"polite\",\n });\n\n },\n [disabled, currentStance, onStanceChange, onToggle],\n );\n\n /**\n * Handle wheel toggle (touch or mouse)\n */\n const handleToggle = useCallback(\n (e: React.TouchEvent | React.MouseEvent) => {\n if (disabled) return;\n e.preventDefault();\n e.stopPropagation();\n\n onToggle();\n triggerHaptic(\"light\");\n\n const nextExpanded = !expanded;\n announceToScreenReader({\n message: createBilingualLabel(\n nextExpanded ? \"자세 휠 열림\" : \"자세 휠 닫힘\",\n nextExpanded ? \"Stance wheel opened\" : \"Stance wheel closed\",\n ).label,\n politeness: \"polite\",\n });\n },\n [disabled, onToggle, expanded],\n );\n\n /**\n * Handle keyboard navigation for stance buttons\n */\n const handleStanceKeyDown = useCallback(\n (stanceIndex: number) => (e: React.KeyboardEvent) => {\n if (disabled) return;\n handleKeyboardNav(e.nativeEvent, {\n onActivate: () => {\n if (stanceIndex === currentStance) {\n onToggle();\n } else {\n onStanceChange(stanceIndex);\n }\n triggerHaptic(\"medium\");\n },\n onCancel: () => {\n onToggle();\n },\n onNavigate: (direction) => {\n let newIndex = stanceIndex;\n if (direction === \"left\" || direction === \"up\") {\n newIndex = (stanceIndex - 1 + 8) % 8;\n } else if (direction === \"right\" || direction === \"down\") {\n newIndex = (stanceIndex + 1) % 8;\n }\n setFocusedStance(newIndex);\n requestAnimationFrame(() => {\n const button = document.querySelector(\n `[data-testid=\"stance-button-pure-${newIndex}\"]`,\n ) as HTMLElement | null;\n button?.focus();\n });\n },\n });\n },\n [disabled, currentStance, onStanceChange, onToggle],\n );\n\n /**\n * Handle keyboard navigation for toggle button\n */\n const handleToggleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (disabled) return;\n handleKeyboardNav(e.nativeEvent, {\n onActivate: () => {\n onToggle();\n triggerHaptic(\"light\");\n },\n });\n },\n [disabled, onToggle],\n );\n\n const dynamicBottom = bottom ?? (expanded ? 100 : 34);\n\n const currentStanceColor = getColorRGB(\n getStanceColor(TRIGRAM_STANCES_ORDER[currentStance]),\n );\n const goldColor = getColorRGB(KOREAN_COLORS.ACCENT_GOLD);\n const primaryColor = getColorRGB(KOREAN_COLORS.PRIMARY_CYAN);\n\n if (expanded) {\n const wheelSize = 200;\n const segmentAngle = 360 / 8;\n\n return (\n <div\n style={{\n position: \"absolute\", // Changed from fixed to position relative to container\n bottom: `${dynamicBottom}px`,\n left: \"50%\",\n transform: \"translateX(-50%)\",\n opacity: disabled ? 0.3 : opacity,\n pointerEvents: disabled ? \"none\" : \"auto\",\n transition: \"all 0.3s ease\",\n zIndex: 1000,\n }}\n data-testid=\"stance-wheel-pure-expanded\"\n role=\"radiogroup\"\n aria-label={\n createBilingualLabel(\n \"팔괘 자세 선택\",\n \"Eight Trigram Stance Selection\",\n ).label\n }\n aria-activedescendant={`stance-button-pure-${currentStance}`}\n >\n <div\n style={{\n width: `${wheelSize}px`,\n height: `${wheelSize}px`,\n position: \"relative\",\n }}\n >\n {/* Stance buttons arranged in circle */}\n {TRIGRAM_STANCES_ORDER.map((stance, index) => {\n const angle = index * segmentAngle;\n const radian = (angle - 90) * (Math.PI / 180); // -90 to start from top\n const x = Math.cos(radian) * 80 + 100;\n const y = Math.sin(radian) * 80 + 100;\n const isActive = index === currentStance;\n const isHovered = index === hoveredStance;\n const stanceColor = getColorRGB(getStanceColor(stance));\n\n return (\n <button\n key={stance}\n onTouchStart={(e) => handleStanceSelect(e, index)}\n onTouchEnd={(e) => {\n e.preventDefault();\n e.stopPropagation();\n setHoveredStance(null);\n }}\n onMouseDown={(e) => handleStanceSelect(e, index)}\n onMouseEnter={() => setHoveredStance(index)}\n onMouseLeave={() => setHoveredStance(null)}\n onKeyDown={handleStanceKeyDown(index)}\n onFocus={() => setFocusedStance(index)}\n onBlur={() => setFocusedStance(null)}\n style={{\n position: \"absolute\",\n left: `${x - 25}px`,\n top: `${y - 25}px`,\n width: \"50px\",\n height: \"50px\",\n borderRadius: \"50%\",\n background: isActive\n ? `rgba(${goldColor.r}, ${goldColor.g}, ${goldColor.b}, 0.95)`\n : `rgba(${stanceColor.r}, ${stanceColor.g}, ${stanceColor.b}, 0.8)`,\n border: `3px solid ${isActive ? \"#fff\" : `rgba(${stanceColor.r}, ${stanceColor.g}, ${stanceColor.b}, 1)`}`,\n fontSize: \"24px\",\n color: isActive ? \"#000\" : \"#fff\",\n fontWeight: \"bold\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n cursor: \"pointer\",\n userSelect: \"none\",\n touchAction: \"none\",\n transition: \"all 0.2s ease\",\n transform: isActive || isHovered ? \"scale(1.15)\" : \"scale(1)\",\n boxShadow: isActive\n ? `0 0 25px rgba(${goldColor.r}, ${goldColor.g}, ${goldColor.b}, 0.9)`\n : isHovered\n ? `0 0 15px rgba(${stanceColor.r}, ${stanceColor.g}, ${stanceColor.b}, 0.8)`\n : `0 4px 10px rgba(0, 0, 0, 0.5)`,\n ...getFocusStyle(focusedStance === index, {\n boxShadow: `0 0 0 4px rgba(${primaryColor.r}, ${primaryColor.g}, ${primaryColor.b}, 0.5), 0 0 25px rgba(${goldColor.r}, ${goldColor.g}, ${goldColor.b}, 0.9)`,\n outlineColor: KOREAN_COLORS.PRIMARY_CYAN,\n outlineWidth: 3,\n }),\n }}\n aria-label={\n createBilingualLabel(\n `${STANCE_KOREAN_NAMES[index]} ${TRIGRAM_SYMBOLS[index]}`,\n `${stance} stance`,\n ).label\n }\n aria-checked={isActive}\n role=\"radio\"\n tabIndex={0}\n disabled={disabled}\n id={`stance-button-pure-${index}`}\n data-testid={`stance-button-pure-${index}`}\n >\n <div style={{ fontSize: \"20px\", lineHeight: 1 }}>\n {TRIGRAM_SYMBOLS[index]}\n </div>\n <div style={{ fontSize: \"8px\", marginTop: \"2px\" }}>\n {STANCE_KOREAN_NAMES[index]}\n </div>\n </button>\n );\n })}\n\n {/* Center label */}\n <div\n style={{\n position: \"absolute\",\n top: \"50%\",\n left: \"50%\",\n transform: \"translate(-50%, -50%)\",\n fontSize: \"12px\",\n color: `rgba(${primaryColor.r}, ${primaryColor.g}, ${primaryColor.b}, 0.9)`,\n textShadow: \"0 1px 3px rgba(0, 0, 0, 0.8)\",\n fontWeight: \"bold\",\n textAlign: \"center\",\n pointerEvents: \"none\",\n }}\n >\n 자세 선택\n <br />\n <span style={{ fontSize: \"10px\" }}>Stance</span>\n </div>\n </div>\n </div>\n );\n }\n\n return (\n <div\n style={{\n position: \"absolute\", // Changed from fixed to position relative to container\n bottom: `${dynamicBottom}px`,\n left: \"50%\",\n transform: \"translateX(-50%)\",\n opacity: disabled ? 0.3 : opacity,\n pointerEvents: disabled ? \"none\" : \"auto\",\n transition: \"all 0.3s ease\",\n zIndex: 1000,\n }}\n data-testid=\"stance-wheel-pure-collapsed\"\n >\n <button\n onTouchStart={handleToggle}\n onMouseDown={handleToggle}\n onKeyDown={handleToggleKeyDown}\n onFocus={() => setFocusedStance(currentStance)}\n onBlur={() => setFocusedStance(null)}\n style={{\n width: \"60px\",\n height: \"60px\",\n borderRadius: \"50%\",\n background: `rgba(${currentStanceColor.r}, ${currentStanceColor.g}, ${currentStanceColor.b}, 0.9)`,\n border: `3px solid rgba(${goldColor.r}, ${goldColor.g}, ${goldColor.b}, 0.9)`,\n fontSize: \"28px\",\n color: \"#fff\",\n fontWeight: \"bold\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n cursor: \"pointer\",\n userSelect: \"none\",\n touchAction: \"none\",\n transition: \"all 0.2s ease\",\n boxShadow: `0 4px 15px rgba(0, 0, 0, 0.6), 0 0 20px rgba(${currentStanceColor.r}, ${currentStanceColor.g}, ${currentStanceColor.b}, 0.6)`,\n ...getFocusStyle(focusedStance === currentStance, {\n boxShadow: `0 0 0 4px rgba(${primaryColor.r}, ${primaryColor.g}, ${primaryColor.b}, 0.5), 0 4px 15px rgba(0, 0, 0, 0.6), 0 0 20px rgba(${currentStanceColor.r}, ${currentStanceColor.g}, ${currentStanceColor.b}, 0.6)`,\n outlineColor: KOREAN_COLORS.PRIMARY_CYAN,\n outlineWidth: 3,\n }),\n }}\n disabled={disabled}\n aria-label={\n createBilingualLabel(\n `현재 자세: ${STANCE_KOREAN_NAMES[currentStance]} ${TRIGRAM_SYMBOLS[currentStance]}. 자세 휠 열기`,\n `Current stance: ${TRIGRAM_STANCES_ORDER[currentStance]}. Open stance wheel`,\n ).label\n }\n aria-expanded={expanded}\n aria-haspopup=\"menu\"\n role=\"button\"\n tabIndex={disabled ? -1 : 0}\n data-testid=\"stance-wheel-pure-toggle\"\n >\n <div style={{ fontSize: \"24px\", lineHeight: 1 }}>\n {TRIGRAM_SYMBOLS[currentStance]}\n </div>\n <div style={{ fontSize: \"10px\", marginTop: \"2px\" }}>\n {STANCE_KOREAN_NAMES[currentStance]}\n </div>\n </button>\n </div>\n );\n};\n"],"mappings":"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"}
|
|
@@ -84,7 +84,6 @@ export interface TouchOptimizerReturn {
|
|
|
84
84
|
* );
|
|
85
85
|
* ```
|
|
86
86
|
*
|
|
87
|
-
* @public
|
|
88
87
|
* @korean 터치최적화사용
|
|
89
88
|
*/
|
|
90
89
|
export declare function useTouchOptimizer(onTouchStart: (x: number, y: number, timestamp: number) => void, onTouchMove: (x: number, y: number, timestamp: number) => void, onTouchEnd: (x: number, y: number, timestamp: number) => void, options?: TouchOptimizerOptions): TouchOptimizerReturn;
|
|
@@ -113,7 +112,6 @@ export declare function useTouchOptimizer(onTouchStart: (x: number, y: number, t
|
|
|
113
112
|
* );
|
|
114
113
|
* ```
|
|
115
114
|
*
|
|
116
|
-
* @public
|
|
117
115
|
* @korean 최적화된업데이트적용
|
|
118
116
|
*/
|
|
119
117
|
export declare function applyOptimizedUpdate(element: HTMLElement | null, visualUpdate: (element: HTMLElement) => void, stateUpdate: () => void): void;
|
|
@@ -135,7 +133,6 @@ export declare function applyOptimizedUpdate(element: HTMLElement | null, visual
|
|
|
135
133
|
* };
|
|
136
134
|
* ```
|
|
137
135
|
*
|
|
138
|
-
* @public
|
|
139
136
|
* @korean 변환스타일생성
|
|
140
137
|
*/
|
|
141
138
|
export declare function createTransformStyle(pressed: boolean, scale?: number): string;
|
|
@@ -147,7 +144,6 @@ export declare function createTransformStyle(pressed: boolean, scale?: number):
|
|
|
147
144
|
*
|
|
148
145
|
* @returns CSS filter string
|
|
149
146
|
*
|
|
150
|
-
* @public
|
|
151
147
|
* @korean 필터스타일생성
|
|
152
148
|
*/
|
|
153
149
|
export declare function createFilterStyle(pressed: boolean, brightness?: number): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TouchOptimizer.d.ts","sourceRoot":"","sources":["../../../../src/components/shared/mobile/TouchOptimizer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,oDAAoD;IACpD,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IACpC,2DAA2D;IAC3D,QAAQ,CAAC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IACvC,oDAAoD;IACpD,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,8DAA8D;IAC9D,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC;CACxC;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,qCAAqC;IACrC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,8BAA8B;IAC9B,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;CAC9B;AAED
|
|
1
|
+
{"version":3,"file":"TouchOptimizer.d.ts","sourceRoot":"","sources":["../../../../src/components/shared/mobile/TouchOptimizer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAIH;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,oDAAoD;IACpD,QAAQ,CAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IACpC,2DAA2D;IAC3D,QAAQ,CAAC,mBAAmB,CAAC,EAAE,OAAO,CAAC;IACvC,oDAAoD;IACpD,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,8DAA8D;IAC9D,QAAQ,CAAC,oBAAoB,CAAC,EAAE,MAAM,CAAC;CACxC;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,qCAAqC;IACrC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,8BAA8B;IAC9B,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,wBAAgB,iBAAiB,CAC/B,YAAY,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,EAC/D,WAAW,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,EAC9D,UAAU,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,EAC7D,OAAO,GAAE,qBAA0B,GAClC,oBAAoB,CA4NtB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,WAAW,GAAG,IAAI,EAC3B,YAAY,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,EAC5C,WAAW,EAAE,MAAM,IAAI,GACtB,IAAI,CAcN;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,OAAO,EAChB,KAAK,GAAE,MAAa,GACnB,MAAM,CAKR;AAED;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,OAAO,EAChB,UAAU,GAAE,MAAY,GACvB,MAAM,CAKR"}
|
|
@@ -25,7 +25,6 @@ import "react";
|
|
|
25
25
|
* );
|
|
26
26
|
* ```
|
|
27
27
|
*
|
|
28
|
-
* @public
|
|
29
28
|
* @korean 최적화된업데이트적용
|
|
30
29
|
*/
|
|
31
30
|
function applyOptimizedUpdate(element, visualUpdate, stateUpdate) {
|
|
@@ -55,7 +54,6 @@ function applyOptimizedUpdate(element, visualUpdate, stateUpdate) {
|
|
|
55
54
|
* };
|
|
56
55
|
* ```
|
|
57
56
|
*
|
|
58
|
-
* @public
|
|
59
57
|
* @korean 변환스타일생성
|
|
60
58
|
*/
|
|
61
59
|
function createTransformStyle(pressed, scale = .95) {
|
|
@@ -70,7 +68,6 @@ function createTransformStyle(pressed, scale = .95) {
|
|
|
70
68
|
*
|
|
71
69
|
* @returns CSS filter string
|
|
72
70
|
*
|
|
73
|
-
* @public
|
|
74
71
|
* @korean 필터스타일생성
|
|
75
72
|
*/
|
|
76
73
|
function createFilterStyle(pressed, brightness = 1.2) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TouchOptimizer.js","names":[],"sources":["../../../../src/components/shared/mobile/TouchOptimizer.ts"],"sourcesContent":["/**\n * TouchOptimizer\n * \n * High-performance touch event handling with <16ms latency\n * Uses requestAnimationFrame for immediate visual updates and\n * requestIdleCallback for deferred state updates to maintain 60fps\n * \n * Key Features:\n * - RAF-based visual updates (<16ms latency)\n * - Touch event coalescing (60-70% overhead reduction)\n * - Passive event listeners where appropriate\n * - Transform-only CSS animations (GPU-accelerated)\n * \n * @module components/mobile/TouchOptimizer\n * @category Mobile Controls\n * @korean 터치 최적화\n */\n\nimport { useCallback, useEffect, useRef, useState } from 'react';\n\n/**\n * Touch position data\n */\nexport interface TouchPosition {\n readonly x: number;\n readonly y: number;\n readonly timestamp: number;\n}\n\n/**\n * Touch optimization options\n */\nexport interface TouchOptimizerOptions {\n /** Enable touch event coalescing (default: true) */\n readonly enableCoalescing?: boolean;\n /** Use passive listeners where possible (default: true) */\n readonly usePassiveListeners?: boolean;\n /** Enable RAF for visual updates (default: true) */\n readonly useRAF?: boolean;\n /** Coalescing sample rate (default: 3 - use last 3 events) */\n readonly coalescingSampleRate?: number;\n}\n\n/**\n * Touch optimizer return type\n */\nexport interface TouchOptimizerReturn {\n /** Current RAF ID (for debugging) */\n readonly rafId: number | null;\n /** Whether touch is active */\n readonly isTouching: boolean;\n}\n\n/**\n * Custom hook for optimized touch handling with <16ms latency\n * \n * Uses requestAnimationFrame for immediate visual feedback and\n * defers state updates to avoid blocking the main thread\n * \n * @param onTouchStart - Callback for touch start (immediate)\n * @param onTouchMove - Callback for touch move (coalesced)\n * @param onTouchEnd - Callback for touch end (immediate)\n * @param options - Optimization options\n * \n * @example\n * ```tsx\n * const { isTouching } = useTouchOptimizer(\n * (x, y) => {\n * // Immediate visual update (same frame)\n * buttonRef.current.style.transform = 'scale(0.95)';\n * \n * // Defer state update\n * requestIdleCallback(() => {\n * setPressed(true);\n * onAction();\n * });\n * },\n * (x, y) => {\n * // Handle coalesced touch move\n * updatePosition(x, y);\n * },\n * () => {\n * // Immediate visual reset\n * buttonRef.current.style.transform = 'scale(1)';\n * \n * requestIdleCallback(() => {\n * setPressed(false);\n * });\n * }\n * );\n * ```\n * \n * @public\n * @korean 터치최적화사용\n */\nexport function useTouchOptimizer(\n onTouchStart: (x: number, y: number, timestamp: number) => void,\n onTouchMove: (x: number, y: number, timestamp: number) => void,\n onTouchEnd: (x: number, y: number, timestamp: number) => void,\n options: TouchOptimizerOptions = {}\n): TouchOptimizerReturn {\n const {\n enableCoalescing = true,\n usePassiveListeners = true,\n useRAF = true,\n coalescingSampleRate = 3,\n } = options;\n\n const rafIdRef = useRef<number | null>(null);\n const touchStateRef = useRef<TouchPosition | null>(null);\n const isTouchingRef = useRef<boolean>(false);\n const pendingMoveRef = useRef<TouchPosition | null>(null);\n \n // State for returning values (not using refs in return)\n const [rafId, setRafId] = useState<number | null>(null);\n const [isTouching, setIsTouching] = useState<boolean>(false);\n\n /**\n * Cancel pending RAF\n */\n const cancelPendingRAF = useCallback(() => {\n if (rafIdRef.current !== null) {\n cancelAnimationFrame(rafIdRef.current);\n rafIdRef.current = null;\n setRafId(null);\n }\n }, []);\n\n /**\n * Process touch start with RAF\n */\n const processTouchStart = useCallback(\n (x: number, y: number) => {\n const timestamp = performance.now();\n touchStateRef.current = { x, y, timestamp };\n isTouchingRef.current = true;\n setIsTouching(true);\n\n if (useRAF) {\n // Schedule immediate visual update (next frame, <16ms)\n cancelPendingRAF();\n rafIdRef.current = requestAnimationFrame(() => {\n onTouchStart(x, y, timestamp);\n rafIdRef.current = null;\n setRafId(null);\n });\n setRafId(rafIdRef.current);\n } else {\n // Direct call (no RAF)\n onTouchStart(x, y, timestamp);\n }\n },\n [onTouchStart, useRAF, cancelPendingRAF]\n );\n\n /**\n * Process coalesced touch move with RAF\n */\n const processTouchMove = useCallback(\n (x: number, y: number) => {\n const timestamp = performance.now();\n pendingMoveRef.current = { x, y, timestamp };\n\n if (useRAF && rafIdRef.current === null) {\n // Schedule update for next frame\n rafIdRef.current = requestAnimationFrame(() => {\n if (pendingMoveRef.current) {\n const { x, y, timestamp } = pendingMoveRef.current;\n onTouchMove(x, y, timestamp);\n pendingMoveRef.current = null;\n }\n rafIdRef.current = null;\n setRafId(null);\n });\n setRafId(rafIdRef.current);\n } else if (!useRAF) {\n // Direct call (no RAF)\n onTouchMove(x, y, timestamp);\n }\n },\n [onTouchMove, useRAF]\n );\n\n /**\n * Process touch end with RAF\n */\n const processTouchEnd = useCallback(\n (x: number, y: number) => {\n const timestamp = performance.now();\n isTouchingRef.current = false;\n setIsTouching(false);\n touchStateRef.current = null;\n pendingMoveRef.current = null;\n\n if (useRAF) {\n // Schedule immediate visual update (next frame, <16ms)\n cancelPendingRAF();\n rafIdRef.current = requestAnimationFrame(() => {\n onTouchEnd(x, y, timestamp);\n rafIdRef.current = null;\n setRafId(null);\n });\n setRafId(rafIdRef.current);\n } else {\n // Direct call (no RAF)\n onTouchEnd(x, y, timestamp);\n }\n },\n [onTouchEnd, useRAF, cancelPendingRAF]\n );\n\n /**\n * Handle touch start event\n */\n const handleTouchStart = useCallback(\n (e: TouchEvent) => {\n // Prevent default to eliminate 300ms delay\n if (!usePassiveListeners) {\n e.preventDefault();\n }\n\n const touch = e.touches[0];\n if (touch) {\n processTouchStart(touch.clientX, touch.clientY);\n }\n },\n [processTouchStart, usePassiveListeners]\n );\n\n /**\n * Handle touch move event with coalescing\n */\n const handleTouchMove = useCallback(\n (e: TouchEvent) => {\n if (!isTouchingRef.current) return;\n\n // Get coalesced events for smooth tracking\n let events: readonly Touch[] = [e.touches[0]];\n \n if (enableCoalescing) {\n // Feature detection: getCoalescedEvents() is experimental (Chrome 58+, Edge 79+)\n // Not supported in Safari or Firefox as of 2024\n // Fallback to single event if not supported\n const eventWithCoalescing = e as TouchEvent & { getCoalescedEvents?: () => TouchEvent[] };\n if (typeof eventWithCoalescing.getCoalescedEvents === 'function') {\n try {\n const coalesced = eventWithCoalescing.getCoalescedEvents();\n if (coalesced && coalesced.length > 0) {\n // Use only the last N events to reduce overhead\n const recentEvents = coalesced.slice(-coalescingSampleRate);\n events = recentEvents.map((evt: TouchEvent) => evt.touches[0]).filter((touch): touch is Touch => touch !== undefined);\n }\n } catch {\n // Fallback to single event if getCoalescedEvents fails (expected in Safari/Firefox)\n }\n }\n }\n\n // Process only the last event (most recent position)\n const lastTouch = events[events.length - 1];\n if (lastTouch) {\n processTouchMove(lastTouch.clientX, lastTouch.clientY);\n }\n },\n [enableCoalescing, coalescingSampleRate, processTouchMove]\n );\n\n /**\n * Handle touch end event\n */\n const handleTouchEnd = useCallback(\n (e: TouchEvent) => {\n if (!isTouchingRef.current) return;\n\n // Prevent default to eliminate delays\n if (!usePassiveListeners) {\n e.preventDefault();\n }\n\n const touch = e.changedTouches[0];\n if (touch) {\n processTouchEnd(touch.clientX, touch.clientY);\n }\n },\n [processTouchEnd, usePassiveListeners]\n );\n\n /**\n * Handle touch cancel event\n */\n const handleTouchCancel = useCallback(() => {\n isTouchingRef.current = false;\n setIsTouching(false);\n touchStateRef.current = null;\n pendingMoveRef.current = null;\n cancelPendingRAF();\n }, [cancelPendingRAF]);\n\n /**\n * Setup touch event listeners\n * \n * Note: Event listeners are attached to the document for each component instance.\n * This allows independent touch handling per component but may result in multiple\n * document-level listeners if many components use this hook simultaneously.\n * For applications with many touch-optimized components, consider implementing\n * an event delegation pattern or singleton event manager for better efficiency.\n */\n useEffect(() => {\n const options: AddEventListenerOptions = {\n passive: usePassiveListeners,\n };\n\n document.addEventListener('touchstart', handleTouchStart, options);\n document.addEventListener('touchmove', handleTouchMove, options);\n document.addEventListener('touchend', handleTouchEnd, options);\n document.addEventListener('touchcancel', handleTouchCancel, options);\n\n return () => {\n document.removeEventListener('touchstart', handleTouchStart);\n document.removeEventListener('touchmove', handleTouchMove);\n document.removeEventListener('touchend', handleTouchEnd);\n document.removeEventListener('touchcancel', handleTouchCancel);\n cancelPendingRAF();\n };\n }, [\n handleTouchStart,\n handleTouchMove,\n handleTouchEnd,\n handleTouchCancel,\n usePassiveListeners,\n cancelPendingRAF,\n ]);\n\n return {\n rafId,\n isTouching,\n };\n}\n\n/**\n * Helper function to create optimized visual updates\n * Updates DOM directly for immediate feedback, defers state\n * \n * @param element - DOM element to update\n * @param visualUpdate - Function to update visual state (runs in RAF)\n * @param stateUpdate - Function to update React state (runs in idle)\n * \n * @example\n * ```tsx\n * applyOptimizedUpdate(\n * buttonRef.current,\n * (el) => {\n * // Immediate visual feedback (<16ms)\n * el.style.transform = 'scale(0.95)';\n * el.style.filter = 'brightness(1.2)';\n * },\n * () => {\n * // Deferred state update (non-blocking)\n * setPressed(true);\n * onAction();\n * }\n * );\n * ```\n * \n * @public\n * @korean 최적화된업데이트적용\n */\nexport function applyOptimizedUpdate(\n element: HTMLElement | null,\n visualUpdate: (element: HTMLElement) => void,\n stateUpdate: () => void\n): void {\n // Immediate visual update (same frame)\n if (element) {\n requestAnimationFrame(() => {\n visualUpdate(element);\n });\n }\n\n // Deferred state update (when idle)\n if (typeof (window as Window & typeof globalThis).requestIdleCallback === 'function') {\n (window as Window & typeof globalThis).requestIdleCallback(() => {\n stateUpdate();\n });\n } else {\n // Fallback for browsers without requestIdleCallback\n setTimeout(stateUpdate, 0);\n }\n}\n\n/**\n * Create transform-only style for GPU-accelerated animations\n * Avoids layout thrashing by only using transform\n * \n * @param pressed - Whether element is pressed\n * @param scale - Scale value when pressed (default: 0.95)\n * \n * @returns CSS transform string\n * \n * @example\n * ```tsx\n * const style = {\n * transform: createTransformStyle(isPressed, 0.95),\n * transition: 'transform 0.1s ease-out',\n * willChange: 'transform', // Hint to GPU\n * };\n * ```\n * \n * @public\n * @korean 변환스타일생성\n */\nexport function createTransformStyle(\n pressed: boolean,\n scale: number = 0.95\n): string {\n if (pressed) {\n return `scale(${scale})`;\n }\n return 'scale(1)';\n}\n\n/**\n * Create filter style for visual effects\n * \n * @param pressed - Whether element is pressed\n * @param brightness - Brightness multiplier when pressed (default: 1.2)\n * \n * @returns CSS filter string\n * \n * @public\n * @korean 필터스타일생성\n */\nexport function createFilterStyle(\n pressed: boolean,\n brightness: number = 1.2\n): string {\n if (pressed) {\n return `brightness(${brightness})`;\n }\n return 'brightness(1)';\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA+WA,SAAgB,qBACd,SACA,cACA,aACM;CAEN,IAAI,SACF,4BAA4B;EAC1B,aAAa,QAAQ;GACrB;CAIJ,IAAI,OAAQ,OAAsC,wBAAwB,YACxE,OAAuC,0BAA0B;EAC/D,aAAa;GACb;MAGF,WAAW,aAAa,EAAE;;;;;;;;;;;;;;;;;;;;;;;AAyB9B,SAAgB,qBACd,SACA,QAAgB,KACR;CACR,IAAI,SACF,OAAO,SAAS,MAAM;CAExB,OAAO;;;;;;;;;;;;;AAcT,SAAgB,kBACd,SACA,aAAqB,KACb;CACR,IAAI,SACF,OAAO,cAAc,WAAW;CAElC,OAAO"}
|
|
1
|
+
{"version":3,"file":"TouchOptimizer.js","names":[],"sources":["../../../../src/components/shared/mobile/TouchOptimizer.ts"],"sourcesContent":["/**\n * TouchOptimizer\n * \n * High-performance touch event handling with <16ms latency\n * Uses requestAnimationFrame for immediate visual updates and\n * requestIdleCallback for deferred state updates to maintain 60fps\n * \n * Key Features:\n * - RAF-based visual updates (<16ms latency)\n * - Touch event coalescing (60-70% overhead reduction)\n * - Passive event listeners where appropriate\n * - Transform-only CSS animations (GPU-accelerated)\n * \n * @module components/mobile/TouchOptimizer\n * @category Mobile Controls\n * @korean 터치 최적화\n */\n\nimport { useCallback, useEffect, useRef, useState } from 'react';\n\n/**\n * Touch position data\n */\nexport interface TouchPosition {\n readonly x: number;\n readonly y: number;\n readonly timestamp: number;\n}\n\n/**\n * Touch optimization options\n */\nexport interface TouchOptimizerOptions {\n /** Enable touch event coalescing (default: true) */\n readonly enableCoalescing?: boolean;\n /** Use passive listeners where possible (default: true) */\n readonly usePassiveListeners?: boolean;\n /** Enable RAF for visual updates (default: true) */\n readonly useRAF?: boolean;\n /** Coalescing sample rate (default: 3 - use last 3 events) */\n readonly coalescingSampleRate?: number;\n}\n\n/**\n * Touch optimizer return type\n */\nexport interface TouchOptimizerReturn {\n /** Current RAF ID (for debugging) */\n readonly rafId: number | null;\n /** Whether touch is active */\n readonly isTouching: boolean;\n}\n\n/**\n * Custom hook for optimized touch handling with <16ms latency\n * \n * Uses requestAnimationFrame for immediate visual feedback and\n * defers state updates to avoid blocking the main thread\n * \n * @param onTouchStart - Callback for touch start (immediate)\n * @param onTouchMove - Callback for touch move (coalesced)\n * @param onTouchEnd - Callback for touch end (immediate)\n * @param options - Optimization options\n * \n * @example\n * ```tsx\n * const { isTouching } = useTouchOptimizer(\n * (x, y) => {\n * // Immediate visual update (same frame)\n * buttonRef.current.style.transform = 'scale(0.95)';\n * \n * // Defer state update\n * requestIdleCallback(() => {\n * setPressed(true);\n * onAction();\n * });\n * },\n * (x, y) => {\n * // Handle coalesced touch move\n * updatePosition(x, y);\n * },\n * () => {\n * // Immediate visual reset\n * buttonRef.current.style.transform = 'scale(1)';\n * \n * requestIdleCallback(() => {\n * setPressed(false);\n * });\n * }\n * );\n * ```\n * \n * @korean 터치최적화사용\n */\nexport function useTouchOptimizer(\n onTouchStart: (x: number, y: number, timestamp: number) => void,\n onTouchMove: (x: number, y: number, timestamp: number) => void,\n onTouchEnd: (x: number, y: number, timestamp: number) => void,\n options: TouchOptimizerOptions = {}\n): TouchOptimizerReturn {\n const {\n enableCoalescing = true,\n usePassiveListeners = true,\n useRAF = true,\n coalescingSampleRate = 3,\n } = options;\n\n const rafIdRef = useRef<number | null>(null);\n const touchStateRef = useRef<TouchPosition | null>(null);\n const isTouchingRef = useRef<boolean>(false);\n const pendingMoveRef = useRef<TouchPosition | null>(null);\n \n const [rafId, setRafId] = useState<number | null>(null);\n const [isTouching, setIsTouching] = useState<boolean>(false);\n\n /**\n * Cancel pending RAF\n */\n const cancelPendingRAF = useCallback(() => {\n if (rafIdRef.current !== null) {\n cancelAnimationFrame(rafIdRef.current);\n rafIdRef.current = null;\n setRafId(null);\n }\n }, []);\n\n /**\n * Process touch start with RAF\n */\n const processTouchStart = useCallback(\n (x: number, y: number) => {\n const timestamp = performance.now();\n touchStateRef.current = { x, y, timestamp };\n isTouchingRef.current = true;\n setIsTouching(true);\n\n if (useRAF) {\n cancelPendingRAF();\n rafIdRef.current = requestAnimationFrame(() => {\n onTouchStart(x, y, timestamp);\n rafIdRef.current = null;\n setRafId(null);\n });\n setRafId(rafIdRef.current);\n } else {\n onTouchStart(x, y, timestamp);\n }\n },\n [onTouchStart, useRAF, cancelPendingRAF]\n );\n\n /**\n * Process coalesced touch move with RAF\n */\n const processTouchMove = useCallback(\n (x: number, y: number) => {\n const timestamp = performance.now();\n pendingMoveRef.current = { x, y, timestamp };\n\n if (useRAF && rafIdRef.current === null) {\n rafIdRef.current = requestAnimationFrame(() => {\n if (pendingMoveRef.current) {\n const { x, y, timestamp } = pendingMoveRef.current;\n onTouchMove(x, y, timestamp);\n pendingMoveRef.current = null;\n }\n rafIdRef.current = null;\n setRafId(null);\n });\n setRafId(rafIdRef.current);\n } else if (!useRAF) {\n onTouchMove(x, y, timestamp);\n }\n },\n [onTouchMove, useRAF]\n );\n\n /**\n * Process touch end with RAF\n */\n const processTouchEnd = useCallback(\n (x: number, y: number) => {\n const timestamp = performance.now();\n isTouchingRef.current = false;\n setIsTouching(false);\n touchStateRef.current = null;\n pendingMoveRef.current = null;\n\n if (useRAF) {\n cancelPendingRAF();\n rafIdRef.current = requestAnimationFrame(() => {\n onTouchEnd(x, y, timestamp);\n rafIdRef.current = null;\n setRafId(null);\n });\n setRafId(rafIdRef.current);\n } else {\n onTouchEnd(x, y, timestamp);\n }\n },\n [onTouchEnd, useRAF, cancelPendingRAF]\n );\n\n /**\n * Handle touch start event\n */\n const handleTouchStart = useCallback(\n (e: TouchEvent) => {\n if (!usePassiveListeners) {\n e.preventDefault();\n }\n\n const touch = e.touches[0];\n if (touch) {\n processTouchStart(touch.clientX, touch.clientY);\n }\n },\n [processTouchStart, usePassiveListeners]\n );\n\n /**\n * Handle touch move event with coalescing\n */\n const handleTouchMove = useCallback(\n (e: TouchEvent) => {\n if (!isTouchingRef.current) return;\n\n let events: readonly Touch[] = [e.touches[0]];\n \n if (enableCoalescing) {\n const eventWithCoalescing = e as TouchEvent & { getCoalescedEvents?: () => TouchEvent[] };\n if (typeof eventWithCoalescing.getCoalescedEvents === 'function') {\n try {\n const coalesced = eventWithCoalescing.getCoalescedEvents();\n if (coalesced && coalesced.length > 0) {\n const recentEvents = coalesced.slice(-coalescingSampleRate);\n events = recentEvents.map((evt: TouchEvent) => evt.touches[0]).filter((touch): touch is Touch => touch !== undefined);\n }\n } catch { /* ignore coalescing errors */ }\n }\n }\n\n const lastTouch = events[events.length - 1];\n if (lastTouch) {\n processTouchMove(lastTouch.clientX, lastTouch.clientY);\n }\n },\n [enableCoalescing, coalescingSampleRate, processTouchMove]\n );\n\n /**\n * Handle touch end event\n */\n const handleTouchEnd = useCallback(\n (e: TouchEvent) => {\n if (!isTouchingRef.current) return;\n\n if (!usePassiveListeners) {\n e.preventDefault();\n }\n\n const touch = e.changedTouches[0];\n if (touch) {\n processTouchEnd(touch.clientX, touch.clientY);\n }\n },\n [processTouchEnd, usePassiveListeners]\n );\n\n /**\n * Handle touch cancel event\n */\n const handleTouchCancel = useCallback(() => {\n isTouchingRef.current = false;\n setIsTouching(false);\n touchStateRef.current = null;\n pendingMoveRef.current = null;\n cancelPendingRAF();\n }, [cancelPendingRAF]);\n\n /**\n * Setup touch event listeners\n * \n * Note: Event listeners are attached to the document for each component instance.\n * This allows independent touch handling per component but may result in multiple\n * document-level listeners if many components use this hook simultaneously.\n * For applications with many touch-optimized components, consider implementing\n * an event delegation pattern or singleton event manager for better efficiency.\n */\n useEffect(() => {\n const options: AddEventListenerOptions = {\n passive: usePassiveListeners,\n };\n\n document.addEventListener('touchstart', handleTouchStart, options);\n document.addEventListener('touchmove', handleTouchMove, options);\n document.addEventListener('touchend', handleTouchEnd, options);\n document.addEventListener('touchcancel', handleTouchCancel, options);\n\n return () => {\n document.removeEventListener('touchstart', handleTouchStart);\n document.removeEventListener('touchmove', handleTouchMove);\n document.removeEventListener('touchend', handleTouchEnd);\n document.removeEventListener('touchcancel', handleTouchCancel);\n cancelPendingRAF();\n };\n }, [\n handleTouchStart,\n handleTouchMove,\n handleTouchEnd,\n handleTouchCancel,\n usePassiveListeners,\n cancelPendingRAF,\n ]);\n\n return {\n rafId,\n isTouching,\n };\n}\n\n/**\n * Helper function to create optimized visual updates\n * Updates DOM directly for immediate feedback, defers state\n * \n * @param element - DOM element to update\n * @param visualUpdate - Function to update visual state (runs in RAF)\n * @param stateUpdate - Function to update React state (runs in idle)\n * \n * @example\n * ```tsx\n * applyOptimizedUpdate(\n * buttonRef.current,\n * (el) => {\n * // Immediate visual feedback (<16ms)\n * el.style.transform = 'scale(0.95)';\n * el.style.filter = 'brightness(1.2)';\n * },\n * () => {\n * // Deferred state update (non-blocking)\n * setPressed(true);\n * onAction();\n * }\n * );\n * ```\n * \n * @korean 최적화된업데이트적용\n */\nexport function applyOptimizedUpdate(\n element: HTMLElement | null,\n visualUpdate: (element: HTMLElement) => void,\n stateUpdate: () => void\n): void {\n if (element) {\n requestAnimationFrame(() => {\n visualUpdate(element);\n });\n }\n\n if (typeof (window as Window & typeof globalThis).requestIdleCallback === 'function') {\n (window as Window & typeof globalThis).requestIdleCallback(() => {\n stateUpdate();\n });\n } else {\n setTimeout(stateUpdate, 0);\n }\n}\n\n/**\n * Create transform-only style for GPU-accelerated animations\n * Avoids layout thrashing by only using transform\n * \n * @param pressed - Whether element is pressed\n * @param scale - Scale value when pressed (default: 0.95)\n * \n * @returns CSS transform string\n * \n * @example\n * ```tsx\n * const style = {\n * transform: createTransformStyle(isPressed, 0.95),\n * transition: 'transform 0.1s ease-out',\n * willChange: 'transform', // Hint to GPU\n * };\n * ```\n * \n * @korean 변환스타일생성\n */\nexport function createTransformStyle(\n pressed: boolean,\n scale: number = 0.95\n): string {\n if (pressed) {\n return `scale(${scale})`;\n }\n return 'scale(1)';\n}\n\n/**\n * Create filter style for visual effects\n * \n * @param pressed - Whether element is pressed\n * @param brightness - Brightness multiplier when pressed (default: 1.2)\n * \n * @returns CSS filter string\n * \n * @korean 필터스타일생성\n */\nexport function createFilterStyle(\n pressed: boolean,\n brightness: number = 1.2\n): string {\n if (pressed) {\n return `brightness(${brightness})`;\n }\n return 'brightness(1)';\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4VA,SAAgB,qBACd,SACA,cACA,aACM;CACN,IAAI,SACF,4BAA4B;EAC1B,aAAa,QAAQ;GACrB;CAGJ,IAAI,OAAQ,OAAsC,wBAAwB,YACxE,OAAuC,0BAA0B;EAC/D,aAAa;GACb;MAEF,WAAW,aAAa,EAAE;;;;;;;;;;;;;;;;;;;;;;AAwB9B,SAAgB,qBACd,SACA,QAAgB,KACR;CACR,IAAI,SACF,OAAO,SAAS,MAAM;CAExB,OAAO;;;;;;;;;;;;AAaT,SAAgB,kBACd,SACA,aAAqB,KACb;CACR,IAAI,SACF,OAAO,cAAc,WAAW;CAElC,OAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VirtualDPad.d.ts","sourceRoot":"","sources":["../../../../src/components/shared/mobile/VirtualDPad.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,KAAyC,MAAM,OAAO,CAAC;AAQ9D;;GAEG;AACH,MAAM,MAAM,SAAS,GACjB,IAAI,GACJ,UAAU,GACV,OAAO,GACP,YAAY,GACZ,MAAM,GACN,WAAW,GACX,MAAM,GACN,SAAS,CAAC;AAEd;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,KAAK,CAAC;AAE5C;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,sCAAsC;IACtC,QAAQ,CAAC,MAAM,EAAE,CACf,SAAS,EAAE,SAAS,GAAG,IAAI,EAC3B,SAAS,EAAE,aAAa,KACrB,IAAI,CAAC;IACV,gCAAgC;IAChC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,iDAAiD;IACjD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,iEAAiE;IACjE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,iDAAiD;IACjD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,0CAA0C;IAC1C,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;
|
|
1
|
+
{"version":3,"file":"VirtualDPad.d.ts","sourceRoot":"","sources":["../../../../src/components/shared/mobile/VirtualDPad.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,KAAyC,MAAM,OAAO,CAAC;AAQ9D;;GAEG;AACH,MAAM,MAAM,SAAS,GACjB,IAAI,GACJ,UAAU,GACV,OAAO,GACP,YAAY,GACZ,MAAM,GACN,WAAW,GACX,MAAM,GACN,SAAS,CAAC;AAEd;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,KAAK,CAAC;AAE5C;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,sCAAsC;IACtC,QAAQ,CAAC,MAAM,EAAE,CACf,SAAS,EAAE,SAAS,GAAG,IAAI,EAC3B,SAAS,EAAE,aAAa,KACrB,IAAI,CAAC;IACV,gCAAgC;IAChC,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,iDAAiD;IACjD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,iEAAiE;IACjE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,iDAAiD;IACjD,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,0CAA0C;IAC1C,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;CAC3B;AAkVD;;;GAGG;AACH,eAAO,MAAM,WAAW,8CAYvB,CAAC"}
|