@sonhoseong/mfa-lib 1.3.8 → 1.3.10
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/components/button/ScrollTopButton.js +5 -3
- package/dist/components/error/ErrorBoundary.js +14 -4
- package/dist/components/error/NotFound.d.ts +20 -0
- package/dist/components/error/NotFound.d.ts.map +1 -0
- package/dist/components/error/NotFound.js +84 -0
- package/dist/components/error/index.d.ts +2 -0
- package/dist/components/error/index.d.ts.map +1 -1
- package/dist/components/error/index.js +1 -0
- package/dist/components/icons/Icons.d.ts +51 -0
- package/dist/components/icons/Icons.d.ts.map +1 -0
- package/dist/components/icons/Icons.js +100 -0
- package/dist/components/icons/index.d.ts +5 -0
- package/dist/components/icons/index.d.ts.map +1 -0
- package/dist/components/icons/index.js +4 -0
- package/dist/components/index.d.ts +3 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +6 -0
- package/dist/components/layout/Container.js +7 -2
- package/dist/components/loading/DeferredComponent.d.ts +19 -0
- package/dist/components/loading/DeferredComponent.d.ts.map +1 -0
- package/dist/components/loading/DeferredComponent.js +32 -0
- package/dist/components/loading/GlobalLoading.js +14 -3
- package/dist/components/loading/index.d.ts +1 -0
- package/dist/components/loading/index.d.ts.map +1 -1
- package/dist/components/loading/index.js +1 -0
- package/dist/components/logo/Logo.js +12 -3
- package/dist/components/modal/ModalContainer.js +17 -8
- package/dist/components/modal/ModalContext.js +2 -3
- package/dist/components/navigation/AppNavbar.js +21 -9
- package/dist/components/navigation/AppSidebar.css +58 -3
- package/dist/components/navigation/AppSidebar.d.ts +1 -1
- package/dist/components/navigation/AppSidebar.d.ts.map +1 -1
- package/dist/components/navigation/AppSidebar.js +58 -15
- package/dist/components/navigation/Footer.d.ts +15 -0
- package/dist/components/navigation/Footer.d.ts.map +1 -0
- package/dist/components/navigation/Footer.js +12 -0
- package/dist/components/navigation/Header.d.ts.map +1 -1
- package/dist/components/navigation/Header.js +17 -4
- package/dist/components/navigation/Lnb.d.ts +2 -7
- package/dist/components/navigation/Lnb.d.ts.map +1 -1
- package/dist/components/navigation/Lnb.js +34 -8
- package/dist/components/navigation/StickyNav.js +19 -11
- package/dist/components/navigation/index.d.ts +1 -0
- package/dist/components/navigation/index.d.ts.map +1 -1
- package/dist/components/navigation/index.js +1 -0
- package/dist/components/page/LoginPage.d.ts +4 -1
- package/dist/components/page/LoginPage.d.ts.map +1 -1
- package/dist/components/page/LoginPage.js +146 -21
- package/dist/components/remote/RemoteErrorBoundary.d.ts +28 -0
- package/dist/components/remote/RemoteErrorBoundary.d.ts.map +1 -0
- package/dist/components/remote/RemoteErrorBoundary.js +44 -0
- package/dist/components/remote/RemoteErrorFallback.d.ts +16 -0
- package/dist/components/remote/RemoteErrorFallback.d.ts.map +1 -0
- package/dist/components/remote/RemoteErrorFallback.js +76 -0
- package/dist/components/remote/index.d.ts +8 -0
- package/dist/components/remote/index.d.ts.map +1 -0
- package/dist/components/remote/index.js +5 -0
- package/dist/components/router/BrowserRouter.d.ts +13 -0
- package/dist/components/router/BrowserRouter.d.ts.map +1 -0
- package/dist/components/router/BrowserRouter.js +17 -0
- package/dist/components/router/RouteGuard.d.ts +79 -0
- package/dist/components/router/RouteGuard.d.ts.map +1 -0
- package/dist/components/router/RouteGuard.js +86 -0
- package/dist/components/router/index.d.ts +4 -0
- package/dist/components/router/index.d.ts.map +1 -0
- package/dist/components/router/index.js +2 -0
- package/dist/components/toast/ToastContainer.js +17 -6
- package/dist/components/toast/ToastContext.js +2 -3
- package/dist/hooks/index.d.ts +9 -1
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +15 -1
- package/dist/hooks/use-auth.d.ts +2 -1
- package/dist/hooks/use-auth.d.ts.map +1 -1
- package/dist/hooks/use-auth.js +19 -18
- package/dist/hooks/use-debounce.d.ts +56 -0
- package/dist/hooks/use-debounce.d.ts.map +1 -0
- package/dist/hooks/use-debounce.js +140 -0
- package/dist/hooks/use-effect-once.d.ts +77 -0
- package/dist/hooks/use-effect-once.d.ts.map +1 -0
- package/dist/hooks/use-effect-once.js +124 -0
- package/dist/hooks/use-error-notification.d.ts +1 -1
- package/dist/hooks/use-error-notification.js +1 -1
- package/dist/hooks/use-global-loading.d.ts +1 -1
- package/dist/hooks/use-global-loading.js +1 -1
- package/dist/hooks/use-initialize.d.ts +8 -1
- package/dist/hooks/use-initialize.d.ts.map +1 -1
- package/dist/hooks/use-initialize.js +126 -23
- package/dist/hooks/use-modal.d.ts +21 -5
- package/dist/hooks/use-modal.d.ts.map +1 -1
- package/dist/hooks/use-modal.js +57 -17
- package/dist/hooks/use-navigate.d.ts +1 -1
- package/dist/hooks/use-navigate.js +1 -1
- package/dist/hooks/use-network-status.d.ts +15 -0
- package/dist/hooks/use-network-status.d.ts.map +1 -0
- package/dist/hooks/use-network-status.js +49 -0
- package/dist/hooks/use-permission.d.ts +22 -0
- package/dist/hooks/use-permission.d.ts.map +1 -0
- package/dist/hooks/use-permission.js +73 -0
- package/dist/hooks/use-recent-menu.d.ts +46 -0
- package/dist/hooks/use-recent-menu.d.ts.map +1 -0
- package/dist/hooks/use-recent-menu.js +169 -0
- package/dist/hooks/use-scroll-restoration.d.ts +51 -0
- package/dist/hooks/use-scroll-restoration.d.ts.map +1 -0
- package/dist/hooks/use-scroll-restoration.js +143 -0
- package/dist/hooks/use-supabase-auth.d.ts +49 -0
- package/dist/hooks/use-supabase-auth.d.ts.map +1 -0
- package/dist/hooks/use-supabase-auth.js +229 -0
- package/dist/hooks/use-track-history.d.ts +2 -1
- package/dist/hooks/use-track-history.d.ts.map +1 -1
- package/dist/hooks/use-track-history.js +14 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/network/axios-factory.d.ts +30 -1
- package/dist/network/axios-factory.d.ts.map +1 -1
- package/dist/network/axios-factory.js +192 -24
- package/dist/network/index.d.ts +3 -1
- package/dist/network/index.d.ts.map +1 -1
- package/dist/network/index.js +5 -1
- package/dist/network/supabase-client.d.ts +28 -0
- package/dist/network/supabase-client.d.ts.map +1 -0
- package/dist/network/supabase-client.js +46 -0
- package/dist/store/app-store.d.ts +222 -12
- package/dist/store/app-store.d.ts.map +1 -1
- package/dist/store/app-store.js +46 -29
- package/dist/store/index.d.ts +2 -0
- package/dist/store/index.d.ts.map +1 -1
- package/dist/store/index.js +3 -0
- package/dist/store/menu-slice.d.ts +96 -0
- package/dist/store/menu-slice.d.ts.map +1 -0
- package/dist/store/menu-slice.js +98 -0
- package/dist/store/recent-menu-slice.d.ts +209 -0
- package/dist/store/recent-menu-slice.d.ts.map +1 -0
- package/dist/store/recent-menu-slice.js +110 -0
- package/dist/store/store-access.d.ts +1 -1
- package/dist/store/store-access.js +1 -1
- package/dist/types/index.d.ts +74 -17
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/service.d.ts +1 -1
- package/dist/types/service.js +1 -1
- package/dist/utils/classnames.d.ts +65 -0
- package/dist/utils/classnames.d.ts.map +1 -0
- package/dist/utils/classnames.js +98 -0
- package/dist/utils/formatter.d.ts +78 -0
- package/dist/utils/formatter.d.ts.map +1 -0
- package/dist/utils/formatter.js +216 -0
- package/dist/utils/index.d.ts +5 -0
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +5 -0
- package/dist/utils/permission.d.ts +33 -0
- package/dist/utils/permission.d.ts.map +1 -0
- package/dist/utils/permission.js +132 -0
- package/dist/utils/query-string.d.ts +67 -0
- package/dist/utils/query-string.d.ts.map +1 -0
- package/dist/utils/query-string.js +136 -0
- package/dist/utils/storage.d.ts +1 -1
- package/dist/utils/storage.js +1 -1
- package/dist/utils/validation.d.ts +98 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +260 -0
- package/package.json +5 -3
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Menu Slice
|
|
3
|
+
* 메뉴 상태 관리 (GNB, LNB, 선택 상태)
|
|
4
|
+
*/
|
|
5
|
+
import { createSlice, createSelector } from '@reduxjs/toolkit';
|
|
6
|
+
const initialState = {
|
|
7
|
+
gnbItems: [],
|
|
8
|
+
lnbItems: [],
|
|
9
|
+
selectedGnbId: '',
|
|
10
|
+
selectedLnbId: '',
|
|
11
|
+
expandedIds: [],
|
|
12
|
+
isLoading: false,
|
|
13
|
+
};
|
|
14
|
+
// ============================================
|
|
15
|
+
// Slice
|
|
16
|
+
// ============================================
|
|
17
|
+
const menuSlice = createSlice({
|
|
18
|
+
name: 'menu',
|
|
19
|
+
initialState,
|
|
20
|
+
reducers: {
|
|
21
|
+
setGnbItems: (state, action) => {
|
|
22
|
+
state.gnbItems = action.payload;
|
|
23
|
+
},
|
|
24
|
+
setLnbItems: (state, action) => {
|
|
25
|
+
state.lnbItems = action.payload;
|
|
26
|
+
},
|
|
27
|
+
setSelectedGnbId: (state, action) => {
|
|
28
|
+
state.selectedGnbId = action.payload;
|
|
29
|
+
},
|
|
30
|
+
setSelectedLnbId: (state, action) => {
|
|
31
|
+
state.selectedLnbId = action.payload;
|
|
32
|
+
},
|
|
33
|
+
setExpandedIds: (state, action) => {
|
|
34
|
+
state.expandedIds = action.payload;
|
|
35
|
+
},
|
|
36
|
+
toggleExpanded: (state, action) => {
|
|
37
|
+
const id = action.payload;
|
|
38
|
+
const index = state.expandedIds.indexOf(id);
|
|
39
|
+
if (index >= 0) {
|
|
40
|
+
state.expandedIds.splice(index, 1);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
state.expandedIds.push(id);
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
setMenuLoading: (state, action) => {
|
|
47
|
+
state.isLoading = action.payload;
|
|
48
|
+
},
|
|
49
|
+
resetMenu: () => initialState,
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
export const { setGnbItems, setLnbItems, setSelectedGnbId, setSelectedLnbId, setExpandedIds, toggleExpanded, setMenuLoading, resetMenu, } = menuSlice.actions;
|
|
53
|
+
// 기본 Selectors
|
|
54
|
+
export const selectMenuState = (state) => state.menu;
|
|
55
|
+
export const selectGnbItems = (state) => state.menu.gnbItems;
|
|
56
|
+
export const selectLnbItems = (state) => state.menu.lnbItems;
|
|
57
|
+
export const selectSelectedGnbId = (state) => state.menu.selectedGnbId;
|
|
58
|
+
export const selectSelectedLnbId = (state) => state.menu.selectedLnbId;
|
|
59
|
+
export const selectExpandedIds = (state) => state.menu.expandedIds;
|
|
60
|
+
export const selectMenuLoading = (state) => state.menu.isLoading;
|
|
61
|
+
// 파생 Selectors (Memoized)
|
|
62
|
+
export const selectSelectedGnb = createSelector([selectGnbItems, selectSelectedGnbId], (gnbItems, selectedId) => gnbItems.find((item) => item.id === selectedId) || null);
|
|
63
|
+
export const selectSelectedLnb = createSelector([selectLnbItems, selectSelectedLnbId], (lnbItems, selectedId) => {
|
|
64
|
+
// 중첩 메뉴에서 찾기
|
|
65
|
+
const findItem = (items) => {
|
|
66
|
+
for (const item of items) {
|
|
67
|
+
if (item.id === selectedId)
|
|
68
|
+
return item;
|
|
69
|
+
if (item.children) {
|
|
70
|
+
const found = findItem(item.children);
|
|
71
|
+
if (found)
|
|
72
|
+
return found;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return null;
|
|
76
|
+
};
|
|
77
|
+
return findItem(lnbItems);
|
|
78
|
+
});
|
|
79
|
+
// 현재 경로의 breadcrumb 계산
|
|
80
|
+
export const selectBreadcrumb = createSelector([selectLnbItems, selectSelectedLnbId], (lnbItems, selectedId) => {
|
|
81
|
+
const breadcrumb = [];
|
|
82
|
+
const findPath = (items, path = []) => {
|
|
83
|
+
for (const item of items) {
|
|
84
|
+
const currentPath = [...path, item];
|
|
85
|
+
if (item.id === selectedId) {
|
|
86
|
+
breadcrumb.push(...currentPath);
|
|
87
|
+
return true;
|
|
88
|
+
}
|
|
89
|
+
if (item.children && findPath(item.children, currentPath)) {
|
|
90
|
+
return true;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return false;
|
|
94
|
+
};
|
|
95
|
+
findPath(lnbItems);
|
|
96
|
+
return breadcrumb;
|
|
97
|
+
});
|
|
98
|
+
export default menuSlice.reducer;
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recent Menu Slice
|
|
3
|
+
* 최근 방문 메뉴 상태 관리 (탭)
|
|
4
|
+
*/
|
|
5
|
+
import { PayloadAction } from '@reduxjs/toolkit';
|
|
6
|
+
import { RecentMenu } from '../types';
|
|
7
|
+
export interface RecentMenuState {
|
|
8
|
+
/** 최근 메뉴 목록 */
|
|
9
|
+
list: RecentMenu[];
|
|
10
|
+
/** 현재 활성 메뉴 ID */
|
|
11
|
+
currentId: string;
|
|
12
|
+
/** 최대 탭 개수 */
|
|
13
|
+
maxTabs: number;
|
|
14
|
+
}
|
|
15
|
+
export declare const recentMenuSlice: import("@reduxjs/toolkit").Slice<RecentMenuState, {
|
|
16
|
+
/** 최근 메뉴 목록 설정 (복구용) */
|
|
17
|
+
setRecentMenuList: (state: {
|
|
18
|
+
list: {
|
|
19
|
+
id: string;
|
|
20
|
+
pathname: string;
|
|
21
|
+
search: string;
|
|
22
|
+
title: string;
|
|
23
|
+
service?: string | undefined;
|
|
24
|
+
state?: any;
|
|
25
|
+
data?: any;
|
|
26
|
+
}[];
|
|
27
|
+
currentId: string;
|
|
28
|
+
maxTabs: number;
|
|
29
|
+
}, action: PayloadAction<RecentMenu[]>) => void;
|
|
30
|
+
/** 최근 메뉴 추가/업데이트 */
|
|
31
|
+
addRecentMenu: (state: {
|
|
32
|
+
list: {
|
|
33
|
+
id: string;
|
|
34
|
+
pathname: string;
|
|
35
|
+
search: string;
|
|
36
|
+
title: string;
|
|
37
|
+
service?: string | undefined;
|
|
38
|
+
state?: any;
|
|
39
|
+
data?: any;
|
|
40
|
+
}[];
|
|
41
|
+
currentId: string;
|
|
42
|
+
maxTabs: number;
|
|
43
|
+
}, action: PayloadAction<RecentMenu>) => void;
|
|
44
|
+
/** 최근 메뉴 제거 */
|
|
45
|
+
removeRecentMenu: (state: {
|
|
46
|
+
list: {
|
|
47
|
+
id: string;
|
|
48
|
+
pathname: string;
|
|
49
|
+
search: string;
|
|
50
|
+
title: string;
|
|
51
|
+
service?: string | undefined;
|
|
52
|
+
state?: any;
|
|
53
|
+
data?: any;
|
|
54
|
+
}[];
|
|
55
|
+
currentId: string;
|
|
56
|
+
maxTabs: number;
|
|
57
|
+
}, action: PayloadAction<string>) => void;
|
|
58
|
+
/** 현재 메뉴 변경 */
|
|
59
|
+
setCurrentRecentMenu: (state: {
|
|
60
|
+
list: {
|
|
61
|
+
id: string;
|
|
62
|
+
pathname: string;
|
|
63
|
+
search: string;
|
|
64
|
+
title: string;
|
|
65
|
+
service?: string | undefined;
|
|
66
|
+
state?: any;
|
|
67
|
+
data?: any;
|
|
68
|
+
}[];
|
|
69
|
+
currentId: string;
|
|
70
|
+
maxTabs: number;
|
|
71
|
+
}, action: PayloadAction<string>) => void;
|
|
72
|
+
/** 메뉴 상태 업데이트 (스크롤 위치, 검색 조건 등) */
|
|
73
|
+
updateRecentMenuState: (state: {
|
|
74
|
+
list: {
|
|
75
|
+
id: string;
|
|
76
|
+
pathname: string;
|
|
77
|
+
search: string;
|
|
78
|
+
title: string;
|
|
79
|
+
service?: string | undefined;
|
|
80
|
+
state?: any;
|
|
81
|
+
data?: any;
|
|
82
|
+
}[];
|
|
83
|
+
currentId: string;
|
|
84
|
+
maxTabs: number;
|
|
85
|
+
}, action: PayloadAction<{
|
|
86
|
+
id: string;
|
|
87
|
+
state?: any;
|
|
88
|
+
data?: any;
|
|
89
|
+
}>) => void;
|
|
90
|
+
/** 모든 최근 메뉴 제거 */
|
|
91
|
+
clearRecentMenu: (state: {
|
|
92
|
+
list: {
|
|
93
|
+
id: string;
|
|
94
|
+
pathname: string;
|
|
95
|
+
search: string;
|
|
96
|
+
title: string;
|
|
97
|
+
service?: string | undefined;
|
|
98
|
+
state?: any;
|
|
99
|
+
data?: any;
|
|
100
|
+
}[];
|
|
101
|
+
currentId: string;
|
|
102
|
+
maxTabs: number;
|
|
103
|
+
}) => void;
|
|
104
|
+
/** 현재 메뉴 외 모든 메뉴 제거 */
|
|
105
|
+
closeOtherMenus: (state: {
|
|
106
|
+
list: {
|
|
107
|
+
id: string;
|
|
108
|
+
pathname: string;
|
|
109
|
+
search: string;
|
|
110
|
+
title: string;
|
|
111
|
+
service?: string | undefined;
|
|
112
|
+
state?: any;
|
|
113
|
+
data?: any;
|
|
114
|
+
}[];
|
|
115
|
+
currentId: string;
|
|
116
|
+
maxTabs: number;
|
|
117
|
+
}) => void;
|
|
118
|
+
/** 최대 탭 개수 설정 */
|
|
119
|
+
setMaxTabs: (state: {
|
|
120
|
+
list: {
|
|
121
|
+
id: string;
|
|
122
|
+
pathname: string;
|
|
123
|
+
search: string;
|
|
124
|
+
title: string;
|
|
125
|
+
service?: string | undefined;
|
|
126
|
+
state?: any;
|
|
127
|
+
data?: any;
|
|
128
|
+
}[];
|
|
129
|
+
currentId: string;
|
|
130
|
+
maxTabs: number;
|
|
131
|
+
}, action: PayloadAction<number>) => void;
|
|
132
|
+
}, "recentMenu", "recentMenu", import("@reduxjs/toolkit").SliceSelectors<RecentMenuState>>;
|
|
133
|
+
export declare const setRecentMenuList: import("@reduxjs/toolkit").ActionCreatorWithPayload<RecentMenu[], "recentMenu/setRecentMenuList">, addRecentMenu: import("@reduxjs/toolkit").ActionCreatorWithPayload<RecentMenu, "recentMenu/addRecentMenu">, removeRecentMenu: import("@reduxjs/toolkit").ActionCreatorWithPayload<string, "recentMenu/removeRecentMenu">, setCurrentRecentMenu: import("@reduxjs/toolkit").ActionCreatorWithPayload<string, "recentMenu/setCurrentRecentMenu">, updateRecentMenuState: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
|
|
134
|
+
id: string;
|
|
135
|
+
state?: any;
|
|
136
|
+
data?: any;
|
|
137
|
+
}, "recentMenu/updateRecentMenuState">, clearRecentMenu: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"recentMenu/clearRecentMenu">, closeOtherMenus: import("@reduxjs/toolkit").ActionCreatorWithoutPayload<"recentMenu/closeOtherMenus">, setMaxTabs: import("@reduxjs/toolkit").ActionCreatorWithPayload<number, "recentMenu/setMaxTabs">;
|
|
138
|
+
interface RootStateWithRecentMenu {
|
|
139
|
+
recentMenu: RecentMenuState;
|
|
140
|
+
}
|
|
141
|
+
export declare const selectRecentMenuState: (state: RootStateWithRecentMenu) => RecentMenuState;
|
|
142
|
+
export declare const selectRecentMenuList: (state: RootStateWithRecentMenu) => RecentMenu[];
|
|
143
|
+
export declare const selectCurrentRecentMenuId: (state: RootStateWithRecentMenu) => string;
|
|
144
|
+
export declare const selectCurrentRecentMenu: ((state: RootStateWithRecentMenu) => RecentMenu | null) & {
|
|
145
|
+
clearCache: () => void;
|
|
146
|
+
resultsCount: () => number;
|
|
147
|
+
resetResultsCount: () => void;
|
|
148
|
+
} & {
|
|
149
|
+
resultFunc: (resultFuncArgs_0: RecentMenu[], resultFuncArgs_1: string) => RecentMenu | null;
|
|
150
|
+
memoizedResultFunc: ((resultFuncArgs_0: RecentMenu[], resultFuncArgs_1: string) => RecentMenu | null) & {
|
|
151
|
+
clearCache: () => void;
|
|
152
|
+
resultsCount: () => number;
|
|
153
|
+
resetResultsCount: () => void;
|
|
154
|
+
};
|
|
155
|
+
lastResult: () => RecentMenu | null;
|
|
156
|
+
dependencies: [(state: RootStateWithRecentMenu) => RecentMenu[], (state: RootStateWithRecentMenu) => string];
|
|
157
|
+
recomputations: () => number;
|
|
158
|
+
resetRecomputations: () => void;
|
|
159
|
+
dependencyRecomputations: () => number;
|
|
160
|
+
resetDependencyRecomputations: () => void;
|
|
161
|
+
} & {
|
|
162
|
+
memoize: typeof import("reselect").weakMapMemoize;
|
|
163
|
+
argsMemoize: typeof import("reselect").weakMapMemoize;
|
|
164
|
+
};
|
|
165
|
+
export declare const selectRecentMenuCount: ((state: RootStateWithRecentMenu) => number) & {
|
|
166
|
+
clearCache: () => void;
|
|
167
|
+
resultsCount: () => number;
|
|
168
|
+
resetResultsCount: () => void;
|
|
169
|
+
} & {
|
|
170
|
+
resultFunc: (resultFuncArgs_0: RecentMenu[]) => number;
|
|
171
|
+
memoizedResultFunc: ((resultFuncArgs_0: RecentMenu[]) => number) & {
|
|
172
|
+
clearCache: () => void;
|
|
173
|
+
resultsCount: () => number;
|
|
174
|
+
resetResultsCount: () => void;
|
|
175
|
+
};
|
|
176
|
+
lastResult: () => number;
|
|
177
|
+
dependencies: [(state: RootStateWithRecentMenu) => RecentMenu[]];
|
|
178
|
+
recomputations: () => number;
|
|
179
|
+
resetRecomputations: () => void;
|
|
180
|
+
dependencyRecomputations: () => number;
|
|
181
|
+
resetDependencyRecomputations: () => void;
|
|
182
|
+
} & {
|
|
183
|
+
memoize: typeof import("reselect").weakMapMemoize;
|
|
184
|
+
argsMemoize: typeof import("reselect").weakMapMemoize;
|
|
185
|
+
};
|
|
186
|
+
export declare const selectHasRecentMenu: ((state: RootStateWithRecentMenu) => boolean) & {
|
|
187
|
+
clearCache: () => void;
|
|
188
|
+
resultsCount: () => number;
|
|
189
|
+
resetResultsCount: () => void;
|
|
190
|
+
} & {
|
|
191
|
+
resultFunc: (resultFuncArgs_0: RecentMenu[]) => boolean;
|
|
192
|
+
memoizedResultFunc: ((resultFuncArgs_0: RecentMenu[]) => boolean) & {
|
|
193
|
+
clearCache: () => void;
|
|
194
|
+
resultsCount: () => number;
|
|
195
|
+
resetResultsCount: () => void;
|
|
196
|
+
};
|
|
197
|
+
lastResult: () => boolean;
|
|
198
|
+
dependencies: [(state: RootStateWithRecentMenu) => RecentMenu[]];
|
|
199
|
+
recomputations: () => number;
|
|
200
|
+
resetRecomputations: () => void;
|
|
201
|
+
dependencyRecomputations: () => number;
|
|
202
|
+
resetDependencyRecomputations: () => void;
|
|
203
|
+
} & {
|
|
204
|
+
memoize: typeof import("reselect").weakMapMemoize;
|
|
205
|
+
argsMemoize: typeof import("reselect").weakMapMemoize;
|
|
206
|
+
};
|
|
207
|
+
declare const _default: import("redux").Reducer<RecentMenuState>;
|
|
208
|
+
export default _default;
|
|
209
|
+
//# sourceMappingURL=recent-menu-slice.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recent-menu-slice.d.ts","sourceRoot":"","sources":["../../src/store/recent-menu-slice.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAe,aAAa,EAAkB,MAAM,kBAAkB,CAAC;AAC9E,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAOtC,MAAM,WAAW,eAAe;IAC9B,eAAe;IACf,IAAI,EAAE,UAAU,EAAE,CAAC;IACnB,kBAAkB;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc;IACd,OAAO,EAAE,MAAM,CAAC;CACjB;AAYD,eAAO,MAAM,eAAe;IAIxB,wBAAwB;;;;;;;;;;;mBAnBf,MAAM;iBAER,MAAM;eAkBsB,aAAa,CAAC,UAAU,EAAE,CAAC;IAI9D,oBAAoB;;;;;;;;;;;mBAxBX,MAAM;iBAER,MAAM;eAuBkB,aAAa,CAAC,UAAU,CAAC;IA6BxD,eAAe;;;;;;;;;;;mBAtDN,MAAM;iBAER,MAAM;eAqDqB,aAAa,CAAC,MAAM,CAAC;IAmBvD,eAAe;;;;;;;;;;;mBA1EN,MAAM;iBAER,MAAM;eAyEyB,aAAa,CAAC,MAAM,CAAC;IAI3D,mCAAmC;;;;;;;;;;;mBA/E1B,MAAM;iBAER,MAAM;eAgFH,aAAa,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,GAAG,CAAC;QAAC,IAAI,CAAC,EAAE,GAAG,CAAA;KAAE,CAAC;IAchE,kBAAkB;;;;;;;;;;;mBAhGT,MAAM;iBAER,MAAM;;IAqGb,uBAAuB;;;;;;;;;;;mBAvGd,MAAM;iBAER,MAAM;;IA4Gb,iBAAiB;;;;;;;;;;;mBA9GR,MAAM;iBAER,MAAM;eA6Ge,aAAa,CAAC,MAAM,CAAC;0FAInD,CAAC;AAEH,eAAO,MACL,iBAAiB,qGACjB,aAAa,+FACb,gBAAgB,8FAChB,oBAAoB,kGACpB,qBAAqB;QAxCW,MAAM;YAAU,GAAG;WAAS,GAAG;wCAyC/D,eAAe,wFACf,eAAe,wFACf,UAAU,sFACe,CAAC;AAM5B,UAAU,uBAAuB;IAC/B,UAAU,EAAE,eAAe,CAAC;CAC7B;AAGD,eAAO,MAAM,qBAAqB,GAAI,OAAO,uBAAuB,oBAAqB,CAAC;AAC1F,eAAO,MAAM,oBAAoB,GAAI,OAAO,uBAAuB,iBAA0B,CAAC;AAC9F,eAAO,MAAM,yBAAyB,GAAI,OAAO,uBAAuB,WAA+B,CAAC;AAGxG,eAAO,MAAM,uBAAuB;;;;;;;;;;;;2BAJQ,uBAAuB,2BAClB,uBAAuB;;;;;;;;CAMvE,CAAC;AAEF,eAAO,MAAM,qBAAqB;;;;;;;;;;;;2BATU,uBAAuB;;;;;;;;CAYlE,CAAC;AAEF,eAAO,MAAM,mBAAmB;;;;;;;;;;;;2BAdY,uBAAuB;;;;;;;;CAiBlE,CAAC;;AAEF,wBAAuC"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recent Menu Slice
|
|
3
|
+
* 최근 방문 메뉴 상태 관리 (탭)
|
|
4
|
+
*/
|
|
5
|
+
import { createSlice, createSelector } from '@reduxjs/toolkit';
|
|
6
|
+
import { storage } from '../utils/storage';
|
|
7
|
+
const initialState = {
|
|
8
|
+
list: [],
|
|
9
|
+
currentId: '',
|
|
10
|
+
maxTabs: 10,
|
|
11
|
+
};
|
|
12
|
+
// ============================================
|
|
13
|
+
// Slice
|
|
14
|
+
// ============================================
|
|
15
|
+
export const recentMenuSlice = createSlice({
|
|
16
|
+
name: 'recentMenu',
|
|
17
|
+
initialState,
|
|
18
|
+
reducers: {
|
|
19
|
+
/** 최근 메뉴 목록 설정 (복구용) */
|
|
20
|
+
setRecentMenuList: (state, action) => {
|
|
21
|
+
state.list = action.payload;
|
|
22
|
+
},
|
|
23
|
+
/** 최근 메뉴 추가/업데이트 */
|
|
24
|
+
addRecentMenu: (state, action) => {
|
|
25
|
+
const newMenu = action.payload;
|
|
26
|
+
const existingIndex = state.list.findIndex((m) => m.id === newMenu.id);
|
|
27
|
+
if (existingIndex >= 0) {
|
|
28
|
+
// 이미 존재하면 업데이트
|
|
29
|
+
state.list[existingIndex] = {
|
|
30
|
+
...state.list[existingIndex],
|
|
31
|
+
...newMenu,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
// 새로 추가
|
|
36
|
+
if (state.list.length >= state.maxTabs) {
|
|
37
|
+
// 최대 개수 초과 시 가장 오래된 것 제거 (현재 활성 제외)
|
|
38
|
+
const oldestIndex = state.list.findIndex((m) => m.id !== state.currentId);
|
|
39
|
+
if (oldestIndex >= 0) {
|
|
40
|
+
state.list.splice(oldestIndex, 1);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
state.list.push(newMenu);
|
|
44
|
+
}
|
|
45
|
+
// 현재 메뉴로 설정
|
|
46
|
+
state.currentId = newMenu.id;
|
|
47
|
+
// localStorage에 저장
|
|
48
|
+
storage.setRecentMenu(state.list);
|
|
49
|
+
},
|
|
50
|
+
/** 최근 메뉴 제거 */
|
|
51
|
+
removeRecentMenu: (state, action) => {
|
|
52
|
+
const id = action.payload;
|
|
53
|
+
const index = state.list.findIndex((m) => m.id === id);
|
|
54
|
+
if (index >= 0) {
|
|
55
|
+
state.list.splice(index, 1);
|
|
56
|
+
// 현재 메뉴가 제거되면 다른 메뉴로 전환
|
|
57
|
+
if (state.currentId === id) {
|
|
58
|
+
// 이전 또는 다음 메뉴로 전환
|
|
59
|
+
const newCurrent = state.list[Math.max(0, index - 1)];
|
|
60
|
+
state.currentId = newCurrent?.id || '';
|
|
61
|
+
}
|
|
62
|
+
// localStorage에 저장
|
|
63
|
+
storage.setRecentMenu(state.list);
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
/** 현재 메뉴 변경 */
|
|
67
|
+
setCurrentRecentMenu: (state, action) => {
|
|
68
|
+
state.currentId = action.payload;
|
|
69
|
+
},
|
|
70
|
+
/** 메뉴 상태 업데이트 (스크롤 위치, 검색 조건 등) */
|
|
71
|
+
updateRecentMenuState: (state, action) => {
|
|
72
|
+
const { id, state: menuState, data } = action.payload;
|
|
73
|
+
const menu = state.list.find((m) => m.id === id);
|
|
74
|
+
if (menu) {
|
|
75
|
+
if (menuState !== undefined)
|
|
76
|
+
menu.state = menuState;
|
|
77
|
+
if (data !== undefined)
|
|
78
|
+
menu.data = data;
|
|
79
|
+
// localStorage에 저장
|
|
80
|
+
storage.setRecentMenu(state.list);
|
|
81
|
+
}
|
|
82
|
+
},
|
|
83
|
+
/** 모든 최근 메뉴 제거 */
|
|
84
|
+
clearRecentMenu: (state) => {
|
|
85
|
+
state.list = [];
|
|
86
|
+
state.currentId = '';
|
|
87
|
+
storage.setRecentMenu([]);
|
|
88
|
+
},
|
|
89
|
+
/** 현재 메뉴 외 모든 메뉴 제거 */
|
|
90
|
+
closeOtherMenus: (state) => {
|
|
91
|
+
const currentMenu = state.list.find((m) => m.id === state.currentId);
|
|
92
|
+
state.list = currentMenu ? [currentMenu] : [];
|
|
93
|
+
storage.setRecentMenu(state.list);
|
|
94
|
+
},
|
|
95
|
+
/** 최대 탭 개수 설정 */
|
|
96
|
+
setMaxTabs: (state, action) => {
|
|
97
|
+
state.maxTabs = action.payload;
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
export const { setRecentMenuList, addRecentMenu, removeRecentMenu, setCurrentRecentMenu, updateRecentMenuState, clearRecentMenu, closeOtherMenus, setMaxTabs, } = recentMenuSlice.actions;
|
|
102
|
+
// 기본 Selectors
|
|
103
|
+
export const selectRecentMenuState = (state) => state.recentMenu;
|
|
104
|
+
export const selectRecentMenuList = (state) => state.recentMenu.list;
|
|
105
|
+
export const selectCurrentRecentMenuId = (state) => state.recentMenu.currentId;
|
|
106
|
+
// 파생 Selectors (Memoized)
|
|
107
|
+
export const selectCurrentRecentMenu = createSelector([selectRecentMenuList, selectCurrentRecentMenuId], (list, currentId) => list.find((m) => m.id === currentId) || null);
|
|
108
|
+
export const selectRecentMenuCount = createSelector([selectRecentMenuList], (list) => list.length);
|
|
109
|
+
export const selectHasRecentMenu = createSelector([selectRecentMenuList], (list) => list.length > 0);
|
|
110
|
+
export default recentMenuSlice.reducer;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,12 +1,69 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* MFA 공통 타입 정의
|
|
3
3
|
*/
|
|
4
|
+
import { ReactNode } from 'react';
|
|
4
5
|
export * from './service';
|
|
6
|
+
/** 사용자 역할 */
|
|
7
|
+
export type UserRole = 'admin' | 'user' | 'editor' | 'viewer' | 'guest';
|
|
8
|
+
/** 권한 액션 타입 */
|
|
9
|
+
export type PermissionAction = 'read' | 'write' | 'delete' | 'admin';
|
|
10
|
+
/** 개별 권한 */
|
|
11
|
+
export interface Permission {
|
|
12
|
+
/** 메뉴/리소스 코드 */
|
|
13
|
+
code: string;
|
|
14
|
+
/** 허용된 액션 목록 */
|
|
15
|
+
actions: PermissionAction[];
|
|
16
|
+
}
|
|
17
|
+
/** 사용자 타입 */
|
|
5
18
|
export interface User {
|
|
6
19
|
id: string;
|
|
7
20
|
name: string;
|
|
8
21
|
email: string;
|
|
9
|
-
role?:
|
|
22
|
+
role?: UserRole | string;
|
|
23
|
+
avatar?: string;
|
|
24
|
+
/** 사용자 권한 목록 */
|
|
25
|
+
permissions?: Permission[];
|
|
26
|
+
}
|
|
27
|
+
/** 메뉴 권한 요구사항 */
|
|
28
|
+
export interface MenuPermission {
|
|
29
|
+
/** 필요한 메뉴 코드 (OR 조건) */
|
|
30
|
+
requiredCodes?: string[];
|
|
31
|
+
/** 필요한 역할 (OR 조건) */
|
|
32
|
+
requiredRoles?: UserRole[];
|
|
33
|
+
/** 필요한 액션 */
|
|
34
|
+
requiredAction?: PermissionAction;
|
|
35
|
+
}
|
|
36
|
+
/** LNB 메뉴 아이템 (기본) */
|
|
37
|
+
export interface LnbMenuItem {
|
|
38
|
+
id: string;
|
|
39
|
+
title: string;
|
|
40
|
+
path?: string;
|
|
41
|
+
/** 아이콘 (ReactNode 또는 문자열) */
|
|
42
|
+
icon?: ReactNode | string;
|
|
43
|
+
/** 하위 메뉴 */
|
|
44
|
+
children?: LnbMenuItem[];
|
|
45
|
+
/** 권한 요구사항 (없으면 모두 접근 가능) */
|
|
46
|
+
permission?: MenuPermission;
|
|
47
|
+
/** 메뉴 숨김 여부 */
|
|
48
|
+
hidden?: boolean;
|
|
49
|
+
/** 비활성화 여부 */
|
|
50
|
+
disabled?: boolean;
|
|
51
|
+
/** 뱃지 */
|
|
52
|
+
badge?: {
|
|
53
|
+
text: string;
|
|
54
|
+
variant?: 'primary' | 'secondary' | 'success' | 'warning' | 'error';
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/** MenuItem은 LnbMenuItem의 별칭 (하위 호환) */
|
|
58
|
+
export type MenuItem = LnbMenuItem;
|
|
59
|
+
/** Remote에서 export하는 LnbItems 구조 (KOMCA 패턴) */
|
|
60
|
+
export interface RemoteLnbItems {
|
|
61
|
+
/** 경로 prefix */
|
|
62
|
+
pathPrefix?: string;
|
|
63
|
+
/** Guest용 메뉴 (비로그인) */
|
|
64
|
+
hasPrefixList?: LnbMenuItem[];
|
|
65
|
+
/** Auth용 메뉴 (로그인) */
|
|
66
|
+
hasPrefixAuthList?: LnbMenuItem[];
|
|
10
67
|
}
|
|
11
68
|
export interface AppState {
|
|
12
69
|
accessToken: string;
|
|
@@ -25,24 +82,22 @@ export interface RecentMenu {
|
|
|
25
82
|
state?: any;
|
|
26
83
|
data?: any;
|
|
27
84
|
}
|
|
28
|
-
export interface MenuItem {
|
|
29
|
-
id: string;
|
|
30
|
-
title: string;
|
|
31
|
-
path: string;
|
|
32
|
-
icon?: string;
|
|
33
|
-
children?: MenuItem[];
|
|
34
|
-
}
|
|
35
|
-
export interface MenuState {
|
|
36
|
-
menuList: MenuItem[];
|
|
37
|
-
}
|
|
38
|
-
export interface RecentMenuState {
|
|
39
|
-
list: RecentMenu[];
|
|
40
|
-
currentId: string;
|
|
41
|
-
}
|
|
42
85
|
export interface HostRootState {
|
|
43
86
|
app: AppState;
|
|
44
|
-
recentMenu:
|
|
45
|
-
|
|
87
|
+
recentMenu: {
|
|
88
|
+
list: RecentMenu[];
|
|
89
|
+
currentId: string;
|
|
90
|
+
maxTabs?: number;
|
|
91
|
+
};
|
|
92
|
+
menu?: {
|
|
93
|
+
gnbItems: LnbMenuItem[];
|
|
94
|
+
lnbItems: LnbMenuItem[];
|
|
95
|
+
selectedGnbId: string;
|
|
96
|
+
selectedLnbId: string;
|
|
97
|
+
expandedIds: string[];
|
|
98
|
+
isLoading: boolean;
|
|
99
|
+
};
|
|
100
|
+
[key: string]: unknown;
|
|
46
101
|
}
|
|
47
102
|
export interface HostStore {
|
|
48
103
|
getState: () => HostRootState;
|
|
@@ -50,9 +105,11 @@ export interface HostStore {
|
|
|
50
105
|
subscribe: (listener: () => void) => () => void;
|
|
51
106
|
replaceReducer: (reducer: any) => void;
|
|
52
107
|
}
|
|
108
|
+
export type InjectReducerFn = (key: string, reducer: import('@reduxjs/toolkit').Reducer) => void;
|
|
53
109
|
declare global {
|
|
54
110
|
interface Window {
|
|
55
111
|
__REDUX_STORE__: HostStore;
|
|
112
|
+
__INJECT_REDUCER__?: InjectReducerFn;
|
|
56
113
|
}
|
|
57
114
|
}
|
|
58
115
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
|
package/dist/types/service.d.ts
CHANGED
package/dist/types/service.js
CHANGED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ClassName 유틸리티
|
|
3
|
+
* 조건부 클래스 이름 결합 (clsx/classnames 대체)
|
|
4
|
+
* 외부 의존성 없이 구현
|
|
5
|
+
*/
|
|
6
|
+
export type ClassValue = string | number | boolean | null | undefined | ClassValue[] | Record<string, boolean | null | undefined>;
|
|
7
|
+
/**
|
|
8
|
+
* 여러 클래스 이름을 조건부로 결합
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* // 기본 사용
|
|
12
|
+
* cn('foo', 'bar') // 'foo bar'
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* // 조건부 클래스
|
|
16
|
+
* cn('btn', { 'btn-primary': isPrimary, 'btn-disabled': isDisabled })
|
|
17
|
+
* // isPrimary=true, isDisabled=false -> 'btn btn-primary'
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* // 배열 사용
|
|
21
|
+
* cn(['foo', 'bar'], 'baz') // 'foo bar baz'
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* // falsy 값 무시
|
|
25
|
+
* cn('foo', null, undefined, false, 'bar') // 'foo bar'
|
|
26
|
+
*/
|
|
27
|
+
export declare function cn(...inputs: ClassValue[]): string;
|
|
28
|
+
/**
|
|
29
|
+
* cn의 별칭 (classNames)
|
|
30
|
+
*/
|
|
31
|
+
export declare const classNames: typeof cn;
|
|
32
|
+
/**
|
|
33
|
+
* cn의 별칭 (clsx 호환)
|
|
34
|
+
*/
|
|
35
|
+
export declare const clsx: typeof cn;
|
|
36
|
+
/**
|
|
37
|
+
* 조건부 클래스 생성 헬퍼
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* const buttonClass = createClassVariants({
|
|
41
|
+
* base: 'btn',
|
|
42
|
+
* variants: {
|
|
43
|
+
* variant: {
|
|
44
|
+
* primary: 'btn-primary',
|
|
45
|
+
* secondary: 'btn-secondary',
|
|
46
|
+
* },
|
|
47
|
+
* size: {
|
|
48
|
+
* sm: 'btn-sm',
|
|
49
|
+
* md: 'btn-md',
|
|
50
|
+
* lg: 'btn-lg',
|
|
51
|
+
* },
|
|
52
|
+
* },
|
|
53
|
+
* });
|
|
54
|
+
*
|
|
55
|
+
* buttonClass({ variant: 'primary', size: 'lg' })
|
|
56
|
+
* // 'btn btn-primary btn-lg'
|
|
57
|
+
*/
|
|
58
|
+
export declare function createClassVariants<T extends Record<string, Record<string, string>>>(config: {
|
|
59
|
+
base?: string;
|
|
60
|
+
variants: T;
|
|
61
|
+
}): (options: Partial<{
|
|
62
|
+
[K in keyof T]: keyof T[K];
|
|
63
|
+
}>) => string;
|
|
64
|
+
export default cn;
|
|
65
|
+
//# sourceMappingURL=classnames.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classnames.d.ts","sourceRoot":"","sources":["../../src/utils/classnames.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,MAAM,MAAM,UAAU,GAClB,MAAM,GACN,MAAM,GACN,OAAO,GACP,IAAI,GACJ,SAAS,GACT,UAAU,EAAE,GACZ,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;AAE/C;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,EAAE,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,CAqBlD;AAED;;GAEG;AACH,eAAO,MAAM,UAAU,WAAK,CAAC;AAE7B;;GAEG;AACH,eAAO,MAAM,IAAI,WAAK,CAAC;AAEvB;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,mBAAmB,CACjC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAChD,MAAM,EAAE;IACR,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,CAAC,CAAC;CACb,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC;KAAG,CAAC,IAAI,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;CAAE,CAAC,KAAK,MAAM,CAkB/D;AAED,eAAe,EAAE,CAAC"}
|