@bwg-ui/core 1.3.0 → 1.3.2

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.
Files changed (45) hide show
  1. package/dist/chunks/{CMSearchIntfGwP01-_h2B12Ig.js → CMSearchIntfGwP01-Bx5cpkhH.js} +1 -1
  2. package/dist/chunks/{CMSearchIntfGwP01-D7XtXMLy.cjs → CMSearchIntfGwP01-Uhl4uqiV.cjs} +1 -1
  3. package/dist/chunks/{MenuReport-DuWbbKBC.cjs → MenuReport-CPwq8w-z.cjs} +1 -1
  4. package/dist/chunks/{MenuReport-Bw3AvR6b.js → MenuReport-DxJIaW8D.js} +1 -1
  5. package/dist/chunks/{common-components-BOJo6FH_.cjs → common-components-Dd_AsKs7.cjs} +99 -99
  6. package/dist/chunks/{common-components-BjfrRYiU.js → common-components-dzN5Nuq0.js} +7245 -7093
  7. package/dist/chunks/{layout-components-DNhUIx4u.js → layout-components-B25FFvXj.js} +1017 -768
  8. package/dist/chunks/layout-components-Cz7Zets7.cjs +35 -0
  9. package/dist/components/common/BwgDetail.d.ts.map +1 -1
  10. package/dist/components/common/BwgGrid.d.ts.map +1 -1
  11. package/dist/components/common/BwgPagination.d.ts.map +1 -1
  12. package/dist/components/common/index.cjs +1 -1
  13. package/dist/components/common/index.js +1 -1
  14. package/dist/components/guide/index.cjs +1 -1
  15. package/dist/components/guide/index.js +1 -1
  16. package/dist/components/layout/BwgPortal01.d.ts.map +1 -1
  17. package/dist/components/layout/custom/ConfigurableHeader.d.ts.map +1 -1
  18. package/dist/components/layout/custom/ConfigurableMenuTab.d.ts.map +1 -1
  19. package/dist/components/layout/custom/ConfigurableSidebar.d.ts.map +1 -1
  20. package/dist/components/layout/default/LoadingContainer.d.ts.map +1 -1
  21. package/dist/components/layout/index.cjs +1 -1
  22. package/dist/components/layout/index.js +1 -1
  23. package/dist/components/popup/index.cjs +1 -1
  24. package/dist/components/popup/index.js +1 -1
  25. package/dist/index.cjs +1 -1
  26. package/dist/index.js +2 -2
  27. package/dist/stores/index.cjs +2 -2
  28. package/dist/stores/index.d.ts +12 -2
  29. package/dist/stores/index.d.ts.map +1 -1
  30. package/dist/stores/index.js +312 -216
  31. package/dist/stores/menuViewStore.d.ts +12 -2
  32. package/dist/stores/menuViewStore.d.ts.map +1 -1
  33. package/dist/stores/userStore.d.ts +19 -0
  34. package/dist/stores/userStore.d.ts.map +1 -1
  35. package/dist/styles/assets/images/contents/icon/ico-tab-hashtag-grey.svg +11 -0
  36. package/dist/styles/assets/images/contents/icon/ico-tab-hashtag.svg +11 -0
  37. package/dist/styles/components.css +71 -0
  38. package/dist/styles/layout.css +1289 -1234
  39. package/dist/utils/gridUtils.d.ts +6 -6
  40. package/dist/utils/gridUtils.d.ts.map +1 -1
  41. package/dist/utils/index.cjs +1 -1
  42. package/dist/utils/index.d.ts.map +1 -1
  43. package/dist/utils/index.js +936 -971
  44. package/package.json +1 -1
  45. package/dist/chunks/layout-components-Ddn-4n36.cjs +0 -35
@@ -1,10 +1,10 @@
1
- import { create as b } from "zustand";
2
- import { callService as N, getServiceCode as w, getUserId as v, getUserInfo as ee, getCookie as te, encryptSha256 as oe, setCookie as $ } from "../utils/index.js";
3
- import { message as L } from "antd";
4
- import { l as se } from "../chunks/layout-components-DNhUIx4u.js";
1
+ import { create as N } from "zustand";
2
+ import { callService as b, getServiceCode as F, getUserId as v, getUserInfo as ee, getCookie as te, encryptSha256 as oe, setCookie as $ } from "../utils/index.js";
3
+ import { message as K, Modal as se } from "antd";
4
+ import { l as ne } from "../chunks/layout-components-B25FFvXj.js";
5
5
  import { useState as X, useCallback as W } from "react";
6
- import { useNavigate as ne } from "react-router-dom";
7
- function re(n, r) {
6
+ import { useNavigate as re } from "react-router-dom";
7
+ function ae(n, r) {
8
8
  let e;
9
9
  try {
10
10
  e = n();
@@ -21,12 +21,12 @@ function re(n, r) {
21
21
  removeItem: (o) => e.removeItem(o)
22
22
  };
23
23
  }
24
- const E = (n) => (r) => {
24
+ const B = (n) => (r) => {
25
25
  try {
26
26
  const e = n(r);
27
27
  return e instanceof Promise ? e : {
28
28
  then(s) {
29
- return E(s)(e);
29
+ return B(s)(e);
30
30
  },
31
31
  catch(s) {
32
32
  return this;
@@ -38,13 +38,13 @@ const E = (n) => (r) => {
38
38
  return this;
39
39
  },
40
40
  catch(s) {
41
- return E(s)(e);
41
+ return B(s)(e);
42
42
  }
43
43
  };
44
44
  }
45
- }, ae = (n, r) => (e, s, o) => {
45
+ }, de = (n, r) => (e, s, o) => {
46
46
  let t = {
47
- storage: re(() => localStorage),
47
+ storage: ae(() => localStorage),
48
48
  partialize: (C) => C,
49
49
  version: 0,
50
50
  merge: (C, g) => ({
@@ -71,8 +71,8 @@ const E = (n) => (r) => {
71
71
  state: C,
72
72
  version: t.version
73
73
  });
74
- }, f = o.setState;
75
- o.setState = (C, g) => (f(C, g), l());
74
+ }, h = o.setState;
75
+ o.setState = (C, g) => (h(C, g), l());
76
76
  const m = n(
77
77
  (...C) => (e(...C), l()),
78
78
  s,
@@ -80,42 +80,42 @@ const E = (n) => (r) => {
80
80
  );
81
81
  o.getInitialState = () => m;
82
82
  let u;
83
- const h = () => {
83
+ const f = () => {
84
84
  var C, g;
85
85
  if (!i) return;
86
- a = !1, d.forEach((y) => {
86
+ a = !1, d.forEach((I) => {
87
87
  var S;
88
- return y((S = s()) != null ? S : m);
88
+ return I((S = s()) != null ? S : m);
89
89
  });
90
90
  const k = ((g = t.onRehydrateStorage) == null ? void 0 : g.call(t, (C = s()) != null ? C : m)) || void 0;
91
- return E(i.getItem.bind(i))(t.name).then((y) => {
92
- if (y)
93
- if (typeof y.version == "number" && y.version !== t.version) {
91
+ return B(i.getItem.bind(i))(t.name).then((I) => {
92
+ if (I)
93
+ if (typeof I.version == "number" && I.version !== t.version) {
94
94
  if (t.migrate) {
95
95
  const S = t.migrate(
96
- y.state,
97
- y.version
96
+ I.state,
97
+ I.version
98
98
  );
99
- return S instanceof Promise ? S.then((_) => [!0, _]) : [!0, S];
99
+ return S instanceof Promise ? S.then((T) => [!0, T]) : [!0, S];
100
100
  }
101
101
  console.error(
102
102
  "State loaded from storage couldn't be migrated since no migrate function was provided"
103
103
  );
104
104
  } else
105
- return [!1, y.state];
105
+ return [!1, I.state];
106
106
  return [!1, void 0];
107
- }).then((y) => {
107
+ }).then((I) => {
108
108
  var S;
109
- const [_, Q] = y;
109
+ const [T, Q] = I;
110
110
  if (u = t.merge(
111
111
  Q,
112
112
  (S = s()) != null ? S : m
113
- ), e(u, !0), _)
113
+ ), e(u, !0), T)
114
114
  return l();
115
115
  }).then(() => {
116
- k?.(u, void 0), u = s(), a = !0, c.forEach((y) => y(u));
117
- }).catch((y) => {
118
- k?.(void 0, y);
116
+ k?.(u, void 0), u = s(), a = !0, c.forEach((I) => I(u));
117
+ }).catch((I) => {
118
+ k?.(void 0, I);
119
119
  });
120
120
  };
121
121
  return o.persist = {
@@ -129,7 +129,7 @@ const E = (n) => (r) => {
129
129
  i?.removeItem(t.name);
130
130
  },
131
131
  getOptions: () => t,
132
- rehydrate: () => h(),
132
+ rehydrate: () => f(),
133
133
  hasHydrated: () => a,
134
134
  onHydrate: (C) => (d.add(C), () => {
135
135
  d.delete(C);
@@ -137,8 +137,8 @@ const E = (n) => (r) => {
137
137
  onFinishHydration: (C) => (c.add(C), () => {
138
138
  c.delete(C);
139
139
  })
140
- }, t.skipHydration || h(), u || m;
141
- }, M = ae, H = b()(
140
+ }, t.skipHydration || f(), u || m;
141
+ }, M = de, H = N()(
142
142
  M(
143
143
  (n, r) => ({
144
144
  user: null,
@@ -152,6 +152,10 @@ const E = (n) => (r) => {
152
152
  // 기본값: 크게
153
153
  enableProtectWrapper: !0,
154
154
  // 기본값: 활성화
155
+ gridLayouts: {},
156
+ // 그리드 레이아웃 정보 (sysCd별로 관리)
157
+ theme: "modern",
158
+ // 기본값: modern
155
159
  isLoggedIn: () => !!r().user,
156
160
  // 로그인
157
161
  setLoginUser: (e, s) => {
@@ -186,6 +190,10 @@ const E = (n) => (r) => {
186
190
  setEnableProtectWrapper: (e) => {
187
191
  n({ enableProtectWrapper: e });
188
192
  },
193
+ // 테마 설정
194
+ setTheme: (e) => {
195
+ n({ theme: e }), console.log("테마 변경:", e);
196
+ },
189
197
  // 권한 확인 결과 가져오기
190
198
  getButtonAuth: (e, s) => {
191
199
  const o = `${e}_${s}`;
@@ -204,6 +212,40 @@ const E = (n) => (r) => {
204
212
  // 권한 확인 결과 초기화
205
213
  clearButtonAuths: () => {
206
214
  n({ buttonAuths: {} });
215
+ },
216
+ // 그리드 레이아웃 관련 메서드
217
+ getGridLayouts: (e) => r().gridLayouts[e] || [],
218
+ getGridLayout: (e, s, o) => r().getGridLayouts(e).find(
219
+ (d) => d.menuId === s && d.gridId === o
220
+ ) || null,
221
+ saveGridLayout: (e, s, o, t) => {
222
+ const a = { ...r().gridLayouts };
223
+ a[e] || (a[e] = []);
224
+ const d = a[e].findIndex(
225
+ (i) => i.menuId === s && i.gridId === o
226
+ ), c = {
227
+ menuId: s,
228
+ gridId: o,
229
+ layout: t
230
+ };
231
+ d >= 0 ? a[e][d] = c : a[e].push(c), n({ gridLayouts: a }), console.log(
232
+ `[UserStore] 그리드 레이아웃 저장 완료: ${e}/${s}/${o}`
233
+ );
234
+ },
235
+ removeGridLayout: (e, s, o) => {
236
+ const t = { ...r().gridLayouts };
237
+ t[e] && (t[e] = t[e].filter(
238
+ (a) => !(a.menuId === s && a.gridId === o)
239
+ ), n({ gridLayouts: t }), console.log(
240
+ `[UserStore] 그리드 레이아웃 삭제 완료: ${e}/${s}/${o}`
241
+ ));
242
+ },
243
+ clearGridLayouts: (e) => {
244
+ const s = { ...r().gridLayouts };
245
+ delete s[e], n({ gridLayouts: s }), console.log(`[UserStore] ${e}의 모든 그리드 레이아웃 삭제 완료`);
246
+ },
247
+ clearAllGridLayouts: () => {
248
+ n({ gridLayouts: {} }), console.log("[UserStore] 전체 그리드 레이아웃 삭제 완료");
207
249
  }
208
250
  }),
209
251
  {
@@ -216,13 +258,17 @@ const E = (n) => (r) => {
216
258
  gridSize: n.gridSize,
217
259
  spacingSize: n.spacingSize,
218
260
  enableProtectWrapper: n.enableProtectWrapper,
261
+ gridLayouts: n.gridLayouts,
262
+ // 그리드 레이아웃 정보 저장
263
+ theme: n.theme,
264
+ // 테마 정보 저장
219
265
  isLoggedIn: n.isLoggedIn
220
266
  // buttonAuthCache는 세션 동안만 유지 (localStorage에 저장 안 함)
221
267
  })
222
268
  // 저장할 상태만 선택
223
269
  }
224
270
  )
225
- ), A = {
271
+ ), w = {
226
272
  CACHE_SIZE_LIMIT: 1e3
227
273
  }, p = {
228
274
  codeCache: /* @__PURE__ */ new Map(),
@@ -274,7 +320,7 @@ const E = (n) => (r) => {
274
320
  });
275
321
  }
276
322
  return console.log("대규모 데이터 변환 완료:", r), r;
277
- }, I = b()(
323
+ }, y = N()(
278
324
  M(
279
325
  (n, r) => ({
280
326
  codeData: null,
@@ -287,7 +333,7 @@ const E = (n) => (r) => {
287
333
  n({ isLoading: !0, error: null });
288
334
  try {
289
335
  console.log("시스템 공통코드 데이터 가져오기 시작: SCMSIGN00301");
290
- const e = await N(w("SRCH_CODE"), {
336
+ const e = await b(F("SRCH_CODE"), {
291
337
  crprCd: "100"
292
338
  });
293
339
  console.log("시스템 공통코드 응답:", e), console.log("시스템 공통코드목록:", e.code), console.log("시스템 공통코드옵션목록:", e.opt);
@@ -319,7 +365,7 @@ const E = (n) => (r) => {
319
365
  n({ isLoading: !0, error: null });
320
366
  try {
321
367
  console.log("업무 공통코드 데이터 가져오기 시작: SCMSIGN00302");
322
- const e = await N("SCMSIGN00302", {
368
+ const e = await b("SCMSIGN00302", {
323
369
  sysCd: __SYS_CD__
324
370
  });
325
371
  console.log("업무 공통코드 응답:", e), console.log("업무 공통코드목록:", e.code), console.log("업무 공통코드옵션목록:", e.opt);
@@ -352,10 +398,10 @@ const E = (n) => (r) => {
352
398
  try {
353
399
  console.log("전체 공통코드 데이터 가져오기 시작 (시스템 + 업무)");
354
400
  const [e, s] = await Promise.all([
355
- N(w("SRCH_CODE"), {
401
+ b(F("SRCH_CODE"), {
356
402
  crprCd: "100"
357
403
  }),
358
- N("SCMSIGN00302", {
404
+ b("SCMSIGN00302", {
359
405
  sysCd: __SYS_CD__
360
406
  })
361
407
  ]);
@@ -420,25 +466,25 @@ const E = (n) => (r) => {
420
466
  })
421
467
  }
422
468
  )
423
- ), G = b()(
469
+ ), G = N()(
424
470
  M(
425
471
  (n, r) => ({
426
472
  // 공통 데이터 스토어에서 상태 가져오기
427
473
  get codeData() {
428
- return I.getState().codeData;
474
+ return y.getState().codeData;
429
475
  },
430
476
  get isLoading() {
431
- return I.getState().isLoading;
477
+ return y.getState().isLoading;
432
478
  },
433
479
  get error() {
434
- return I.getState().error;
480
+ return y.getState().error;
435
481
  },
436
482
  get lastUpdated() {
437
- return I.getState().lastUpdated;
483
+ return y.getState().lastUpdated;
438
484
  },
439
485
  // 공통코드 가져오기 (중앙 스토어 사용)
440
486
  fetchCommonCodes: async () => {
441
- await I.getState().fetchData();
487
+ await y.getState().fetchData();
442
488
  },
443
489
  // 1. 통합된 코드 목록 조회 (그룹코드 필수, 옵션으로 필터링)
444
490
  getCodeList: (e, s) => {
@@ -449,36 +495,36 @@ const E = (n) => (r) => {
449
495
  excludeParentCode: d = !1
450
496
  } = s || {}, c = `simpleCodeList_${e}_${o}_${t}_${a}_${d}`;
451
497
  if (p.optionCache.has(c)) {
452
- const h = p.cacheHits.get(c) || 0;
453
- return p.cacheHits.set(c, h + 1), p.optionCache.get(c);
498
+ const f = p.cacheHits.get(c) || 0;
499
+ return p.cacheHits.set(c, f + 1), p.optionCache.get(c);
454
500
  }
455
- const i = I.getState().codeData;
501
+ const i = y.getState().codeData;
456
502
  if (!i) return [];
457
503
  if (!p.isGroupLoaded(e) && !i[e])
458
504
  return console.warn(`그룹 ${e}가 아직 로드되지 않았습니다.`), [];
459
- const l = [], f = i[e];
460
- f && Object.values(f).forEach((h) => {
461
- if (!(o && !h.enabled) && !(t && h.systemCodeYn !== "Y"))
505
+ const l = [], h = i[e];
506
+ h && Object.values(h).forEach((f) => {
507
+ if (!(o && !f.enabled) && !(t && f.systemCodeYn !== "Y"))
462
508
  if (d) {
463
- const C = e.length, g = h.codeValue.substring(C);
509
+ const C = e.length, g = f.codeValue.substring(C);
464
510
  g.length > 0 && l.push({
465
- ...h,
511
+ ...f,
466
512
  codeValue: g
467
513
  // 자식코드만 사용
468
514
  });
469
515
  } else
470
- l.push(h);
516
+ l.push(f);
471
517
  });
472
518
  let m;
473
- a ? m = l.sort((h, C) => h.sortOrder !== C.sortOrder ? h.sortOrder - C.sortOrder : h.codeValue.localeCompare(C.codeValue)) : m = l.sort(
474
- (h, C) => h.codeValue.localeCompare(C.codeValue)
519
+ a ? m = l.sort((f, C) => f.sortOrder !== C.sortOrder ? f.sortOrder - C.sortOrder : f.codeValue.localeCompare(C.codeValue)) : m = l.sort(
520
+ (f, C) => f.codeValue.localeCompare(C.codeValue)
475
521
  );
476
- const u = m.map((h) => ({
477
- label: h.codeNm,
478
- value: h.codeValue,
479
- tagColor: h.labelColor
522
+ const u = m.map((f) => ({
523
+ label: f.codeNm,
524
+ value: f.codeValue,
525
+ tagColor: f.labelColor
480
526
  }));
481
- return p.optionCache.size >= A.CACHE_SIZE_LIMIT && p.cleanupCache(), p.optionCache.set(c, u), p.cacheHits.set(c, 1), u;
527
+ return p.optionCache.size >= w.CACHE_SIZE_LIMIT && p.cleanupCache(), p.optionCache.set(c, u), p.cacheHits.set(c, 1), u;
482
528
  },
483
529
  // 2. 코드를 던졌을 때 코드명을 리턴 (대규모 최적화)
484
530
  getCodeName: (e) => {
@@ -486,7 +532,7 @@ const E = (n) => (r) => {
486
532
  const o = p.cacheHits.get(`name_${e}`) || 0;
487
533
  return p.cacheHits.set(`name_${e}`, o + 1), p.nameCache.get(e);
488
534
  }
489
- const s = I.getState().codeData;
535
+ const s = y.getState().codeData;
490
536
  if (!s) return null;
491
537
  for (const o of Object.values(s))
492
538
  for (const t of Object.values(o))
@@ -500,7 +546,7 @@ const E = (n) => (r) => {
500
546
  const o = p.cacheHits.get(`color_${e}`) || 0;
501
547
  return p.cacheHits.set(`color_${e}`, o + 1), p.colorCache.get(e);
502
548
  }
503
- const s = I.getState().codeData;
549
+ const s = y.getState().codeData;
504
550
  if (!s) return null;
505
551
  for (const o of Object.values(s))
506
552
  for (const t of Object.values(o))
@@ -518,7 +564,7 @@ const E = (n) => (r) => {
518
564
  const i = p.cacheHits.get(s) || 0;
519
565
  return p.cacheHits.set(s, i + 1), p.optionCache.get(s);
520
566
  }
521
- const o = I.getState().codeData;
567
+ const o = y.getState().codeData;
522
568
  if (!o) return { labels: [], values: [], lookupDisplay: !0 };
523
569
  const t = o[e];
524
570
  if (!t) return { labels: [], values: [], lookupDisplay: !0 };
@@ -536,7 +582,7 @@ const E = (n) => (r) => {
536
582
  const l = p.cacheHits.get(t) || 0;
537
583
  return p.cacheHits.set(t, l + 1), p.codeCache.get(t);
538
584
  }
539
- const a = I.getState().codeData;
585
+ const a = y.getState().codeData;
540
586
  if (!a) return [];
541
587
  const d = [], c = a[e];
542
588
  c && Object.values(c).forEach((l) => {
@@ -547,9 +593,9 @@ const E = (n) => (r) => {
547
593
  });
548
594
  });
549
595
  const i = d.sort(
550
- (l, f) => l.codeValue.localeCompare(f.codeValue)
596
+ (l, h) => l.codeValue.localeCompare(h.codeValue)
551
597
  );
552
- return p.codeCache.size >= A.CACHE_SIZE_LIMIT && p.cleanupCache(), p.codeCache.set(t, i), p.cacheHits.set(t, 1), i;
598
+ return p.codeCache.size >= w.CACHE_SIZE_LIMIT && p.cleanupCache(), p.codeCache.set(t, i), p.cacheHits.set(t, 1), i;
553
599
  },
554
600
  // 6. 옵션코드별로 코드 목록 조회 (SimpleCodeItem 형태로 반환)
555
601
  getCodeListByOption: (e, s, o) => {
@@ -564,12 +610,12 @@ const E = (n) => (r) => {
564
610
  c
565
611
  );
566
612
  }
567
- const i = I.getState().codeData;
613
+ const i = y.getState().codeData;
568
614
  if (!i) return [];
569
615
  if (!p.isGroupLoaded(e) && !i[e])
570
616
  return console.warn(`그룹 ${e}가 아직 로드되지 않았습니다.`), [];
571
- const l = [], f = i[e];
572
- f && Object.values(f).forEach((u) => {
617
+ const l = [], h = i[e];
618
+ h && Object.values(h).forEach((u) => {
573
619
  t && !u.enabled || a && u.systemCodeYn !== "Y" || u.options && u.options[s] && l.push({
574
620
  label: u.options[s],
575
621
  // optnNm 값
@@ -580,9 +626,9 @@ const E = (n) => (r) => {
580
626
  });
581
627
  });
582
628
  let m;
583
- return d ? m = l.sort((u, h) => u.value.localeCompare(h.value)) : m = l.sort(
584
- (u, h) => u.value.localeCompare(h.value)
585
- ), p.codeCache.size >= A.CACHE_SIZE_LIMIT && p.cleanupCache(), p.codeCache.set(c, m), p.cacheHits.set(c, 1), m;
629
+ return d ? m = l.sort((u, f) => u.value.localeCompare(f.value)) : m = l.sort(
630
+ (u, f) => u.value.localeCompare(f.value)
631
+ ), p.codeCache.size >= w.CACHE_SIZE_LIMIT && p.cleanupCache(), p.codeCache.set(c, m), p.cacheHits.set(c, 1), m;
586
632
  },
587
633
  // 7. 그룹코드 목록 조회
588
634
  getAvailableGroupCodes: () => {
@@ -591,7 +637,7 @@ const E = (n) => (r) => {
591
637
  const t = p.cacheHits.get(e) || 0;
592
638
  return p.cacheHits.set(e, t + 1), JSON.parse(p.nameCache.get(e));
593
639
  }
594
- const s = I.getState().codeData;
640
+ const s = y.getState().codeData;
595
641
  if (!s) return [];
596
642
  const o = Object.keys(s).sort();
597
643
  return p.nameCache.set(
@@ -601,7 +647,7 @@ const E = (n) => (r) => {
601
647
  },
602
648
  // 공통코드 초기화
603
649
  clearCodes: () => {
604
- I.getState().clearData();
650
+ y.getState().clearData();
605
651
  }
606
652
  }),
607
653
  {
@@ -611,25 +657,25 @@ const E = (n) => (r) => {
611
657
  })
612
658
  }
613
659
  )
614
- ), ve = b()(
660
+ ), Pe = N()(
615
661
  M(
616
662
  (n, r) => ({
617
663
  // 공통 데이터 스토어에서 상태 가져오기
618
664
  get codeData() {
619
- return I.getState().codeData;
665
+ return y.getState().codeData;
620
666
  },
621
667
  get isLoading() {
622
- return I.getState().isLoading;
668
+ return y.getState().isLoading;
623
669
  },
624
670
  get error() {
625
- return I.getState().error;
671
+ return y.getState().error;
626
672
  },
627
673
  get lastUpdated() {
628
- return I.getState().lastUpdated;
674
+ return y.getState().lastUpdated;
629
675
  },
630
676
  // 공통코드 가져오기 (중앙 스토어 사용)
631
677
  fetchCommonCodes: async () => {
632
- await I.getState().fetchData();
678
+ await y.getState().fetchData();
633
679
  },
634
680
  // 그룹코드와 옵션코드를 던졌을 때 상세코드의 옵션값을 리턴 (대규모 최적화)
635
681
  getOptionValue: (e, s) => {
@@ -638,7 +684,7 @@ const E = (n) => (r) => {
638
684
  const d = p.cacheHits.get(o) || 0;
639
685
  return p.cacheHits.set(o, d + 1), p.optionCache.get(o);
640
686
  }
641
- const t = I.getState().codeData;
687
+ const t = y.getState().codeData;
642
688
  if (!t) return null;
643
689
  const a = t[e];
644
690
  if (a && a[s]) {
@@ -659,7 +705,7 @@ const E = (n) => (r) => {
659
705
  },
660
706
  // 공통코드 초기화
661
707
  clearCodes: () => {
662
- I.getState().clearData();
708
+ y.getState().clearData();
663
709
  }
664
710
  }),
665
711
  {
@@ -669,25 +715,25 @@ const E = (n) => (r) => {
669
715
  })
670
716
  }
671
717
  )
672
- ), Pe = b()(
718
+ ), Le = N()(
673
719
  M(
674
720
  (n, r) => ({
675
721
  // 공통 데이터 스토어에서 상태 가져오기
676
722
  get codeData() {
677
- return I.getState().codeData;
723
+ return y.getState().codeData;
678
724
  },
679
725
  get isLoading() {
680
- return I.getState().isLoading;
726
+ return y.getState().isLoading;
681
727
  },
682
728
  get error() {
683
- return I.getState().error;
729
+ return y.getState().error;
684
730
  },
685
731
  get lastUpdated() {
686
- return I.getState().lastUpdated;
732
+ return y.getState().lastUpdated;
687
733
  },
688
734
  // 공통코드 가져오기 (중앙 스토어 사용)
689
735
  fetchCommonCodes: async () => {
690
- await I.getState().fetchData();
736
+ await y.getState().fetchData();
691
737
  },
692
738
  // 코드를 던졌을 때 컬러코드를 리턴 (대규모 최적화)
693
739
  getColorCode: (e) => {
@@ -695,7 +741,7 @@ const E = (n) => (r) => {
695
741
  const o = p.cacheHits.get(`color_${e}`) || 0;
696
742
  return p.cacheHits.set(`color_${e}`, o + 1), p.colorCache.get(e);
697
743
  }
698
- const s = I.getState().codeData;
744
+ const s = y.getState().codeData;
699
745
  if (!s) return null;
700
746
  for (const o of Object.values(s))
701
747
  for (const t of Object.values(o))
@@ -713,7 +759,7 @@ const E = (n) => (r) => {
713
759
  const t = p.cacheHits.get(e) || 0;
714
760
  return p.cacheHits.set(e, t + 1), p.optionCache.get(e);
715
761
  }
716
- const s = I.getState().codeData;
762
+ const s = y.getState().codeData;
717
763
  if (!s) return [];
718
764
  const o = [];
719
765
  return Object.values(s).forEach((t) => {
@@ -727,7 +773,7 @@ const E = (n) => (r) => {
727
773
  },
728
774
  // 공통코드 초기화
729
775
  clearCodes: () => {
730
- I.getState().clearData();
776
+ y.getState().clearData();
731
777
  }
732
778
  }),
733
779
  {
@@ -737,7 +783,7 @@ const E = (n) => (r) => {
737
783
  })
738
784
  }
739
785
  )
740
- ), de = (n, r) => ({
786
+ ), ce = (n, r) => ({
741
787
  nodes: {},
742
788
  rootIds: [],
743
789
  loadedFor: void 0,
@@ -749,11 +795,11 @@ const E = (n) => (r) => {
749
795
  (s) => s.type === "M" && s.menuId === e
750
796
  ),
751
797
  getPrntBkmkIdByMenuId: (e) => {
752
- const s = O(r().nodes, e);
798
+ const s = D(r().nodes, e);
753
799
  return s ? r().nodes[s]?.prntBkmkId ?? "-" : "-";
754
800
  },
755
801
  getNodeByMenuId: (e) => {
756
- const s = O(r().nodes, e);
802
+ const s = D(r().nodes, e);
757
803
  if (!s) return null;
758
804
  const o = r().nodes[s];
759
805
  return o?.type === "M" ? o : null;
@@ -778,7 +824,7 @@ const E = (n) => (r) => {
778
824
  if (!(!s && o.loadedFor === e && Object.keys(o.nodes).length)) {
779
825
  n({ loading: !0, error: void 0 });
780
826
  try {
781
- const t = await N("SCMBKMK00101", { userId: e }), a = Array.isArray(t?.sub) ? t.sub : [], d = ce(a), c = D(
827
+ const t = await b("SCMBKMK00101", { userId: e }), a = Array.isArray(t?.sub) ? t.sub : [], d = pe(a), c = L(
782
828
  d.nodes,
783
829
  d.rootIds
784
830
  );
@@ -809,7 +855,7 @@ const E = (n) => (r) => {
809
855
  },
810
856
  // ====== 공통: 생성 ======
811
857
  addNode: async (e) => {
812
- const s = K(r()), o = pe();
858
+ const s = _(r()), o = le();
813
859
  n((t) => {
814
860
  const a = e.sortOrdr ?? U(t, e.prntBkmkId), d = {
815
861
  ...t,
@@ -838,11 +884,11 @@ const E = (n) => (r) => {
838
884
  rootIds: t.rootIds.slice(),
839
885
  treeNodes: t.treeNodes
840
886
  };
841
- return le(d, o, e.prntBkmkId), d.treeNodes = D(d.nodes, d.rootIds), d;
887
+ return ie(d, o, e.prntBkmkId), d.treeNodes = L(d.nodes, d.rootIds), d;
842
888
  });
843
889
  try {
844
890
  let t = o;
845
- const a = U(r(), e.prntBkmkId), d = await N("SCMBKMK00102", {
891
+ const a = U(r(), e.prntBkmkId), d = await b("SCMBKMK00102", {
846
892
  iudFlag: "I",
847
893
  type: e.type,
848
894
  sysCd: e.sysCd,
@@ -856,10 +902,10 @@ const E = (n) => (r) => {
856
902
  chngId: v()
857
903
  });
858
904
  return t = String(d?.bkmkId ?? d?.itemId ?? o), n((c) => {
859
- const i = ue(c, o, t);
905
+ const i = me(c, o, t);
860
906
  return {
861
907
  ...i,
862
- treeNodes: D(i.nodes, i.rootIds)
908
+ treeNodes: L(i.nodes, i.rootIds)
863
909
  };
864
910
  }), t;
865
911
  } catch (t) {
@@ -875,10 +921,10 @@ const E = (n) => (r) => {
875
921
  if (!u || u.type !== "F")
876
922
  throw new Error("부모는 폴더만 가능합니다.");
877
923
  }
878
- const l = i.prntBkmkId ?? "-", f = l === "-" ? c : d[l].children ||= [];
924
+ const l = i.prntBkmkId ?? "-", h = l === "-" ? c : d[l].children ||= [];
879
925
  {
880
- const u = f.indexOf(e);
881
- u >= 0 && f.splice(u, 1);
926
+ const u = h.indexOf(e);
927
+ u >= 0 && h.splice(u, 1);
882
928
  }
883
929
  const m = s === "-" ? c : d[s].children ||= [];
884
930
  m.splice(
@@ -887,7 +933,7 @@ const E = (n) => (r) => {
887
933
  e
888
934
  ), i.prntBkmkId = s, n({ nodes: d, rootIds: c }), z(d, c, s), z(d, c, l);
889
935
  try {
890
- await N("SCMBKMK00104", {
936
+ await b("SCMBKMK00104", {
891
937
  // 백엔드 명칭 호환
892
938
  bkmkId: e,
893
939
  prntBkmkId: s,
@@ -900,7 +946,7 @@ const E = (n) => (r) => {
900
946
  },
901
947
  // ====== 공통: 삭제 ======
902
948
  removeNode: async (e) => {
903
- const s = K(r());
949
+ const s = _(r());
904
950
  n((o) => {
905
951
  if (!o.nodes[e]) return o;
906
952
  const t = {
@@ -909,17 +955,17 @@ const E = (n) => (r) => {
909
955
  rootIds: o.rootIds.slice(),
910
956
  treeNodes: o.treeNodes
911
957
  };
912
- return J(t, e), t.treeNodes = D(t.nodes, t.rootIds), t;
958
+ return J(t, e), t.treeNodes = L(t.nodes, t.rootIds), t;
913
959
  });
914
960
  try {
915
- await N("SCMBKMK00103", { bkmkId: e });
961
+ await b("SCMBKMK00103", { bkmkId: e });
916
962
  } catch (o) {
917
963
  throw n(s), o;
918
964
  }
919
965
  },
920
966
  // ====== 공통: 수정 ======
921
967
  editNode: async ({ bkmkId: e, userId: s, bkmkNm: o, prntBkmkId: t, sortOrdr: a }) => {
922
- const d = K(r());
968
+ const d = _(r());
923
969
  n((c) => {
924
970
  const i = { ...c, nodes: { ...c.nodes } }, l = i.nodes[e];
925
971
  return l?.type === "F" && typeof o == "string" && (i.nodes[e] = {
@@ -928,7 +974,7 @@ const E = (n) => (r) => {
928
974
  }), i;
929
975
  });
930
976
  try {
931
- await N("SCMBKMK00102", {
977
+ await b("SCMBKMK00102", {
932
978
  iudFlag: "U",
933
979
  userId: s,
934
980
  bkmkId: e,
@@ -949,7 +995,7 @@ const E = (n) => (r) => {
949
995
  sysCd: o,
950
996
  userId: t
951
997
  }),
952
- addMenuToFolder: async (e, s) => O(r().nodes, s.menuId) ? "이미 북마크에 저장된 메뉴입니다." : await r().addNode({
998
+ addMenuToFolder: async (e, s) => D(r().nodes, s.menuId) ? "이미 북마크에 저장된 메뉴입니다." : await r().addNode({
953
999
  type: "M",
954
1000
  prntBkmkId: e,
955
1001
  sysCd: "KH",
@@ -977,7 +1023,7 @@ const E = (n) => (r) => {
977
1023
  });
978
1024
  },
979
1025
  removeMenuByMenuId: async (e) => {
980
- const s = r(), o = O(s.nodes, e);
1026
+ const s = r(), o = D(s.nodes, e);
981
1027
  o && await r().removeNode(o);
982
1028
  },
983
1029
  removeMenu: async (e) => {
@@ -1001,8 +1047,8 @@ const E = (n) => (r) => {
1001
1047
  const i = e[c];
1002
1048
  if (!i || t && i.type !== "F") return null;
1003
1049
  if (i.type === "F") {
1004
- const l = i, f = (l.children || []).map((u) => d(u)).filter(Boolean);
1005
- return a(l.bkmkNm) || f.length > 0 ? {
1050
+ const l = i, h = (l.children || []).map((u) => d(u)).filter(Boolean);
1051
+ return a(l.bkmkNm) || h.length > 0 ? {
1006
1052
  key: l.bkmkId,
1007
1053
  type: "F",
1008
1054
  title: `📁 ${l.bkmkNm}`,
@@ -1010,14 +1056,14 @@ const E = (n) => (r) => {
1010
1056
  prntBkmkId: l.prntBkmkId,
1011
1057
  sortOrdr: l.sortOrdr,
1012
1058
  fullPath: l.fullPath,
1013
- children: f.length ? f : void 0
1059
+ children: h.length ? h : void 0
1014
1060
  } : null;
1015
1061
  } else {
1016
- const l = i, f = l.menuNm ? `${l.menuNm} (${l.menuId})` : l.menuId;
1017
- return a(f) ? {
1062
+ const l = i, h = l.menuNm ? `${l.menuNm} (${l.menuId})` : l.menuId;
1063
+ return a(h) ? {
1018
1064
  key: l.bkmkId,
1019
1065
  type: "M",
1020
- title: `📄 ${f}`,
1066
+ title: `📄 ${h}`,
1021
1067
  prntBkmkId: l.prntBkmkId,
1022
1068
  sortOrdr: l.sortOrdr,
1023
1069
  fullPath: l.fullPath,
@@ -1027,8 +1073,8 @@ const E = (n) => (r) => {
1027
1073
  };
1028
1074
  return s.map(d).filter(Boolean);
1029
1075
  }
1030
- }), q = b(de);
1031
- function ce(n) {
1076
+ }), q = N(ce);
1077
+ function pe(n) {
1032
1078
  const r = {}, e = [], s = (o) => {
1033
1079
  o.forEach((t) => {
1034
1080
  const a = {
@@ -1067,14 +1113,14 @@ function ce(n) {
1067
1113
  );
1068
1114
  }), { nodes: r, rootIds: e };
1069
1115
  }
1070
- function K(n) {
1116
+ function _(n) {
1071
1117
  return {
1072
1118
  ...n,
1073
1119
  nodes: JSON.parse(JSON.stringify(n.nodes)),
1074
1120
  rootIds: n.rootIds.slice()
1075
1121
  };
1076
1122
  }
1077
- function pe() {
1123
+ function le() {
1078
1124
  return `tmp_${Math.random().toString(36).slice(2, 10)}`;
1079
1125
  }
1080
1126
  function U(n, r) {
@@ -1082,7 +1128,7 @@ function U(n, r) {
1082
1128
  const e = n.nodes[r];
1083
1129
  return e ? e.children.length : 0;
1084
1130
  }
1085
- function le(n, r, e) {
1131
+ function ie(n, r, e) {
1086
1132
  const s = n.nodes[r];
1087
1133
  if (s)
1088
1134
  if (e && e !== "-") {
@@ -1092,7 +1138,7 @@ function le(n, r, e) {
1092
1138
  } else
1093
1139
  s.prntBkmkId = "-", n.rootIds = [...n.rootIds, r];
1094
1140
  }
1095
- function ie(n, r) {
1141
+ function ue(n, r) {
1096
1142
  const e = n.nodes[r];
1097
1143
  if (!e) return;
1098
1144
  const s = e.prntBkmkId;
@@ -1105,11 +1151,11 @@ function ie(n, r) {
1105
1151
  function J(n, r) {
1106
1152
  const e = n.nodes[r];
1107
1153
  if (!e) return;
1108
- e.type === "F" && e.children.slice().forEach((a) => J(n, a)), ie(n, r);
1154
+ e.type === "F" && e.children.slice().forEach((a) => J(n, a)), ue(n, r);
1109
1155
  const { [r]: s, ...o } = n.nodes;
1110
1156
  n.nodes = o;
1111
1157
  }
1112
- function ue(n, r, e) {
1158
+ function me(n, r, e) {
1113
1159
  if (r === e) return n;
1114
1160
  const s = n.nodes[r];
1115
1161
  if (!s) return n;
@@ -1131,7 +1177,7 @@ function ue(n, r, e) {
1131
1177
  function x(n) {
1132
1178
  return n.rootIds.find((r) => n.nodes[r]?.type === "F") ?? null;
1133
1179
  }
1134
- function D(n, r) {
1180
+ function L(n, r) {
1135
1181
  const e = {};
1136
1182
  Object.values(n).forEach((c) => {
1137
1183
  const i = c.bkmkId, l = c.prntBkmkId;
@@ -1144,12 +1190,12 @@ function D(n, r) {
1144
1190
  s.add(c);
1145
1191
  try {
1146
1192
  if (i.type === "F") {
1147
- const f = i, m = e[c] ?? [];
1193
+ const h = i, m = e[c] ?? [];
1148
1194
  return {
1149
1195
  type: "F",
1150
1196
  bkmkId: c,
1151
- bkmkNm: f.bkmkNm,
1152
- prntBkmkId: f.prntBkmkId,
1197
+ bkmkNm: h.bkmkNm,
1198
+ prntBkmkId: h.prntBkmkId,
1153
1199
  children: m.map(o).filter(Boolean)
1154
1200
  };
1155
1201
  }
@@ -1170,7 +1216,7 @@ function D(n, r) {
1170
1216
  /* @__PURE__ */ new Set([...r, ...t, ...a])
1171
1217
  ).map(o).filter(Boolean);
1172
1218
  }
1173
- function O(n, r) {
1219
+ function D(n, r) {
1174
1220
  for (const e of Object.values(n))
1175
1221
  if (e.type === "M" && e.menuId === r) return e.bkmkId;
1176
1222
  return null;
@@ -1181,19 +1227,19 @@ function z(n, r, e) {
1181
1227
  a && (a.sortOrdr = t);
1182
1228
  });
1183
1229
  }
1184
- const T = {
1230
+ const E = {
1185
1231
  DEFAULT_PRNT_GBCD: 1
1186
- }, me = (n) => n && typeof n == "object" && typeof n.menuId == "string" && typeof n.menuNm == "string", j = (n) => Array.isArray(n) && n.every(me);
1187
- let B = [], Y = [];
1188
- const Ce = (n) => {
1232
+ }, Ce = (n) => n && typeof n == "object" && typeof n.menuId == "string" && typeof n.menuNm == "string", j = (n) => Array.isArray(n) && n.every(Ce);
1233
+ let A = [], Y = [];
1234
+ const fe = (n) => {
1189
1235
  if (n && typeof n == "object") {
1190
1236
  const r = n;
1191
1237
  if (r.menus && j(r.menus)) return r.menus;
1192
1238
  if (j(n)) return n;
1193
1239
  }
1194
1240
  return console.warn("⚠️ 메뉴 응답이 비어있거나 예상과 다릅니다."), [];
1195
- }, he = (n, r) => !!r && n.crprCd === r.crprCd && n.userId === r.userId && (n.prntGbcd ?? T.DEFAULT_PRNT_GBCD) === (r.prntGbcd ?? T.DEFAULT_PRNT_GBCD), fe = (n) => {
1196
- if (B.length === n.length && B.every(
1241
+ }, he = (n, r) => !!r && n.crprCd === r.crprCd && n.userId === r.userId && (n.prntGbcd ?? E.DEFAULT_PRNT_GBCD) === (r.prntGbcd ?? E.DEFAULT_PRNT_GBCD), ye = (n) => {
1242
+ if (A.length === n.length && A.every(
1197
1243
  (t, a) => t.menuId === n[a]?.menuId && t.menuPrntId === n[a]?.menuPrntId
1198
1244
  ))
1199
1245
  return Y;
@@ -1207,8 +1253,8 @@ const Ce = (n) => {
1207
1253
  ...a,
1208
1254
  children: a.children && a.children.length ? s(a.children) : void 0
1209
1255
  })), o = s(e);
1210
- return B = [...n], Y = o, o;
1211
- }, R = b((n, r) => ({
1256
+ return A = [...n], Y = o, o;
1257
+ }, R = N((n, r) => ({
1212
1258
  // 📊 초기 상태값
1213
1259
  menuList: [],
1214
1260
  flatMenuList: [],
@@ -1221,7 +1267,7 @@ const Ce = (n) => {
1221
1267
  const t = {
1222
1268
  crprCd: e,
1223
1269
  userId: s,
1224
- prntGbcd: o ?? T.DEFAULT_PRNT_GBCD
1270
+ prntGbcd: o ?? E.DEFAULT_PRNT_GBCD
1225
1271
  };
1226
1272
  if (he(t, r()._lastFetchParams)) {
1227
1273
  console.log("✅ 중복 fetch 차단", t);
@@ -1229,7 +1275,7 @@ const Ce = (n) => {
1229
1275
  }
1230
1276
  n({ isLoading: !0, error: null, _lastFetchParams: t });
1231
1277
  try {
1232
- const a = await N(w("AUTH_MENU"), t), d = Ce(a), c = fe(d);
1278
+ const a = await b(F("AUTH_MENU"), t), d = fe(a), c = ye(d);
1233
1279
  n({
1234
1280
  flatMenuList: d,
1235
1281
  // 평면 리스트 저장
@@ -1258,19 +1304,21 @@ const Ce = (n) => {
1258
1304
  const { flatMenuList: s } = r();
1259
1305
  return s.find((o) => o.menuId === e) ?? null;
1260
1306
  }
1261
- })), F = {
1307
+ })), O = {
1262
1308
  MAX_TABS: 15
1263
- }, Z = b((n, r) => ({
1309
+ }, Z = N((n, r) => ({
1264
1310
  // 📊 초기 상태값
1265
1311
  activeMenuId: null,
1266
1312
  activeMenuItem: null,
1267
1313
  activeDetailItem: null,
1268
1314
  tabs: [],
1269
1315
  sidebarCollapsed: !1,
1270
- maxTabs: F.MAX_TABS,
1316
+ maxTabs: O.MAX_TABS,
1271
1317
  tabProtectFlag: {},
1272
1318
  tabParams: {},
1273
1319
  componentLabelMap: {},
1320
+ pinnedTabs: /* @__PURE__ */ new Set(),
1321
+ refreshTabKey: {},
1274
1322
  clearMenuViewStore: () => {
1275
1323
  n({
1276
1324
  activeMenuId: null,
@@ -1278,48 +1326,66 @@ const Ce = (n) => {
1278
1326
  activeDetailItem: null,
1279
1327
  tabs: [],
1280
1328
  sidebarCollapsed: !1,
1281
- maxTabs: F.MAX_TABS,
1329
+ maxTabs: O.MAX_TABS,
1282
1330
  tabProtectFlag: {},
1283
1331
  tabParams: {},
1284
- componentLabelMap: {}
1332
+ componentLabelMap: {},
1333
+ pinnedTabs: /* @__PURE__ */ new Set(),
1334
+ refreshTabKey: {}
1285
1335
  });
1286
1336
  },
1287
1337
  // 🔧 탭 추가 (메뉴 아이템 객체로)
1288
1338
  // 사이드바에서 메뉴 클릭 시 호출되는 메인 함수
1289
- openTabFromMenu: (e, s) => {
1290
- const { tabs: o } = r(), t = o.find((d) => d.key === e.menuId), a = o.find((d) => d.key === e.menuId);
1291
- if (t)
1292
- a != null ? (n({ activeMenuId: e.menuId, activeMenuItem: e }), r().setTabParams(e.menuId, s || {}), e?.prsnInfoYn === "Y" && r().setProtectFlagForKey(e.menuId)) : L.warning("유효하지 않은 메뉴정보입니다.");
1293
- else {
1294
- if (o.length > F.MAX_TABS) {
1295
- console.warn("❌ 최대 탭 개수를 초과했습니다."), L.warning(
1296
- `최대 ${F.MAX_TABS}개의 탭만 열 수 있습니다.
1297
- 기존 탭을 닫고 다시 시도해주세요.`
1298
- );
1339
+ openTabFromMenu: (e, s, o) => {
1340
+ const { tabs: t } = r(), a = t.find((i) => i.key === e.menuId), d = o?.skipRefreshModal ?? !1;
1341
+ if (a) {
1342
+ if (d) {
1343
+ r().focusTab(e.menuId), r().setTabParams(e.menuId, s || {}), e?.prsnInfoYn === "Y" && r().setProtectFlagForKey(e.menuId);
1299
1344
  return;
1300
1345
  }
1301
- const d = {
1302
- key: e.menuId,
1303
- label: e.menuNm,
1304
- gubun: "M",
1305
- menuItem: e,
1306
- closable: !0
1307
- };
1308
- n({
1309
- tabs: [...o, d],
1310
- // 목록에 추가
1311
- activeMenuId: e.menuId,
1312
- // 새 탭을 활성화
1313
- activeMenuItem: e
1314
- // 현재 프로그램으로 설정
1315
- }), r().setTabParams(e.menuId, s || {}), e?.prsnInfoYn === "Y" && r().setProtectFlagForKey(e.menuId);
1346
+ se.confirm({
1347
+ title: `[${e.menuNm}] 메뉴이동 알림`,
1348
+ content: "이미 열린 화면입니다. 새로고침 하시겠습니까?",
1349
+ centered: !0,
1350
+ okText: "예",
1351
+ cancelText: "아니오",
1352
+ onOk: () => {
1353
+ r().refreshTab(e.menuId), r().focusTab(e.menuId), r().setTabParams(e.menuId, s || {}), e?.prsnInfoYn === "Y" && r().setProtectFlagForKey(e.menuId);
1354
+ },
1355
+ onCancel: () => {
1356
+ r().focusTab(e.menuId), r().setTabParams(e.menuId, s || {}), e?.prsnInfoYn === "Y" && r().setProtectFlagForKey(e.menuId);
1357
+ }
1358
+ });
1359
+ return;
1316
1360
  }
1361
+ if (t.length >= O.MAX_TABS) {
1362
+ console.warn("❌ 최대 탭 개수를 초과했습니다."), K.warning(
1363
+ `최대 ${O.MAX_TABS}개의 탭만 열 수 있습니다.
1364
+ 기존 탭을 닫고 다시 시도해주세요.`
1365
+ );
1366
+ return;
1367
+ }
1368
+ const c = {
1369
+ key: e.menuId,
1370
+ label: e.menuNm,
1371
+ gubun: "M",
1372
+ menuItem: e,
1373
+ closable: !0
1374
+ };
1375
+ n({
1376
+ tabs: [...t, c],
1377
+ // 탭 목록에 추가
1378
+ activeMenuId: e.menuId,
1379
+ // 새 탭을 활성화
1380
+ activeMenuItem: e
1381
+ // 현재 프로그램으로 설정
1382
+ }), r().setTabParams(e.menuId, s || {}), e?.prsnInfoYn === "Y" && r().setProtectFlagForKey(e.menuId);
1317
1383
  },
1318
1384
  // 🔧 탭 추가 (메뉴 ID로)
1319
1385
  // URL 파라미터로 메뉴 열기 시 사용 (예: ?menuId=CM000301)
1320
- openTabByMenuId: (e, s) => {
1321
- const o = R.getState().findMenuById(e);
1322
- o ? r().openTabFromMenu(o, s) : L.warning("메뉴 ID를 찾을 수 없습니다.");
1386
+ openTabByMenuId: (e, s, o) => {
1387
+ const t = R.getState().findMenuById(e);
1388
+ t ? r().openTabFromMenu(t, s, o) : K.warning("메뉴 ID를 찾을 수 없습니다.");
1323
1389
  },
1324
1390
  openDetailView: (e, s, o) => {
1325
1391
  const { tabs: t } = r();
@@ -1349,17 +1415,19 @@ const Ce = (n) => {
1349
1415
  // 🔧 탭 제거
1350
1416
  // X 버튼 클릭 시 탭을 닫고 관련 상태도 정리
1351
1417
  closeTab: (e) => {
1352
- const { tabs: s, activeMenuId: o } = r();
1353
- s.find((d) => d.key === e);
1354
- const t = s.filter((d) => d.key !== e);
1355
- let a = o;
1418
+ const { tabs: s, activeMenuId: o, pinnedTabs: t } = r();
1419
+ if (t.has(e))
1420
+ return;
1421
+ s.find((c) => c.key === e);
1422
+ const a = s.filter((c) => c.key !== e);
1423
+ let d = o;
1356
1424
  if (o === e) {
1357
- const d = s.findIndex((c) => c.key === e);
1358
- a = t.length ? t[Math.min(d, t.length - 1)]?.key ?? null : null;
1425
+ const c = s.findIndex((i) => i.key === e);
1426
+ d = a.length ? a[Math.min(c, a.length - 1)]?.key ?? null : null;
1359
1427
  }
1360
1428
  n({
1361
- tabs: t
1362
- }), a && r().focusTab(a);
1429
+ tabs: a
1430
+ }), d && r().focusTab(d);
1363
1431
  },
1364
1432
  // 🔧 활성 탭 변경
1365
1433
  // 탭 헤더 클릭 시 해당 탭으로 전환
@@ -1423,8 +1491,36 @@ const Ce = (n) => {
1423
1491
  };
1424
1492
  }),
1425
1493
  // 컴포넌트 라벨 맵 설정
1426
- setComponentLabelMap: (e, s) => n({ componentLabelMap: e })
1427
- })), Ie = b((n, r) => ({
1494
+ setComponentLabelMap: (e, s) => n({ componentLabelMap: e }),
1495
+ // 고정 토글
1496
+ togglePinTab: (e) => n((s) => {
1497
+ const o = new Set(s.pinnedTabs);
1498
+ return o.has(e) ? o.delete(e) : o.add(e), { pinnedTabs: o };
1499
+ }),
1500
+ // 탭 새로고침 (ContentContainer 재적재를 위한 키 변경)
1501
+ refreshTab: (e) => n((s) => ({
1502
+ refreshTabKey: {
1503
+ ...s.refreshTabKey,
1504
+ [e]: Date.now()
1505
+ }
1506
+ })),
1507
+ // 다른 탭 닫기
1508
+ closeOtherTabs: (e) => {
1509
+ const { tabs: s, activeMenuId: o } = r();
1510
+ if (!s.find((c) => c.key === e)) return;
1511
+ const a = r().pinnedTabs;
1512
+ s.filter(
1513
+ (c) => c.key !== e && !a.has(c.key)
1514
+ ).forEach((c) => r().closeTab(c.key)), o !== e && r().focusTab(e);
1515
+ },
1516
+ // 우측 탭 닫기
1517
+ closeRightTabs: (e) => {
1518
+ const { tabs: s } = r(), o = s.findIndex((d) => d.key === e);
1519
+ if (o < 0) return;
1520
+ const t = r().pinnedTabs;
1521
+ s.slice(o + 1).filter((d) => !t.has(d.key)).forEach((d) => r().closeTab(d.key));
1522
+ }
1523
+ })), Ie = N((n, r) => ({
1428
1524
  popups: [],
1429
1525
  activePopupId: null,
1430
1526
  isLoading: !1,
@@ -1435,7 +1531,7 @@ const Ce = (n) => {
1435
1531
  n({ isLoading: !0, error: null });
1436
1532
  try {
1437
1533
  let t = null;
1438
- const a = await N(w("SRCH_POPU"), {
1534
+ const a = await b(F("SRCH_POPU"), {
1439
1535
  crprCd: ee()?.crprCd,
1440
1536
  popuCd: e
1441
1537
  });
@@ -1445,7 +1541,7 @@ const Ce = (n) => {
1445
1541
  const u = `팝업 정보를 찾을 수 없습니다: ${e}`;
1446
1542
  throw console.error(u), new Error(u);
1447
1543
  }
1448
- const i = ((u) => `/src/pages/views/popup/${u}`)(t.popuUrl), l = r().zIndexSeed + 1, f = {
1544
+ const i = ((u) => `/src/pages/views/popup/${u}`)(t.popuUrl), l = r().zIndexSeed + 1, h = {
1449
1545
  popupId: `popup_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
1450
1546
  popupCode: e,
1451
1547
  //config.title을 통해 팝업 제목 변경 가능
@@ -1472,8 +1568,8 @@ const Ce = (n) => {
1472
1568
  return;
1473
1569
  }
1474
1570
  n((u) => ({
1475
- popups: [...u.popups, f],
1476
- activePopupId: f.popupId,
1571
+ popups: [...u.popups, h],
1572
+ activePopupId: h.popupId,
1477
1573
  isLoading: !1,
1478
1574
  zIndexSeed: l
1479
1575
  }));
@@ -1486,7 +1582,7 @@ const Ce = (n) => {
1486
1582
  },
1487
1583
  // 로컬 팝업 열기 (DB 조회 없이 레지스트리 매핑으로 렌더)
1488
1584
  openCorePopup: (e, s) => {
1489
- const o = `popup_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, t = r().zIndexSeed + 1, d = se[e]?.defaultConfig || {}, c = {
1585
+ const o = `popup_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`, t = r().zIndexSeed + 1, d = ne[e]?.defaultConfig || {}, c = {
1490
1586
  ...d,
1491
1587
  ...s,
1492
1588
  // buttons와 callback은 완전히 덮어쓰기 (병합하지 않음)
@@ -1499,19 +1595,19 @@ const Ce = (n) => {
1499
1595
  const m = r().zIndexSeed + 1;
1500
1596
  n({ activePopupId: l.popupId, zIndexSeed: m }), n((u) => ({
1501
1597
  popups: u.popups.map(
1502
- (h) => h.popupId === l.popupId ? {
1503
- ...h,
1598
+ (f) => f.popupId === l.popupId ? {
1599
+ ...f,
1504
1600
  config: c,
1505
1601
  zIndex: m,
1506
1602
  close: () => {
1507
1603
  r().closePopup(l.popupId);
1508
1604
  }
1509
- } : h
1605
+ } : f
1510
1606
  )
1511
1607
  }));
1512
1608
  return;
1513
1609
  }
1514
- const f = {
1610
+ const h = {
1515
1611
  popupId: o,
1516
1612
  popupCode: e,
1517
1613
  popupTitle: c.title || e,
@@ -1531,7 +1627,7 @@ const Ce = (n) => {
1531
1627
  }
1532
1628
  };
1533
1629
  n((m) => ({
1534
- popups: [...m.popups, f],
1630
+ popups: [...m.popups, h],
1535
1631
  activePopupId: o,
1536
1632
  zIndexSeed: t
1537
1633
  }));
@@ -1571,7 +1667,7 @@ const Ce = (n) => {
1571
1667
  )
1572
1668
  }));
1573
1669
  }
1574
- })), V = b()(
1670
+ })), V = N()(
1575
1671
  M(
1576
1672
  (n, r) => ({
1577
1673
  systemMap: [],
@@ -1980,7 +2076,7 @@ const Ce = (n) => {
1980
2076
  // localStorage key
1981
2077
  }
1982
2078
  )
1983
- ), De = b((n) => ({
2079
+ ), De = N((n) => ({
1984
2080
  requestCount: 0,
1985
2081
  loading: !1,
1986
2082
  showLoading: () => n((r) => {
@@ -1991,7 +2087,7 @@ const Ce = (n) => {
1991
2087
  const e = Math.max(0, r.requestCount - 1);
1992
2088
  return { requestCount: e, loading: e > 0 };
1993
2089
  })
1994
- })), Oe = b((n) => ({
2090
+ })), Oe = N((n) => ({
1995
2091
  requestCount: 0,
1996
2092
  loading: !1,
1997
2093
  showLoading: () => n((r) => {
@@ -2003,7 +2099,7 @@ const Ce = (n) => {
2003
2099
  return { requestCount: e, loading: e > 0 };
2004
2100
  })
2005
2101
  }));
2006
- function ye() {
2102
+ function ge() {
2007
2103
  const [n, r] = X(!1), e = W((s) => {
2008
2104
  const o = s?.getModifierState?.("CapsLock");
2009
2105
  typeof o == "boolean" && r(o);
@@ -2017,26 +2113,26 @@ function Fe(n) {
2017
2113
  onAfterLogin: s,
2018
2114
  onError: o,
2019
2115
  rememberCookie: t = { enabled: !0, days: 30 }
2020
- } = n, [a, d] = X(!1), { capsOn: c, onKeyDown: i } = ye(), l = "SCMSIGN00101", f = `${__SYS_CD__}_login_id`, m = {
2021
- id: t?.enabled ? te(f) : void 0,
2116
+ } = n, [a, d] = X(!1), { capsOn: c, onKeyDown: i } = ge(), l = "SCMSIGN00101", h = `${__SYS_CD__}_login_id`, m = {
2117
+ id: t?.enabled ? te(h) : void 0,
2022
2118
  pswr: void 0
2023
2119
  }, u = W(
2024
- async (h, C) => {
2120
+ async (f, C) => {
2025
2121
  d(!0);
2026
2122
  try {
2027
2123
  const g = {
2028
2124
  crprCd: "100",
2029
- id: h.id,
2030
- pswr: await oe(h.pswr)
2031
- }, y = await (r ?? ((S) => N(l, S)))(g);
2032
- if (y?.userInfo?.userId) {
2033
- if (H.getState().setLoginUser(y.userInfo, y?.hrInfo), t?.enabled) {
2125
+ id: f.id,
2126
+ pswr: await oe(f.pswr)
2127
+ }, I = await (r ?? ((S) => b(l, S)))(g);
2128
+ if (I?.userInfo?.userId) {
2129
+ if (H.getState().setLoginUser(I.userInfo, I?.hrInfo), t?.enabled) {
2034
2130
  const S = t.days ?? 30;
2035
- h.remember ? $(f, h.id ?? "", S) : $(f, "", 0);
2131
+ f.remember ? $(h, f.id ?? "", S) : $(h, "", 0);
2036
2132
  }
2037
- return e ? await e() : await G.getState().fetchCommonCodes(), s ? s(y, C) : (L.success(`${y.userInfo.userNm}님 환영합니다.`), C("/main")), { user: y.userInfo, response: y };
2133
+ return e ? await e() : await G.getState().fetchCommonCodes(), s ? s(I, C) : (K.success(`${I.userInfo.userNm}님 환영합니다.`), C("/main")), { user: I.userInfo, response: I };
2038
2134
  } else
2039
- throw o?.({ user: y.userInfo, response: y, navigate: C }), new Error("사용자 정보가 유효하지 않습니다.");
2135
+ throw o?.({ user: I.userInfo, response: I, navigate: C }), new Error("사용자 정보가 유효하지 않습니다.");
2040
2136
  } catch (g) {
2041
2137
  throw o?.(g), g;
2042
2138
  } finally {
@@ -2061,32 +2157,32 @@ function Fe(n) {
2061
2157
  doLogin: u
2062
2158
  };
2063
2159
  }
2064
- function Le() {
2065
- const n = ne();
2160
+ function Te() {
2161
+ const n = re();
2066
2162
  return () => {
2067
2163
  H.getState().clearLoginUser(), V.getState().clearSystemMap(), G.getState().clearCodes(), R.getState().clearMenu(), Z.getState().clearMenuViewStore(), q.getState().clearFavorites(), n("/login");
2068
2164
  };
2069
2165
  }
2070
- const we = () => G.getState(), _e = () => Ie.getState(), Ae = () => H.getState(), Ke = () => q.getState(), Be = () => R.getState(), Ee = () => Z.getState(), Te = () => V.getState();
2166
+ const we = () => G.getState(), _e = () => Ie.getState(), Ae = () => H.getState(), Ke = () => q.getState(), Be = () => R.getState(), Ee = () => Z.getState(), He = () => V.getState();
2071
2167
  export {
2072
- ye as useCapsLock,
2168
+ ge as useCapsLock,
2073
2169
  we as useCode,
2074
2170
  G as useCodeStore,
2075
- Pe as useColorStore,
2171
+ Le as useColorStore,
2076
2172
  Ke as useFavorite,
2077
2173
  q as useFavoriteStore,
2078
2174
  De as useLoadingStore,
2079
2175
  Fe as useLogin,
2080
- Le as useLogout,
2176
+ Te as useLogout,
2081
2177
  Be as useMenuModel,
2082
2178
  R as useMenuModelStore,
2083
2179
  Ee as useMenuView,
2084
2180
  Z as useMenuViewStore,
2085
- ve as useOptionStore,
2181
+ Pe as useOptionStore,
2086
2182
  Oe as usePopupLoadingStore,
2087
2183
  _e as usePopupState,
2088
2184
  Ie as usePopupStore,
2089
- Te as useSystemCode,
2185
+ He as useSystemCode,
2090
2186
  V as useSystemStore,
2091
2187
  Ae as useUser,
2092
2188
  H as useUserStore