@bwg-ui/core 1.1.24 → 1.1.25
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/dist/chunks/AuthContext-CXng9fj0.cjs.map +1 -1
- package/dist/chunks/{AuthContext-Ei2P-z4d.js → AuthContext-DrEpBrpB.js} +7 -3
- package/dist/chunks/AuthContext-DrEpBrpB.js.map +1 -0
- package/dist/chunks/{BwgSwitch-CAI-kEaM.cjs → BwgSwitch-DOlc57wi.cjs} +2 -2
- package/dist/chunks/BwgSwitch-DOlc57wi.cjs.map +1 -0
- package/dist/chunks/{BwgSwitch-B79pseQM.js → BwgSwitch-D_scwi9_.js} +18 -18
- package/dist/chunks/BwgSwitch-D_scwi9_.js.map +1 -0
- package/dist/chunks/{BwgUploader-DaNV2URT.cjs → BwgUploader-CkXwkcUL.cjs} +2 -2
- package/dist/chunks/BwgUploader-CkXwkcUL.cjs.map +1 -0
- package/dist/chunks/{BwgUploader-BcVlE61B.js → BwgUploader-DBFF9BPF.js} +327 -327
- package/dist/chunks/BwgUploader-DBFF9BPF.js.map +1 -0
- package/dist/chunks/LoadingOverlay-DAZJF5wg.js.map +1 -1
- package/dist/chunks/LoadingOverlay-DcmKvoZA.cjs.map +1 -1
- package/dist/chunks/{SSOHandler-DiW4Ft9i.cjs → SSOHandler-BY6LXMLc.cjs} +32 -32
- package/dist/chunks/SSOHandler-BY6LXMLc.cjs.map +1 -0
- package/dist/chunks/{SSOHandler-CkPcSHIm.js → SSOHandler-CxvxEBaH.js} +1977 -1930
- package/dist/chunks/SSOHandler-CxvxEBaH.js.map +1 -0
- package/dist/chunks/ScreenProtectContext-3my4PHFa.js.map +1 -1
- package/dist/chunks/ScreenProtectContext-CVuXrJm6.cjs.map +1 -1
- package/dist/chunks/SearchBoxContext-DwFDOyYG.cjs.map +1 -1
- package/dist/chunks/{SearchBoxContext-BCvEYyFk.js → SearchBoxContext-gWM7FHIw.js} +3 -5
- package/dist/chunks/SearchBoxContext-gWM7FHIw.js.map +1 -0
- package/dist/chunks/ViewContainer-Bhq22_B3.cjs.map +1 -1
- package/dist/chunks/{ViewContainer-CjpJqoGG.js → ViewContainer-D9SKBnrn.js} +40 -28
- package/dist/chunks/ViewContainer-D9SKBnrn.js.map +1 -0
- package/dist/chunks/apiUtils-BZ6s0_NI.cjs.map +1 -1
- package/dist/chunks/{apiUtils-DxzLqPhU.js → apiUtils-DSwE62oG.js} +14 -5
- package/dist/chunks/apiUtils-DSwE62oG.js.map +1 -0
- package/dist/chunks/{codeStore-CfI4Wh5M.js → codeStore-vPj4Y0TK.js} +2 -2
- package/dist/chunks/{codeStore-CfI4Wh5M.js.map → codeStore-vPj4Y0TK.js.map} +1 -1
- package/dist/chunks/{core-bHd8azE6.js → core-Dl0PdDdT.js} +2 -2
- package/dist/chunks/{core-bHd8azE6.js.map → core-Dl0PdDdT.js.map} +1 -1
- package/dist/chunks/{enc-base64-BQYwLKgk.js → enc-base64-D7t4BoUA.js} +3 -3
- package/dist/chunks/{enc-base64-BQYwLKgk.js.map → enc-base64-D7t4BoUA.js.map} +1 -1
- package/dist/chunks/{favoriteStore-Cemc-26t.js → favoriteStore-Bh1FuZm9.js} +2 -2
- package/dist/chunks/{favoriteStore-Cemc-26t.js.map → favoriteStore-Bh1FuZm9.js.map} +1 -1
- package/dist/chunks/{popupStore-Bi6o78lP.js → popupStore-BRRmB4zH.js} +2 -2
- package/dist/chunks/{popupStore-Bi6o78lP.js.map → popupStore-BRRmB4zH.js.map} +1 -1
- package/dist/chunks/{sha256-BZfJs28k.js → sha256-C2-s1oZe.js} +3 -3
- package/dist/chunks/{sha256-BZfJs28k.js.map → sha256-C2-s1oZe.js.map} +1 -1
- package/dist/chunks/usePopup-D2JEuDrO.cjs.map +1 -1
- package/dist/chunks/{usePopup-BSqsnSz7.js → usePopup-DarKTbRC.js} +3 -3
- package/dist/chunks/usePopup-DarKTbRC.js.map +1 -0
- package/dist/components/common/BookmarkMngModal.d.ts +1 -1
- package/dist/components/common/BookmarkMngModal.d.ts.map +1 -1
- package/dist/components/common/BookmarkPopver.d.ts +2 -2
- package/dist/components/common/BookmarkPopver.d.ts.map +1 -1
- package/dist/components/common/BwgButtonGroup.d.ts +5 -5
- package/dist/components/common/BwgButtonGroup.d.ts.map +1 -1
- package/dist/components/common/BwgCmptArea.d.ts +7 -7
- package/dist/components/common/BwgCmptArea.d.ts.map +1 -1
- package/dist/components/common/BwgCol.d.ts +2 -1
- package/dist/components/common/BwgCol.d.ts.map +1 -1
- package/dist/components/common/BwgConfigProvider.d.ts +2 -2
- package/dist/components/common/BwgConfigProvider.d.ts.map +1 -1
- package/dist/components/common/BwgDetail.d.ts +2 -1
- package/dist/components/common/BwgDetail.d.ts.map +1 -1
- package/dist/components/common/BwgDraggable.d.ts +5 -5
- package/dist/components/common/BwgDraggable.d.ts.map +1 -1
- package/dist/components/common/BwgDrawer.d.ts +2 -1
- package/dist/components/common/BwgDrawer.d.ts.map +1 -1
- package/dist/components/common/BwgEditor.d.ts +5 -5
- package/dist/components/common/BwgEditor.d.ts.map +1 -1
- package/dist/components/common/BwgGrid.d.ts +8 -8
- package/dist/components/common/BwgGrid.d.ts.map +1 -1
- package/dist/components/common/BwgInfoArea.d.ts +4 -4
- package/dist/components/common/BwgInfoArea.d.ts.map +1 -1
- package/dist/components/common/BwgPopup.d.ts +3 -3
- package/dist/components/common/BwgPopup.d.ts.map +1 -1
- package/dist/components/common/BwgRow.d.ts +2 -1
- package/dist/components/common/BwgRow.d.ts.map +1 -1
- package/dist/components/common/BwgTitleBox.d.ts +5 -4
- package/dist/components/common/BwgTitleBox.d.ts.map +1 -1
- package/dist/components/common/BwgView.d.ts +4 -4
- package/dist/components/common/BwgView.d.ts.map +1 -1
- package/dist/components/common/ContentBox.d.ts +3 -3
- package/dist/components/common/ContentBox.d.ts.map +1 -1
- package/dist/components/common/ContentLayOut.d.ts +6 -5
- package/dist/components/common/ContentLayOut.d.ts.map +1 -1
- package/dist/components/common/GlobalConfigProvider.d.ts +2 -2
- package/dist/components/common/GlobalConfigProvider.d.ts.map +1 -1
- package/dist/components/common/QuickServiceToggle.d.ts +4 -4
- package/dist/components/common/QuickServiceToggle.d.ts.map +1 -1
- package/dist/components/common/SSOHandler.d.ts +2 -1
- package/dist/components/common/SSOHandler.d.ts.map +1 -1
- package/dist/components/common/SearchBox.d.ts +5 -4
- package/dist/components/common/SearchBox.d.ts.map +1 -1
- package/dist/components/common/index.cjs +1 -1
- package/dist/components/common/index.js +1 -1
- package/dist/components/core/BwgButton.d.ts +3 -2
- package/dist/components/core/BwgButton.d.ts.map +1 -1
- package/dist/components/core/BwgDatePicker.d.ts +3 -3
- package/dist/components/core/BwgDatePicker.d.ts.map +1 -1
- package/dist/components/core/BwgDownload.d.ts +2 -2
- package/dist/components/core/BwgDownload.d.ts.map +1 -1
- package/dist/components/core/BwgForm.d.ts +2 -1
- package/dist/components/core/BwgForm.d.ts.map +1 -1
- package/dist/components/core/BwgFormItem.d.ts +3 -3
- package/dist/components/core/BwgFormItem.d.ts.map +1 -1
- package/dist/components/core/BwgInput.d.ts +2 -2
- package/dist/components/core/BwgInput.d.ts.map +1 -1
- package/dist/components/core/BwgLargeUploader.d.ts +2 -2
- package/dist/components/core/BwgLargeUploader.d.ts.map +1 -1
- package/dist/components/core/BwgMaskedInput.d.ts +2 -2
- package/dist/components/core/BwgMaskedInput.d.ts.map +1 -1
- package/dist/components/core/BwgMaskedPicker.d.ts +2 -2
- package/dist/components/core/BwgMaskedPicker.d.ts.map +1 -1
- package/dist/components/core/BwgRangePicker.d.ts +3 -3
- package/dist/components/core/BwgRangePicker.d.ts.map +1 -1
- package/dist/components/core/BwgSearch.d.ts +1 -1
- package/dist/components/core/BwgSearch.d.ts.map +1 -1
- package/dist/components/core/BwgUploader.d.ts +2 -2
- package/dist/components/core/BwgUploader.d.ts.map +1 -1
- package/dist/components/core/index.cjs +1 -1
- package/dist/components/core/index.js +2 -2
- package/dist/components/layout/ErrorBound.d.ts +3 -3
- package/dist/components/layout/ErrorBound.d.ts.map +1 -1
- package/dist/components/layout/LoadingOverlay.d.ts +3 -2
- package/dist/components/layout/LoadingOverlay.d.ts.map +1 -1
- package/dist/components/layout/PrivateProtectedOverlay.d.ts +3 -2
- package/dist/components/layout/PrivateProtectedOverlay.d.ts.map +1 -1
- package/dist/components/layout/ProgressOverlay.d.ts +2 -2
- package/dist/components/layout/ProgressOverlay.d.ts.map +1 -1
- package/dist/components/layout/ViewContainer.d.ts +3 -3
- package/dist/components/layout/ViewContainer.d.ts.map +1 -1
- package/dist/components/layout/index.js +1 -1
- package/dist/components/popup/MenuReport.d.ts +2 -2
- package/dist/components/popup/MenuReport.d.ts.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.js +11 -11
- package/dist/provider/contexts/AuthContext.d.ts +3 -2
- package/dist/provider/contexts/AuthContext.d.ts.map +1 -1
- package/dist/provider/contexts/CommonCodeContext.d.ts +2 -2
- package/dist/provider/contexts/CommonCodeContext.d.ts.map +1 -1
- package/dist/provider/contexts/ScreenProtectContext.d.ts +5 -5
- package/dist/provider/contexts/ScreenProtectContext.d.ts.map +1 -1
- package/dist/provider/contexts/SearchBoxContext.d.ts +3 -3
- package/dist/provider/contexts/SearchBoxContext.d.ts.map +1 -1
- package/dist/provider/contexts/ServiceCodeContext.d.ts +2 -2
- package/dist/provider/contexts/ServiceCodeContext.d.ts.map +1 -1
- package/dist/provider/index.js +3 -3
- package/dist/stores/index.d.ts.map +1 -1
- package/dist/stores/index.js +6 -6
- package/dist/stores/menuViewStore.d.ts +6 -5
- package/dist/stores/menuViewStore.d.ts.map +1 -1
- package/dist/utils/index.js +2 -2
- package/package.json +1 -1
- package/dist/chunks/AuthContext-Ei2P-z4d.js.map +0 -1
- package/dist/chunks/BwgSwitch-B79pseQM.js.map +0 -1
- package/dist/chunks/BwgSwitch-CAI-kEaM.cjs.map +0 -1
- package/dist/chunks/BwgUploader-BcVlE61B.js.map +0 -1
- package/dist/chunks/BwgUploader-DaNV2URT.cjs.map +0 -1
- package/dist/chunks/SSOHandler-CkPcSHIm.js.map +0 -1
- package/dist/chunks/SSOHandler-DiW4Ft9i.cjs.map +0 -1
- package/dist/chunks/SearchBoxContext-BCvEYyFk.js.map +0 -1
- package/dist/chunks/ViewContainer-CjpJqoGG.js.map +0 -1
- package/dist/chunks/apiUtils-DxzLqPhU.js.map +0 -1
- package/dist/chunks/usePopup-BSqsnSz7.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ScreenProtectContext-3my4PHFa.js","sources":["../../src/provider/contexts/ScreenProtectContext.tsx"],"sourcesContent":["import { Input } from \"antd\";\r\nimport React, {\r\n createContext,\r\n useContext,\r\n useEffect,\r\n useMemo,\r\n useRef,\r\n useState,\r\n} from \"react\";\r\n\r\n/**\r\n * ScreenProtectProvider\r\n * - 전역용(기본값): window 활동감지 + fixed 전체 오버레이\r\n * - 탭스코프용(옵션): eventTarget 활동감지 + absolute 탭 영역 오버레이\r\n */\r\n\r\n// ===================== Lock Context =====================\r\ntype LockContextValue = {\r\n locked: boolean;\r\n lock: () => void;\r\n unlock: (pin?: string) => Promise<void> | void;\r\n setIdleMs: (ms: number) => void;\r\n};\r\n\r\nconst LockContext = createContext<LockContextValue | null>(null);\r\n\r\nexport const useLock = () => {\r\n const ctx = useContext(LockContext);\r\n if (!ctx)\r\n throw new Error(\"useLock must be used within ScreenProtectProvider\");\r\n return ctx;\r\n};\r\n\r\n// ===================== Provider =====================\r\nexport const ScreenProtectProvider: React.FC<{\r\n children: React.ReactNode;\r\n idleMs?: number;\r\n onUnlock?: (pin?: string) => Promise<boolean> | boolean;\r\n persistLocked?: boolean;\r\n storageKey?: string;\r\n\r\n /** ▼ 탭 스코프용 확장 옵션 */\r\n eventTarget?: EventTarget | null; // 활동 감지/가드 대상 (기본: window)\r\n overlayScope?: \"global\" | \"scoped\"; // 캡처가드 범위\r\n overlayId?: string; // 오버레이 DOM id\r\n overlayPosition?: \"fixed\" | \"absolute\"; // 오버레이 위치 (전역: fixed, 탭: absolute)\r\n}> = ({\r\n children,\r\n idleMs = 10_000,\r\n onUnlock,\r\n persistLocked = true,\r\n storageKey = \"inactivityLocked\",\r\n eventTarget,\r\n overlayScope = \"global\",\r\n overlayId = \"lock-overlay-root\",\r\n overlayPosition = \"fixed\",\r\n}) => {\r\n const initialLocked =\r\n persistLocked &&\r\n typeof window !== \"undefined\" &&\r\n window.localStorage.getItem(storageKey) === \"1\";\r\n\r\n const [locked, setLocked] = useState(initialLocked);\r\n const [idle, setIdle] = useState(idleMs);\r\n const isIdleEnabled = Number.isFinite(idle) && idle > 0;\r\n const timerRef = useRef<number | null>(null);\r\n\r\n const lock = () => {\r\n try {\r\n if (persistLocked) window.localStorage.setItem(storageKey, \"1\");\r\n } catch {}\r\n setLocked(true);\r\n };\r\n\r\n const unlock = async (pin?: string) => {\r\n if (onUnlock) {\r\n const ok = await onUnlock(pin);\r\n if (!ok) return;\r\n }\r\n try {\r\n if (persistLocked) window.localStorage.removeItem(storageKey);\r\n } catch {}\r\n setLocked(false);\r\n if (isIdleEnabled) resetTimer();\r\n };\r\n\r\n const doLock = () => {\r\n try {\r\n if (persistLocked) window.localStorage.setItem(storageKey, \"1\");\r\n } catch {}\r\n setLocked(true);\r\n };\r\n\r\n const resetTimer = () => {\r\n if (!isIdleEnabled) return;\r\n if (timerRef.current) window.clearTimeout(timerRef.current);\r\n timerRef.current = window.setTimeout(() => {\r\n doLock();\r\n }, idle);\r\n };\r\n\r\n // 활동 감지: window → target(옵션)으로 스코프 전환 가능\r\n useEffect(() => {\r\n if (!isIdleEnabled) return;\r\n const onActivity = () => {\r\n if (!locked) resetTimer();\r\n };\r\n const opts = { passive: true } as AddEventListenerOptions;\r\n const evts = [\r\n \"pointermove\",\r\n \"pointerdown\",\r\n \"keydown\",\r\n \"wheel\",\r\n \"touchstart\",\r\n ];\r\n\r\n const target = (eventTarget ?? window) as any;\r\n evts.forEach((e) => target.addEventListener(e, onActivity, opts));\r\n resetTimer();\r\n\r\n return () => {\r\n if (timerRef.current) window.clearTimeout(timerRef.current);\r\n evts.forEach((e) => target.removeEventListener(e, onActivity as any));\r\n };\r\n }, [idle, locked, eventTarget, isIdleEnabled]);\r\n\r\n // 잠금 중 캡처가드: 전역(global) 또는 스코프(scoped)로 범위 선택\r\n useEffect(() => {\r\n if (!locked) return;\r\n\r\n const stop = (e: Event) => {\r\n const overlay = document.getElementById(overlayId);\r\n if (overlay && overlay.contains(e.target as Node)) return; // 오버레이 내부는 통과\r\n e.stopPropagation();\r\n e.preventDefault();\r\n };\r\n\r\n const opts = { capture: true } as AddEventListenerOptions;\r\n const evs = [\r\n \"pointerdown\",\r\n \"pointerup\",\r\n \"pointermove\",\r\n \"click\",\r\n \"wheel\",\r\n \"keydown\",\r\n \"keyup\",\r\n \"touchstart\",\r\n \"touchmove\",\r\n ];\r\n\r\n // 전역이면 window, 스코프면 eventTarget(없으면 window)\r\n const guardTarget = (\r\n overlayScope === \"scoped\" ? eventTarget ?? window : window\r\n ) as any;\r\n evs.forEach((t) => guardTarget.addEventListener(t, stop, opts));\r\n return () =>\r\n evs.forEach((t) => guardTarget.removeEventListener(t, stop as any, opts));\r\n }, [locked, overlayScope, overlayId, eventTarget]);\r\n\r\n const value = useMemo(\r\n () => ({ locked, lock, unlock, setIdleMs: setIdle }),\r\n [locked]\r\n );\r\n\r\n return (\r\n <LockContext.Provider value={value}>\r\n <div\r\n style={{ width: \"100%\", height: \"100%\" }}\r\n {...(locked ? ({ inert: \"\" } as any) : {})}\r\n {...(locked ? { \"aria-hidden\": true } : {})}\r\n >\r\n {children}\r\n </div>\r\n {locked && (\r\n <LockOverlay\r\n onUnlock={unlock}\r\n overlayId={overlayId}\r\n overlayPosition={overlayPosition}\r\n />\r\n )}\r\n </LockContext.Provider>\r\n );\r\n};\r\n\r\nconst LockOverlay: React.FC<{\r\n onUnlock: (pin?: string) => void;\r\n overlayId?: string;\r\n overlayPosition?: \"fixed\" | \"absolute\";\r\n}> = ({\r\n onUnlock,\r\n overlayId = \"lock-overlay-root\",\r\n overlayPosition = \"fixed\",\r\n}) => {\r\n const [pinLen] = useState(4);\r\n const [val, setVal] = useState(\"\");\r\n\r\n return (\r\n <div\r\n id={overlayId}\r\n aria-modal=\"true\"\r\n role=\"dialog\"\r\n aria-label=\"Locked screen\"\r\n style={{\r\n position: overlayPosition,\r\n inset: 0,\r\n background: \"rgba(12, 14, 18, 0.85)\",\r\n backdropFilter: \"blur(4px)\",\r\n display: \"grid\",\r\n placeItems: \"center\",\r\n zIndex: 9999,\r\n }}\r\n >\r\n <div className=\"lockscreen-form\" style={{ width: 420, maxWidth: \"92vw\" }}>\r\n <div className=\"lock-icon-wrap\">\r\n <span className=\"lock-icon-box\"></span>\r\n </div>\r\n <h2>잠금됨</h2>\r\n <p>PIN 번호를 입력하세요</p>\r\n <div\r\n className=\"lock-ipt-wrap\"\r\n style={{ display: \"flex\", justifyContent: \"center\" }}\r\n >\r\n <Input.OTP\r\n mask={\"*\"}\r\n autoFocus\r\n length={pinLen}\r\n value={val}\r\n onChange={(v) => {\r\n const next = (v ?? \"\").replace(/\\D/g, \"\").slice(0, pinLen);\r\n setVal(next);\r\n if (next.length === pinLen) onUnlock(next);\r\n }}\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n};\r\n"],"names":["LockContext","createContext","useLock","ctx","useContext","ScreenProtectProvider","children","idleMs","onUnlock","persistLocked","storageKey","eventTarget","overlayScope","overlayId","overlayPosition","initialLocked","locked","setLocked","useState","idle","setIdle","isIdleEnabled","timerRef","useRef","lock","unlock","pin","resetTimer","doLock","useEffect","onActivity","opts","evts","target","stop","overlay","evs","guardTarget","t","value","useMemo","jsxs","jsx","LockOverlay","pinLen","val","setVal","Input","v","next"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ScreenProtectContext-3my4PHFa.js","sources":["../../src/provider/contexts/ScreenProtectContext.tsx"],"sourcesContent":["import { Input } from \"antd\";\r\nimport {\r\n createContext,\r\n FC,\r\n ReactNode,\r\n useContext,\r\n useEffect,\r\n useMemo,\r\n useRef,\r\n useState,\r\n} from 'react';\r\n\r\n/**\r\n * ScreenProtectProvider\r\n * - 전역용(기본값): window 활동감지 + fixed 전체 오버레이\r\n * - 탭스코프용(옵션): eventTarget 활동감지 + absolute 탭 영역 오버레이\r\n */\r\n\r\n// ===================== Lock Context =====================\r\ntype LockContextValue = {\r\n locked: boolean;\r\n lock: () => void;\r\n unlock: (pin?: string) => Promise<void> | void;\r\n setIdleMs: (ms: number) => void;\r\n};\r\n\r\nconst LockContext = createContext<LockContextValue | null>(null);\r\n\r\nexport const useLock = () => {\r\n const ctx = useContext(LockContext);\r\n if (!ctx)\r\n throw new Error('useLock must be used within ScreenProtectProvider');\r\n return ctx;\r\n};\r\n\r\n// ===================== Provider =====================\r\nexport const ScreenProtectProvider: FC<{\r\n children: ReactNode;\r\n idleMs?: number;\r\n onUnlock?: (pin?: string) => Promise<boolean> | boolean;\r\n persistLocked?: boolean;\r\n storageKey?: string;\r\n\r\n /** ▼ 탭 스코프용 확장 옵션 */\r\n eventTarget?: EventTarget | null; // 활동 감지/가드 대상 (기본: window)\r\n overlayScope?: 'global' | 'scoped'; // 캡처가드 범위\r\n overlayId?: string; // 오버레이 DOM id\r\n overlayPosition?: 'fixed' | 'absolute'; // 오버레이 위치 (전역: fixed, 탭: absolute)\r\n}> = ({\r\n children,\r\n idleMs = 10_000,\r\n onUnlock,\r\n persistLocked = true,\r\n storageKey = 'inactivityLocked',\r\n eventTarget,\r\n overlayScope = 'global',\r\n overlayId = 'lock-overlay-root',\r\n overlayPosition = 'fixed',\r\n}) => {\r\n const initialLocked =\r\n persistLocked &&\r\n typeof window !== 'undefined' &&\r\n window.localStorage.getItem(storageKey) === '1';\r\n\r\n const [locked, setLocked] = useState(initialLocked);\r\n const [idle, setIdle] = useState(idleMs);\r\n const isIdleEnabled = Number.isFinite(idle) && idle > 0;\r\n const timerRef = useRef<number | null>(null);\r\n\r\n const lock = () => {\r\n try {\r\n if (persistLocked) window.localStorage.setItem(storageKey, '1');\r\n } catch {}\r\n setLocked(true);\r\n };\r\n\r\n const unlock = async (pin?: string) => {\r\n if (onUnlock) {\r\n const ok = await onUnlock(pin);\r\n if (!ok) return;\r\n }\r\n try {\r\n if (persistLocked) window.localStorage.removeItem(storageKey);\r\n } catch {}\r\n setLocked(false);\r\n if (isIdleEnabled) resetTimer();\r\n };\r\n\r\n const doLock = () => {\r\n try {\r\n if (persistLocked) window.localStorage.setItem(storageKey, '1');\r\n } catch {}\r\n setLocked(true);\r\n };\r\n\r\n const resetTimer = () => {\r\n if (!isIdleEnabled) return;\r\n if (timerRef.current) window.clearTimeout(timerRef.current);\r\n timerRef.current = window.setTimeout(() => {\r\n doLock();\r\n }, idle);\r\n };\r\n\r\n // 활동 감지: window → target(옵션)으로 스코프 전환 가능\r\n useEffect(() => {\r\n if (!isIdleEnabled) return;\r\n const onActivity = () => {\r\n if (!locked) resetTimer();\r\n };\r\n const opts = { passive: true } as AddEventListenerOptions;\r\n const evts = [\r\n 'pointermove',\r\n 'pointerdown',\r\n 'keydown',\r\n 'wheel',\r\n 'touchstart',\r\n ];\r\n\r\n const target = (eventTarget ?? window) as any;\r\n evts.forEach(e => target.addEventListener(e, onActivity, opts));\r\n resetTimer();\r\n\r\n return () => {\r\n if (timerRef.current) window.clearTimeout(timerRef.current);\r\n evts.forEach(e => target.removeEventListener(e, onActivity as any));\r\n };\r\n }, [idle, locked, eventTarget, isIdleEnabled]);\r\n\r\n // 잠금 중 캡처가드: 전역(global) 또는 스코프(scoped)로 범위 선택\r\n useEffect(() => {\r\n if (!locked) return;\r\n\r\n const stop = (e: Event) => {\r\n const overlay = document.getElementById(overlayId);\r\n if (overlay && overlay.contains(e.target as Node)) return; // 오버레이 내부는 통과\r\n e.stopPropagation();\r\n e.preventDefault();\r\n };\r\n\r\n const opts = { capture: true } as AddEventListenerOptions;\r\n const evs = [\r\n 'pointerdown',\r\n 'pointerup',\r\n 'pointermove',\r\n 'click',\r\n 'wheel',\r\n 'keydown',\r\n 'keyup',\r\n 'touchstart',\r\n 'touchmove',\r\n ];\r\n\r\n // 전역이면 window, 스코프면 eventTarget(없으면 window)\r\n const guardTarget = (\r\n overlayScope === 'scoped' ? eventTarget ?? window : window\r\n ) as any;\r\n evs.forEach(t => guardTarget.addEventListener(t, stop, opts));\r\n return () =>\r\n evs.forEach(t => guardTarget.removeEventListener(t, stop as any, opts));\r\n }, [locked, overlayScope, overlayId, eventTarget]);\r\n\r\n const value = useMemo(\r\n () => ({ locked, lock, unlock, setIdleMs: setIdle }),\r\n [locked]\r\n );\r\n\r\n return (\r\n <LockContext.Provider value={value}>\r\n <div\r\n style={{ width: '100%', height: '100%' }}\r\n {...(locked ? ({ inert: '' } as any) : {})}\r\n {...(locked ? { 'aria-hidden': true } : {})}\r\n >\r\n {children}\r\n </div>\r\n {locked && (\r\n <LockOverlay\r\n onUnlock={unlock}\r\n overlayId={overlayId}\r\n overlayPosition={overlayPosition}\r\n />\r\n )}\r\n </LockContext.Provider>\r\n );\r\n};\r\n\r\nconst LockOverlay: FC<{\r\n onUnlock: (pin?: string) => void;\r\n overlayId?: string;\r\n overlayPosition?: 'fixed' | 'absolute';\r\n}> = ({\r\n onUnlock,\r\n overlayId = 'lock-overlay-root',\r\n overlayPosition = 'fixed',\r\n}) => {\r\n const [pinLen] = useState(4);\r\n const [val, setVal] = useState('');\r\n\r\n return (\r\n <div\r\n id={overlayId}\r\n aria-modal='true'\r\n role='dialog'\r\n aria-label='Locked screen'\r\n style={{\r\n position: overlayPosition,\r\n inset: 0,\r\n background: 'rgba(12, 14, 18, 0.85)',\r\n backdropFilter: 'blur(4px)',\r\n display: 'grid',\r\n placeItems: 'center',\r\n zIndex: 9999,\r\n }}\r\n >\r\n <div className='lockscreen-form' style={{ width: 420, maxWidth: '92vw' }}>\r\n <div className='lock-icon-wrap'>\r\n <span className='lock-icon-box'></span>\r\n </div>\r\n <h2>잠금됨</h2>\r\n <p>PIN 번호를 입력하세요</p>\r\n <div\r\n className='lock-ipt-wrap'\r\n style={{ display: 'flex', justifyContent: 'center' }}\r\n >\r\n <Input.OTP\r\n mask={'*'}\r\n autoFocus\r\n length={pinLen}\r\n value={val}\r\n onChange={v => {\r\n const next = (v ?? '').replace(/\\D/g, '').slice(0, pinLen);\r\n setVal(next);\r\n if (next.length === pinLen) onUnlock(next);\r\n }}\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n};\r\n"],"names":["LockContext","createContext","useLock","ctx","useContext","ScreenProtectProvider","children","idleMs","onUnlock","persistLocked","storageKey","eventTarget","overlayScope","overlayId","overlayPosition","initialLocked","locked","setLocked","useState","idle","setIdle","isIdleEnabled","timerRef","useRef","lock","unlock","pin","resetTimer","doLock","useEffect","onActivity","opts","evts","target","stop","overlay","evs","guardTarget","t","value","useMemo","jsxs","jsx","LockOverlay","pinLen","val","setVal","Input","v","next"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ScreenProtectContext-CVuXrJm6.cjs","sources":["../../src/provider/contexts/ScreenProtectContext.tsx"],"sourcesContent":["import { Input } from \"antd\";\r\nimport React, {\r\n createContext,\r\n useContext,\r\n useEffect,\r\n useMemo,\r\n useRef,\r\n useState,\r\n} from \"react\";\r\n\r\n/**\r\n * ScreenProtectProvider\r\n * - 전역용(기본값): window 활동감지 + fixed 전체 오버레이\r\n * - 탭스코프용(옵션): eventTarget 활동감지 + absolute 탭 영역 오버레이\r\n */\r\n\r\n// ===================== Lock Context =====================\r\ntype LockContextValue = {\r\n locked: boolean;\r\n lock: () => void;\r\n unlock: (pin?: string) => Promise<void> | void;\r\n setIdleMs: (ms: number) => void;\r\n};\r\n\r\nconst LockContext = createContext<LockContextValue | null>(null);\r\n\r\nexport const useLock = () => {\r\n const ctx = useContext(LockContext);\r\n if (!ctx)\r\n throw new Error(\"useLock must be used within ScreenProtectProvider\");\r\n return ctx;\r\n};\r\n\r\n// ===================== Provider =====================\r\nexport const ScreenProtectProvider: React.FC<{\r\n children: React.ReactNode;\r\n idleMs?: number;\r\n onUnlock?: (pin?: string) => Promise<boolean> | boolean;\r\n persistLocked?: boolean;\r\n storageKey?: string;\r\n\r\n /** ▼ 탭 스코프용 확장 옵션 */\r\n eventTarget?: EventTarget | null; // 활동 감지/가드 대상 (기본: window)\r\n overlayScope?: \"global\" | \"scoped\"; // 캡처가드 범위\r\n overlayId?: string; // 오버레이 DOM id\r\n overlayPosition?: \"fixed\" | \"absolute\"; // 오버레이 위치 (전역: fixed, 탭: absolute)\r\n}> = ({\r\n children,\r\n idleMs = 10_000,\r\n onUnlock,\r\n persistLocked = true,\r\n storageKey = \"inactivityLocked\",\r\n eventTarget,\r\n overlayScope = \"global\",\r\n overlayId = \"lock-overlay-root\",\r\n overlayPosition = \"fixed\",\r\n}) => {\r\n const initialLocked =\r\n persistLocked &&\r\n typeof window !== \"undefined\" &&\r\n window.localStorage.getItem(storageKey) === \"1\";\r\n\r\n const [locked, setLocked] = useState(initialLocked);\r\n const [idle, setIdle] = useState(idleMs);\r\n const isIdleEnabled = Number.isFinite(idle) && idle > 0;\r\n const timerRef = useRef<number | null>(null);\r\n\r\n const lock = () => {\r\n try {\r\n if (persistLocked) window.localStorage.setItem(storageKey, \"1\");\r\n } catch {}\r\n setLocked(true);\r\n };\r\n\r\n const unlock = async (pin?: string) => {\r\n if (onUnlock) {\r\n const ok = await onUnlock(pin);\r\n if (!ok) return;\r\n }\r\n try {\r\n if (persistLocked) window.localStorage.removeItem(storageKey);\r\n } catch {}\r\n setLocked(false);\r\n if (isIdleEnabled) resetTimer();\r\n };\r\n\r\n const doLock = () => {\r\n try {\r\n if (persistLocked) window.localStorage.setItem(storageKey, \"1\");\r\n } catch {}\r\n setLocked(true);\r\n };\r\n\r\n const resetTimer = () => {\r\n if (!isIdleEnabled) return;\r\n if (timerRef.current) window.clearTimeout(timerRef.current);\r\n timerRef.current = window.setTimeout(() => {\r\n doLock();\r\n }, idle);\r\n };\r\n\r\n // 활동 감지: window → target(옵션)으로 스코프 전환 가능\r\n useEffect(() => {\r\n if (!isIdleEnabled) return;\r\n const onActivity = () => {\r\n if (!locked) resetTimer();\r\n };\r\n const opts = { passive: true } as AddEventListenerOptions;\r\n const evts = [\r\n \"pointermove\",\r\n \"pointerdown\",\r\n \"keydown\",\r\n \"wheel\",\r\n \"touchstart\",\r\n ];\r\n\r\n const target = (eventTarget ?? window) as any;\r\n evts.forEach((e) => target.addEventListener(e, onActivity, opts));\r\n resetTimer();\r\n\r\n return () => {\r\n if (timerRef.current) window.clearTimeout(timerRef.current);\r\n evts.forEach((e) => target.removeEventListener(e, onActivity as any));\r\n };\r\n }, [idle, locked, eventTarget, isIdleEnabled]);\r\n\r\n // 잠금 중 캡처가드: 전역(global) 또는 스코프(scoped)로 범위 선택\r\n useEffect(() => {\r\n if (!locked) return;\r\n\r\n const stop = (e: Event) => {\r\n const overlay = document.getElementById(overlayId);\r\n if (overlay && overlay.contains(e.target as Node)) return; // 오버레이 내부는 통과\r\n e.stopPropagation();\r\n e.preventDefault();\r\n };\r\n\r\n const opts = { capture: true } as AddEventListenerOptions;\r\n const evs = [\r\n \"pointerdown\",\r\n \"pointerup\",\r\n \"pointermove\",\r\n \"click\",\r\n \"wheel\",\r\n \"keydown\",\r\n \"keyup\",\r\n \"touchstart\",\r\n \"touchmove\",\r\n ];\r\n\r\n // 전역이면 window, 스코프면 eventTarget(없으면 window)\r\n const guardTarget = (\r\n overlayScope === \"scoped\" ? eventTarget ?? window : window\r\n ) as any;\r\n evs.forEach((t) => guardTarget.addEventListener(t, stop, opts));\r\n return () =>\r\n evs.forEach((t) => guardTarget.removeEventListener(t, stop as any, opts));\r\n }, [locked, overlayScope, overlayId, eventTarget]);\r\n\r\n const value = useMemo(\r\n () => ({ locked, lock, unlock, setIdleMs: setIdle }),\r\n [locked]\r\n );\r\n\r\n return (\r\n <LockContext.Provider value={value}>\r\n <div\r\n style={{ width: \"100%\", height: \"100%\" }}\r\n {...(locked ? ({ inert: \"\" } as any) : {})}\r\n {...(locked ? { \"aria-hidden\": true } : {})}\r\n >\r\n {children}\r\n </div>\r\n {locked && (\r\n <LockOverlay\r\n onUnlock={unlock}\r\n overlayId={overlayId}\r\n overlayPosition={overlayPosition}\r\n />\r\n )}\r\n </LockContext.Provider>\r\n );\r\n};\r\n\r\nconst LockOverlay: React.FC<{\r\n onUnlock: (pin?: string) => void;\r\n overlayId?: string;\r\n overlayPosition?: \"fixed\" | \"absolute\";\r\n}> = ({\r\n onUnlock,\r\n overlayId = \"lock-overlay-root\",\r\n overlayPosition = \"fixed\",\r\n}) => {\r\n const [pinLen] = useState(4);\r\n const [val, setVal] = useState(\"\");\r\n\r\n return (\r\n <div\r\n id={overlayId}\r\n aria-modal=\"true\"\r\n role=\"dialog\"\r\n aria-label=\"Locked screen\"\r\n style={{\r\n position: overlayPosition,\r\n inset: 0,\r\n background: \"rgba(12, 14, 18, 0.85)\",\r\n backdropFilter: \"blur(4px)\",\r\n display: \"grid\",\r\n placeItems: \"center\",\r\n zIndex: 9999,\r\n }}\r\n >\r\n <div className=\"lockscreen-form\" style={{ width: 420, maxWidth: \"92vw\" }}>\r\n <div className=\"lock-icon-wrap\">\r\n <span className=\"lock-icon-box\"></span>\r\n </div>\r\n <h2>잠금됨</h2>\r\n <p>PIN 번호를 입력하세요</p>\r\n <div\r\n className=\"lock-ipt-wrap\"\r\n style={{ display: \"flex\", justifyContent: \"center\" }}\r\n >\r\n <Input.OTP\r\n mask={\"*\"}\r\n autoFocus\r\n length={pinLen}\r\n value={val}\r\n onChange={(v) => {\r\n const next = (v ?? \"\").replace(/\\D/g, \"\").slice(0, pinLen);\r\n setVal(next);\r\n if (next.length === pinLen) onUnlock(next);\r\n }}\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n};\r\n"],"names":["LockContext","createContext","useLock","ctx","useContext","ScreenProtectProvider","children","idleMs","onUnlock","persistLocked","storageKey","eventTarget","overlayScope","overlayId","overlayPosition","initialLocked","locked","setLocked","useState","idle","setIdle","isIdleEnabled","timerRef","useRef","lock","unlock","pin","resetTimer","doLock","useEffect","onActivity","opts","evts","target","stop","overlay","evs","guardTarget","t","value","useMemo","jsxs","jsx","LockOverlay","pinLen","val","setVal","Input","v","next"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ScreenProtectContext-CVuXrJm6.cjs","sources":["../../src/provider/contexts/ScreenProtectContext.tsx"],"sourcesContent":["import { Input } from \"antd\";\r\nimport {\r\n createContext,\r\n FC,\r\n ReactNode,\r\n useContext,\r\n useEffect,\r\n useMemo,\r\n useRef,\r\n useState,\r\n} from 'react';\r\n\r\n/**\r\n * ScreenProtectProvider\r\n * - 전역용(기본값): window 활동감지 + fixed 전체 오버레이\r\n * - 탭스코프용(옵션): eventTarget 활동감지 + absolute 탭 영역 오버레이\r\n */\r\n\r\n// ===================== Lock Context =====================\r\ntype LockContextValue = {\r\n locked: boolean;\r\n lock: () => void;\r\n unlock: (pin?: string) => Promise<void> | void;\r\n setIdleMs: (ms: number) => void;\r\n};\r\n\r\nconst LockContext = createContext<LockContextValue | null>(null);\r\n\r\nexport const useLock = () => {\r\n const ctx = useContext(LockContext);\r\n if (!ctx)\r\n throw new Error('useLock must be used within ScreenProtectProvider');\r\n return ctx;\r\n};\r\n\r\n// ===================== Provider =====================\r\nexport const ScreenProtectProvider: FC<{\r\n children: ReactNode;\r\n idleMs?: number;\r\n onUnlock?: (pin?: string) => Promise<boolean> | boolean;\r\n persistLocked?: boolean;\r\n storageKey?: string;\r\n\r\n /** ▼ 탭 스코프용 확장 옵션 */\r\n eventTarget?: EventTarget | null; // 활동 감지/가드 대상 (기본: window)\r\n overlayScope?: 'global' | 'scoped'; // 캡처가드 범위\r\n overlayId?: string; // 오버레이 DOM id\r\n overlayPosition?: 'fixed' | 'absolute'; // 오버레이 위치 (전역: fixed, 탭: absolute)\r\n}> = ({\r\n children,\r\n idleMs = 10_000,\r\n onUnlock,\r\n persistLocked = true,\r\n storageKey = 'inactivityLocked',\r\n eventTarget,\r\n overlayScope = 'global',\r\n overlayId = 'lock-overlay-root',\r\n overlayPosition = 'fixed',\r\n}) => {\r\n const initialLocked =\r\n persistLocked &&\r\n typeof window !== 'undefined' &&\r\n window.localStorage.getItem(storageKey) === '1';\r\n\r\n const [locked, setLocked] = useState(initialLocked);\r\n const [idle, setIdle] = useState(idleMs);\r\n const isIdleEnabled = Number.isFinite(idle) && idle > 0;\r\n const timerRef = useRef<number | null>(null);\r\n\r\n const lock = () => {\r\n try {\r\n if (persistLocked) window.localStorage.setItem(storageKey, '1');\r\n } catch {}\r\n setLocked(true);\r\n };\r\n\r\n const unlock = async (pin?: string) => {\r\n if (onUnlock) {\r\n const ok = await onUnlock(pin);\r\n if (!ok) return;\r\n }\r\n try {\r\n if (persistLocked) window.localStorage.removeItem(storageKey);\r\n } catch {}\r\n setLocked(false);\r\n if (isIdleEnabled) resetTimer();\r\n };\r\n\r\n const doLock = () => {\r\n try {\r\n if (persistLocked) window.localStorage.setItem(storageKey, '1');\r\n } catch {}\r\n setLocked(true);\r\n };\r\n\r\n const resetTimer = () => {\r\n if (!isIdleEnabled) return;\r\n if (timerRef.current) window.clearTimeout(timerRef.current);\r\n timerRef.current = window.setTimeout(() => {\r\n doLock();\r\n }, idle);\r\n };\r\n\r\n // 활동 감지: window → target(옵션)으로 스코프 전환 가능\r\n useEffect(() => {\r\n if (!isIdleEnabled) return;\r\n const onActivity = () => {\r\n if (!locked) resetTimer();\r\n };\r\n const opts = { passive: true } as AddEventListenerOptions;\r\n const evts = [\r\n 'pointermove',\r\n 'pointerdown',\r\n 'keydown',\r\n 'wheel',\r\n 'touchstart',\r\n ];\r\n\r\n const target = (eventTarget ?? window) as any;\r\n evts.forEach(e => target.addEventListener(e, onActivity, opts));\r\n resetTimer();\r\n\r\n return () => {\r\n if (timerRef.current) window.clearTimeout(timerRef.current);\r\n evts.forEach(e => target.removeEventListener(e, onActivity as any));\r\n };\r\n }, [idle, locked, eventTarget, isIdleEnabled]);\r\n\r\n // 잠금 중 캡처가드: 전역(global) 또는 스코프(scoped)로 범위 선택\r\n useEffect(() => {\r\n if (!locked) return;\r\n\r\n const stop = (e: Event) => {\r\n const overlay = document.getElementById(overlayId);\r\n if (overlay && overlay.contains(e.target as Node)) return; // 오버레이 내부는 통과\r\n e.stopPropagation();\r\n e.preventDefault();\r\n };\r\n\r\n const opts = { capture: true } as AddEventListenerOptions;\r\n const evs = [\r\n 'pointerdown',\r\n 'pointerup',\r\n 'pointermove',\r\n 'click',\r\n 'wheel',\r\n 'keydown',\r\n 'keyup',\r\n 'touchstart',\r\n 'touchmove',\r\n ];\r\n\r\n // 전역이면 window, 스코프면 eventTarget(없으면 window)\r\n const guardTarget = (\r\n overlayScope === 'scoped' ? eventTarget ?? window : window\r\n ) as any;\r\n evs.forEach(t => guardTarget.addEventListener(t, stop, opts));\r\n return () =>\r\n evs.forEach(t => guardTarget.removeEventListener(t, stop as any, opts));\r\n }, [locked, overlayScope, overlayId, eventTarget]);\r\n\r\n const value = useMemo(\r\n () => ({ locked, lock, unlock, setIdleMs: setIdle }),\r\n [locked]\r\n );\r\n\r\n return (\r\n <LockContext.Provider value={value}>\r\n <div\r\n style={{ width: '100%', height: '100%' }}\r\n {...(locked ? ({ inert: '' } as any) : {})}\r\n {...(locked ? { 'aria-hidden': true } : {})}\r\n >\r\n {children}\r\n </div>\r\n {locked && (\r\n <LockOverlay\r\n onUnlock={unlock}\r\n overlayId={overlayId}\r\n overlayPosition={overlayPosition}\r\n />\r\n )}\r\n </LockContext.Provider>\r\n );\r\n};\r\n\r\nconst LockOverlay: FC<{\r\n onUnlock: (pin?: string) => void;\r\n overlayId?: string;\r\n overlayPosition?: 'fixed' | 'absolute';\r\n}> = ({\r\n onUnlock,\r\n overlayId = 'lock-overlay-root',\r\n overlayPosition = 'fixed',\r\n}) => {\r\n const [pinLen] = useState(4);\r\n const [val, setVal] = useState('');\r\n\r\n return (\r\n <div\r\n id={overlayId}\r\n aria-modal='true'\r\n role='dialog'\r\n aria-label='Locked screen'\r\n style={{\r\n position: overlayPosition,\r\n inset: 0,\r\n background: 'rgba(12, 14, 18, 0.85)',\r\n backdropFilter: 'blur(4px)',\r\n display: 'grid',\r\n placeItems: 'center',\r\n zIndex: 9999,\r\n }}\r\n >\r\n <div className='lockscreen-form' style={{ width: 420, maxWidth: '92vw' }}>\r\n <div className='lock-icon-wrap'>\r\n <span className='lock-icon-box'></span>\r\n </div>\r\n <h2>잠금됨</h2>\r\n <p>PIN 번호를 입력하세요</p>\r\n <div\r\n className='lock-ipt-wrap'\r\n style={{ display: 'flex', justifyContent: 'center' }}\r\n >\r\n <Input.OTP\r\n mask={'*'}\r\n autoFocus\r\n length={pinLen}\r\n value={val}\r\n onChange={v => {\r\n const next = (v ?? '').replace(/\\D/g, '').slice(0, pinLen);\r\n setVal(next);\r\n if (next.length === pinLen) onUnlock(next);\r\n }}\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n};\r\n"],"names":["LockContext","createContext","useLock","ctx","useContext","ScreenProtectProvider","children","idleMs","onUnlock","persistLocked","storageKey","eventTarget","overlayScope","overlayId","overlayPosition","initialLocked","locked","setLocked","useState","idle","setIdle","isIdleEnabled","timerRef","useRef","lock","unlock","pin","resetTimer","doLock","useEffect","onActivity","opts","evts","target","stop","overlay","evs","guardTarget","t","value","useMemo","jsxs","jsx","LockOverlay","pinLen","val","setVal","Input","v","next"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SearchBoxContext-DwFDOyYG.cjs","sources":["../../src/provider/contexts/ServiceCodeContext.tsx","../../src/provider/contexts/SearchBoxContext.tsx"],"sourcesContent":["import
|
|
1
|
+
{"version":3,"file":"SearchBoxContext-DwFDOyYG.cjs","sources":["../../src/provider/contexts/ServiceCodeContext.tsx","../../src/provider/contexts/SearchBoxContext.tsx"],"sourcesContent":["import { createContext, FC, ReactNode, useContext, useEffect } from 'react';\r\nimport {\r\n ServiceCodeKey,\r\n setServiceCodeOverrides,\r\n} from '../../utils/serviceConfig';\r\n\r\n// 서비스코드 설정을 위한 Context 타입\r\ninterface ServiceCodeContextType {\r\n serviceCodes: Partial<Record<ServiceCodeKey, string>>;\r\n getServiceCode: (key: ServiceCodeKey) => string;\r\n}\r\n\r\n// 기본 서비스코드 정의\r\nconst DEFAULT_SERVICE_CODES = {\r\n // 권한 관련\r\n AUTH_BTNS: 'SCMSIGN00202', // 버튼 권한 조회\r\n AUTH_MENU: 'SCMSIGN00201', // 메뉴 권한 조회\r\n SRCH_CODE: 'SCMSIGN00301', // 코드 조회\r\n\r\n // 팝업 관련\r\n SRCH_POPU: 'SCMPOPU00101', // 팝업 조회\r\n\r\n // 즐겨찾기 관련\r\n AUTH_BMRK: 'SCMBMRK00101', // 즐겨찾기 관리\r\n} as const;\r\n\r\n// Context 생성\r\nconst ServiceCodeContext = createContext<ServiceCodeContextType | null>(null);\r\n\r\n// Provider Props 타입\r\ninterface ServiceCodeProviderProps {\r\n children: ReactNode;\r\n /**\r\n * 서비스코드 오버라이드 설정\r\n * 외부 프로젝트에서 기본 서비스코드를 재정의할 수 있습니다.\r\n *\r\n * @example\r\n * ```tsx\r\n * <ServiceCodeProvider\r\n * serviceCodes={{\r\n * AUTH_BTNS: 'CUSTOM_AUTH_BTNS_CODE',\r\n * AUTH_MENU: 'CUSTOM_AUTH_MENU_CODE',\r\n * SRCH_CODE: 'CUSTOM_SRCH_CODE',\r\n * SRCH_POPU: 'CUSTOM_SRCH_POPU_CODE',\r\n * AUTH_BMRK: 'CUSTOM_AUTH_BMRK_CODE',\r\n * }}\r\n * >\r\n * {children}\r\n * </ServiceCodeProvider>\r\n * ```\r\n *\r\n * @description\r\n * - AUTH_BTNS: 버튼 권한 조회 서비스코드\r\n * - AUTH_MENU: 메뉴 권한 조회 서비스코드\r\n * - SRCH_CODE: 코드 조회 서비스코드\r\n * - SRCH_POPU: 팝업 조회 서비스코드\r\n * - AUTH_BMRK: 즐겨찾기 관리 서비스코드\r\n *\r\n * 설정하지 않은 서비스코드는 기본값을 사용합니다.\r\n */\r\n serviceCodes?: Partial<Record<ServiceCodeKey, string>>;\r\n}\r\n\r\n/**\r\n * 서비스코드 Provider 컴포넌트\r\n * 외부 프로젝트에서 서비스코드를 설정할 수 있도록 함\r\n *\r\n * @example\r\n * ```tsx\r\n * import { ServiceCodeProvider } from '@bwg/core/provider';\r\n *\r\n * function App() {\r\n * return (\r\n * <ServiceCodeProvider\r\n * serviceCodes={{\r\n * AUTH_BTNS: 'CUSTOM_AUTH_BTNS_CODE',\r\n * AUTH_MENU: 'CUSTOM_AUTH_MENU_CODE',\r\n * }}\r\n * >\r\n * <YourApp />\r\n * </ServiceCodeProvider>\r\n * );\r\n * }\r\n * ```\r\n */\r\nexport const ServiceCodeProvider: FC<ServiceCodeProviderProps> = ({\r\n children,\r\n serviceCodes = {},\r\n}) => {\r\n // serviceCodes가 변경될 때마다 serviceConfig.ts의 오버라이드를 업데이트\r\n useEffect(() => {\r\n setServiceCodeOverrides(serviceCodes);\r\n }, [serviceCodes]);\r\n\r\n // 서비스코드 가져오기 함수\r\n const getServiceCode = (key: ServiceCodeKey): string => {\r\n // 1. Provider에서 설정된 값 우선 확인\r\n if (serviceCodes[key] && serviceCodes[key]!.trim() !== '') {\r\n console.log(`🔧 Provider 설정 사용: ${key} = ${serviceCodes[key]}`);\r\n return serviceCodes[key]!;\r\n }\r\n\r\n // 2. 기본값 사용\r\n const defaultValue = DEFAULT_SERVICE_CODES[key];\r\n console.log(`🔧 기본값 사용: ${key} = ${defaultValue}`);\r\n return defaultValue;\r\n };\r\n\r\n const contextValue: ServiceCodeContextType = {\r\n serviceCodes,\r\n getServiceCode,\r\n };\r\n\r\n return (\r\n <ServiceCodeContext.Provider value={contextValue}>\r\n {children}\r\n </ServiceCodeContext.Provider>\r\n );\r\n};\r\n\r\n/**\r\n * 서비스코드 Context를 사용하는 Hook\r\n *\r\n * @example\r\n * ```tsx\r\n * const { getServiceCode, serviceCodes } = useServiceCode();\r\n * const authBtnsCode = getServiceCode('AUTH_BTNS');\r\n * ```\r\n */\r\nexport const useServiceCode = (): ServiceCodeContextType => {\r\n const context = useContext(ServiceCodeContext);\r\n if (!context) {\r\n throw new Error('useServiceCode must be used within a ServiceCodeProvider');\r\n }\r\n return context;\r\n};\r\n\r\n/**\r\n * 특정 서비스코드를 가져오는 Hook\r\n *\r\n * @param key - 서비스코드 키\r\n * @returns 실제 서비스코드 값\r\n *\r\n * @example\r\n * ```tsx\r\n * const authBtnsCode = useServiceCodeValue('AUTH_BTNS');\r\n * const authMenuCode = useServiceCodeValue('AUTH_MENU');\r\n * ```\r\n */\r\nexport const useServiceCodeValue = (key: ServiceCodeKey): string => {\r\n const { getServiceCode } = useServiceCode();\r\n return getServiceCode(key);\r\n};\r\n\r\n/**\r\n * 모든 서비스코드를 가져오는 Hook\r\n *\r\n * @returns 모든 서비스코드 객체\r\n *\r\n * @example\r\n * ```tsx\r\n * const allServiceCodes = useAllServiceCodes();\r\n * console.log(allServiceCodes.AUTH_BTNS); // 'SCMSIGN00202' 또는 커스텀 값\r\n * ```\r\n */\r\nexport const useAllServiceCodes = (): Record<ServiceCodeKey, string> => {\r\n const { getServiceCode } = useServiceCode();\r\n const result = {} as Record<ServiceCodeKey, string>;\r\n\r\n for (const key of Object.keys(DEFAULT_SERVICE_CODES) as ServiceCodeKey[]) {\r\n result[key] = getServiceCode(key);\r\n }\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * 서비스코드 설정을 로그로 출력하는 Hook\r\n * 개발 시 현재 설정된 서비스코드를 확인할 수 있습니다.\r\n *\r\n * @example\r\n * ```tsx\r\n * useLogServiceCodeConfig();\r\n * // 콘솔에 현재 설정된 모든 서비스코드가 출력됩니다.\r\n * ```\r\n */\r\nexport const useLogServiceCodeConfig = (): void => {\r\n const { getServiceCode } = useServiceCode();\r\n\r\n console.log('🔧 bwg-core 서비스코드 설정:');\r\n console.log('📋 Provider 설정 > 기본값 순서로 확인');\r\n\r\n for (const key of Object.keys(DEFAULT_SERVICE_CODES) as ServiceCodeKey[]) {\r\n const value = getServiceCode(key);\r\n console.log(` ${key}: ${value}`);\r\n }\r\n};\r\n\r\n// 타입 내보내기\r\nexport type { ServiceCodeKey };\r\n","import {\r\n createContext,\r\n FC,\r\n ReactNode,\r\n RefObject,\r\n useContext,\r\n useRef,\r\n} from 'react';\r\nimport { SearchBoxRef } from '../../components/common/SearchBox';\r\n\r\n// SearchBox Context 타입\r\ninterface SearchBoxContextType {\r\n searchBoxRef: RefObject<SearchBoxRef> | null;\r\n getFormData: () => any;\r\n setFormData: (data: any) => void;\r\n resetForm: () => void;\r\n validateForm: () => Promise<any>;\r\n}\r\n\r\n// Context 생성\r\nconst SearchBoxContext = createContext<SearchBoxContextType | null>(null);\r\n\r\n// Provider Props\r\ninterface SearchBoxProviderProps {\r\n children: ReactNode;\r\n}\r\n\r\n// Provider 컴포넌트\r\nexport const SearchBoxProvider: FC<SearchBoxProviderProps> = ({ children }) => {\r\n const searchBoxRef = useRef<SearchBoxRef>(null);\r\n\r\n const getFormData = () => {\r\n return searchBoxRef.current?.getFormData() || {};\r\n };\r\n\r\n const setFormData = (data: any) => {\r\n searchBoxRef.current?.setFormData(data);\r\n };\r\n\r\n const resetForm = () => {\r\n searchBoxRef.current?.resetForm();\r\n };\r\n\r\n const validateForm = async () => {\r\n return (\r\n (await searchBoxRef.current?.validateForm()) || {\r\n success: false,\r\n error: null,\r\n }\r\n );\r\n };\r\n\r\n const value: SearchBoxContextType = {\r\n searchBoxRef,\r\n getFormData,\r\n setFormData,\r\n resetForm,\r\n validateForm,\r\n };\r\n\r\n return (\r\n <SearchBoxContext.Provider value={value}>\r\n {children}\r\n </SearchBoxContext.Provider>\r\n );\r\n};\r\n\r\n// Hook\r\nexport const useSearchBox = () => {\r\n const context = useContext(SearchBoxContext);\r\n if (!context) {\r\n throw new Error('useSearchBox must be used within a SearchBoxProvider');\r\n }\r\n return context;\r\n};\r\n"],"names":["DEFAULT_SERVICE_CODES","ServiceCodeContext","createContext","ServiceCodeProvider","children","serviceCodes","useEffect","setServiceCodeOverrides","contextValue","key","defaultValue","useServiceCode","context","useContext","useServiceCodeValue","getServiceCode","useAllServiceCodes","result","useLogServiceCodeConfig","value","SearchBoxContext","SearchBoxProvider","searchBoxRef","useRef","data","jsx","useSearchBox"],"mappings":"mHAaMA,EAAwB,CAE5B,UAAW,eACX,UAAW,eACX,UAAW,eAGX,UAAW,eAGX,UAAW,cACb,EAGMC,EAAqBC,EAAAA,cAA6C,IAAI,EA0D/DC,EAAoD,CAAC,CAChE,SAAAC,EACA,aAAAC,EAAe,CAAA,CACjB,IAAM,CAEJC,EAAAA,UAAU,IAAM,CACdC,EAAAA,wBAAwBF,CAAY,CACtC,EAAG,CAACA,CAAY,CAAC,EAgBjB,MAAMG,EAAuC,CAC3C,aAAAH,EACA,eAfsBI,GAAgC,CAEtD,GAAIJ,EAAaI,CAAG,GAAKJ,EAAaI,CAAG,EAAG,KAAA,IAAW,GACrD,eAAQ,IAAI,sBAAsBA,CAAG,MAAMJ,EAAaI,CAAG,CAAC,EAAE,EACvDJ,EAAaI,CAAG,EAIzB,MAAMC,EAAeV,EAAsBS,CAAG,EAC9C,eAAQ,IAAI,cAAcA,CAAG,MAAMC,CAAY,EAAE,EAC1CA,CACT,CAIE,EAGF,+BACGT,EAAmB,SAAnB,CAA4B,MAAOO,EACjC,SAAAJ,EACH,CAEJ,EAWaO,EAAiB,IAA8B,CAC1D,MAAMC,EAAUC,EAAAA,WAAWZ,CAAkB,EAC7C,GAAI,CAACW,EACH,MAAM,IAAI,MAAM,0DAA0D,EAE5E,OAAOA,CACT,EAcaE,EAAuBL,GAAgC,CAClE,KAAM,CAAE,eAAAM,CAAA,EAAmBJ,EAAA,EAC3B,OAAOI,EAAeN,CAAG,CAC3B,EAaaO,EAAqB,IAAsC,CACtE,KAAM,CAAE,eAAAD,CAAA,EAAmBJ,EAAA,EACrBM,EAAS,CAAA,EAEf,UAAWR,KAAO,OAAO,KAAKT,CAAqB,EACjDiB,EAAOR,CAAG,EAAIM,EAAeN,CAAG,EAGlC,OAAOQ,CACT,EAYaC,EAA0B,IAAY,CACjD,KAAM,CAAE,eAAAH,CAAA,EAAmBJ,EAAA,EAE3B,QAAQ,IAAI,uBAAuB,EACnC,QAAQ,IAAI,6BAA6B,EAEzC,UAAWF,KAAO,OAAO,KAAKT,CAAqB,EAAuB,CACxE,MAAMmB,EAAQJ,EAAeN,CAAG,EAChC,QAAQ,IAAI,KAAKA,CAAG,KAAKU,CAAK,EAAE,CAClC,CACF,EChLMC,EAAmBlB,EAAAA,cAA2C,IAAI,EAQ3DmB,EAAgD,CAAC,CAAE,SAAAjB,KAAe,CAC7E,MAAMkB,EAAeC,EAAAA,OAAqB,IAAI,EAuBxCJ,EAA8B,CAClC,aAAAG,EACA,YAvBkB,IACXA,EAAa,SAAS,YAAA,GAAiB,CAAA,EAuB9C,YApBmBE,GAAc,CACjCF,EAAa,SAAS,YAAYE,CAAI,CACxC,EAmBE,UAjBgB,IAAM,CACtBF,EAAa,SAAS,UAAA,CACxB,EAgBE,aAdmB,SAEhB,MAAMA,EAAa,SAAS,gBAAmB,CAC9C,QAAS,GACT,MAAO,IAAA,CAUX,EAGF,OACEG,EAAAA,kBAAAA,IAACL,EAAiB,SAAjB,CAA0B,MAAAD,EACxB,SAAAf,CAAA,CACH,CAEJ,EAGasB,EAAe,IAAM,CAChC,MAAMd,EAAUC,EAAAA,WAAWO,CAAgB,EAC3C,GAAI,CAACR,EACH,MAAM,IAAI,MAAM,sDAAsD,EAExE,OAAOA,CACT"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { j as u } from "./jsx-runtime-Dpn_P65e.js";
|
|
2
2
|
import { useEffect as m, createContext as i, useContext as S, useRef as x } from "react";
|
|
3
|
-
import { ak as f } from "./apiUtils-
|
|
3
|
+
import { ak as f } from "./apiUtils-DSwE62oG.js";
|
|
4
4
|
const n = {
|
|
5
5
|
// 권한 관련
|
|
6
6
|
AUTH_BTNS: "SCMSIGN00202",
|
|
@@ -52,9 +52,7 @@ const n = {
|
|
|
52
52
|
const t = o(e);
|
|
53
53
|
console.log(` ${e}: ${t}`);
|
|
54
54
|
}
|
|
55
|
-
}, d = i(null), w = ({
|
|
56
|
-
children: o
|
|
57
|
-
}) => {
|
|
55
|
+
}, d = i(null), w = ({ children: o }) => {
|
|
58
56
|
const e = x(null), v = {
|
|
59
57
|
searchBoxRef: e,
|
|
60
58
|
getFormData: () => e.current?.getFormData() || {},
|
|
@@ -85,4 +83,4 @@ export {
|
|
|
85
83
|
D as e,
|
|
86
84
|
M as u
|
|
87
85
|
};
|
|
88
|
-
//# sourceMappingURL=SearchBoxContext-
|
|
86
|
+
//# sourceMappingURL=SearchBoxContext-gWM7FHIw.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SearchBoxContext-gWM7FHIw.js","sources":["../../src/provider/contexts/ServiceCodeContext.tsx","../../src/provider/contexts/SearchBoxContext.tsx"],"sourcesContent":["import { createContext, FC, ReactNode, useContext, useEffect } from 'react';\r\nimport {\r\n ServiceCodeKey,\r\n setServiceCodeOverrides,\r\n} from '../../utils/serviceConfig';\r\n\r\n// 서비스코드 설정을 위한 Context 타입\r\ninterface ServiceCodeContextType {\r\n serviceCodes: Partial<Record<ServiceCodeKey, string>>;\r\n getServiceCode: (key: ServiceCodeKey) => string;\r\n}\r\n\r\n// 기본 서비스코드 정의\r\nconst DEFAULT_SERVICE_CODES = {\r\n // 권한 관련\r\n AUTH_BTNS: 'SCMSIGN00202', // 버튼 권한 조회\r\n AUTH_MENU: 'SCMSIGN00201', // 메뉴 권한 조회\r\n SRCH_CODE: 'SCMSIGN00301', // 코드 조회\r\n\r\n // 팝업 관련\r\n SRCH_POPU: 'SCMPOPU00101', // 팝업 조회\r\n\r\n // 즐겨찾기 관련\r\n AUTH_BMRK: 'SCMBMRK00101', // 즐겨찾기 관리\r\n} as const;\r\n\r\n// Context 생성\r\nconst ServiceCodeContext = createContext<ServiceCodeContextType | null>(null);\r\n\r\n// Provider Props 타입\r\ninterface ServiceCodeProviderProps {\r\n children: ReactNode;\r\n /**\r\n * 서비스코드 오버라이드 설정\r\n * 외부 프로젝트에서 기본 서비스코드를 재정의할 수 있습니다.\r\n *\r\n * @example\r\n * ```tsx\r\n * <ServiceCodeProvider\r\n * serviceCodes={{\r\n * AUTH_BTNS: 'CUSTOM_AUTH_BTNS_CODE',\r\n * AUTH_MENU: 'CUSTOM_AUTH_MENU_CODE',\r\n * SRCH_CODE: 'CUSTOM_SRCH_CODE',\r\n * SRCH_POPU: 'CUSTOM_SRCH_POPU_CODE',\r\n * AUTH_BMRK: 'CUSTOM_AUTH_BMRK_CODE',\r\n * }}\r\n * >\r\n * {children}\r\n * </ServiceCodeProvider>\r\n * ```\r\n *\r\n * @description\r\n * - AUTH_BTNS: 버튼 권한 조회 서비스코드\r\n * - AUTH_MENU: 메뉴 권한 조회 서비스코드\r\n * - SRCH_CODE: 코드 조회 서비스코드\r\n * - SRCH_POPU: 팝업 조회 서비스코드\r\n * - AUTH_BMRK: 즐겨찾기 관리 서비스코드\r\n *\r\n * 설정하지 않은 서비스코드는 기본값을 사용합니다.\r\n */\r\n serviceCodes?: Partial<Record<ServiceCodeKey, string>>;\r\n}\r\n\r\n/**\r\n * 서비스코드 Provider 컴포넌트\r\n * 외부 프로젝트에서 서비스코드를 설정할 수 있도록 함\r\n *\r\n * @example\r\n * ```tsx\r\n * import { ServiceCodeProvider } from '@bwg/core/provider';\r\n *\r\n * function App() {\r\n * return (\r\n * <ServiceCodeProvider\r\n * serviceCodes={{\r\n * AUTH_BTNS: 'CUSTOM_AUTH_BTNS_CODE',\r\n * AUTH_MENU: 'CUSTOM_AUTH_MENU_CODE',\r\n * }}\r\n * >\r\n * <YourApp />\r\n * </ServiceCodeProvider>\r\n * );\r\n * }\r\n * ```\r\n */\r\nexport const ServiceCodeProvider: FC<ServiceCodeProviderProps> = ({\r\n children,\r\n serviceCodes = {},\r\n}) => {\r\n // serviceCodes가 변경될 때마다 serviceConfig.ts의 오버라이드를 업데이트\r\n useEffect(() => {\r\n setServiceCodeOverrides(serviceCodes);\r\n }, [serviceCodes]);\r\n\r\n // 서비스코드 가져오기 함수\r\n const getServiceCode = (key: ServiceCodeKey): string => {\r\n // 1. Provider에서 설정된 값 우선 확인\r\n if (serviceCodes[key] && serviceCodes[key]!.trim() !== '') {\r\n console.log(`🔧 Provider 설정 사용: ${key} = ${serviceCodes[key]}`);\r\n return serviceCodes[key]!;\r\n }\r\n\r\n // 2. 기본값 사용\r\n const defaultValue = DEFAULT_SERVICE_CODES[key];\r\n console.log(`🔧 기본값 사용: ${key} = ${defaultValue}`);\r\n return defaultValue;\r\n };\r\n\r\n const contextValue: ServiceCodeContextType = {\r\n serviceCodes,\r\n getServiceCode,\r\n };\r\n\r\n return (\r\n <ServiceCodeContext.Provider value={contextValue}>\r\n {children}\r\n </ServiceCodeContext.Provider>\r\n );\r\n};\r\n\r\n/**\r\n * 서비스코드 Context를 사용하는 Hook\r\n *\r\n * @example\r\n * ```tsx\r\n * const { getServiceCode, serviceCodes } = useServiceCode();\r\n * const authBtnsCode = getServiceCode('AUTH_BTNS');\r\n * ```\r\n */\r\nexport const useServiceCode = (): ServiceCodeContextType => {\r\n const context = useContext(ServiceCodeContext);\r\n if (!context) {\r\n throw new Error('useServiceCode must be used within a ServiceCodeProvider');\r\n }\r\n return context;\r\n};\r\n\r\n/**\r\n * 특정 서비스코드를 가져오는 Hook\r\n *\r\n * @param key - 서비스코드 키\r\n * @returns 실제 서비스코드 값\r\n *\r\n * @example\r\n * ```tsx\r\n * const authBtnsCode = useServiceCodeValue('AUTH_BTNS');\r\n * const authMenuCode = useServiceCodeValue('AUTH_MENU');\r\n * ```\r\n */\r\nexport const useServiceCodeValue = (key: ServiceCodeKey): string => {\r\n const { getServiceCode } = useServiceCode();\r\n return getServiceCode(key);\r\n};\r\n\r\n/**\r\n * 모든 서비스코드를 가져오는 Hook\r\n *\r\n * @returns 모든 서비스코드 객체\r\n *\r\n * @example\r\n * ```tsx\r\n * const allServiceCodes = useAllServiceCodes();\r\n * console.log(allServiceCodes.AUTH_BTNS); // 'SCMSIGN00202' 또는 커스텀 값\r\n * ```\r\n */\r\nexport const useAllServiceCodes = (): Record<ServiceCodeKey, string> => {\r\n const { getServiceCode } = useServiceCode();\r\n const result = {} as Record<ServiceCodeKey, string>;\r\n\r\n for (const key of Object.keys(DEFAULT_SERVICE_CODES) as ServiceCodeKey[]) {\r\n result[key] = getServiceCode(key);\r\n }\r\n\r\n return result;\r\n};\r\n\r\n/**\r\n * 서비스코드 설정을 로그로 출력하는 Hook\r\n * 개발 시 현재 설정된 서비스코드를 확인할 수 있습니다.\r\n *\r\n * @example\r\n * ```tsx\r\n * useLogServiceCodeConfig();\r\n * // 콘솔에 현재 설정된 모든 서비스코드가 출력됩니다.\r\n * ```\r\n */\r\nexport const useLogServiceCodeConfig = (): void => {\r\n const { getServiceCode } = useServiceCode();\r\n\r\n console.log('🔧 bwg-core 서비스코드 설정:');\r\n console.log('📋 Provider 설정 > 기본값 순서로 확인');\r\n\r\n for (const key of Object.keys(DEFAULT_SERVICE_CODES) as ServiceCodeKey[]) {\r\n const value = getServiceCode(key);\r\n console.log(` ${key}: ${value}`);\r\n }\r\n};\r\n\r\n// 타입 내보내기\r\nexport type { ServiceCodeKey };\r\n","import {\r\n createContext,\r\n FC,\r\n ReactNode,\r\n RefObject,\r\n useContext,\r\n useRef,\r\n} from 'react';\r\nimport { SearchBoxRef } from '../../components/common/SearchBox';\r\n\r\n// SearchBox Context 타입\r\ninterface SearchBoxContextType {\r\n searchBoxRef: RefObject<SearchBoxRef> | null;\r\n getFormData: () => any;\r\n setFormData: (data: any) => void;\r\n resetForm: () => void;\r\n validateForm: () => Promise<any>;\r\n}\r\n\r\n// Context 생성\r\nconst SearchBoxContext = createContext<SearchBoxContextType | null>(null);\r\n\r\n// Provider Props\r\ninterface SearchBoxProviderProps {\r\n children: ReactNode;\r\n}\r\n\r\n// Provider 컴포넌트\r\nexport const SearchBoxProvider: FC<SearchBoxProviderProps> = ({ children }) => {\r\n const searchBoxRef = useRef<SearchBoxRef>(null);\r\n\r\n const getFormData = () => {\r\n return searchBoxRef.current?.getFormData() || {};\r\n };\r\n\r\n const setFormData = (data: any) => {\r\n searchBoxRef.current?.setFormData(data);\r\n };\r\n\r\n const resetForm = () => {\r\n searchBoxRef.current?.resetForm();\r\n };\r\n\r\n const validateForm = async () => {\r\n return (\r\n (await searchBoxRef.current?.validateForm()) || {\r\n success: false,\r\n error: null,\r\n }\r\n );\r\n };\r\n\r\n const value: SearchBoxContextType = {\r\n searchBoxRef,\r\n getFormData,\r\n setFormData,\r\n resetForm,\r\n validateForm,\r\n };\r\n\r\n return (\r\n <SearchBoxContext.Provider value={value}>\r\n {children}\r\n </SearchBoxContext.Provider>\r\n );\r\n};\r\n\r\n// Hook\r\nexport const useSearchBox = () => {\r\n const context = useContext(SearchBoxContext);\r\n if (!context) {\r\n throw new Error('useSearchBox must be used within a SearchBoxProvider');\r\n }\r\n return context;\r\n};\r\n"],"names":["DEFAULT_SERVICE_CODES","ServiceCodeContext","createContext","ServiceCodeProvider","children","serviceCodes","useEffect","setServiceCodeOverrides","contextValue","key","defaultValue","useServiceCode","context","useContext","useServiceCodeValue","getServiceCode","useAllServiceCodes","result","useLogServiceCodeConfig","value","SearchBoxContext","SearchBoxProvider","searchBoxRef","useRef","data","jsx","useSearchBox"],"mappings":";;;AAaA,MAAMA,IAAwB;AAAA;AAAA,EAE5B,WAAW;AAAA;AAAA,EACX,WAAW;AAAA;AAAA,EACX,WAAW;AAAA;AAAA;AAAA,EAGX,WAAW;AAAA;AAAA;AAAA,EAGX,WAAW;AAAA;AACb,GAGMC,IAAqBC,EAA6C,IAAI,GA0D/DC,IAAoD,CAAC;AAAA,EAChE,UAAAC;AAAA,EACA,cAAAC,IAAe,CAAA;AACjB,MAAM;AAEJ,EAAAC,EAAU,MAAM;AACd,IAAAC,EAAwBF,CAAY;AAAA,EACtC,GAAG,CAACA,CAAY,CAAC;AAgBjB,QAAMG,IAAuC;AAAA,IAC3C,cAAAH;AAAA,IACA,gBAfqB,CAACI,MAAgC;AAEtD,UAAIJ,EAAaI,CAAG,KAAKJ,EAAaI,CAAG,EAAG,KAAA,MAAW;AACrD,uBAAQ,IAAI,sBAAsBA,CAAG,MAAMJ,EAAaI,CAAG,CAAC,EAAE,GACvDJ,EAAaI,CAAG;AAIzB,YAAMC,IAAeV,EAAsBS,CAAG;AAC9C,qBAAQ,IAAI,cAAcA,CAAG,MAAMC,CAAY,EAAE,GAC1CA;AAAA,IACT;AAAA,EAIE;AAGF,+BACGT,EAAmB,UAAnB,EAA4B,OAAOO,GACjC,UAAAJ,GACH;AAEJ,GAWaO,IAAiB,MAA8B;AAC1D,QAAMC,IAAUC,EAAWZ,CAAkB;AAC7C,MAAI,CAACW;AACH,UAAM,IAAI,MAAM,0DAA0D;AAE5E,SAAOA;AACT,GAcaE,IAAsB,CAACL,MAAgC;AAClE,QAAM,EAAE,gBAAAM,EAAA,IAAmBJ,EAAA;AAC3B,SAAOI,EAAeN,CAAG;AAC3B,GAaaO,IAAqB,MAAsC;AACtE,QAAM,EAAE,gBAAAD,EAAA,IAAmBJ,EAAA,GACrBM,IAAS,CAAA;AAEf,aAAWR,KAAO,OAAO,KAAKT,CAAqB;AACjD,IAAAiB,EAAOR,CAAG,IAAIM,EAAeN,CAAG;AAGlC,SAAOQ;AACT,GAYaC,IAA0B,MAAY;AACjD,QAAM,EAAE,gBAAAH,EAAA,IAAmBJ,EAAA;AAE3B,UAAQ,IAAI,uBAAuB,GACnC,QAAQ,IAAI,6BAA6B;AAEzC,aAAWF,KAAO,OAAO,KAAKT,CAAqB,GAAuB;AACxE,UAAMmB,IAAQJ,EAAeN,CAAG;AAChC,YAAQ,IAAI,KAAKA,CAAG,KAAKU,CAAK,EAAE;AAAA,EAClC;AACF,GChLMC,IAAmBlB,EAA2C,IAAI,GAQ3DmB,IAAgD,CAAC,EAAE,UAAAjB,QAAe;AAC7E,QAAMkB,IAAeC,EAAqB,IAAI,GAuBxCJ,IAA8B;AAAA,IAClC,cAAAG;AAAA,IACA,aAvBkB,MACXA,EAAa,SAAS,YAAA,KAAiB,CAAA;AAAA,IAuB9C,aApBkB,CAACE,MAAc;AACjC,MAAAF,EAAa,SAAS,YAAYE,CAAI;AAAA,IACxC;AAAA,IAmBE,WAjBgB,MAAM;AACtB,MAAAF,EAAa,SAAS,UAAA;AAAA,IACxB;AAAA,IAgBE,cAdmB,YAEhB,MAAMA,EAAa,SAAS,kBAAmB;AAAA,MAC9C,SAAS;AAAA,MACT,OAAO;AAAA,IAAA;AAAA,EAUX;AAGF,SACEG,gBAAAA,EAAAA,IAACL,EAAiB,UAAjB,EAA0B,OAAAD,GACxB,UAAAf,EAAA,CACH;AAEJ,GAGasB,IAAe,MAAM;AAChC,QAAMd,IAAUC,EAAWO,CAAgB;AAC3C,MAAI,CAACR;AACH,UAAM,IAAI,MAAM,sDAAsD;AAExE,SAAOA;AACT;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ViewContainer-Bhq22_B3.cjs","sources":["../../src/components/layout/ErrorBound.tsx","../../src/components/layout/PrivateProtectedOverlay.tsx","../../src/components/layout/ProgressOverlay.tsx","../../src/components/layout/ProtectLayout.tsx","../../src/components/layout/PublicLayout.tsx","../../src/components/layout/ViewContainer.tsx"],"sourcesContent":["import React, { Component, ErrorInfo, ReactNode } from 'react';\r\nimport { Result, Button } from 'antd';\r\nimport { ReloadOutlined, HomeOutlined } from '@ant-design/icons';\r\nimport { useNavigate } from 'react-router-dom';\r\n\r\ninterface Props {\r\n children: ReactNode;\r\n fallback?: ReactNode;\r\n}\r\n\r\ninterface State {\r\n hasError: boolean;\r\n error?: Error;\r\n errorInfo?: ErrorInfo;\r\n}\r\n\r\n// 에러 페이지 컴포넌트\r\nexport const ErrorPage: React.FC<{\r\n error?: Error;\r\n resetError?: () => void;\r\n onGoHome?: () => void;\r\n}> = ({ error, resetError, onGoHome }) => {\r\n const navigate = useNavigate();\r\n\r\n const handleGoHome = () => {\r\n if (onGoHome) {\r\n onGoHome();\r\n } else {\r\n // 기본 홈 이동 로직\r\n navigate('/');\r\n }\r\n };\r\n\r\n return (\r\n <div\r\n style={{\r\n padding: '40px 20px',\r\n textAlign: 'center',\r\n backgroundColor: '#fafafa',\r\n minHeight: '400px',\r\n display: 'flex',\r\n flexDirection: 'column',\r\n justifyContent: 'center',\r\n alignItems: 'center',\r\n }}\r\n >\r\n <Result\r\n status=\"error\"\r\n title=\"컴포넌트 로딩 중 오류가 발생했습니다\"\r\n subTitle={\r\n error\r\n ? `오류 내용: ${error.message}`\r\n : '알 수 없는 오류가 발생했습니다'\r\n }\r\n extra={[\r\n <Button\r\n key=\"retry\"\r\n type=\"primary\"\r\n icon={<ReloadOutlined />}\r\n onClick={resetError}\r\n style={{ marginRight: 8 }}\r\n >\r\n 다시 시도\r\n </Button>,\r\n <Button key=\"home\" icon={<HomeOutlined />} onClick={handleGoHome}>\r\n 홈으로\r\n </Button>,\r\n ]}\r\n />\r\n {error && (\r\n <details\r\n style={{\r\n marginTop: '20px',\r\n textAlign: 'left',\r\n maxWidth: '600px',\r\n backgroundColor: '#fff',\r\n padding: '16px',\r\n borderRadius: '6px',\r\n border: '1px solid #d9d9d9',\r\n }}\r\n >\r\n <summary style={{ cursor: 'pointer', fontWeight: 'bold' }}>\r\n 오류 상세 정보\r\n </summary>\r\n <pre\r\n style={{\r\n marginTop: '8px',\r\n fontSize: '12px',\r\n color: '#666',\r\n whiteSpace: 'pre-wrap',\r\n wordBreak: 'break-word',\r\n }}\r\n >\r\n {error.stack}\r\n </pre>\r\n </details>\r\n )}\r\n </div>\r\n );\r\n};\r\n\r\n// 에러 경계 클래스 컴포넌트\r\nexport class ErrorBound extends Component<Props, State> {\r\n constructor(props: Props) {\r\n super(props);\r\n this.state = { hasError: false };\r\n }\r\n\r\n static getDerivedStateFromError(error: Error): State {\r\n return { hasError: true, error };\r\n }\r\n\r\n componentDidCatch(error: Error, errorInfo: ErrorInfo) {\r\n console.error('ErrorBound caught an error:', error, errorInfo);\r\n this.setState({\r\n error,\r\n errorInfo,\r\n });\r\n }\r\n\r\n resetError = () => {\r\n this.setState({ hasError: false, error: undefined, errorInfo: undefined });\r\n };\r\n\r\n render() {\r\n if (this.state.hasError) {\r\n if (this.props.fallback) {\r\n return this.props.fallback;\r\n }\r\n\r\n return (\r\n <div\r\n style={{\r\n padding: '40px 20px',\r\n textAlign: 'center',\r\n backgroundColor: '#fafafa',\r\n display: 'flex',\r\n flexDirection: 'column',\r\n justifyContent: 'center',\r\n alignItems: 'center',\r\n }}\r\n >\r\n <Result\r\n status=\"error\"\r\n title=\"컴포넌트 로딩 중 오류가 발생했습니다\"\r\n subTitle={\r\n this.state.error\r\n ? `오류 내용: ${this.state.error.message}`\r\n : '알 수 없는 오류가 발생했습니다'\r\n }\r\n extra={[\r\n <Button\r\n key=\"retry\"\r\n type=\"primary\"\r\n icon={<ReloadOutlined />}\r\n onClick={this.resetError}\r\n style={{ marginRight: 8 }}\r\n >\r\n 다시 시도\r\n </Button>,\r\n ]}\r\n />\r\n {this.state.error && (\r\n <details\r\n style={{\r\n marginTop: '20px',\r\n textAlign: 'left',\r\n maxWidth: '600px',\r\n backgroundColor: '#fff',\r\n padding: '16px',\r\n borderRadius: '6px',\r\n border: '1px solid #d9d9d9',\r\n }}\r\n >\r\n <summary style={{ cursor: 'pointer', fontWeight: 'bold' }}>\r\n 오류 상세 정보\r\n </summary>\r\n <pre\r\n style={{\r\n marginTop: '8px',\r\n fontSize: '12px',\r\n color: '#666',\r\n whiteSpace: 'pre-wrap',\r\n wordBreak: 'break-word',\r\n }}\r\n >\r\n {this.state.error.stack}\r\n </pre>\r\n </details>\r\n )}\r\n </div>\r\n );\r\n }\r\n\r\n return this.props.children;\r\n }\r\n}\r\n\r\n// 함수형 컴포넌트용 에러 경계 훅\r\nexport const useErrorHandler = () => {\r\n const [error, setError] = React.useState<Error | null>(null);\r\n\r\n const handleError = React.useCallback((error: Error) => {\r\n console.error('useErrorHandler caught an error:', error);\r\n setError(error);\r\n }, []);\r\n\r\n const resetError = React.useCallback(() => {\r\n setError(null);\r\n }, []);\r\n\r\n return { error, handleError, resetError };\r\n};\r\n","import { ScreenProtectProvider, useLock } from \"@/provider/contexts/ScreenProtectContext\";\r\nimport { useCallback, useEffect, useRef, useState } from \"react\";\r\n\r\n// ──────────────────────────────────────────────\r\n// 공통 스타일 유틸\r\n// ──────────────────────────────────────────────\r\nconst createTabStyle = (isActive: boolean) => ({\r\n position: 'absolute' as const,\r\n inset: 0,\r\n visibility: isActive ? ('visible' as const) : ('hidden' as const),\r\n opacity: isActive ? 1 : 0,\r\n transition: 'opacity 0.2s ease-in-out',\r\n pointerEvents: isActive ? ('auto' as const) : ('none' as const),\r\n });\r\n\r\n// ──────────────────────────────────────────────\r\n// AutoLock (활성 탭일 때 잠금 트리거)\r\n// ──────────────────────────────────────────────\r\nconst AutoLock: React.FC<{ once?: boolean }> = ({ once = true }) => {\r\n const { lock } = useLock();\r\n const called = useRef(false);\r\n useEffect(() => {\r\n if (once && called.current) return;\r\n called.current = true;\r\n lock();\r\n }, [once, lock]);\r\n return null;\r\n };\r\n\r\n// ──────────────────────────────────────────────\r\n// PrivateProtectedOverlay (개인정보 포함 화면 보호레이어)\r\n// ──────────────────────────────────────────────\r\nconst PrivateProtectedOverlay: React.FC<{\r\n isActive: boolean;\r\n flagged: boolean;\r\n tabKey: string;\r\n onUnlock: () => void;\r\n children: React.ReactNode;\r\n }> = ({ isActive, flagged, tabKey, onUnlock, children }) => {\r\n const shellRef = useRef<HTMLDivElement>(null);\r\n const [ready, setReady] = useState(false);\r\n \r\n const setShellRef = useCallback((el: HTMLDivElement | null) => {\r\n (shellRef as React.MutableRefObject<HTMLDivElement | null>).current = el;\r\n setReady(!!el);\r\n }, []);\r\n \r\n const shellStyle = createTabStyle(isActive);\r\n \r\n return (\r\n <div ref={setShellRef} style={shellStyle}>\r\n {ready ? (\r\n <ScreenProtectProvider\r\n idleMs={Number.POSITIVE_INFINITY}\r\n persistLocked={false}\r\n overlayScope=\"scoped\"\r\n overlayPosition=\"absolute\"\r\n eventTarget={shellRef.current!}\r\n overlayId={`tab-overlay-${tabKey}`}\r\n onUnlock={async () => {\r\n onUnlock();\r\n return true;\r\n }}\r\n >\r\n {isActive && flagged ? <AutoLock once /> : null}\r\n {children}\r\n </ScreenProtectProvider>\r\n ) : (\r\n children\r\n )}\r\n </div>\r\n );\r\n };\r\n\r\n export default PrivateProtectedOverlay;","import { useAuth } from \"@/provider/contexts/AuthContext\";\r\nimport { Spin } from \"antd\";\r\nimport React, { useEffect } from 'react';\r\n\r\nconst DOTLINE_STYLE_ID = 'bwg-dot-line-wave-v4';\r\nfunction ensureDotLineWaveStylesV4() {\r\n if (typeof document === 'undefined') return;\r\n if (document.getElementById(DOTLINE_STYLE_ID)) return;\r\n\r\n const style = document.createElement('style');\r\n style.id = DOTLINE_STYLE_ID;\r\n style.textContent = `\r\n .bwg-dotline {\r\n display: inline-flex;\r\n align-items: center;\r\n gap: var(--bwg-gap, 12px);\r\n height: calc(var(--bwg-size, 12px) + 2 * var(--bwg-amp, 12px));\r\n line-height: 0;\r\n }\r\n .bwg-dotline .dot {\r\n width: var(--bwg-size, 12px);\r\n height: var(--bwg-size, 12px);\r\n border-radius: 50%;\r\n background: currentColor;\r\n will-change: transform, opacity;\r\n filter: drop-shadow(0 1px 2px rgba(0,0,0,.12));\r\n animation: bwg-dotline-sine var(--bwg-speed, 780ms) linear infinite;\r\n }\r\n\r\n /* sin(θ) 근사: 0, 45, 90, 135, 180, 225, 270, 315, 360deg */\r\n @keyframes bwg-dotline-sine {\r\n 0% { transform: translate3d(0, 0, 0) scale(.98); opacity: .80; }\r\n 12.5%{ transform: translate3d(0, calc(-0.7071 * var(--bwg-amp, 12px)), 0) scale(1.03); opacity: .92; }\r\n 25% { transform: translate3d(0, calc(-1 * var(--bwg-amp, 12px)), 0) scale(1.06); opacity: 1; }\r\n 37.5%{ transform: translate3d(0, calc(-0.7071 * var(--bwg-amp, 12px)), 0) scale(1.03); opacity: .92; }\r\n 50% { transform: translate3d(0, 0, 0) scale(.98); opacity: .80; }\r\n 62.5%{ transform: translate3d(0, calc( 0.7071 * var(--bwg-amp, 12px)), 0) scale(.97); opacity: .78; }\r\n 75% { transform: translate3d(0, calc( 1 * var(--bwg-amp, 12px)), 0) scale(.96); opacity: .76; }\r\n 87.5%{ transform: translate3d(0, calc( 0.7071 * var(--bwg-amp, 12px)), 0) scale(.97); opacity: .78; }\r\n 100% { transform: translate3d(0, 0, 0) scale(.98); opacity: .80; }\r\n }\r\n\r\n @media (prefers-reduced-motion: reduce) {\r\n .bwg-dotline .dot { animation: none; }\r\n }\r\n `;\r\n document.head.appendChild(style);\r\n}\r\n\r\n/* 직선 도트 파동 인디케이터 */\r\nconst DotLineSmoothIndicator: React.FC<{\r\n colors?: string[]; // 각 점 색\r\n count?: number; // 점 개수 (기본: colors 길이)\r\n size?: number; // 점 지름\r\n gap?: number; // 점 간격\r\n amp?: number; // 진폭(px)\r\n speedMs?: number; // 한 주기(ms)\r\n direction?: 'ltr' | 'rtl'; // 파동 진행 방향\r\n phase?: number; // 점 간 지연 비율(0~1) — 낮출수록 부드러움\r\n}> = ({\r\n colors = ['#DAD3FF', '#B3A6FF', '#9380FF', '#816BFA'],\r\n count,\r\n size = 12,\r\n gap = 10,\r\n amp = 16,\r\n speedMs = 900,\r\n direction = 'ltr',\r\n phase = 0.7,\r\n}) => {\r\n useEffect(() => { ensureDotLineWaveStylesV4(); }, []);\r\n\r\n const n = count ?? colors.length;\r\n const dots = Array.from({ length: n });\r\n const baseStyle = {\r\n ['--bwg-size' as any]: `${size}px`,\r\n ['--bwg-gap' as any]: `${gap}px`,\r\n ['--bwg-amp' as any]: `${amp}px`,\r\n ['--bwg-speed' as any]: `${speedMs}ms`,\r\n } as React.CSSProperties;\r\n\r\n const perDotDelay = (speedMs / n) * phase;\r\n\r\n return (\r\n <span className=\"bwg-dotline\" role=\"img\" aria-label=\"loading\" style={baseStyle}>\r\n {dots.map((_, i) => (\r\n <span\r\n key={i}\r\n className=\"dot\"\r\n style={{\r\n backgroundColor: colors[i % colors.length],\r\n animationDelay:\r\n direction === 'ltr'\r\n ? `${(i * perDotDelay)}ms`\r\n : `${((n - 1 - i) * perDotDelay)}ms`,\r\n }}\r\n />\r\n ))}\r\n </span>\r\n );\r\n};\r\n\r\n\r\n/**\r\n * 진행 중 표시\r\n * @returns ProgressOverlay\r\n */\r\nconst ProgressOverlay: React.FC<{spin?: boolean | null; text?: string }> = ({spin = null, text = '인증중...',}) => {\r\n const { busy } = useAuth();\r\n const show = (spin ?? busy);\r\n if (!show) return null;\r\n return (\r\n <div\r\n style={{\r\n position: \"fixed\",\r\n height: \"100vh\",\r\n left: 0,\r\n right: 0,\r\n top: 0,\r\n display: \"flex\",\r\n flexDirection:'column',\r\n justifyContent: \"center\",\r\n alignItems: \"center\",\r\n gap: 8,\r\n padding: \"8px 12px\",\r\n background: \"rgba(0,0,0,0.6)\",\r\n color: \"#fff\",\r\n zIndex: 10000,\r\n }}\r\n aria-live=\"polite\"\r\n aria-busy=\"true\"\r\n role=\"status\"\r\n >\r\n <Spin\r\n indicator={\r\n <DotLineSmoothIndicator\r\n colors={['#DAD3FF', '#B3A6FF', '#9380FF', '#816BFA']}\r\n size={12}\r\n gap={10}\r\n amp={16}\r\n speedMs={900}\r\n phase={0.75} \r\n direction=\"ltr\"\r\n />\r\n }\r\n />\r\n <span className=\"bwg-spin-txt\" style={{marginTop:\"15px\"}}>{text}</span>\r\n </div>\r\n );\r\n };\r\n\r\nexport default ProgressOverlay;","import { useAuth } from \"@/provider/contexts/AuthContext\";\r\nimport { ScreenProtectProvider } from \"@/provider/contexts/ScreenProtectContext\";\r\nimport { isLocal } from \"@/utils/envUtils\";\r\nimport { ConfigProvider } from \"antd\";\r\nimport { Outlet } from \"react-router-dom\";\r\nimport ProgressOverlay from \"./ProgressOverlay\";\r\n\r\n/**\r\n * 보호 레이아웃\r\n * @returns ProtectedLayout\r\n */\r\nconst ProtectedLayout = () => {\r\n const { reauthWithPin } = useAuth();\r\n // NOTE: 인증 여부 체크는 각 페이지(/main)의 스토어 가드에 위임합니다.\r\n // 필요하다면 여기서도 RequireAuth로 감싸세요.\r\n return (\r\n <ScreenProtectProvider idleMs={30 * 60_000} onUnlock={async (pin) => {\r\n if(isLocal) {\r\n // 로컬에서는 항상 true\r\n return true;\r\n }\r\n return !!pin && (await reauthWithPin(pin));\r\n }}>\r\n {/* Ensure AntD portals mount inside protected shell if you need it */}\r\n <ConfigProvider getPopupContainer={() => document.getElementById(\"app-shell\") || document.body}>\r\n <div id=\"app-shell\">\r\n <ProgressOverlay />\r\n <Outlet />\r\n </div>\r\n </ConfigProvider>\r\n </ScreenProtectProvider>\r\n );\r\n }\r\n\r\n export default ProtectedLayout;","import { Outlet } from \"react-router-dom\";\r\nimport ProgressOverlay from \"./ProgressOverlay\";\r\n\r\n/**\r\n * 공개 레이아웃\r\n * @returns PublicLayout\r\n */\r\nconst PublicLayout = () => {\r\n return (\r\n <div>\r\n <ProgressOverlay />\r\n <Outlet />\r\n </div>\r\n );\r\n}\r\n\r\nexport default PublicLayout;","import { CloseOutlined, ExclamationCircleTwoTone } from \"@ant-design/icons\";\r\nimport { Button, Result, Space, Typography } from \"antd\";\r\nimport React, { memo, Suspense } from \"react\";\r\nimport { useMenuViewStore } from \"../../stores/menuViewStore\";\r\nimport { ErrorBound } from \"./ErrorBound\";\r\n\r\nconst ViewContainer = ({\r\n isActive,\r\n instance,\r\n params,\r\n }: {\r\n isActive: boolean;\r\n instance?: React.ComponentType;\r\n params?: Record<string, any>;\r\n }) => {\r\n const { activeMenuId, closeTab } = useMenuViewStore();\r\n\r\n // 현재 활성 탭 닫기 핸들러\r\n const onClose = () => {\r\n if (activeMenuId) {\r\n closeTab(activeMenuId);\r\n }\r\n };\r\n\r\n if(instance) {\r\n return (\r\n <div\r\n style={{\r\n position: 'absolute',\r\n top: 0,\r\n left: 0,\r\n width: '100%',\r\n height: '100%',\r\n visibility: isActive ? 'visible' : 'hidden',\r\n opacity: isActive ? 1 : 0,\r\n transition: 'opacity 0.2s ease-in-out',\r\n pointerEvents: isActive ? 'auto' : 'none',\r\n }}\r\n >\r\n <ErrorBound>\r\n <Suspense fallback={null}>\r\n {instance && React.createElement(instance, { params } as any)}\r\n </Suspense>\r\n </ErrorBound>\r\n </div>\r\n );\r\n } else {\r\n return (\r\n <div\r\n style={{\r\n position: 'absolute',\r\n top: 0,\r\n left: 0,\r\n width: '100%',\r\n height: '100%',\r\n display: 'flex',\r\n justifyContent: 'center',\r\n alignItems: 'center',\r\n visibility: isActive ? 'visible' : 'hidden',\r\n opacity: isActive ? 1 : 0,\r\n transition: 'opacity 0.2s ease-in-out',\r\n pointerEvents: isActive ? 'auto' : 'none',\r\n }}\r\n >\r\n <div\r\n style={{\r\n width: 500,\r\n maxWidth: '90%',\r\n background: '#fff',\r\n borderRadius: 16,\r\n boxShadow: '0 8px 30px rgba(0,0,0,0.05)',\r\n padding: 24,\r\n }}\r\n >\r\n <Result\r\n icon={<ExclamationCircleTwoTone twoToneColor=\"#69b1ff\" />}\r\n status=\"warning\"\r\n title=\"등록된 메뉴 정보가 없거나 유효한 메뉴가 아닙니다.\"\r\n subTitle={\r\n <Typography.Text type=\"secondary\">\r\n 자세한 내용은 관리자에게 문의바랍니다.\r\n </Typography.Text>\r\n }\r\n extra={\r\n <Space>\r\n <Button icon={<CloseOutlined />} onClick={onClose}>\r\n 탭 닫기\r\n </Button>\r\n </Space>\r\n }\r\n />\r\n </div>\r\n </div>\r\n );\r\n }\r\n};\r\n\r\nexport default memo(ViewContainer);"],"names":["ErrorBound","Component","props","error","errorInfo","jsxs","jsx","Result","Button","ReloadOutlined","createTabStyle","isActive","AutoLock","once","lock","useLock","called","useRef","useEffect","PrivateProtectedOverlay","flagged","tabKey","onUnlock","children","shellRef","ready","setReady","useState","setShellRef","useCallback","el","shellStyle","ScreenProtectProvider","DOTLINE_STYLE_ID","ensureDotLineWaveStylesV4","style","DotLineSmoothIndicator","colors","count","size","gap","amp","speedMs","direction","phase","n","dots","baseStyle","perDotDelay","_","i","ProgressOverlay","spin","text","busy","useAuth","Spin","ProtectedLayout","reauthWithPin","pin","isLocal","ConfigProvider","Outlet","PublicLayout","ViewContainer","instance","params","activeMenuId","closeTab","useMenuViewStore","onClose","Suspense","React","ExclamationCircleTwoTone","Typography","Space","CloseOutlined","ViewContainer$1","memo"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ViewContainer-Bhq22_B3.cjs","sources":["../../src/components/layout/ErrorBound.tsx","../../src/components/layout/PrivateProtectedOverlay.tsx","../../src/components/layout/ProgressOverlay.tsx","../../src/components/layout/ProtectLayout.tsx","../../src/components/layout/PublicLayout.tsx","../../src/components/layout/ViewContainer.tsx"],"sourcesContent":["import { HomeOutlined, ReloadOutlined } from '@ant-design/icons';\r\nimport { Button, Result } from 'antd';\r\nimport {\r\n Component,\r\n ErrorInfo,\r\n FC,\r\n ReactNode,\r\n useCallback,\r\n useState,\r\n} from 'react';\r\nimport { useNavigate } from 'react-router-dom';\r\n\r\ninterface Props {\r\n children: ReactNode;\r\n fallback?: ReactNode;\r\n}\r\n\r\ninterface State {\r\n hasError: boolean;\r\n error?: Error;\r\n errorInfo?: ErrorInfo;\r\n}\r\n\r\n// 에러 페이지 컴포넌트\r\nexport const ErrorPage: FC<{\r\n error?: Error;\r\n resetError?: () => void;\r\n onGoHome?: () => void;\r\n}> = ({ error, resetError, onGoHome }) => {\r\n const navigate = useNavigate();\r\n\r\n const handleGoHome = () => {\r\n if (onGoHome) {\r\n onGoHome();\r\n } else {\r\n // 기본 홈 이동 로직\r\n navigate('/');\r\n }\r\n };\r\n\r\n return (\r\n <div\r\n style={{\r\n padding: '40px 20px',\r\n textAlign: 'center',\r\n backgroundColor: '#fafafa',\r\n minHeight: '400px',\r\n display: 'flex',\r\n flexDirection: 'column',\r\n justifyContent: 'center',\r\n alignItems: 'center',\r\n }}\r\n >\r\n <Result\r\n status='error'\r\n title='컴포넌트 로딩 중 오류가 발생했습니다'\r\n subTitle={\r\n error\r\n ? `오류 내용: ${error.message}`\r\n : '알 수 없는 오류가 발생했습니다'\r\n }\r\n extra={[\r\n <Button\r\n key='retry'\r\n type='primary'\r\n icon={<ReloadOutlined />}\r\n onClick={resetError}\r\n style={{ marginRight: 8 }}\r\n >\r\n 다시 시도\r\n </Button>,\r\n <Button key='home' icon={<HomeOutlined />} onClick={handleGoHome}>\r\n 홈으로\r\n </Button>,\r\n ]}\r\n />\r\n {error && (\r\n <details\r\n style={{\r\n marginTop: '20px',\r\n textAlign: 'left',\r\n maxWidth: '600px',\r\n backgroundColor: '#fff',\r\n padding: '16px',\r\n borderRadius: '6px',\r\n border: '1px solid #d9d9d9',\r\n }}\r\n >\r\n <summary style={{ cursor: 'pointer', fontWeight: 'bold' }}>\r\n 오류 상세 정보\r\n </summary>\r\n <pre\r\n style={{\r\n marginTop: '8px',\r\n fontSize: '12px',\r\n color: '#666',\r\n whiteSpace: 'pre-wrap',\r\n wordBreak: 'break-word',\r\n }}\r\n >\r\n {error.stack}\r\n </pre>\r\n </details>\r\n )}\r\n </div>\r\n );\r\n};\r\n\r\n// 에러 경계 클래스 컴포넌트\r\nexport class ErrorBound extends Component<Props, State> {\r\n constructor(props: Props) {\r\n super(props);\r\n this.state = { hasError: false };\r\n }\r\n\r\n static getDerivedStateFromError(error: Error): State {\r\n return { hasError: true, error };\r\n }\r\n\r\n componentDidCatch(error: Error, errorInfo: ErrorInfo) {\r\n console.error('ErrorBound caught an error:', error, errorInfo);\r\n this.setState({\r\n error,\r\n errorInfo,\r\n });\r\n }\r\n\r\n resetError = () => {\r\n this.setState({ hasError: false, error: undefined, errorInfo: undefined });\r\n };\r\n\r\n render() {\r\n if (this.state.hasError) {\r\n if (this.props.fallback) {\r\n return this.props.fallback;\r\n }\r\n\r\n return (\r\n <div\r\n style={{\r\n padding: '40px 20px',\r\n textAlign: 'center',\r\n backgroundColor: '#fafafa',\r\n display: 'flex',\r\n flexDirection: 'column',\r\n justifyContent: 'center',\r\n alignItems: 'center',\r\n }}\r\n >\r\n <Result\r\n status='error'\r\n title='컴포넌트 로딩 중 오류가 발생했습니다'\r\n subTitle={\r\n this.state.error\r\n ? `오류 내용: ${this.state.error.message}`\r\n : '알 수 없는 오류가 발생했습니다'\r\n }\r\n extra={[\r\n <Button\r\n key='retry'\r\n type='primary'\r\n icon={<ReloadOutlined />}\r\n onClick={this.resetError}\r\n style={{ marginRight: 8 }}\r\n >\r\n 다시 시도\r\n </Button>,\r\n ]}\r\n />\r\n {this.state.error && (\r\n <details\r\n style={{\r\n marginTop: '20px',\r\n textAlign: 'left',\r\n maxWidth: '600px',\r\n backgroundColor: '#fff',\r\n padding: '16px',\r\n borderRadius: '6px',\r\n border: '1px solid #d9d9d9',\r\n }}\r\n >\r\n <summary style={{ cursor: 'pointer', fontWeight: 'bold' }}>\r\n 오류 상세 정보\r\n </summary>\r\n <pre\r\n style={{\r\n marginTop: '8px',\r\n fontSize: '12px',\r\n color: '#666',\r\n whiteSpace: 'pre-wrap',\r\n wordBreak: 'break-word',\r\n }}\r\n >\r\n {this.state.error.stack}\r\n </pre>\r\n </details>\r\n )}\r\n </div>\r\n );\r\n }\r\n\r\n return this.props.children;\r\n }\r\n}\r\n\r\n// 함수형 컴포넌트용 에러 경계 훅\r\nexport const useErrorHandler = () => {\r\n const [error, setError] = useState<Error | null>(null);\r\n\r\n const handleError = useCallback((error: Error) => {\r\n console.error('useErrorHandler caught an error:', error);\r\n setError(error);\r\n }, []);\r\n\r\n const resetError = useCallback(() => {\r\n setError(null);\r\n }, []);\r\n\r\n return { error, handleError, resetError };\r\n};\r\n","import {\r\n ScreenProtectProvider,\r\n useLock,\r\n} from '@/provider/contexts/ScreenProtectContext';\r\nimport {\r\n FC,\r\n MutableRefObject,\r\n ReactNode,\r\n useCallback,\r\n useEffect,\r\n useRef,\r\n useState,\r\n} from 'react';\r\n\r\n// ──────────────────────────────────────────────\r\n// 공통 스타일 유틸\r\n// ──────────────────────────────────────────────\r\nconst createTabStyle = (isActive: boolean) => ({\r\n position: 'absolute' as const,\r\n inset: 0,\r\n visibility: isActive ? ('visible' as const) : ('hidden' as const),\r\n opacity: isActive ? 1 : 0,\r\n transition: 'opacity 0.2s ease-in-out',\r\n pointerEvents: isActive ? ('auto' as const) : ('none' as const),\r\n});\r\n\r\n// ──────────────────────────────────────────────\r\n// AutoLock (활성 탭일 때 잠금 트리거)\r\n// ──────────────────────────────────────────────\r\nconst AutoLock: FC<{ once?: boolean }> = ({ once = true }) => {\r\n const { lock } = useLock();\r\n const called = useRef(false);\r\n useEffect(() => {\r\n if (once && called.current) return;\r\n called.current = true;\r\n lock();\r\n }, [once, lock]);\r\n return null;\r\n};\r\n\r\n// ──────────────────────────────────────────────\r\n// PrivateProtectedOverlay (개인정보 포함 화면 보호레이어)\r\n// ──────────────────────────────────────────────\r\nconst PrivateProtectedOverlay: FC<{\r\n isActive: boolean;\r\n flagged: boolean;\r\n tabKey: string;\r\n onUnlock: () => void;\r\n children: ReactNode;\r\n}> = ({ isActive, flagged, tabKey, onUnlock, children }) => {\r\n const shellRef = useRef<HTMLDivElement>(null);\r\n const [ready, setReady] = useState(false);\r\n\r\n const setShellRef = useCallback((el: HTMLDivElement | null) => {\r\n (shellRef as MutableRefObject<HTMLDivElement | null>).current = el;\r\n setReady(!!el);\r\n }, []);\r\n\r\n const shellStyle = createTabStyle(isActive);\r\n\r\n return (\r\n <div ref={setShellRef} style={shellStyle}>\r\n {ready ? (\r\n <ScreenProtectProvider\r\n idleMs={Number.POSITIVE_INFINITY}\r\n persistLocked={false}\r\n overlayScope='scoped'\r\n overlayPosition='absolute'\r\n eventTarget={shellRef.current!}\r\n overlayId={`tab-overlay-${tabKey}`}\r\n onUnlock={async () => {\r\n onUnlock();\r\n return true;\r\n }}\r\n >\r\n {isActive && flagged ? <AutoLock once /> : null}\r\n {children}\r\n </ScreenProtectProvider>\r\n ) : (\r\n children\r\n )}\r\n </div>\r\n );\r\n};\r\n\r\nexport default PrivateProtectedOverlay;\r\n","import { useAuth } from \"@/provider/contexts/AuthContext\";\r\nimport { Spin } from \"antd\";\r\nimport { CSSProperties, FC, useEffect } from 'react';\r\n\r\nconst DOTLINE_STYLE_ID = 'bwg-dot-line-wave-v4';\r\nfunction ensureDotLineWaveStylesV4() {\r\n if (typeof document === 'undefined') return;\r\n if (document.getElementById(DOTLINE_STYLE_ID)) return;\r\n\r\n const style = document.createElement('style');\r\n style.id = DOTLINE_STYLE_ID;\r\n style.textContent = `\r\n .bwg-dotline {\r\n display: inline-flex;\r\n align-items: center;\r\n gap: var(--bwg-gap, 12px);\r\n height: calc(var(--bwg-size, 12px) + 2 * var(--bwg-amp, 12px));\r\n line-height: 0;\r\n }\r\n .bwg-dotline .dot {\r\n width: var(--bwg-size, 12px);\r\n height: var(--bwg-size, 12px);\r\n border-radius: 50%;\r\n background: currentColor;\r\n will-change: transform, opacity;\r\n filter: drop-shadow(0 1px 2px rgba(0,0,0,.12));\r\n animation: bwg-dotline-sine var(--bwg-speed, 780ms) linear infinite;\r\n }\r\n\r\n /* sin(θ) 근사: 0, 45, 90, 135, 180, 225, 270, 315, 360deg */\r\n @keyframes bwg-dotline-sine {\r\n 0% { transform: translate3d(0, 0, 0) scale(.98); opacity: .80; }\r\n 12.5%{ transform: translate3d(0, calc(-0.7071 * var(--bwg-amp, 12px)), 0) scale(1.03); opacity: .92; }\r\n 25% { transform: translate3d(0, calc(-1 * var(--bwg-amp, 12px)), 0) scale(1.06); opacity: 1; }\r\n 37.5%{ transform: translate3d(0, calc(-0.7071 * var(--bwg-amp, 12px)), 0) scale(1.03); opacity: .92; }\r\n 50% { transform: translate3d(0, 0, 0) scale(.98); opacity: .80; }\r\n 62.5%{ transform: translate3d(0, calc( 0.7071 * var(--bwg-amp, 12px)), 0) scale(.97); opacity: .78; }\r\n 75% { transform: translate3d(0, calc( 1 * var(--bwg-amp, 12px)), 0) scale(.96); opacity: .76; }\r\n 87.5%{ transform: translate3d(0, calc( 0.7071 * var(--bwg-amp, 12px)), 0) scale(.97); opacity: .78; }\r\n 100% { transform: translate3d(0, 0, 0) scale(.98); opacity: .80; }\r\n }\r\n\r\n @media (prefers-reduced-motion: reduce) {\r\n .bwg-dotline .dot { animation: none; }\r\n }\r\n `;\r\n document.head.appendChild(style);\r\n}\r\n\r\n/* 직선 도트 파동 인디케이터 */\r\nconst DotLineSmoothIndicator: FC<{\r\n colors?: string[]; // 각 점 색\r\n count?: number; // 점 개수 (기본: colors 길이)\r\n size?: number; // 점 지름\r\n gap?: number; // 점 간격\r\n amp?: number; // 진폭(px)\r\n speedMs?: number; // 한 주기(ms)\r\n direction?: 'ltr' | 'rtl'; // 파동 진행 방향\r\n phase?: number; // 점 간 지연 비율(0~1) — 낮출수록 부드러움\r\n}> = ({\r\n colors = ['#DAD3FF', '#B3A6FF', '#9380FF', '#816BFA'],\r\n count,\r\n size = 12,\r\n gap = 10,\r\n amp = 16,\r\n speedMs = 900,\r\n direction = 'ltr',\r\n phase = 0.7,\r\n}) => {\r\n useEffect(() => {\r\n ensureDotLineWaveStylesV4();\r\n }, []);\r\n\r\n const n = count ?? colors.length;\r\n const dots = Array.from({ length: n });\r\n const baseStyle = {\r\n ['--bwg-size' as any]: `${size}px`,\r\n ['--bwg-gap' as any]: `${gap}px`,\r\n ['--bwg-amp' as any]: `${amp}px`,\r\n ['--bwg-speed' as any]: `${speedMs}ms`,\r\n } as CSSProperties;\r\n\r\n const perDotDelay = (speedMs / n) * phase;\r\n\r\n return (\r\n <span\r\n className='bwg-dotline'\r\n role='img'\r\n aria-label='loading'\r\n style={baseStyle}\r\n >\r\n {dots.map((_, i) => (\r\n <span\r\n key={i}\r\n className='dot'\r\n style={{\r\n backgroundColor: colors[i % colors.length],\r\n animationDelay:\r\n direction === 'ltr'\r\n ? `${i * perDotDelay}ms`\r\n : `${(n - 1 - i) * perDotDelay}ms`,\r\n }}\r\n />\r\n ))}\r\n </span>\r\n );\r\n};\r\n\r\n/**\r\n * 진행 중 표시\r\n * @returns ProgressOverlay\r\n */\r\nconst ProgressOverlay: FC<{ spin?: boolean | null; text?: string }> = ({\r\n spin = null,\r\n text = '인증중...',\r\n}) => {\r\n const { busy } = useAuth();\r\n const show = spin ?? busy;\r\n if (!show) return null;\r\n return (\r\n <div\r\n style={{\r\n position: 'fixed',\r\n height: '100vh',\r\n left: 0,\r\n right: 0,\r\n top: 0,\r\n display: 'flex',\r\n flexDirection: 'column',\r\n justifyContent: 'center',\r\n alignItems: 'center',\r\n gap: 8,\r\n padding: '8px 12px',\r\n background: 'rgba(0,0,0,0.6)',\r\n color: '#fff',\r\n zIndex: 10000,\r\n }}\r\n aria-live='polite'\r\n aria-busy='true'\r\n role='status'\r\n >\r\n <Spin\r\n indicator={\r\n <DotLineSmoothIndicator\r\n colors={['#DAD3FF', '#B3A6FF', '#9380FF', '#816BFA']}\r\n size={12}\r\n gap={10}\r\n amp={16}\r\n speedMs={900}\r\n phase={0.75}\r\n direction='ltr'\r\n />\r\n }\r\n />\r\n <span className='bwg-spin-txt' style={{ marginTop: '15px' }}>\r\n {text}\r\n </span>\r\n </div>\r\n );\r\n};\r\n\r\nexport default ProgressOverlay;","import { useAuth } from \"@/provider/contexts/AuthContext\";\r\nimport { ScreenProtectProvider } from \"@/provider/contexts/ScreenProtectContext\";\r\nimport { isLocal } from \"@/utils/envUtils\";\r\nimport { ConfigProvider } from \"antd\";\r\nimport { Outlet } from \"react-router-dom\";\r\nimport ProgressOverlay from \"./ProgressOverlay\";\r\n\r\n/**\r\n * 보호 레이아웃\r\n * @returns ProtectedLayout\r\n */\r\nconst ProtectedLayout = () => {\r\n const { reauthWithPin } = useAuth();\r\n // NOTE: 인증 여부 체크는 각 페이지(/main)의 스토어 가드에 위임합니다.\r\n // 필요하다면 여기서도 RequireAuth로 감싸세요.\r\n return (\r\n <ScreenProtectProvider idleMs={30 * 60_000} onUnlock={async (pin) => {\r\n if(isLocal) {\r\n // 로컬에서는 항상 true\r\n return true;\r\n }\r\n return !!pin && (await reauthWithPin(pin));\r\n }}>\r\n {/* Ensure AntD portals mount inside protected shell if you need it */}\r\n <ConfigProvider getPopupContainer={() => document.getElementById(\"app-shell\") || document.body}>\r\n <div id=\"app-shell\">\r\n <ProgressOverlay />\r\n <Outlet />\r\n </div>\r\n </ConfigProvider>\r\n </ScreenProtectProvider>\r\n );\r\n }\r\n\r\n export default ProtectedLayout;","import { Outlet } from \"react-router-dom\";\r\nimport ProgressOverlay from \"./ProgressOverlay\";\r\n\r\n/**\r\n * 공개 레이아웃\r\n * @returns PublicLayout\r\n */\r\nconst PublicLayout = () => {\r\n return (\r\n <div>\r\n <ProgressOverlay />\r\n <Outlet />\r\n </div>\r\n );\r\n}\r\n\r\nexport default PublicLayout;","import { CloseOutlined, ExclamationCircleTwoTone } from \"@ant-design/icons\";\r\nimport { Button, Result, Space, Typography } from \"antd\";\r\nimport { ComponentType, createElement, memo, Suspense } from 'react';\r\nimport { useMenuViewStore } from '../../stores/menuViewStore';\r\nimport { ErrorBound } from './ErrorBound';\r\n\r\nconst ViewContainer = ({\r\n isActive,\r\n instance,\r\n params,\r\n}: {\r\n isActive: boolean;\r\n instance?: ComponentType;\r\n params?: Record<string, any>;\r\n}) => {\r\n const { activeMenuId, closeTab } = useMenuViewStore();\r\n\r\n // 현재 활성 탭 닫기 핸들러\r\n const onClose = () => {\r\n if (activeMenuId) {\r\n closeTab(activeMenuId);\r\n }\r\n };\r\n\r\n if (instance) {\r\n return (\r\n <div\r\n style={{\r\n position: 'absolute',\r\n top: 0,\r\n left: 0,\r\n width: '100%',\r\n height: '100%',\r\n visibility: isActive ? 'visible' : 'hidden',\r\n opacity: isActive ? 1 : 0,\r\n transition: 'opacity 0.2s ease-in-out',\r\n pointerEvents: isActive ? 'auto' : 'none',\r\n }}\r\n >\r\n <ErrorBound>\r\n <Suspense fallback={null}>\r\n {instance && createElement(instance, { params } as any)}\r\n </Suspense>\r\n </ErrorBound>\r\n </div>\r\n );\r\n } else {\r\n return (\r\n <div\r\n style={{\r\n position: 'absolute',\r\n top: 0,\r\n left: 0,\r\n width: '100%',\r\n height: '100%',\r\n display: 'flex',\r\n justifyContent: 'center',\r\n alignItems: 'center',\r\n visibility: isActive ? 'visible' : 'hidden',\r\n opacity: isActive ? 1 : 0,\r\n transition: 'opacity 0.2s ease-in-out',\r\n pointerEvents: isActive ? 'auto' : 'none',\r\n }}\r\n >\r\n <div\r\n style={{\r\n width: 500,\r\n maxWidth: '90%',\r\n background: '#fff',\r\n borderRadius: 16,\r\n boxShadow: '0 8px 30px rgba(0,0,0,0.05)',\r\n padding: 24,\r\n }}\r\n >\r\n <Result\r\n icon={<ExclamationCircleTwoTone twoToneColor='#69b1ff' />}\r\n status='warning'\r\n title='등록된 메뉴 정보가 없거나 유효한 메뉴가 아닙니다.'\r\n subTitle={\r\n <Typography.Text type='secondary'>\r\n 자세한 내용은 관리자에게 문의바랍니다.\r\n </Typography.Text>\r\n }\r\n extra={\r\n <Space>\r\n <Button icon={<CloseOutlined />} onClick={onClose}>\r\n 탭 닫기\r\n </Button>\r\n </Space>\r\n }\r\n />\r\n </div>\r\n </div>\r\n );\r\n }\r\n};\r\n\r\nexport default memo(ViewContainer);"],"names":["ErrorBound","Component","props","error","errorInfo","jsxs","jsx","Result","Button","ReloadOutlined","createTabStyle","isActive","AutoLock","once","lock","useLock","called","useRef","useEffect","PrivateProtectedOverlay","flagged","tabKey","onUnlock","children","shellRef","ready","setReady","useState","setShellRef","useCallback","el","shellStyle","ScreenProtectProvider","DOTLINE_STYLE_ID","ensureDotLineWaveStylesV4","style","DotLineSmoothIndicator","colors","count","size","gap","amp","speedMs","direction","phase","n","dots","baseStyle","perDotDelay","_","i","ProgressOverlay","spin","text","busy","useAuth","Spin","ProtectedLayout","reauthWithPin","pin","isLocal","ConfigProvider","Outlet","PublicLayout","ViewContainer","instance","params","activeMenuId","closeTab","useMenuViewStore","onClose","Suspense","createElement","ExclamationCircleTwoTone","Typography","Space","CloseOutlined","ViewContainer$1","memo"],"mappings":"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"}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { j as e } from "./jsx-runtime-Dpn_P65e.js";
|
|
2
2
|
import { S as m, u as E } from "./ScreenProtectContext-3my4PHFa.js";
|
|
3
|
-
import
|
|
4
|
-
import { u as y } from "./AuthContext-
|
|
5
|
-
import { a7 as D, aH as P } from "./apiUtils-
|
|
6
|
-
import { Result as b, Button as w, Spin as
|
|
3
|
+
import { Component as k, useRef as f, useState as C, useCallback as S, useEffect as g, memo as T, Suspense as F, createElement as I } from "react";
|
|
4
|
+
import { u as y } from "./AuthContext-DrEpBrpB.js";
|
|
5
|
+
import { a7 as D, aH as P } from "./apiUtils-DSwE62oG.js";
|
|
6
|
+
import { Result as b, Button as w, Spin as B, ConfigProvider as L, Space as R, Typography as $ } from "antd";
|
|
7
7
|
import { Outlet as j } from "react-router-dom";
|
|
8
8
|
import { ReloadOutlined as z, CloseOutlined as N, ExclamationCircleTwoTone as O } from "@ant-design/icons";
|
|
9
|
-
class V extends
|
|
9
|
+
class V extends k {
|
|
10
10
|
constructor(r) {
|
|
11
11
|
super(r), this.resetError = () => {
|
|
12
12
|
this.setState({ hasError: !1, error: void 0, errorInfo: void 0 });
|
|
@@ -91,22 +91,22 @@ class V extends C {
|
|
|
91
91
|
) : this.props.children;
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
|
-
const
|
|
94
|
+
const W = (t) => ({
|
|
95
95
|
position: "absolute",
|
|
96
96
|
inset: 0,
|
|
97
97
|
visibility: t ? "visible" : "hidden",
|
|
98
98
|
opacity: t ? 1 : 0,
|
|
99
99
|
transition: "opacity 0.2s ease-in-out",
|
|
100
100
|
pointerEvents: t ? "auto" : "none"
|
|
101
|
-
}),
|
|
101
|
+
}), M = ({ once: t = !0 }) => {
|
|
102
102
|
const { lock: r } = E(), s = f(!1);
|
|
103
103
|
return g(() => {
|
|
104
104
|
t && s.current || (s.current = !0, r());
|
|
105
105
|
}, [t, r]), null;
|
|
106
106
|
}, ee = ({ isActive: t, flagged: r, tabKey: s, onUnlock: a, children: o }) => {
|
|
107
|
-
const n = f(null), [d, p] =
|
|
107
|
+
const n = f(null), [d, p] = C(!1), i = S((l) => {
|
|
108
108
|
n.current = l, p(!!l);
|
|
109
|
-
}, []), u =
|
|
109
|
+
}, []), u = W(t);
|
|
110
110
|
return /* @__PURE__ */ e.jsx("div", { ref: i, style: u, children: d ? /* @__PURE__ */ e.jsxs(
|
|
111
111
|
m,
|
|
112
112
|
{
|
|
@@ -118,13 +118,13 @@ const _ = (t) => ({
|
|
|
118
118
|
overlayId: `tab-overlay-${s}`,
|
|
119
119
|
onUnlock: async () => (a(), !0),
|
|
120
120
|
children: [
|
|
121
|
-
t && r ? /* @__PURE__ */ e.jsx(
|
|
121
|
+
t && r ? /* @__PURE__ */ e.jsx(M, { once: !0 }) : null,
|
|
122
122
|
o
|
|
123
123
|
]
|
|
124
124
|
}
|
|
125
125
|
) : o });
|
|
126
126
|
}, x = "bwg-dot-line-wave-v4";
|
|
127
|
-
function
|
|
127
|
+
function _() {
|
|
128
128
|
if (typeof document > "u" || document.getElementById(x)) return;
|
|
129
129
|
const t = document.createElement("style");
|
|
130
130
|
t.id = x, t.textContent = `
|
|
@@ -174,7 +174,7 @@ const A = ({
|
|
|
174
174
|
phase: p = 0.7
|
|
175
175
|
}) => {
|
|
176
176
|
g(() => {
|
|
177
|
-
|
|
177
|
+
_();
|
|
178
178
|
}, []);
|
|
179
179
|
const i = r ?? t.length, u = Array.from({ length: i }), l = {
|
|
180
180
|
"--bwg-size": `${s}px`,
|
|
@@ -182,18 +182,30 @@ const A = ({
|
|
|
182
182
|
"--bwg-amp": `${o}px`,
|
|
183
183
|
"--bwg-speed": `${n}ms`
|
|
184
184
|
}, h = n / i * p;
|
|
185
|
-
return /* @__PURE__ */ e.jsx(
|
|
185
|
+
return /* @__PURE__ */ e.jsx(
|
|
186
186
|
"span",
|
|
187
187
|
{
|
|
188
|
-
className: "
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
188
|
+
className: "bwg-dotline",
|
|
189
|
+
role: "img",
|
|
190
|
+
"aria-label": "loading",
|
|
191
|
+
style: l,
|
|
192
|
+
children: u.map((Y, c) => /* @__PURE__ */ e.jsx(
|
|
193
|
+
"span",
|
|
194
|
+
{
|
|
195
|
+
className: "dot",
|
|
196
|
+
style: {
|
|
197
|
+
backgroundColor: t[c % t.length],
|
|
198
|
+
animationDelay: d === "ltr" ? `${c * h}ms` : `${(i - 1 - c) * h}ms`
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
c
|
|
202
|
+
))
|
|
203
|
+
}
|
|
204
|
+
);
|
|
205
|
+
}, v = ({
|
|
206
|
+
spin: t = null,
|
|
207
|
+
text: r = "인증중..."
|
|
208
|
+
}) => {
|
|
197
209
|
const { busy: s } = y();
|
|
198
210
|
return t ?? s ? /* @__PURE__ */ e.jsxs(
|
|
199
211
|
"div",
|
|
@@ -219,7 +231,7 @@ const A = ({
|
|
|
219
231
|
role: "status",
|
|
220
232
|
children: [
|
|
221
233
|
/* @__PURE__ */ e.jsx(
|
|
222
|
-
|
|
234
|
+
B,
|
|
223
235
|
{
|
|
224
236
|
indicator: /* @__PURE__ */ e.jsx(
|
|
225
237
|
A,
|
|
@@ -241,7 +253,7 @@ const A = ({
|
|
|
241
253
|
) : null;
|
|
242
254
|
}, te = () => {
|
|
243
255
|
const { reauthWithPin: t } = y();
|
|
244
|
-
return /* @__PURE__ */ e.jsx(m, { idleMs: 30 * 6e4, onUnlock: async (r) => D ? !0 : !!r && await t(r), children: /* @__PURE__ */ e.jsx(
|
|
256
|
+
return /* @__PURE__ */ e.jsx(m, { idleMs: 30 * 6e4, onUnlock: async (r) => D ? !0 : !!r && await t(r), children: /* @__PURE__ */ e.jsx(L, { getPopupContainer: () => document.getElementById("app-shell") || document.body, children: /* @__PURE__ */ e.jsxs("div", { id: "app-shell", children: [
|
|
245
257
|
/* @__PURE__ */ e.jsx(v, {}),
|
|
246
258
|
/* @__PURE__ */ e.jsx(j, {})
|
|
247
259
|
] }) }) });
|
|
@@ -270,7 +282,7 @@ const A = ({
|
|
|
270
282
|
transition: "opacity 0.2s ease-in-out",
|
|
271
283
|
pointerEvents: t ? "auto" : "none"
|
|
272
284
|
},
|
|
273
|
-
children: /* @__PURE__ */ e.jsx(V, { children: /* @__PURE__ */ e.jsx(
|
|
285
|
+
children: /* @__PURE__ */ e.jsx(V, { children: /* @__PURE__ */ e.jsx(F, { fallback: null, children: r && I(r, { params: s }) }) })
|
|
274
286
|
}
|
|
275
287
|
) : /* @__PURE__ */ e.jsx(
|
|
276
288
|
"div",
|
|
@@ -307,14 +319,14 @@ const A = ({
|
|
|
307
319
|
status: "warning",
|
|
308
320
|
title: "등록된 메뉴 정보가 없거나 유효한 메뉴가 아닙니다.",
|
|
309
321
|
subTitle: /* @__PURE__ */ e.jsx($.Text, { type: "secondary", children: "자세한 내용은 관리자에게 문의바랍니다." }),
|
|
310
|
-
extra: /* @__PURE__ */ e.jsx(
|
|
322
|
+
extra: /* @__PURE__ */ e.jsx(R, { children: /* @__PURE__ */ e.jsx(w, { icon: /* @__PURE__ */ e.jsx(N, {}), onClick: n, children: "탭 닫기" }) })
|
|
311
323
|
}
|
|
312
324
|
)
|
|
313
325
|
}
|
|
314
326
|
)
|
|
315
327
|
}
|
|
316
328
|
);
|
|
317
|
-
}, se =
|
|
329
|
+
}, se = T(U);
|
|
318
330
|
export {
|
|
319
331
|
V as E,
|
|
320
332
|
ee as P,
|
|
@@ -323,4 +335,4 @@ export {
|
|
|
323
335
|
te as b,
|
|
324
336
|
re as c
|
|
325
337
|
};
|
|
326
|
-
//# sourceMappingURL=ViewContainer-
|
|
338
|
+
//# sourceMappingURL=ViewContainer-D9SKBnrn.js.map
|