blacktrigram 0.7.11 → 0.7.13
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/DATA_MODEL.md +347 -0
- package/lib/App.d.ts.map +1 -1
- package/lib/App2.js +0 -6
- package/lib/App2.js.map +1 -1
- package/lib/assets/index.css +102 -94
- package/lib/components/screens/combat/CombatScreen3D.d.ts +1 -1
- package/lib/components/screens/combat/CombatScreen3D.js +2 -2
- package/lib/components/screens/combat/CombatScreen3D.js.map +1 -1
- package/lib/components/screens/combat/components/controls/CombatButtons.d.ts.map +1 -1
- package/lib/components/screens/combat/components/controls/CombatButtons.js +22 -7
- package/lib/components/screens/combat/components/controls/CombatButtons.js.map +1 -1
- package/lib/components/screens/combat/components/controls/CombatControlsPanel.d.ts +2 -0
- package/lib/components/screens/combat/components/controls/CombatControlsPanel.d.ts.map +1 -1
- package/lib/components/screens/combat/components/controls/CombatControlsPanel.js +7 -4
- package/lib/components/screens/combat/components/controls/CombatControlsPanel.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 +15 -5
- package/lib/components/screens/combat/components/controls/PauseMenu.js.map +1 -1
- package/lib/components/screens/combat/components/feedback/RoundAnnouncementOverlayHtml.js +15 -16
- package/lib/components/screens/combat/components/feedback/RoundAnnouncementOverlayHtml.js.map +1 -1
- package/lib/components/screens/combat/components/hud/DifficultyIndicator.js +1 -2
- package/lib/components/screens/combat/components/hud/DifficultyIndicator.js.map +1 -1
- package/lib/components/screens/combat/components/hud/PlayerStateOverlayHtml.js +28 -24
- package/lib/components/screens/combat/components/hud/PlayerStateOverlayHtml.js.map +1 -1
- package/lib/components/screens/combat/components/indicators/InputBufferDisplay.js +2 -4
- package/lib/components/screens/combat/components/indicators/InputBufferDisplay.js.map +1 -1
- package/lib/components/screens/controls/ControlsScreen3D.d.ts.map +1 -1
- package/lib/components/screens/controls/ControlsScreen3D.js +3 -2
- package/lib/components/screens/controls/ControlsScreen3D.js.map +1 -1
- package/lib/components/screens/controls/components/InteractiveControlDemoOverlayHtml.js +28 -30
- package/lib/components/screens/controls/components/InteractiveControlDemoOverlayHtml.js.map +1 -1
- package/lib/components/screens/controls/components/VisualKeyboard3D.d.ts.map +1 -1
- package/lib/components/screens/controls/components/VisualKeyboard3D.js +4 -3
- package/lib/components/screens/controls/components/VisualKeyboard3D.js.map +1 -1
- package/lib/components/screens/intro/IntroScreen3D.js +1 -1
- package/lib/components/screens/intro/components/MenuButtonsOverlayHtml.d.ts.map +1 -1
- package/lib/components/screens/intro/components/MenuButtonsOverlayHtml.js +5 -2
- package/lib/components/screens/intro/components/MenuButtonsOverlayHtml.js.map +1 -1
- package/lib/components/screens/philosophy/components/TrigramSymbol3D.d.ts.map +1 -1
- package/lib/components/screens/training/components/FootworkDrillsOverlayHtml.js +4 -4
- package/lib/components/screens/training/components/FootworkDrillsOverlayHtml.js.map +1 -1
- package/lib/components/screens/training/components/hud/TrainingTopHUD.js +1 -1
- package/lib/components/screens/training/components/hud/TrainingTopHUD.js.map +1 -1
- package/lib/components/shared/base/ResponsiveContainer.d.ts +6 -0
- package/lib/components/shared/base/ResponsiveContainer.d.ts.map +1 -1
- package/lib/components/shared/three/effects/ActionFeedback.js +1 -2
- package/lib/components/shared/three/effects/ActionFeedback.js.map +1 -1
- package/lib/components/shared/three/effects/DamageNumbers.js +1 -2
- package/lib/components/shared/three/effects/DamageNumbers.js.map +1 -1
- package/lib/components/shared/three/ui/BodyPartHealthDisplay.js +5 -5
- package/lib/components/shared/three/ui/BodyPartHealthDisplay.js.map +1 -1
- package/lib/components/shared/three/ui/BreathingIndicator2.js +3 -2
- package/lib/components/shared/three/ui/BreathingIndicator2.js.map +1 -1
- package/lib/components/shared/three/ui/TechniqueCard.d.ts.map +1 -1
- package/lib/components/shared/three/ui/TechniqueCard.js +27 -30
- 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 +57 -59
- package/lib/components/shared/three/ui/VitalPointOverlayControlsHtml.js.map +1 -1
- package/lib/components/shared/ui/BaseHUDContainer.d.ts +40 -0
- package/lib/components/shared/ui/BaseHUDContainer.d.ts.map +1 -1
- package/lib/components/shared/ui/BaseHUDContainer.js +40 -0
- package/lib/components/shared/ui/BaseHUDContainer.js.map +1 -1
- package/lib/components/shared/ui/MobileHUDLayout.d.ts +13 -0
- package/lib/components/shared/ui/MobileHUDLayout.d.ts.map +1 -1
- package/lib/components/shared/ui/SplashScreen.js +10 -10
- package/lib/components/shared/ui/SplashScreen.js.map +1 -1
- package/lib/components/shared/ui/VitalPointOverlayControlsPure.d.ts.map +1 -1
- package/lib/components/shared/ui/VitalPointOverlayControlsPure.js +57 -62
- package/lib/components/shared/ui/VitalPointOverlayControlsPure.js.map +1 -1
- package/lib/components/shared/ui/VolumeControl.js +7 -7
- package/lib/components/shared/ui/VolumeControl.js.map +1 -1
- package/package.json +9 -9
|
@@ -16,6 +16,46 @@ import { jsx } from "react/jsx-runtime";
|
|
|
16
16
|
* - Pointer events handling
|
|
17
17
|
* - Backdrop blur effects
|
|
18
18
|
*
|
|
19
|
+
* ## Z-Index Stacking Order (Combat HUD Layers)
|
|
20
|
+
*
|
|
21
|
+
* The combat screen renders multiple overlapping HUD panels. The stacking
|
|
22
|
+
* order is managed by the Z_INDEX constants from LayoutTypes.ts:
|
|
23
|
+
*
|
|
24
|
+
* | Layer | Z-Index | Description |
|
|
25
|
+
* |---------------------|---------|------------------------------------|
|
|
26
|
+
* | BACKGROUND | 0 | 3D scene background |
|
|
27
|
+
* | ARENA | 10 | Combat arena mesh |
|
|
28
|
+
* | PLAYERS | 20 | Character models |
|
|
29
|
+
* | EFFECTS | 30 | Particles and VFX |
|
|
30
|
+
* | HUD_BACKGROUND | 40 | HUD panel backgrounds |
|
|
31
|
+
* | HUD (default) | 50 | Left/Right/Top/Bottom HUD panels |
|
|
32
|
+
* | TECHNIQUE_BAR | 55 | Technique bar overlay |
|
|
33
|
+
* | HUD_OVERLAY | 60 | PlayerStateOverlay and sub-HUDs |
|
|
34
|
+
* | MOBILE_CONTROLS | 100 | Touch controls on mobile |
|
|
35
|
+
* | MODAL | 200 | Modal dialogs |
|
|
36
|
+
* | TOOLTIP | 300 | Tooltips and hints |
|
|
37
|
+
* | PAUSE_MENU | 1000 | Pause menu overlay |
|
|
38
|
+
* | LOADING | 2000 | Loading screens |
|
|
39
|
+
* | DEBUG | 9000 | Performance debug overlay |
|
|
40
|
+
*
|
|
41
|
+
* All BaseHUDContainer instances default to Z_INDEX.HUD (50). Parent
|
|
42
|
+
* screens can override via the `zIndex` prop when a different layer
|
|
43
|
+
* is needed (e.g., overlays at HUD_OVERLAY = 60).
|
|
44
|
+
*
|
|
45
|
+
* ## Viewport Breakpoints (Expected HUD Sizes)
|
|
46
|
+
*
|
|
47
|
+
* | Viewport | Width | Left/Right HUD | Top HUD | Bottom HUD |
|
|
48
|
+
* |---------------------|----------|----------------|---------|------------|
|
|
49
|
+
* | Small Phone (≤375) | ≤375px | ~120-150px | ~50px | ~90px |
|
|
50
|
+
* | Mobile (<768) | <768px | ~180-200px | ~60px | ~110px |
|
|
51
|
+
* | Tablet (768-1199) | 768-1199 | ~220-260px | ~65px | ~120px |
|
|
52
|
+
* | Desktop (≥1200) | ≥1200px | ~260-300px | ~70px | ~130px |
|
|
53
|
+
* | 4K (≥1920) | ≥1920px | ~300-400px | ~80px | ~140px |
|
|
54
|
+
*
|
|
55
|
+
* Width/height values are passed by the parent screen and scaled via
|
|
56
|
+
* positionScale multipliers. This table documents the expected ranges
|
|
57
|
+
* produced by CombatScreen3D and TrainingScreen3D layout calculations.
|
|
58
|
+
*
|
|
19
59
|
* @module components/shared/ui
|
|
20
60
|
* @korean 기본HUD컨테이너 - 공통 패턴을 가진 재사용 가능한 HUD 컨테이너
|
|
21
61
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BaseHUDContainer.js","names":[],"sources":["../../../../src/components/shared/ui/BaseHUDContainer.tsx"],"sourcesContent":["/**\n * BaseHUDContainer - Reusable HUD container with common patterns\n *\n * Provides consistent container styling and positioning for all HUD components.\n * Eliminates code duplication across Training and Combat HUDs.\n *\n * Features:\n * - Responsive positioning based on HUD position (left, right, top, bottom)\n * - Korean cyberpunk theming with gradients and borders\n * - Pointer events handling\n * - Backdrop blur effects\n *\n * @module components/shared/ui\n * @korean 기본HUD컨테이너 - 공통 패턴을 가진 재사용 가능한 HUD 컨테이너\n */\n\nimport React from \"react\";\nimport { Z_INDEX } from \"../../../types/LayoutTypes\";\nimport { KOREAN_COLORS } from \"@/types/constants\";\nimport { hexToRgbaString } from \"../../../utils/colorUtils\";\n\n/**\n * HUD position type\n */\nexport type HUDPosition = \"left\" | \"right\" | \"top\" | \"bottom\";\n\n/**\n * Props for BaseHUDContainer component\n */\nexport interface BaseHUDContainerProps {\n /** Position of the HUD (left, right, top, bottom) */\n readonly position: HUDPosition;\n /** Width in pixels (used for left/right positions; top/bottom use 100% width) */\n readonly width: number;\n /** Height in pixels */\n readonly height: number;\n /** Top offset in pixels (for left/right HUDs) */\n readonly topOffset?: number;\n /** Internal padding in pixels */\n readonly padding?: number;\n /** Gap between sections in pixels */\n readonly gap?: number;\n /** Z-index for layering */\n readonly zIndex?: number;\n /** Additional CSS styles */\n readonly style?: React.CSSProperties;\n /** Child elements */\n readonly children: React.ReactNode;\n /** Test ID for testing */\n readonly dataTestId?: string;\n}\n\n/**\n * BaseHUDContainer Component\n *\n * Reusable container for HUD elements with consistent styling and positioning.\n * Handles left, right, top, and bottom positions with appropriate borders,\n * gradients, and responsive behavior.\n *\n * @example\n * ```tsx\n * <BaseHUDContainer\n * position=\"left\"\n * width={268}\n * height={940}\n * topOffset={70}\n * padding={12}\n * gap={14}\n * dataTestId=\"combat-left-hud\"\n * >\n * <PlayerHUD player={player} />\n * <SpeedIndicator speed={speed} />\n * </BaseHUDContainer>\n * ```\n */\nexport const BaseHUDContainer: React.FC<BaseHUDContainerProps> = ({\n position,\n width,\n height,\n topOffset = 0,\n padding = 10,\n gap = 12,\n zIndex = Z_INDEX.HUD,\n style = {},\n children,\n dataTestId,\n}) => {\n // Calculate position-specific styles\n // Using KOREAN_COLORS directly for stable memoization instead of useKoreanTheme\n const containerStyle = React.useMemo<React.CSSProperties>(() => {\n const baseStyle: React.CSSProperties = {\n position: \"absolute\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"stretch\",\n pointerEvents: \"none\",\n padding: `${padding}px`,\n boxSizing: \"border-box\",\n gap: `${gap}px`,\n zIndex,\n backdropFilter: \"blur(8px)\",\n };\n\n switch (position) {\n case \"left\":\n return {\n ...baseStyle,\n left: 0,\n top: `${topOffset}px`,\n width: `${width}px`,\n height: `${height}px`,\n justifyContent: \"flex-start\",\n borderRight: `2px solid ${hexToRgbaString(KOREAN_COLORS.PRIMARY_CYAN, 0.4)}`,\n background: `linear-gradient(90deg, ${hexToRgbaString(KOREAN_COLORS.UI_BACKGROUND_DARK, 0.85)} 0%, ${hexToRgbaString(KOREAN_COLORS.UI_BACKGROUND_DARK, 0.4)} 100%)`,\n };\n\n case \"right\":\n return {\n ...baseStyle,\n right: 0,\n top: `${topOffset}px`,\n width: `${width}px`,\n height: `${height}px`,\n justifyContent: \"flex-start\",\n borderLeft: `2px solid ${hexToRgbaString(KOREAN_COLORS.PRIMARY_CYAN, 0.4)}`,\n background: `linear-gradient(270deg, ${hexToRgbaString(KOREAN_COLORS.UI_BACKGROUND_DARK, 0.85)} 0%, ${hexToRgbaString(KOREAN_COLORS.UI_BACKGROUND_DARK, 0.4)} 100%)`,\n };\n\n case \"top\":\n return {\n ...baseStyle,\n top: 0,\n left: 0,\n width: \"100%\",\n height: `${height}px`,\n flexDirection: \"row\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n borderBottom: `2px solid ${hexToRgbaString(KOREAN_COLORS.PRIMARY_CYAN, 0.4)}`,\n background: `linear-gradient(180deg, ${hexToRgbaString(KOREAN_COLORS.UI_BACKGROUND_DARK, 0.9)} 0%, ${hexToRgbaString(KOREAN_COLORS.UI_BACKGROUND_DARK, 0.7)} 100%)`,\n };\n\n case \"bottom\":\n return {\n ...baseStyle,\n bottom: 0,\n left: 0,\n width: \"100%\",\n height: `${height}px`,\n flexDirection: \"row\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n borderTop: `2px solid ${hexToRgbaString(KOREAN_COLORS.PRIMARY_CYAN, 0.4)}`,\n background: `linear-gradient(0deg, ${hexToRgbaString(KOREAN_COLORS.UI_BACKGROUND_DARK, 0.9)} 0%, ${hexToRgbaString(KOREAN_COLORS.UI_BACKGROUND_DARK, 0.7)} 100%)`,\n };\n }\n }, [position, width, height, topOffset, padding, gap, zIndex]);\n\n return (\n <div style={{ ...containerStyle, ...style }} data-testid={dataTestId}>\n {children}\n </div>\n );\n};\n\nexport default BaseHUDContainer;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2EA,IAAa,oBAAqD,EAChE,UACA,OACA,QACA,YAAY,GACZ,UAAU,IACV,MAAM,IACN,SAAS,QAAQ,KACjB,QAAQ,EAAE,EACV,UACA,iBACI;AAwEJ,QACE,oBAAC,OAAD;EAAK,OAAO;GAAE,GAtEO,MAAM,cAAmC;IAC9D,MAAM,YAAiC;KACrC,UAAU;KACV,SAAS;KACT,eAAe;KACf,YAAY;KACZ,eAAe;KACf,SAAS,GAAG,QAAQ;KACpB,WAAW;KACX,KAAK,GAAG,IAAI;KACZ;KACA,gBAAgB;KACjB;AAED,YAAQ,UAAR;KACE,KAAK,OACH,QAAO;MACL,GAAG;MACH,MAAM;MACN,KAAK,GAAG,UAAU;MAClB,OAAO,GAAG,MAAM;MAChB,QAAQ,GAAG,OAAO;MAClB,gBAAgB;MAChB,aAAa,aAAa,gBAAgB,cAAc,cAAc,GAAI;MAC1E,YAAY,0BAA0B,gBAAgB,cAAc,oBAAoB,IAAK,CAAC,OAAO,gBAAgB,cAAc,oBAAoB,GAAI,CAAC;MAC7J;KAEH,KAAK,QACH,QAAO;MACL,GAAG;MACH,OAAO;MACP,KAAK,GAAG,UAAU;MAClB,OAAO,GAAG,MAAM;MAChB,QAAQ,GAAG,OAAO;MAClB,gBAAgB;MAChB,YAAY,aAAa,gBAAgB,cAAc,cAAc,GAAI;MACzE,YAAY,2BAA2B,gBAAgB,cAAc,oBAAoB,IAAK,CAAC,OAAO,gBAAgB,cAAc,oBAAoB,GAAI,CAAC;MAC9J;KAEH,KAAK,MACH,QAAO;MACL,GAAG;MACH,KAAK;MACL,MAAM;MACN,OAAO;MACP,QAAQ,GAAG,OAAO;MAClB,eAAe;MACf,gBAAgB;MAChB,YAAY;MACZ,cAAc,aAAa,gBAAgB,cAAc,cAAc,GAAI;MAC3E,YAAY,2BAA2B,gBAAgB,cAAc,oBAAoB,GAAI,CAAC,OAAO,gBAAgB,cAAc,oBAAoB,GAAI,CAAC;MAC7J;KAEH,KAAK,SACH,QAAO;MACL,GAAG;MACH,QAAQ;MACR,MAAM;MACN,OAAO;MACP,QAAQ,GAAG,OAAO;MAClB,eAAe;MACf,gBAAgB;MAChB,YAAY;MACZ,WAAW,aAAa,gBAAgB,cAAc,cAAc,GAAI;MACxE,YAAY,yBAAyB,gBAAgB,cAAc,oBAAoB,GAAI,CAAC,OAAO,gBAAgB,cAAc,oBAAoB,GAAI,CAAC;MAC3J;;MAEJ;IAAC;IAAU;IAAO;IAAQ;IAAW;IAAS;IAAK;IAAO,CAAC;GAG3B,GAAG;GAAO;EAAE,eAAa;EACvD;EACG,CAAA"}
|
|
1
|
+
{"version":3,"file":"BaseHUDContainer.js","names":[],"sources":["../../../../src/components/shared/ui/BaseHUDContainer.tsx"],"sourcesContent":["/**\n * BaseHUDContainer - Reusable HUD container with common patterns\n *\n * Provides consistent container styling and positioning for all HUD components.\n * Eliminates code duplication across Training and Combat HUDs.\n *\n * Features:\n * - Responsive positioning based on HUD position (left, right, top, bottom)\n * - Korean cyberpunk theming with gradients and borders\n * - Pointer events handling\n * - Backdrop blur effects\n *\n * ## Z-Index Stacking Order (Combat HUD Layers)\n *\n * The combat screen renders multiple overlapping HUD panels. The stacking\n * order is managed by the Z_INDEX constants from LayoutTypes.ts:\n *\n * | Layer | Z-Index | Description |\n * |---------------------|---------|------------------------------------|\n * | BACKGROUND | 0 | 3D scene background |\n * | ARENA | 10 | Combat arena mesh |\n * | PLAYERS | 20 | Character models |\n * | EFFECTS | 30 | Particles and VFX |\n * | HUD_BACKGROUND | 40 | HUD panel backgrounds |\n * | HUD (default) | 50 | Left/Right/Top/Bottom HUD panels |\n * | TECHNIQUE_BAR | 55 | Technique bar overlay |\n * | HUD_OVERLAY | 60 | PlayerStateOverlay and sub-HUDs |\n * | MOBILE_CONTROLS | 100 | Touch controls on mobile |\n * | MODAL | 200 | Modal dialogs |\n * | TOOLTIP | 300 | Tooltips and hints |\n * | PAUSE_MENU | 1000 | Pause menu overlay |\n * | LOADING | 2000 | Loading screens |\n * | DEBUG | 9000 | Performance debug overlay |\n *\n * All BaseHUDContainer instances default to Z_INDEX.HUD (50). Parent\n * screens can override via the `zIndex` prop when a different layer\n * is needed (e.g., overlays at HUD_OVERLAY = 60).\n *\n * ## Viewport Breakpoints (Expected HUD Sizes)\n *\n * | Viewport | Width | Left/Right HUD | Top HUD | Bottom HUD |\n * |---------------------|----------|----------------|---------|------------|\n * | Small Phone (≤375) | ≤375px | ~120-150px | ~50px | ~90px |\n * | Mobile (<768) | <768px | ~180-200px | ~60px | ~110px |\n * | Tablet (768-1199) | 768-1199 | ~220-260px | ~65px | ~120px |\n * | Desktop (≥1200) | ≥1200px | ~260-300px | ~70px | ~130px |\n * | 4K (≥1920) | ≥1920px | ~300-400px | ~80px | ~140px |\n *\n * Width/height values are passed by the parent screen and scaled via\n * positionScale multipliers. This table documents the expected ranges\n * produced by CombatScreen3D and TrainingScreen3D layout calculations.\n *\n * @module components/shared/ui\n * @korean 기본HUD컨테이너 - 공통 패턴을 가진 재사용 가능한 HUD 컨테이너\n */\n\nimport React from \"react\";\nimport { Z_INDEX } from \"../../../types/LayoutTypes\";\nimport { KOREAN_COLORS } from \"@/types/constants\";\nimport { hexToRgbaString } from \"../../../utils/colorUtils\";\n\n/**\n * HUD position type\n */\nexport type HUDPosition = \"left\" | \"right\" | \"top\" | \"bottom\";\n\n/**\n * Props for BaseHUDContainer component\n */\nexport interface BaseHUDContainerProps {\n /** Position of the HUD (left, right, top, bottom) */\n readonly position: HUDPosition;\n /** Width in pixels (used for left/right positions; top/bottom use 100% width) */\n readonly width: number;\n /** Height in pixels */\n readonly height: number;\n /** Top offset in pixels (for left/right HUDs) */\n readonly topOffset?: number;\n /** Internal padding in pixels */\n readonly padding?: number;\n /** Gap between sections in pixels */\n readonly gap?: number;\n /** Z-index for layering */\n readonly zIndex?: number;\n /** Additional CSS styles */\n readonly style?: React.CSSProperties;\n /** Child elements */\n readonly children: React.ReactNode;\n /** Test ID for testing */\n readonly dataTestId?: string;\n}\n\n/**\n * BaseHUDContainer Component\n *\n * Reusable container for HUD elements with consistent styling and positioning.\n * Handles left, right, top, and bottom positions with appropriate borders,\n * gradients, and responsive behavior.\n *\n * @example\n * ```tsx\n * <BaseHUDContainer\n * position=\"left\"\n * width={268}\n * height={940}\n * topOffset={70}\n * padding={12}\n * gap={14}\n * dataTestId=\"combat-left-hud\"\n * >\n * <PlayerHUD player={player} />\n * <SpeedIndicator speed={speed} />\n * </BaseHUDContainer>\n * ```\n */\nexport const BaseHUDContainer: React.FC<BaseHUDContainerProps> = ({\n position,\n width,\n height,\n topOffset = 0,\n padding = 10,\n gap = 12,\n zIndex = Z_INDEX.HUD,\n style = {},\n children,\n dataTestId,\n}) => {\n // Calculate position-specific styles\n // Using KOREAN_COLORS directly for stable memoization instead of useKoreanTheme\n //\n // Z-index stacking: defaults to Z_INDEX.HUD (50). Combat screen layers\n // are ordered as: HUD_BACKGROUND (40) < HUD (50) < TECHNIQUE_BAR (55) < HUD_OVERLAY (60).\n // Left/Right/Top/Bottom HUDs all share the same z-index (HUD = 50) and\n // rely on DOM order for overlap resolution. The PlayerStateOverlay sits\n // at HUD_OVERLAY (60) to appear above all HUD panels.\n //\n // Safe area note: left/right HUD panels are anchored to the viewport edge\n // with left: 0 / right: 0. Reducing the width prop alone will not move a\n // panel out of a landscape notch or horizontal safe-area cutout. If the\n // parent needs to avoid env(safe-area-inset-left) /\n // env(safe-area-inset-right), it should also provide a horizontal offset\n // via the existing style prop (for example, left/right or horizontal\n // padding) in addition to any width adjustments. Horizontal safe-area\n // insets affect left/right panel widths and offsets, not topOffset (which\n // is purely vertical). For portrait notch/status-bar avoidance, the parent\n // should incorporate layout.safeArea.top into the topOffset calculation.\n const containerStyle = React.useMemo<React.CSSProperties>(() => {\n const baseStyle: React.CSSProperties = {\n position: \"absolute\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"stretch\",\n pointerEvents: \"none\",\n padding: `${padding}px`,\n boxSizing: \"border-box\",\n gap: `${gap}px`,\n zIndex,\n backdropFilter: \"blur(8px)\",\n };\n\n switch (position) {\n case \"left\":\n return {\n ...baseStyle,\n left: 0,\n top: `${topOffset}px`,\n width: `${width}px`,\n height: `${height}px`,\n justifyContent: \"flex-start\",\n borderRight: `2px solid ${hexToRgbaString(KOREAN_COLORS.PRIMARY_CYAN, 0.4)}`,\n background: `linear-gradient(90deg, ${hexToRgbaString(KOREAN_COLORS.UI_BACKGROUND_DARK, 0.85)} 0%, ${hexToRgbaString(KOREAN_COLORS.UI_BACKGROUND_DARK, 0.4)} 100%)`,\n };\n\n case \"right\":\n return {\n ...baseStyle,\n right: 0,\n top: `${topOffset}px`,\n width: `${width}px`,\n height: `${height}px`,\n justifyContent: \"flex-start\",\n borderLeft: `2px solid ${hexToRgbaString(KOREAN_COLORS.PRIMARY_CYAN, 0.4)}`,\n background: `linear-gradient(270deg, ${hexToRgbaString(KOREAN_COLORS.UI_BACKGROUND_DARK, 0.85)} 0%, ${hexToRgbaString(KOREAN_COLORS.UI_BACKGROUND_DARK, 0.4)} 100%)`,\n };\n\n case \"top\":\n return {\n ...baseStyle,\n top: 0,\n left: 0,\n width: \"100%\",\n height: `${height}px`,\n flexDirection: \"row\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n borderBottom: `2px solid ${hexToRgbaString(KOREAN_COLORS.PRIMARY_CYAN, 0.4)}`,\n background: `linear-gradient(180deg, ${hexToRgbaString(KOREAN_COLORS.UI_BACKGROUND_DARK, 0.9)} 0%, ${hexToRgbaString(KOREAN_COLORS.UI_BACKGROUND_DARK, 0.7)} 100%)`,\n };\n\n case \"bottom\":\n return {\n ...baseStyle,\n bottom: 0,\n left: 0,\n width: \"100%\",\n height: `${height}px`,\n flexDirection: \"row\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n borderTop: `2px solid ${hexToRgbaString(KOREAN_COLORS.PRIMARY_CYAN, 0.4)}`,\n background: `linear-gradient(0deg, ${hexToRgbaString(KOREAN_COLORS.UI_BACKGROUND_DARK, 0.9)} 0%, ${hexToRgbaString(KOREAN_COLORS.UI_BACKGROUND_DARK, 0.7)} 100%)`,\n };\n }\n }, [position, width, height, topOffset, padding, gap, zIndex]);\n\n return (\n <div style={{ ...containerStyle, ...style }} data-testid={dataTestId}>\n {children}\n </div>\n );\n};\n\nexport default BaseHUDContainer;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmHA,IAAa,oBAAqD,EAChE,UACA,OACA,QACA,YAAY,GACZ,UAAU,IACV,MAAM,IACN,SAAS,QAAQ,KACjB,QAAQ,EAAE,EACV,UACA,iBACI;AAyFJ,QACE,oBAAC,OAAD;EAAK,OAAO;GAAE,GAtEO,MAAM,cAAmC;IAC9D,MAAM,YAAiC;KACrC,UAAU;KACV,SAAS;KACT,eAAe;KACf,YAAY;KACZ,eAAe;KACf,SAAS,GAAG,QAAQ;KACpB,WAAW;KACX,KAAK,GAAG,IAAI;KACZ;KACA,gBAAgB;KACjB;AAED,YAAQ,UAAR;KACE,KAAK,OACH,QAAO;MACL,GAAG;MACH,MAAM;MACN,KAAK,GAAG,UAAU;MAClB,OAAO,GAAG,MAAM;MAChB,QAAQ,GAAG,OAAO;MAClB,gBAAgB;MAChB,aAAa,aAAa,gBAAgB,cAAc,cAAc,GAAI;MAC1E,YAAY,0BAA0B,gBAAgB,cAAc,oBAAoB,IAAK,CAAC,OAAO,gBAAgB,cAAc,oBAAoB,GAAI,CAAC;MAC7J;KAEH,KAAK,QACH,QAAO;MACL,GAAG;MACH,OAAO;MACP,KAAK,GAAG,UAAU;MAClB,OAAO,GAAG,MAAM;MAChB,QAAQ,GAAG,OAAO;MAClB,gBAAgB;MAChB,YAAY,aAAa,gBAAgB,cAAc,cAAc,GAAI;MACzE,YAAY,2BAA2B,gBAAgB,cAAc,oBAAoB,IAAK,CAAC,OAAO,gBAAgB,cAAc,oBAAoB,GAAI,CAAC;MAC9J;KAEH,KAAK,MACH,QAAO;MACL,GAAG;MACH,KAAK;MACL,MAAM;MACN,OAAO;MACP,QAAQ,GAAG,OAAO;MAClB,eAAe;MACf,gBAAgB;MAChB,YAAY;MACZ,cAAc,aAAa,gBAAgB,cAAc,cAAc,GAAI;MAC3E,YAAY,2BAA2B,gBAAgB,cAAc,oBAAoB,GAAI,CAAC,OAAO,gBAAgB,cAAc,oBAAoB,GAAI,CAAC;MAC7J;KAEH,KAAK,SACH,QAAO;MACL,GAAG;MACH,QAAQ;MACR,MAAM;MACN,OAAO;MACP,QAAQ,GAAG,OAAO;MAClB,eAAe;MACf,gBAAgB;MAChB,YAAY;MACZ,WAAW,aAAa,gBAAgB,cAAc,cAAc,GAAI;MACxE,YAAY,yBAAyB,gBAAgB,cAAc,oBAAoB,GAAI,CAAC,OAAO,gBAAgB,cAAc,oBAAoB,GAAI,CAAC;MAC3J;;MAEJ;IAAC;IAAU;IAAO;IAAQ;IAAW;IAAS;IAAK;IAAO,CAAC;GAG3B,GAAG;GAAO;EAAE,eAAa;EACvD;EACG,CAAA"}
|
|
@@ -52,6 +52,19 @@ export interface MobileHUDLayoutProps {
|
|
|
52
52
|
* - Minimal screen real estate usage
|
|
53
53
|
* - Safe area aware positioning
|
|
54
54
|
*
|
|
55
|
+
* Landscape Safe Area Notes:
|
|
56
|
+
* - In landscape on notched devices (iPhone X+), the left and right health
|
|
57
|
+
* bars are currently anchored using `layout.spacing.md` from their
|
|
58
|
+
* respective edges.
|
|
59
|
+
* - The `useResponsiveLayout` hook provides safe-area values, and this
|
|
60
|
+
* component uses `layout.safeArea.top` for vertical offset.
|
|
61
|
+
* - However, the current health bar positioning does not directly apply
|
|
62
|
+
* `layout.safeArea.left` / `layout.safeArea.right` for horizontal notch or
|
|
63
|
+
* cutout avoidance in landscape mode.
|
|
64
|
+
* - Consumers that require landscape horizontal safe-area protection should
|
|
65
|
+
* add `env(safe-area-inset-left)` / `env(safe-area-inset-right)` via CSS
|
|
66
|
+
* or ensure the parent container applies equivalent horizontal offsets.
|
|
67
|
+
*
|
|
55
68
|
* @example
|
|
56
69
|
* ```tsx
|
|
57
70
|
* <MobileHUDLayout
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MobileHUDLayout.d.ts","sourceRoot":"","sources":["../../../../src/components/shared/ui/MobileHUDLayout.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,KAAkB,MAAM,OAAO,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAU/C;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,qBAAqB;IACrB,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,qBAAqB;IACrB,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,gCAAgC;IAChC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,2BAA2B;IAC3B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,qBAAqB;IACrB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,6BAA6B;IAC7B,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,0BAA0B;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAkMD
|
|
1
|
+
{"version":3,"file":"MobileHUDLayout.d.ts","sourceRoot":"","sources":["../../../../src/components/shared/ui/MobileHUDLayout.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,KAAkB,MAAM,OAAO,CAAC;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAU/C;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,qBAAqB;IACrB,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,qBAAqB;IACrB,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,gCAAgC;IAChC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,2BAA2B;IAC3B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,qBAAqB;IACrB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,6BAA6B;IAC7B,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,0BAA0B;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAkMD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CAkG1D,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { KOREAN_COLORS } from "../../../types/constants/colors.js";
|
|
2
2
|
import { FONT_FAMILY } from "../../../types/constants/typography.js";
|
|
3
|
-
import { toHex } from "../../../utils/colorUtils.js";
|
|
3
|
+
import { hexColorToCSS, toHex } from "../../../utils/colorUtils.js";
|
|
4
4
|
import { shouldUseMobileControls } from "../../../utils/deviceDetection.js";
|
|
5
5
|
import { useCallback, useMemo, useState } from "react";
|
|
6
6
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
@@ -39,8 +39,8 @@ var SplashScreen = ({ onStart, width, height }) => {
|
|
|
39
39
|
flexDirection: "column",
|
|
40
40
|
justifyContent: "center",
|
|
41
41
|
alignItems: "center",
|
|
42
|
-
background:
|
|
43
|
-
color:
|
|
42
|
+
background: `linear-gradient(180deg, ${hexColorToCSS(KOREAN_COLORS.UI_BACKGROUND_DARK)} 0%, ${hexColorToCSS(KOREAN_COLORS.ARENA_BACKGROUND)} 100%)`,
|
|
43
|
+
color: hexColorToCSS(KOREAN_COLORS.TEXT_PRIMARY),
|
|
44
44
|
fontFamily: FONT_FAMILY.CYBER,
|
|
45
45
|
position: "relative",
|
|
46
46
|
overflow: "hidden"
|
|
@@ -115,7 +115,7 @@ var SplashScreen = ({ onStart, width, height }) => {
|
|
|
115
115
|
/* @__PURE__ */ jsx("p", {
|
|
116
116
|
style: {
|
|
117
117
|
fontSize: `${layoutCalculation.bodyFontSize}px`,
|
|
118
|
-
color:
|
|
118
|
+
color: hexColorToCSS(KOREAN_COLORS.TEXT_TERTIARY),
|
|
119
119
|
marginTop: "20px",
|
|
120
120
|
letterSpacing: "1px"
|
|
121
121
|
},
|
|
@@ -134,8 +134,8 @@ var SplashScreen = ({ onStart, width, height }) => {
|
|
|
134
134
|
fontSize: `${layoutCalculation.buttonFontSize}px`,
|
|
135
135
|
fontFamily: FONT_FAMILY.CYBER,
|
|
136
136
|
fontWeight: 700,
|
|
137
|
-
color: isLoading ?
|
|
138
|
-
background: isLoading ?
|
|
137
|
+
color: isLoading ? hexColorToCSS(KOREAN_COLORS.UI_DISABLED_TEXT) : hexColorToCSS(KOREAN_COLORS.BLACK),
|
|
138
|
+
background: isLoading ? hexColorToCSS(KOREAN_COLORS.UI_BACKGROUND_LIGHT) : `linear-gradient(135deg, #${HEX_COLORS.PRIMARY_CYAN} 0%, #${HEX_COLORS.ACCENT_GOLD} 100%)`,
|
|
139
139
|
border: "none",
|
|
140
140
|
borderRadius: "8px",
|
|
141
141
|
cursor: isLoading ? "not-allowed" : "pointer",
|
|
@@ -167,7 +167,7 @@ var SplashScreen = ({ onStart, width, height }) => {
|
|
|
167
167
|
style: {
|
|
168
168
|
marginTop: "40px",
|
|
169
169
|
textAlign: "center",
|
|
170
|
-
color:
|
|
170
|
+
color: hexColorToCSS(KOREAN_COLORS.UI_GRAY),
|
|
171
171
|
fontSize: `${layoutCalculation.instructionsFontSize}px`,
|
|
172
172
|
maxWidth: "600px",
|
|
173
173
|
padding: "0 20px",
|
|
@@ -183,16 +183,16 @@ var SplashScreen = ({ onStart, width, height }) => {
|
|
|
183
183
|
}),
|
|
184
184
|
/* @__PURE__ */ jsxs("div", {
|
|
185
185
|
role: "contentinfo",
|
|
186
|
-
"aria-label": `Application version 0.7.
|
|
186
|
+
"aria-label": `Application version 0.7.13`,
|
|
187
187
|
style: {
|
|
188
188
|
position: "absolute",
|
|
189
189
|
bottom: "20px",
|
|
190
190
|
right: "20px",
|
|
191
|
-
color:
|
|
191
|
+
color: hexColorToCSS(KOREAN_COLORS.UI_STEEL_GRAY),
|
|
192
192
|
fontSize: "10px",
|
|
193
193
|
zIndex: 1
|
|
194
194
|
},
|
|
195
|
-
children: ["v", "0.7.
|
|
195
|
+
children: ["v", "0.7.13"]
|
|
196
196
|
})
|
|
197
197
|
]
|
|
198
198
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SplashScreen.js","names":[],"sources":["../../../../src/components/shared/ui/SplashScreen.tsx"],"sourcesContent":["import React, { useCallback, useMemo, useState } from \"react\";\nimport { FONT_FAMILY, KOREAN_COLORS } from \"@/types/constants\";\nimport { toHex } from \"../../../utils/colorUtils\";\nimport { shouldUseMobileControls } from \"../../../utils/deviceDetection\";\n\n// Declare global APP_VERSION constant (injected by build process)\ndeclare const APP_VERSION: string | undefined;\n\n// Constants\n// Small delay to show loading state for visual feedback.\n// 100ms is sufficient for users to perceive the state change\n// without feeling sluggish. This value can be tuned for UX.\nconst LOADING_DELAY_MS = 100;\n\n// Pre-compute hex colors from Korean color constants\nconst HEX_COLORS = {\n PRIMARY_CYAN: toHex(KOREAN_COLORS.PRIMARY_CYAN),\n ACCENT_GOLD: toHex(KOREAN_COLORS.ACCENT_GOLD),\n} as const;\n\nexport interface SplashScreenProps {\n readonly onStart: () => void;\n readonly width: number;\n readonly height: number;\n}\n\n/**\n * Splash screen that requires user interaction before starting the game.\n * This is necessary to initialize AudioContext which requires a user gesture.\n */\nexport const SplashScreen: React.FC<SplashScreenProps> = ({\n onStart,\n width,\n height,\n}) => {\n const [isLoading, setIsLoading] = useState(false);\n\n // Use proper device detection (user-agent priority for high-res phones)\n // This ensures mobile layout is used even on 4K Android devices\n // User-agent doesn't change during session, so no dependencies needed\n const isMobile = useMemo(() => shouldUseMobileControls(), []);\n\n // Memoize responsive layout values\n const layoutCalculation = useMemo(\n () => ({\n titleFontSize: isMobile ? 36 : 64,\n subtitleFontSize: isMobile ? 16 : 24,\n bodyFontSize: isMobile ? 12 : 14,\n instructionsFontSize: isMobile ? 11 : 12,\n buttonPadding: isMobile ? \"16px 48px\" : \"20px 60px\",\n buttonFontSize: isMobile ? 16 : 20,\n }),\n [isMobile],\n );\n\n const handleStart = useCallback(() => {\n setIsLoading(true);\n // Small delay to show loading state\n setTimeout(() => {\n onStart();\n }, LOADING_DELAY_MS);\n }, [onStart]);\n\n return (\n <div\n style={{\n width,\n height,\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"center\",\n alignItems: \"center\",\n background: \"linear-gradient(180deg, #0a0f12 0%, #1a1a2e 100%)\",\n color: \"#fff\",\n fontFamily: FONT_FAMILY.CYBER,\n position: \"relative\",\n overflow: \"hidden\",\n }}\n data-testid=\"splash-screen\"\n >\n {/* Animated background grid - decorative only */}\n <div\n role=\"presentation\"\n aria-hidden=\"true\"\n style={{\n position: \"absolute\",\n inset: 0,\n background: `\n repeating-linear-gradient(\n 0deg,\n transparent,\n transparent 50px,\n #${HEX_COLORS.PRIMARY_CYAN}08 50px,\n #${HEX_COLORS.PRIMARY_CYAN}08 51px\n ),\n repeating-linear-gradient(\n 90deg,\n transparent,\n transparent 50px,\n #${HEX_COLORS.PRIMARY_CYAN}08 50px,\n #${HEX_COLORS.PRIMARY_CYAN}08 51px\n )\n `,\n opacity: 0.3,\n }}\n />\n\n {/* Screen reader live region for loading state */}\n <div\n aria-live=\"polite\"\n aria-atomic=\"true\"\n style={{\n position: \"absolute\",\n left: \"-10000px\",\n width: \"1px\",\n height: \"1px\",\n overflow: \"hidden\",\n }}\n >\n {isLoading ? \"Initializing audio and loading game\" : \"Ready to start\"}\n </div>\n\n {/* Logo/Title */}\n <div\n style={{\n marginBottom: \"60px\",\n textAlign: \"center\",\n zIndex: 1,\n }}\n >\n <h1\n style={{\n fontSize: `${layoutCalculation.titleFontSize}px`,\n fontWeight: 900,\n color: `#${HEX_COLORS.PRIMARY_CYAN}`,\n textShadow: `0 0 20px #${HEX_COLORS.PRIMARY_CYAN}80`,\n marginBottom: \"20px\",\n letterSpacing: \"4px\",\n }}\n >\n 흑괘\n </h1>\n <h2\n style={{\n fontSize: `${layoutCalculation.subtitleFontSize}px`,\n fontWeight: 400,\n color: `#${HEX_COLORS.ACCENT_GOLD}`,\n letterSpacing: \"2px\",\n marginTop: 0,\n }}\n >\n BLACK TRIGRAM\n </h2>\n <p\n style={{\n fontSize: `${layoutCalculation.bodyFontSize}px`,\n color: \"#aaa\",\n marginTop: \"20px\",\n letterSpacing: \"1px\",\n }}\n >\n Korean Martial Arts Dojang\n </p>\n </div>\n\n {/* Start Button */}\n <button\n onClick={handleStart}\n disabled={isLoading}\n aria-label={\n isLoading\n ? \"Starting game and initializing audio\"\n : \"Start game and initialize audio\"\n }\n aria-busy={isLoading}\n aria-describedby=\"splash-instructions\"\n style={{\n padding: layoutCalculation.buttonPadding,\n fontSize: `${layoutCalculation.buttonFontSize}px`,\n fontFamily: FONT_FAMILY.CYBER,\n fontWeight: 700,\n color: isLoading ? \"#666\" : \"#000\",\n background: isLoading\n ? \"#333\"\n : `linear-gradient(135deg, #${HEX_COLORS.PRIMARY_CYAN} 0%, #${HEX_COLORS.ACCENT_GOLD} 100%)`,\n border: \"none\",\n borderRadius: \"8px\",\n cursor: isLoading ? \"not-allowed\" : \"pointer\",\n textTransform: \"uppercase\",\n letterSpacing: \"2px\",\n transition: \"all 0.3s ease\",\n boxShadow: isLoading\n ? \"none\"\n : `0 4px 20px #${HEX_COLORS.PRIMARY_CYAN}40`,\n position: \"relative\",\n zIndex: 1,\n opacity: isLoading ? 0.6 : 1,\n }}\n onMouseEnter={(e) => {\n if (!isLoading) {\n e.currentTarget.style.transform = \"scale(1.05)\";\n e.currentTarget.style.boxShadow = `0 6px 30px #${HEX_COLORS.PRIMARY_CYAN}60`;\n }\n }}\n onMouseLeave={(e) => {\n if (!isLoading) {\n e.currentTarget.style.transform = \"scale(1)\";\n e.currentTarget.style.boxShadow = `0 4px 20px #${HEX_COLORS.PRIMARY_CYAN}40`;\n }\n }}\n data-testid=\"splash-start-button\"\n >\n {isLoading ? \"시작 중... Starting...\" : \"시작 | Start\"}\n </button>\n\n {/* Instructions */}\n <div\n id=\"splash-instructions\"\n style={{\n marginTop: \"40px\",\n textAlign: \"center\",\n color: \"#888\",\n fontSize: `${layoutCalculation.instructionsFontSize}px`,\n maxWidth: \"600px\",\n padding: \"0 20px\",\n zIndex: 1,\n }}\n >\n <p style={{ margin: \"8px 0\" }}>\n Audio initialization requires user interaction\n </p>\n <p style={{ margin: \"8px 0\" }}>\n Click the button above to enable sound and start the game\n </p>\n </div>\n\n {/* Version info */}\n <div\n role=\"contentinfo\"\n aria-label={`Application version ${typeof APP_VERSION !== \"undefined\" ? APP_VERSION : \"0.5.3\"}`}\n style={{\n position: \"absolute\",\n bottom: \"20px\",\n right: \"20px\",\n color: \"#555\",\n fontSize: \"10px\",\n zIndex: 1,\n }}\n >\n v{typeof APP_VERSION !== \"undefined\" ? APP_VERSION : \"0.5.3\"}\n </div>\n </div>\n );\n};\n\nexport default SplashScreen;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SplashScreen.js","names":[],"sources":["../../../../src/components/shared/ui/SplashScreen.tsx"],"sourcesContent":["import React, { useCallback, useMemo, useState } from \"react\";\nimport { FONT_FAMILY, KOREAN_COLORS } from \"@/types/constants\";\nimport { hexColorToCSS, toHex } from \"../../../utils/colorUtils\";\nimport { shouldUseMobileControls } from \"../../../utils/deviceDetection\";\n\n// Declare global APP_VERSION constant (injected by build process)\ndeclare const APP_VERSION: string | undefined;\n\n// Constants\n// Small delay to show loading state for visual feedback.\n// 100ms is sufficient for users to perceive the state change\n// without feeling sluggish. This value can be tuned for UX.\nconst LOADING_DELAY_MS = 100;\n\n// Pre-compute hex colors from Korean color constants\nconst HEX_COLORS = {\n PRIMARY_CYAN: toHex(KOREAN_COLORS.PRIMARY_CYAN),\n ACCENT_GOLD: toHex(KOREAN_COLORS.ACCENT_GOLD),\n} as const;\n\nexport interface SplashScreenProps {\n readonly onStart: () => void;\n readonly width: number;\n readonly height: number;\n}\n\n/**\n * Splash screen that requires user interaction before starting the game.\n * This is necessary to initialize AudioContext which requires a user gesture.\n */\nexport const SplashScreen: React.FC<SplashScreenProps> = ({\n onStart,\n width,\n height,\n}) => {\n const [isLoading, setIsLoading] = useState(false);\n\n // Use proper device detection (user-agent priority for high-res phones)\n // This ensures mobile layout is used even on 4K Android devices\n // User-agent doesn't change during session, so no dependencies needed\n const isMobile = useMemo(() => shouldUseMobileControls(), []);\n\n // Memoize responsive layout values\n const layoutCalculation = useMemo(\n () => ({\n titleFontSize: isMobile ? 36 : 64,\n subtitleFontSize: isMobile ? 16 : 24,\n bodyFontSize: isMobile ? 12 : 14,\n instructionsFontSize: isMobile ? 11 : 12,\n buttonPadding: isMobile ? \"16px 48px\" : \"20px 60px\",\n buttonFontSize: isMobile ? 16 : 20,\n }),\n [isMobile],\n );\n\n const handleStart = useCallback(() => {\n setIsLoading(true);\n // Small delay to show loading state\n setTimeout(() => {\n onStart();\n }, LOADING_DELAY_MS);\n }, [onStart]);\n\n return (\n <div\n style={{\n width,\n height,\n display: \"flex\",\n flexDirection: \"column\",\n justifyContent: \"center\",\n alignItems: \"center\",\n background: `linear-gradient(180deg, ${hexColorToCSS(KOREAN_COLORS.UI_BACKGROUND_DARK)} 0%, ${hexColorToCSS(KOREAN_COLORS.ARENA_BACKGROUND)} 100%)`,\n color: hexColorToCSS(KOREAN_COLORS.TEXT_PRIMARY),\n fontFamily: FONT_FAMILY.CYBER,\n position: \"relative\",\n overflow: \"hidden\",\n }}\n data-testid=\"splash-screen\"\n >\n {/* Animated background grid - decorative only */}\n <div\n role=\"presentation\"\n aria-hidden=\"true\"\n style={{\n position: \"absolute\",\n inset: 0,\n background: `\n repeating-linear-gradient(\n 0deg,\n transparent,\n transparent 50px,\n #${HEX_COLORS.PRIMARY_CYAN}08 50px,\n #${HEX_COLORS.PRIMARY_CYAN}08 51px\n ),\n repeating-linear-gradient(\n 90deg,\n transparent,\n transparent 50px,\n #${HEX_COLORS.PRIMARY_CYAN}08 50px,\n #${HEX_COLORS.PRIMARY_CYAN}08 51px\n )\n `,\n opacity: 0.3,\n }}\n />\n\n {/* Screen reader live region for loading state */}\n <div\n aria-live=\"polite\"\n aria-atomic=\"true\"\n style={{\n position: \"absolute\",\n left: \"-10000px\",\n width: \"1px\",\n height: \"1px\",\n overflow: \"hidden\",\n }}\n >\n {isLoading ? \"Initializing audio and loading game\" : \"Ready to start\"}\n </div>\n\n {/* Logo/Title */}\n <div\n style={{\n marginBottom: \"60px\",\n textAlign: \"center\",\n zIndex: 1,\n }}\n >\n <h1\n style={{\n fontSize: `${layoutCalculation.titleFontSize}px`,\n fontWeight: 900,\n color: `#${HEX_COLORS.PRIMARY_CYAN}`,\n textShadow: `0 0 20px #${HEX_COLORS.PRIMARY_CYAN}80`,\n marginBottom: \"20px\",\n letterSpacing: \"4px\",\n }}\n >\n 흑괘\n </h1>\n <h2\n style={{\n fontSize: `${layoutCalculation.subtitleFontSize}px`,\n fontWeight: 400,\n color: `#${HEX_COLORS.ACCENT_GOLD}`,\n letterSpacing: \"2px\",\n marginTop: 0,\n }}\n >\n BLACK TRIGRAM\n </h2>\n <p\n style={{\n fontSize: `${layoutCalculation.bodyFontSize}px`,\n color: hexColorToCSS(KOREAN_COLORS.TEXT_TERTIARY),\n marginTop: \"20px\",\n letterSpacing: \"1px\",\n }}\n >\n Korean Martial Arts Dojang\n </p>\n </div>\n\n {/* Start Button */}\n <button\n onClick={handleStart}\n disabled={isLoading}\n aria-label={\n isLoading\n ? \"Starting game and initializing audio\"\n : \"Start game and initialize audio\"\n }\n aria-busy={isLoading}\n aria-describedby=\"splash-instructions\"\n style={{\n padding: layoutCalculation.buttonPadding,\n fontSize: `${layoutCalculation.buttonFontSize}px`,\n fontFamily: FONT_FAMILY.CYBER,\n fontWeight: 700,\n color: isLoading ? hexColorToCSS(KOREAN_COLORS.UI_DISABLED_TEXT) : hexColorToCSS(KOREAN_COLORS.BLACK),\n background: isLoading\n ? hexColorToCSS(KOREAN_COLORS.UI_BACKGROUND_LIGHT)\n : `linear-gradient(135deg, #${HEX_COLORS.PRIMARY_CYAN} 0%, #${HEX_COLORS.ACCENT_GOLD} 100%)`,\n border: \"none\",\n borderRadius: \"8px\",\n cursor: isLoading ? \"not-allowed\" : \"pointer\",\n textTransform: \"uppercase\",\n letterSpacing: \"2px\",\n transition: \"all 0.3s ease\",\n boxShadow: isLoading\n ? \"none\"\n : `0 4px 20px #${HEX_COLORS.PRIMARY_CYAN}40`,\n position: \"relative\",\n zIndex: 1,\n opacity: isLoading ? 0.6 : 1,\n }}\n onMouseEnter={(e) => {\n if (!isLoading) {\n e.currentTarget.style.transform = \"scale(1.05)\";\n e.currentTarget.style.boxShadow = `0 6px 30px #${HEX_COLORS.PRIMARY_CYAN}60`;\n }\n }}\n onMouseLeave={(e) => {\n if (!isLoading) {\n e.currentTarget.style.transform = \"scale(1)\";\n e.currentTarget.style.boxShadow = `0 4px 20px #${HEX_COLORS.PRIMARY_CYAN}40`;\n }\n }}\n data-testid=\"splash-start-button\"\n >\n {isLoading ? \"시작 중... Starting...\" : \"시작 | Start\"}\n </button>\n\n {/* Instructions */}\n <div\n id=\"splash-instructions\"\n style={{\n marginTop: \"40px\",\n textAlign: \"center\",\n color: hexColorToCSS(KOREAN_COLORS.UI_GRAY),\n fontSize: `${layoutCalculation.instructionsFontSize}px`,\n maxWidth: \"600px\",\n padding: \"0 20px\",\n zIndex: 1,\n }}\n >\n <p style={{ margin: \"8px 0\" }}>\n Audio initialization requires user interaction\n </p>\n <p style={{ margin: \"8px 0\" }}>\n Click the button above to enable sound and start the game\n </p>\n </div>\n\n {/* Version info */}\n <div\n role=\"contentinfo\"\n aria-label={`Application version ${typeof APP_VERSION !== \"undefined\" ? APP_VERSION : \"0.5.3\"}`}\n style={{\n position: \"absolute\",\n bottom: \"20px\",\n right: \"20px\",\n color: hexColorToCSS(KOREAN_COLORS.UI_STEEL_GRAY),\n fontSize: \"10px\",\n zIndex: 1,\n }}\n >\n v{typeof APP_VERSION !== \"undefined\" ? APP_VERSION : \"0.5.3\"}\n </div>\n </div>\n );\n};\n\nexport default SplashScreen;\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VitalPointOverlayControlsPure.d.ts","sourceRoot":"","sources":["../../../../src/components/shared/ui/VitalPointOverlayControlsPure.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAyC,MAAM,OAAO,CAAC;AAK9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"VitalPointOverlayControlsPure.d.ts","sourceRoot":"","sources":["../../../../src/components/shared/ui/VitalPointOverlayControlsPure.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,KAAyC,MAAM,OAAO,CAAC;AAK9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAI3D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAE7E,YAAY,EAAE,gBAAgB,EAAE,MAAM,sCAAsC,CAAC;AAE7E;;GAEG;AACH,MAAM,WAAW,kCAAkC;IACjD,2CAA2C;IAC3C,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,uCAAuC;IACvC,QAAQ,CAAC,eAAe,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACrD,+BAA+B;IAC/B,QAAQ,CAAC,eAAe,EAAE,kBAAkB,EAAE,CAAC;IAC/C,4CAA4C;IAC5C,QAAQ,CAAC,uBAAuB,EAAE,CAAC,OAAO,EAAE,kBAAkB,EAAE,KAAK,IAAI,CAAC;IAC1E,4BAA4B;IAC5B,QAAQ,CAAC,YAAY,EAAE,gBAAgB,CAAC;IACxC,0CAA0C;IAC1C,QAAQ,CAAC,oBAAoB,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAClE,2BAA2B;IAC3B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,yCAAyC;IACzC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACvD,+BAA+B;IAC/B,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,6CAA6C;IAC7C,QAAQ,CAAC,kBAAkB,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IACrD,qCAAqC;IACrC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,4CAA4C;IAC5C,QAAQ,CAAC,gBAAgB,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;IACvD,8BAA8B;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,kCAAkC;IAClC,QAAQ,CAAC,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,+BAA+B;IAC/B,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B;;;;;OAKG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE;QACxB,+DAA+D;QAC/D,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,gEAAgE;QAChE,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,iEAAiE;QACjE,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,kEAAkE;QAClE,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;CACH;AAqBD;;;GAGG;AACH,eAAO,MAAM,6BAA6B,EAAE,KAAK,CAAC,EAAE,CAClD,kCAAkC,CA6oBnC,CAAC;AAEF,eAAe,6BAA6B,CAAC"}
|
|
@@ -3,6 +3,7 @@ import { KOREAN_COLORS } from "../../../types/constants/colors.js";
|
|
|
3
3
|
import { FONT_FAMILY } from "../../../types/constants/typography.js";
|
|
4
4
|
import { Z_INDEX } from "../../../types/LayoutTypes.js";
|
|
5
5
|
import KOREAN_VITAL_POINTS, { getVitalPointsStats } from "../../../systems/vitalpoint/KoreanVitalPoints.js";
|
|
6
|
+
import { hexColorToCSS, hexToRgbaString } from "../../../utils/colorUtils.js";
|
|
6
7
|
import { useCallback, useMemo, useState } from "react";
|
|
7
8
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
8
9
|
//#region src/components/shared/ui/VitalPointOverlayControlsPure.tsx
|
|
@@ -24,22 +25,16 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
|
24
25
|
* @module components/shared/ui/VitalPointOverlayControlsPure
|
|
25
26
|
*/
|
|
26
27
|
/**
|
|
27
|
-
* Convert numeric color to CSS hex string
|
|
28
|
-
*/
|
|
29
|
-
var colorToHex = (color) => {
|
|
30
|
-
return `#${color.toString(16).padStart(6, "0")}`;
|
|
31
|
-
};
|
|
32
|
-
/**
|
|
33
28
|
* Get color for severity level
|
|
34
29
|
*/
|
|
35
30
|
var getSeverityColor = (severity) => {
|
|
36
31
|
switch (severity) {
|
|
37
|
-
case VitalPointSeverity.LETHAL: return
|
|
38
|
-
case VitalPointSeverity.CRITICAL: return
|
|
39
|
-
case VitalPointSeverity.MAJOR: return
|
|
40
|
-
case VitalPointSeverity.MODERATE: return
|
|
41
|
-
case VitalPointSeverity.MINOR: return
|
|
42
|
-
default: return
|
|
32
|
+
case VitalPointSeverity.LETHAL: return hexColorToCSS(KOREAN_COLORS.NEGATIVE_RED);
|
|
33
|
+
case VitalPointSeverity.CRITICAL: return hexColorToCSS(KOREAN_COLORS.HEALTH_LOW);
|
|
34
|
+
case VitalPointSeverity.MAJOR: return hexColorToCSS(KOREAN_COLORS.ACCENT_GOLD);
|
|
35
|
+
case VitalPointSeverity.MODERATE: return hexColorToCSS(KOREAN_COLORS.TRIGRAM_GEON_PRIMARY);
|
|
36
|
+
case VitalPointSeverity.MINOR: return hexColorToCSS(KOREAN_COLORS.POSITIVE_GREEN);
|
|
37
|
+
default: return hexColorToCSS(KOREAN_COLORS.NEON_CYAN);
|
|
43
38
|
}
|
|
44
39
|
};
|
|
45
40
|
/**
|
|
@@ -125,13 +120,13 @@ var VitalPointOverlayControlsPure = ({ visible, onVisibleChange, severityFilters
|
|
|
125
120
|
right: finalPosition.right,
|
|
126
121
|
bottom: finalPosition.bottom,
|
|
127
122
|
width: panelWidth,
|
|
128
|
-
background: `${
|
|
129
|
-
border: `2px solid ${
|
|
123
|
+
background: `${hexColorToCSS(KOREAN_COLORS.UI_BACKGROUND_DARK)}f0`,
|
|
124
|
+
border: `2px solid ${hexColorToCSS(KOREAN_COLORS.PRIMARY_CYAN)}`,
|
|
130
125
|
borderRadius: "12px",
|
|
131
126
|
padding: isMobile ? "12px" : "16px",
|
|
132
127
|
fontFamily: FONT_FAMILY.KOREAN,
|
|
133
|
-
color:
|
|
134
|
-
boxShadow: `0 0 30px ${
|
|
128
|
+
color: hexColorToCSS(KOREAN_COLORS.TEXT_PRIMARY),
|
|
129
|
+
boxShadow: `0 0 30px ${hexColorToCSS(KOREAN_COLORS.PRIMARY_CYAN)}40, inset 0 0 20px ${hexColorToCSS(KOREAN_COLORS.UI_BACKGROUND_DARK)}80`,
|
|
135
130
|
transition: "all 0.3s ease",
|
|
136
131
|
pointerEvents: "all",
|
|
137
132
|
zIndex: Z_INDEX.MODAL
|
|
@@ -145,8 +140,8 @@ var VitalPointOverlayControlsPure = ({ visible, onVisibleChange, severityFilters
|
|
|
145
140
|
alignItems: "center",
|
|
146
141
|
marginBottom: "12px",
|
|
147
142
|
paddingBottom: "12px",
|
|
148
|
-
borderBottom: `1px solid ${
|
|
149
|
-
background: `linear-gradient(90deg, ${
|
|
143
|
+
borderBottom: `1px solid ${hexColorToCSS(KOREAN_COLORS.PRIMARY_CYAN)}40`,
|
|
144
|
+
background: `linear-gradient(90deg, ${hexColorToCSS(KOREAN_COLORS.UI_BACKGROUND_DARK)}00 0%, ${hexColorToCSS(KOREAN_COLORS.PRIMARY_CYAN)}10 50%, ${hexColorToCSS(KOREAN_COLORS.UI_BACKGROUND_DARK)}00 100%)`
|
|
150
145
|
},
|
|
151
146
|
children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", {
|
|
152
147
|
style: {
|
|
@@ -157,7 +152,7 @@ var VitalPointOverlayControlsPure = ({ visible, onVisibleChange, severityFilters
|
|
|
157
152
|
}), /* @__PURE__ */ jsxs("div", {
|
|
158
153
|
style: {
|
|
159
154
|
fontSize: smallFontSize,
|
|
160
|
-
color:
|
|
155
|
+
color: hexColorToCSS(KOREAN_COLORS.TEXT_SECONDARY),
|
|
161
156
|
marginTop: "2px"
|
|
162
157
|
},
|
|
163
158
|
children: [
|
|
@@ -169,23 +164,23 @@ var VitalPointOverlayControlsPure = ({ visible, onVisibleChange, severityFilters
|
|
|
169
164
|
})] }), /* @__PURE__ */ jsx("button", {
|
|
170
165
|
onClick: () => setExpanded(!expanded),
|
|
171
166
|
style: {
|
|
172
|
-
background: `linear-gradient(135deg, ${
|
|
173
|
-
border: `2px solid ${
|
|
167
|
+
background: `linear-gradient(135deg, ${hexColorToCSS(KOREAN_COLORS.UI_BACKGROUND_MEDIUM)} 0%, ${hexColorToCSS(KOREAN_COLORS.UI_BACKGROUND_DARK)} 100%)`,
|
|
168
|
+
border: `2px solid ${hexColorToCSS(KOREAN_COLORS.PRIMARY_CYAN)}`,
|
|
174
169
|
borderRadius: "6px",
|
|
175
170
|
padding: "8px 14px",
|
|
176
|
-
color:
|
|
171
|
+
color: hexColorToCSS(KOREAN_COLORS.TEXT_PRIMARY),
|
|
177
172
|
fontSize,
|
|
178
173
|
cursor: "pointer",
|
|
179
174
|
transition: "all 0.2s ease",
|
|
180
|
-
boxShadow: `0 2px 8px ${
|
|
175
|
+
boxShadow: `0 2px 8px ${hexColorToCSS(KOREAN_COLORS.PRIMARY_CYAN)}30`
|
|
181
176
|
},
|
|
182
177
|
onMouseEnter: (e) => {
|
|
183
178
|
e.currentTarget.style.transform = "scale(1.05)";
|
|
184
|
-
e.currentTarget.style.boxShadow = `0 4px 12px ${
|
|
179
|
+
e.currentTarget.style.boxShadow = `0 4px 12px ${hexColorToCSS(KOREAN_COLORS.PRIMARY_CYAN)}50`;
|
|
185
180
|
},
|
|
186
181
|
onMouseLeave: (e) => {
|
|
187
182
|
e.currentTarget.style.transform = "scale(1)";
|
|
188
|
-
e.currentTarget.style.boxShadow = `0 2px 8px ${
|
|
183
|
+
e.currentTarget.style.boxShadow = `0 2px 8px ${hexColorToCSS(KOREAN_COLORS.PRIMARY_CYAN)}30`;
|
|
189
184
|
},
|
|
190
185
|
"data-testid": "toggle-expand-button",
|
|
191
186
|
children: expanded ? "▼" : "▶"
|
|
@@ -198,25 +193,25 @@ var VitalPointOverlayControlsPure = ({ visible, onVisibleChange, severityFilters
|
|
|
198
193
|
style: {
|
|
199
194
|
width: "100%",
|
|
200
195
|
height: buttonHeight,
|
|
201
|
-
background: visible ? `linear-gradient(135deg, ${
|
|
202
|
-
border: `2px solid ${visible ?
|
|
196
|
+
background: visible ? `linear-gradient(135deg, ${hexColorToCSS(KOREAN_COLORS.ACCENT_GOLD)} 0%, ${hexColorToCSS(KOREAN_COLORS.SECONDARY_YELLOW)} 100%)` : `linear-gradient(135deg, ${hexColorToCSS(KOREAN_COLORS.UI_BACKGROUND_MEDIUM)} 0%, ${hexColorToCSS(KOREAN_COLORS.UI_BACKGROUND_DARK)} 100%)`,
|
|
197
|
+
border: `2px solid ${visible ? hexColorToCSS(KOREAN_COLORS.ACCENT_GOLD) : hexColorToCSS(KOREAN_COLORS.PRIMARY_CYAN)}`,
|
|
203
198
|
borderRadius: "8px",
|
|
204
|
-
color: visible ?
|
|
199
|
+
color: visible ? hexColorToCSS(KOREAN_COLORS.KOREAN_BLACK) : hexColorToCSS(KOREAN_COLORS.TEXT_PRIMARY),
|
|
205
200
|
fontSize: isMobile ? 13 : 15,
|
|
206
201
|
fontWeight: "bold",
|
|
207
202
|
cursor: "pointer",
|
|
208
203
|
transition: "all 0.3s ease",
|
|
209
|
-
boxShadow: visible ? `0 4px 16px ${
|
|
204
|
+
boxShadow: visible ? `0 4px 16px ${hexColorToCSS(KOREAN_COLORS.ACCENT_GOLD)}60, inset 0 2px 4px ${hexToRgbaString(KOREAN_COLORS.TEXT_PRIMARY, .2)}` : `0 2px 8px ${hexColorToCSS(KOREAN_COLORS.PRIMARY_CYAN)}30`,
|
|
210
205
|
textTransform: "uppercase",
|
|
211
206
|
letterSpacing: "0.5px"
|
|
212
207
|
},
|
|
213
208
|
onMouseEnter: (e) => {
|
|
214
209
|
e.currentTarget.style.transform = "translateY(-2px)";
|
|
215
|
-
e.currentTarget.style.boxShadow = visible ? `0 6px 20px ${
|
|
210
|
+
e.currentTarget.style.boxShadow = visible ? `0 6px 20px ${hexColorToCSS(KOREAN_COLORS.ACCENT_GOLD)}80` : `0 4px 12px ${hexColorToCSS(KOREAN_COLORS.PRIMARY_CYAN)}50`;
|
|
216
211
|
},
|
|
217
212
|
onMouseLeave: (e) => {
|
|
218
213
|
e.currentTarget.style.transform = "translateY(0)";
|
|
219
|
-
e.currentTarget.style.boxShadow = visible ? `0 4px 16px ${
|
|
214
|
+
e.currentTarget.style.boxShadow = visible ? `0 4px 16px ${hexColorToCSS(KOREAN_COLORS.ACCENT_GOLD)}60` : `0 2px 8px ${hexColorToCSS(KOREAN_COLORS.PRIMARY_CYAN)}30`;
|
|
220
215
|
},
|
|
221
216
|
"data-testid": "toggle-visibility-button",
|
|
222
217
|
children: visible ? "✓ 활성화 | Enabled" : "비활성화 | Disabled"
|
|
@@ -229,7 +224,7 @@ var VitalPointOverlayControlsPure = ({ visible, onVisibleChange, severityFilters
|
|
|
229
224
|
style: {
|
|
230
225
|
fontSize,
|
|
231
226
|
marginBottom: "8px",
|
|
232
|
-
color:
|
|
227
|
+
color: hexColorToCSS(KOREAN_COLORS.ACCENT_CYAN),
|
|
233
228
|
fontWeight: "600",
|
|
234
229
|
textTransform: "uppercase",
|
|
235
230
|
letterSpacing: "1px"
|
|
@@ -247,11 +242,11 @@ var VitalPointOverlayControlsPure = ({ visible, onVisibleChange, severityFilters
|
|
|
247
242
|
return /* @__PURE__ */ jsx("button", {
|
|
248
243
|
onClick: () => toggleSeverityFilter(severity),
|
|
249
244
|
style: {
|
|
250
|
-
background: isActive ? `linear-gradient(135deg, ${severityColor} 0%, ${severityColor}cc 100%)` : `${
|
|
245
|
+
background: isActive ? `linear-gradient(135deg, ${severityColor} 0%, ${severityColor}cc 100%)` : `${hexColorToCSS(KOREAN_COLORS.UI_BACKGROUND_MEDIUM)}`,
|
|
251
246
|
border: `2px solid ${severityColor}`,
|
|
252
247
|
borderRadius: "6px",
|
|
253
248
|
padding: "6px 12px",
|
|
254
|
-
color:
|
|
249
|
+
color: hexColorToCSS(KOREAN_COLORS.TEXT_PRIMARY),
|
|
255
250
|
fontSize: smallFontSize,
|
|
256
251
|
cursor: "pointer",
|
|
257
252
|
opacity: isActive ? 1 : .6,
|
|
@@ -279,7 +274,7 @@ var VitalPointOverlayControlsPure = ({ visible, onVisibleChange, severityFilters
|
|
|
279
274
|
style: {
|
|
280
275
|
fontSize,
|
|
281
276
|
marginBottom: "8px",
|
|
282
|
-
color:
|
|
277
|
+
color: hexColorToCSS(KOREAN_COLORS.ACCENT_CYAN),
|
|
283
278
|
fontWeight: "600",
|
|
284
279
|
textTransform: "uppercase",
|
|
285
280
|
letterSpacing: "1px"
|
|
@@ -296,17 +291,17 @@ var VitalPointOverlayControlsPure = ({ visible, onVisibleChange, severityFilters
|
|
|
296
291
|
return /* @__PURE__ */ jsxs("button", {
|
|
297
292
|
onClick: () => onRegionFilterChange(option.value),
|
|
298
293
|
style: {
|
|
299
|
-
background: isActive ? `linear-gradient(135deg, ${
|
|
300
|
-
border: `2px solid ${
|
|
294
|
+
background: isActive ? `linear-gradient(135deg, ${hexColorToCSS(KOREAN_COLORS.PRIMARY_CYAN)} 0%, ${hexColorToCSS(KOREAN_COLORS.ACCENT_BLUE)} 100%)` : `${hexColorToCSS(KOREAN_COLORS.UI_BACKGROUND_MEDIUM)}`,
|
|
295
|
+
border: `2px solid ${hexColorToCSS(KOREAN_COLORS.PRIMARY_CYAN)}`,
|
|
301
296
|
borderRadius: "6px",
|
|
302
297
|
padding: "6px 12px",
|
|
303
|
-
color:
|
|
298
|
+
color: hexColorToCSS(KOREAN_COLORS.TEXT_PRIMARY),
|
|
304
299
|
fontSize: smallFontSize,
|
|
305
300
|
cursor: "pointer",
|
|
306
301
|
opacity: isActive ? 1 : .6,
|
|
307
302
|
transition: "all 0.2s ease",
|
|
308
303
|
fontWeight: isActive ? "bold" : "normal",
|
|
309
|
-
boxShadow: isActive ? `0 2px 8px ${
|
|
304
|
+
boxShadow: isActive ? `0 2px 8px ${hexColorToCSS(KOREAN_COLORS.PRIMARY_CYAN)}50` : "none"
|
|
310
305
|
},
|
|
311
306
|
onMouseEnter: (e) => {
|
|
312
307
|
e.currentTarget.style.opacity = "1";
|
|
@@ -332,7 +327,7 @@ var VitalPointOverlayControlsPure = ({ visible, onVisibleChange, severityFilters
|
|
|
332
327
|
style: {
|
|
333
328
|
fontSize,
|
|
334
329
|
marginBottom: "8px",
|
|
335
|
-
color:
|
|
330
|
+
color: hexColorToCSS(KOREAN_COLORS.ACCENT_CYAN),
|
|
336
331
|
fontWeight: "600",
|
|
337
332
|
textTransform: "uppercase",
|
|
338
333
|
letterSpacing: "1px"
|
|
@@ -348,22 +343,22 @@ var VitalPointOverlayControlsPure = ({ visible, onVisibleChange, severityFilters
|
|
|
348
343
|
style: {
|
|
349
344
|
width: "100%",
|
|
350
345
|
height: buttonHeight,
|
|
351
|
-
background: `${
|
|
352
|
-
border: `2px solid ${
|
|
346
|
+
background: `${hexColorToCSS(KOREAN_COLORS.UI_BACKGROUND_MEDIUM)}`,
|
|
347
|
+
border: `2px solid ${hexColorToCSS(KOREAN_COLORS.PRIMARY_CYAN)}40`,
|
|
353
348
|
borderRadius: "8px",
|
|
354
349
|
padding: "0 40px 0 14px",
|
|
355
|
-
color:
|
|
350
|
+
color: hexColorToCSS(KOREAN_COLORS.TEXT_PRIMARY),
|
|
356
351
|
fontSize,
|
|
357
352
|
fontFamily: FONT_FAMILY.KOREAN,
|
|
358
353
|
transition: "all 0.2s ease",
|
|
359
354
|
outline: "none"
|
|
360
355
|
},
|
|
361
356
|
onFocus: (e) => {
|
|
362
|
-
e.currentTarget.style.borderColor =
|
|
363
|
-
e.currentTarget.style.boxShadow = `0 0 12px ${
|
|
357
|
+
e.currentTarget.style.borderColor = hexColorToCSS(KOREAN_COLORS.PRIMARY_CYAN);
|
|
358
|
+
e.currentTarget.style.boxShadow = `0 0 12px ${hexColorToCSS(KOREAN_COLORS.PRIMARY_CYAN)}40`;
|
|
364
359
|
},
|
|
365
360
|
onBlur: (e) => {
|
|
366
|
-
e.currentTarget.style.borderColor = `${
|
|
361
|
+
e.currentTarget.style.borderColor = `${hexColorToCSS(KOREAN_COLORS.PRIMARY_CYAN)}40`;
|
|
367
362
|
e.currentTarget.style.boxShadow = "none";
|
|
368
363
|
},
|
|
369
364
|
"data-testid": "search-input"
|
|
@@ -376,7 +371,7 @@ var VitalPointOverlayControlsPure = ({ visible, onVisibleChange, severityFilters
|
|
|
376
371
|
transform: "translateY(-50%)",
|
|
377
372
|
background: "transparent",
|
|
378
373
|
border: "none",
|
|
379
|
-
color:
|
|
374
|
+
color: hexColorToCSS(KOREAN_COLORS.TEXT_SECONDARY),
|
|
380
375
|
cursor: "pointer",
|
|
381
376
|
fontSize: "16px",
|
|
382
377
|
padding: "4px",
|
|
@@ -387,11 +382,11 @@ var VitalPointOverlayControlsPure = ({ visible, onVisibleChange, severityFilters
|
|
|
387
382
|
transition: "all 0.2s ease"
|
|
388
383
|
},
|
|
389
384
|
onMouseEnter: (e) => {
|
|
390
|
-
e.currentTarget.style.color =
|
|
391
|
-
e.currentTarget.style.background = `${
|
|
385
|
+
e.currentTarget.style.color = hexColorToCSS(KOREAN_COLORS.ACCENT_RED);
|
|
386
|
+
e.currentTarget.style.background = `${hexColorToCSS(KOREAN_COLORS.UI_BACKGROUND_MEDIUM)}`;
|
|
392
387
|
},
|
|
393
388
|
onMouseLeave: (e) => {
|
|
394
|
-
e.currentTarget.style.color =
|
|
389
|
+
e.currentTarget.style.color = hexColorToCSS(KOREAN_COLORS.TEXT_SECONDARY);
|
|
395
390
|
e.currentTarget.style.background = "transparent";
|
|
396
391
|
},
|
|
397
392
|
"data-testid": "search-clear-button",
|
|
@@ -406,7 +401,7 @@ var VitalPointOverlayControlsPure = ({ visible, onVisibleChange, severityFilters
|
|
|
406
401
|
style: {
|
|
407
402
|
fontSize,
|
|
408
403
|
marginBottom: "8px",
|
|
409
|
-
color:
|
|
404
|
+
color: hexColorToCSS(KOREAN_COLORS.ACCENT_CYAN),
|
|
410
405
|
fontWeight: "600",
|
|
411
406
|
textTransform: "uppercase",
|
|
412
407
|
letterSpacing: "1px"
|
|
@@ -432,7 +427,7 @@ var VitalPointOverlayControlsPure = ({ visible, onVisibleChange, severityFilters
|
|
|
432
427
|
style: {
|
|
433
428
|
width: "16px",
|
|
434
429
|
height: "16px",
|
|
435
|
-
accentColor:
|
|
430
|
+
accentColor: hexColorToCSS(KOREAN_COLORS.PRIMARY_CYAN)
|
|
436
431
|
},
|
|
437
432
|
"data-testid": "show-labels-checkbox"
|
|
438
433
|
}), /* @__PURE__ */ jsx("span", {
|
|
@@ -453,7 +448,7 @@ var VitalPointOverlayControlsPure = ({ visible, onVisibleChange, severityFilters
|
|
|
453
448
|
style: {
|
|
454
449
|
width: "16px",
|
|
455
450
|
height: "16px",
|
|
456
|
-
accentColor:
|
|
451
|
+
accentColor: hexColorToCSS(KOREAN_COLORS.PRIMARY_CYAN)
|
|
457
452
|
},
|
|
458
453
|
"data-testid": "animated-checkbox"
|
|
459
454
|
}), /* @__PURE__ */ jsx("span", {
|
|
@@ -474,21 +469,21 @@ var VitalPointOverlayControlsPure = ({ visible, onVisibleChange, severityFilters
|
|
|
474
469
|
style: {
|
|
475
470
|
width: "100%",
|
|
476
471
|
height: buttonHeight - 4,
|
|
477
|
-
background: `${
|
|
478
|
-
border: `2px solid ${
|
|
472
|
+
background: `${hexColorToCSS(KOREAN_COLORS.UI_BACKGROUND_MEDIUM)}`,
|
|
473
|
+
border: `2px solid ${hexColorToCSS(KOREAN_COLORS.ACCENT_ORANGE)}`,
|
|
479
474
|
borderRadius: "6px",
|
|
480
|
-
color:
|
|
475
|
+
color: hexColorToCSS(KOREAN_COLORS.ACCENT_ORANGE),
|
|
481
476
|
fontSize: smallFontSize,
|
|
482
477
|
cursor: "pointer",
|
|
483
478
|
transition: "all 0.2s ease",
|
|
484
479
|
fontWeight: "bold"
|
|
485
480
|
},
|
|
486
481
|
onMouseEnter: (e) => {
|
|
487
|
-
e.currentTarget.style.background = `${
|
|
482
|
+
e.currentTarget.style.background = `${hexColorToCSS(KOREAN_COLORS.ACCENT_ORANGE)}20`;
|
|
488
483
|
e.currentTarget.style.transform = "translateY(-1px)";
|
|
489
484
|
},
|
|
490
485
|
onMouseLeave: (e) => {
|
|
491
|
-
e.currentTarget.style.background = `${
|
|
486
|
+
e.currentTarget.style.background = `${hexColorToCSS(KOREAN_COLORS.UI_BACKGROUND_MEDIUM)}`;
|
|
492
487
|
e.currentTarget.style.transform = "translateY(0)";
|
|
493
488
|
},
|
|
494
489
|
"data-testid": "reset-filters-button",
|
|
@@ -499,7 +494,7 @@ var VitalPointOverlayControlsPure = ({ visible, onVisibleChange, severityFilters
|
|
|
499
494
|
style: {
|
|
500
495
|
fontSize,
|
|
501
496
|
marginBottom: "6px",
|
|
502
|
-
color:
|
|
497
|
+
color: hexColorToCSS(KOREAN_COLORS.ACCENT_CYAN)
|
|
503
498
|
},
|
|
504
499
|
children: [
|
|
505
500
|
"크기 | Scale: ",
|
|
@@ -515,7 +510,7 @@ var VitalPointOverlayControlsPure = ({ visible, onVisibleChange, severityFilters
|
|
|
515
510
|
onChange: (e) => onScaleChange(parseFloat(e.target.value)),
|
|
516
511
|
style: {
|
|
517
512
|
width: "100%",
|
|
518
|
-
accentColor:
|
|
513
|
+
accentColor: hexColorToCSS(KOREAN_COLORS.PRIMARY_CYAN)
|
|
519
514
|
},
|
|
520
515
|
"data-testid": "scale-slider"
|
|
521
516
|
})] }),
|
|
@@ -523,9 +518,9 @@ var VitalPointOverlayControlsPure = ({ visible, onVisibleChange, severityFilters
|
|
|
523
518
|
style: {
|
|
524
519
|
marginTop: "12px",
|
|
525
520
|
paddingTop: "12px",
|
|
526
|
-
borderTop: `1px solid ${
|
|
521
|
+
borderTop: `1px solid ${hexColorToCSS(KOREAN_COLORS.PRIMARY_CYAN)}40`,
|
|
527
522
|
fontSize: smallFontSize,
|
|
528
|
-
color:
|
|
523
|
+
color: hexColorToCSS(KOREAN_COLORS.TEXT_SECONDARY)
|
|
529
524
|
},
|
|
530
525
|
children: [/* @__PURE__ */ jsxs("div", { children: [
|
|
531
526
|
"머리: ",
|