@thefreshop/tb 1.0.15 → 1.0.17

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.
@@ -1,25 +1,22 @@
1
1
  import { userType } from "./user.types";
2
- import { navType, tabType } from "./tbframe.types";
2
+ import { tabType } from "./tbframe.types";
3
3
  export type ProviderType = {
4
4
  topkey: string;
5
5
  setTopkey: (value: string) => void;
6
- tabs: tabType[];
7
- currentTab?: tabType;
8
- setCurrentTab: (value: tabType) => void;
9
- addTabs: (value: tabType) => void;
10
- removeTabs: (value: tabType) => void;
6
+ tabList: tabType[];
7
+ setTabList: (tabList: tabType[]) => void;
8
+ tabKeys: string[];
9
+ currentTabKey?: string;
10
+ setCurrentTabKey: (key: string) => void;
11
+ addTabKey: (key: string) => void;
12
+ removeTabKey: (key: string) => void;
13
+ startTabKey?: string;
14
+ setStartTabKey: (key: string) => void;
11
15
  loginUser: (value: userType | null) => void;
12
16
  logout: (force?: boolean) => void;
13
17
  user?: userType;
14
- startpage?: React.ReactNode;
15
- setStartpage: (value: React.ReactNode) => void;
16
18
  SetWarning: (value: ErrMsgType) => void;
17
19
  errMsg?: ErrMsgType;
18
- setGlobalpages: (value: tabType[]) => void;
19
- globalpages?: tabType[];
20
- addGlobalTabs: (key: string) => void;
21
- setMenupages: (value: navType) => void;
22
- goTabs: (key: string) => void;
23
20
  };
24
21
  export type ErrMsgType = {
25
22
  err?: string;
@@ -2,10 +2,9 @@ export interface tbframeType {
2
2
  islogin?: boolean;
3
3
  isgroup?: boolean;
4
4
  isgroupauth?: boolean;
5
- startpage?: React.ReactNode;
5
+ startTabKey?: string;
6
6
  loginpage?: React.ReactNode;
7
7
  logoutComponent?: React.ReactNode;
8
- globalpages?: tabType[];
9
8
  }
10
9
  export declare const baseAdminDat: TbFrameType;
11
10
  export type TbFrameType = {
@@ -50,6 +49,7 @@ export type menuType = {
50
49
  };
51
50
  export type navType = {
52
51
  menuSet: menuSetType[];
52
+ globalTabs?: tabType[];
53
53
  openIcon?: React.ReactElement | JSX.Element;
54
54
  closeIcon?: React.ReactElement | JSX.Element;
55
55
  };
package/dist/esm/index.js CHANGED
@@ -22,18 +22,17 @@ const tbContext = createContext(undefined);
22
22
  const SESSION_STORAGE_KEY = "tbFrameState";
23
23
  const TbProvider = ({ children }) => {
24
24
  const [topkey, setTopkey] = useState("");
25
- const [currentTab, setCurrentTab] = useState();
25
+ const [tabList, setTabList] = useState([]);
26
+ const [currentTabKey, setCurrentTabKey] = useState();
27
+ const [startTabKey, setStartTabKey] = useState();
26
28
  const [user, setloginUser] = useState();
27
- // const [tabs, setTabs] = useState<tabType[]>([]);
28
- const [startpage, setStartpage] = useState();
29
29
  const [errMsg, setErrMsg] = useState();
30
- const [globalpages, setGlobalpages] = useState();
31
- const [menupages, setMenupages] = useState();
32
30
  // 1. 초기 상태를 sessionStorage 불러오도록 수정
33
- const [tabs, setTabs] = useState(() => {
31
+ const [tabKeys, setTabKeys] = useState(() => {
34
32
  try {
35
33
  const savedState = sessionStorage.getItem(SESSION_STORAGE_KEY);
36
- return savedState ? JSON.parse(savedState).tabs : [];
34
+ const tt = savedState ? JSON.parse(savedState).tabs : [];
35
+ return tt === undefined ? [] : tt;
37
36
  }
38
37
  catch (error) {
39
38
  console.error("Failed to parse state from sessionStorage", error);
@@ -42,50 +41,33 @@ const TbProvider = ({ children }) => {
42
41
  });
43
42
  // 2. 상태가 변경될 때마다 sessionStorage 저장하는 useEffect 추가
44
43
  useEffect(() => {
45
- // page 속성(React 컴포넌트) 제외하고 sessionStorage에 저장
46
- const tabsToSave = tabs.map(({ page, ...rest }) => rest);
47
- const stateToSave = {
48
- tabs: tabsToSave,
49
- // ... 저장할 다른 상태들 ...
50
- };
51
- sessionStorage.setItem(SESSION_STORAGE_KEY, JSON.stringify(stateToSave)); // 순환 구조 오류 방지
52
- }, [tabs, currentTab /* ... 다른 상태 의존성 ... */]);
53
- const addTabs = (tab) => {
54
- setCurrentTab(tab);
55
- if (tabs.find((m) => m.key === tab.key) === undefined) {
56
- setTabs([...tabs, tab]);
44
+ // 불러올 때의 데이터 구조({ tabs: ... }) 일치시키기 위해 객체 형태로 저장
45
+ const stateToSave = { tabs: tabKeys };
46
+ sessionStorage.setItem(SESSION_STORAGE_KEY, JSON.stringify(stateToSave));
47
+ }, [tabKeys, currentTabKey /* ... 다른 상태 의존성 ... */]);
48
+ const addTabKey = (key) => {
49
+ setCurrentTabKey(key);
50
+ if (tabKeys.find((m) => m === key) === undefined) {
51
+ setTabKeys([...tabKeys, key]);
57
52
  }
58
53
  };
59
- const removeTabs = (tab) => {
54
+ const removeTabKey = (key) => {
60
55
  // console.log('tab', tab)
61
- let newTabs = [...tabs];
62
- const itemToFind = newTabs.find((m) => m.key === tab.key);
56
+ let newTabs = [...tabKeys];
57
+ const itemToFind = newTabs.find((m) => m === key);
63
58
  if (itemToFind !== undefined) {
64
59
  const idx = newTabs.indexOf(itemToFind);
65
60
  if (idx > -1)
66
61
  newTabs.splice(idx, 1);
67
- setTabs(newTabs);
62
+ setTabKeys(newTabs);
68
63
  // console.log('newTabs', newTabs)
69
- if (currentTab === tab) {
70
- setCurrentTab(newTabs[idx === 0 ? 0 : idx - 1]);
64
+ if (currentTabKey === key) {
65
+ setCurrentTabKey(newTabs[idx === 0 ? 0 : idx - 1]);
71
66
  }
72
67
  }
73
68
  };
74
69
  const loginUser = (user) => {
75
70
  if (user !== null) {
76
- if (startpage) {
77
- addTabs({
78
- title: "HOME",
79
- key: "HOME",
80
- page: startpage,
81
- noremove: true,
82
- });
83
- setCurrentTab({
84
- title: "HOME",
85
- key: "HOME",
86
- page: startpage,
87
- });
88
- }
89
71
  if (user?.user_group?.group_section_start) {
90
72
  setTopkey(user?.user_group?.group_section_start);
91
73
  }
@@ -97,63 +79,49 @@ const TbProvider = ({ children }) => {
97
79
  };
98
80
  const logout = (force = false) => {
99
81
  setloginUser(undefined);
100
- setCurrentTab(undefined);
101
- setTabs([]);
82
+ setCurrentTabKey(undefined);
83
+ setTabKeys([]);
102
84
  setTopkey("");
103
85
  if (force)
104
86
  window.location.reload();
105
87
  };
106
- const addGlobalTabs = (key) => {
107
- // console.log(key)
108
- const newtab = globalpages?.find((m) => {
109
- return m.key === key;
110
- });
111
- // console.log(globalpages, newtab)
112
- if (newtab) {
113
- addTabs(newtab);
114
- }
115
- };
116
- const goTabs = (key) => {
117
- let gotab;
118
- menupages?.menuSet.forEach((item) => {
119
- item.menuSetting.forEach((sub) => {
120
- sub.children?.forEach((page) => {
121
- if (page.tab.key === key)
122
- gotab = page;
123
- });
124
- });
125
- });
126
- if (gotab) {
127
- addTabs(gotab);
128
- }
129
- const newtab = globalpages?.find((m) => {
130
- return m.key === key;
131
- });
132
- // console.log(globalpages, newtab)
133
- if (newtab) {
134
- addTabs(newtab);
135
- }
136
- };
88
+ // const goTabKey = (key: string) => {
89
+ // let gotab;
90
+ // menupages?.menuSet.forEach((item: menuSetType) => {
91
+ // item.menuSetting.forEach((sub) => {
92
+ // sub.children?.forEach((page) => {
93
+ // if (page.tab.key === key) gotab = page;
94
+ // });
95
+ // });
96
+ // });
97
+ // if (gotab) {
98
+ // addTabKey(gotab);
99
+ // }
100
+ // const newtab = globalpages?.find((m) => {
101
+ // return m.key === key;
102
+ // });
103
+ // // console.log(globalpages, newtab)
104
+ // if (newtab) {
105
+ // addTabKey(newtab);
106
+ // }
107
+ // };
137
108
  return (React__default.createElement(tbContext.Provider, { value: {
138
109
  topkey,
139
110
  setTopkey,
140
- tabs,
141
- addTabs,
142
- removeTabs,
143
- currentTab,
144
- setCurrentTab,
111
+ tabKeys,
112
+ removeTabKey,
113
+ currentTabKey,
114
+ setCurrentTabKey,
115
+ addTabKey,
145
116
  loginUser,
146
117
  logout,
147
118
  user,
148
- startpage,
149
- setStartpage,
119
+ startTabKey,
120
+ setStartTabKey,
150
121
  SetWarning,
151
122
  errMsg,
152
- setGlobalpages,
153
- globalpages,
154
- addGlobalTabs,
155
- setMenupages,
156
- goTabs,
123
+ tabList,
124
+ setTabList,
157
125
  } }, children));
158
126
  };
159
127
  const useTbState = () => {
@@ -203,7 +171,8 @@ var styles$8 = {"topframe":"top-module_topframe__LhKDg","top_left":"top-module_t
203
171
  styleInject(css_248z$a);
204
172
 
205
173
  const Top = ({ setting, top: { title = topbase.title, titleimage, topMenuSetting, menuStyle, imgstyle, titleStyle, topRight }, }) => {
206
- const { logout, user, setCurrentTab, startpage } = useTbState();
174
+ const { logout, user, addTabKey, setCurrentTabKey } = useTbState();
175
+ const navigate = useNavigate();
207
176
  const userTop = () => {
208
177
  let topmenutable = [];
209
178
  if (user?.user_group?.group_key === "master" || setting.islogin === false) {
@@ -223,12 +192,11 @@ const Top = ({ setting, top: { title = topbase.title, titleimage, topMenuSetting
223
192
  };
224
193
  return (React__default.createElement("div", { className: styles$8.topframe },
225
194
  React__default.createElement("div", { className: styles$8.top_left, style: { cursor: "pointer" }, onClick: () => {
226
- if (startpage)
227
- setCurrentTab({
228
- title: "startpage",
229
- key: "startpage",
230
- page: startpage,
231
- });
195
+ if (setting?.startTabKey) {
196
+ addTabKey(setting?.startTabKey);
197
+ setCurrentTabKey(setting?.startTabKey);
198
+ navigate("/" + setting?.startTabKey);
199
+ }
232
200
  console.log("home");
233
201
  } },
234
202
  titleimage ? React__default.createElement("img", { src: titleimage, className: styles$8.toplogo, alt: "logo", style: imgstyle }) : null,
@@ -276,7 +244,7 @@ const Menu = ({ menu_setting: { tab, icon, children, hasPage, defalultOpen }, op
276
244
  const { title, key, page } = tab;
277
245
  const [hover, setHover] = useState(false);
278
246
  const [subOpen, setSubOpen] = useState(false);
279
- const { addTabs, currentTab, user } = useTbState();
247
+ const { addTabKey, currentTabKey, user } = useTbState();
280
248
  const navigate = useNavigate();
281
249
  useEffect(() => {
282
250
  if (defalultOpen) {
@@ -303,18 +271,14 @@ const Menu = ({ menu_setting: { tab, icon, children, hasPage, defalultOpen }, op
303
271
  return usersubmenutable;
304
272
  };
305
273
  return (React__default.createElement("div", null,
306
- React__default.createElement("div", { className: `${styles$9.nav_item} ${currentTab?.key === key ? styles$9.menu_select : hover ? styles$9.menu_hover : styles$9.menu_nomal}`, onMouseEnter: () => {
274
+ React__default.createElement("div", { className: `${styles$9.nav_item} ${currentTabKey === key ? styles$9.menu_select : hover ? styles$9.menu_hover : styles$9.menu_nomal}`, onMouseEnter: () => {
307
275
  setHover(true);
308
276
  }, onMouseLeave: () => {
309
277
  setHover(false);
310
278
  }, onClick: () => {
311
279
  setSubOpen((prev) => !prev);
312
- if (hasPage && currentTab?.key !== key) {
313
- addTabs({
314
- title,
315
- key,
316
- page,
317
- });
280
+ if (hasPage && currentTabKey !== key) {
281
+ addTabKey(key);
318
282
  navigate("/" + key);
319
283
  }
320
284
  // console.log(tabs)
@@ -327,19 +291,15 @@ const Menu = ({ menu_setting: { tab, icon, children, hasPage, defalultOpen }, op
327
291
  const SubMenu = ({ menu_setting: { tab, icon, hasPage } }) => {
328
292
  const { title, key, page } = tab;
329
293
  const [hover, setHover] = useState(false);
330
- const { addTabs, currentTab } = useTbState();
294
+ const { addTabKey, currentTabKey } = useTbState();
331
295
  const navigate = useNavigate();
332
- return (React__default.createElement("div", { className: `${styles$9.sub_item} ${currentTab?.key === key ? styles$9.menu_select : hover ? styles$9.menu_hover : styles$9.menu_nomal}`, onMouseEnter: () => {
296
+ return (React__default.createElement("div", { className: `${styles$9.sub_item} ${currentTabKey === key ? styles$9.menu_select : hover ? styles$9.menu_hover : styles$9.menu_nomal}`, onMouseEnter: () => {
333
297
  setHover(true);
334
298
  }, onMouseLeave: () => {
335
299
  setHover(false);
336
300
  }, onClick: () => {
337
- if (hasPage && currentTab?.key !== key)
338
- addTabs({
339
- title,
340
- key,
341
- page,
342
- });
301
+ if (hasPage && currentTabKey !== key)
302
+ addTabKey(key);
343
303
  navigate("/" + key);
344
304
  // console.log(tabs)
345
305
  } },
@@ -352,9 +312,10 @@ var styles$7 = {"bottom_item":"bottom-module_bottom_item__fac0H"};
352
312
  styleInject(css_248z$9);
353
313
 
354
314
  const Bottom = ({ bottom }) => {
355
- const { currentTab, user } = useTbState();
315
+ const { currentTabKey, user, tabList } = useTbState();
316
+ const tab = tabList.find((tab) => tab.key === currentTabKey);
356
317
  return (React__default.createElement("div", { className: styles$7.bottom_item },
357
- React__default.createElement("div", null, currentTab?.title),
318
+ React__default.createElement("div", null, tab?.title),
358
319
  React__default.createElement("div", { style: { display: "flex", gap: 16 } },
359
320
  React__default.createElement("div", null,
360
321
  user?.user_name ?? "이름없음",
@@ -370,53 +331,44 @@ var styles$6 = {"tabFrame":"tabs-module_tabFrame__qyHsD","tab_item":"tabs-module
370
331
  styleInject(css_248z$8);
371
332
 
372
333
  const Tabs = ({ nav: { menuSet, openIcon, closeIcon } }) => {
373
- const { tabs, removeTabs, setCurrentTab, addTabs, currentTab, globalpages } = useTbState();
334
+ const { tabList, tabKeys, removeTabKey, setCurrentTabKey, addTabKey, currentTabKey } = useTbState();
374
335
  const navigate = useNavigate();
375
336
  const location = useLocation();
376
337
  const findTabs = useCallback((pathKey) => {
377
338
  // 1. 현재 열린 탭 중에 있는지 확인
378
- const existingTab = tabs.find((t) => t.key === pathKey);
379
- if (existingTab) {
380
- setCurrentTab(existingTab);
339
+ const existingTabKey = tabKeys.find((key) => key === pathKey);
340
+ if (existingTabKey) {
341
+ setCurrentTabKey(existingTabKey);
381
342
  return;
382
343
  }
383
344
  // 2. 없다면, 전체 페이지 목록에서 찾아서 추가
384
345
  let tabInfo;
385
346
  // 2-1. 메뉴 페이지에서 찾기
386
347
  menuSet.forEach((item) => {
387
- item.menuSetting.forEach((sub) => {
388
- if (sub.tab.key === pathKey)
389
- tabInfo = sub;
390
- else {
391
- sub.children?.forEach((page) => {
392
- if (page.tab.key === pathKey)
393
- tabInfo = page;
394
- });
395
- }
348
+ tabList.forEach((tab) => {
349
+ if (tab.key === pathKey)
350
+ tabInfo = pathKey;
396
351
  });
397
352
  });
398
- // 2-2. 전역 페이지에서 찾기 (메뉴에 없으면)
399
- if (!tabInfo) {
400
- tabInfo = globalpages?.find((m) => m.key === pathKey);
401
- }
402
353
  if (tabInfo) {
403
- addTabs(tabInfo);
354
+ addTabKey(tabInfo);
404
355
  }
405
- }, [tabs, globalpages]);
356
+ }, [tabKeys]);
406
357
  // 3. 페이지 로드 시 URL을 기반으로 currentTab을 설정하는 useEffect 추가
407
358
  useEffect(() => {
408
359
  const pathKey = location.pathname.substring(1); // 맨 앞의 '/' 제거
409
360
  findTabs(pathKey);
410
361
  }, []);
411
- return (React__default.createElement("div", { className: styles$6.tabFrame }, tabs?.map((m) => {
412
- return (React__default.createElement("div", { key: m.key, className: `${styles$6.tab_item} ${currentTab?.key === m.key ? styles$6.tab_select : styles$6.tab_normal}` },
362
+ return (React__default.createElement("div", { className: styles$6.tabFrame }, tabKeys?.map((key) => {
363
+ const tab = tabList.find((tab) => tab.key === key);
364
+ return (React__default.createElement("div", { key: key, className: `${styles$6.tab_item} ${currentTabKey === key ? styles$6.tab_select : styles$6.tab_normal}` },
413
365
  React__default.createElement("div", { className: styles$6.tab_item_text, onClick: () => {
414
- setCurrentTab(m);
415
- navigate("/" + m.key);
366
+ setCurrentTabKey(key);
367
+ navigate("/" + key);
416
368
  // console.log('setCurrentTab', m)
417
- } }, m.title),
418
- !m.noremove && (React__default.createElement("div", { className: styles$6.tab_item_button },
419
- React__default.createElement("button", { className: styles$6.tab_x_button, onClick: () => removeTabs(m) }, "x")))));
369
+ } }, tab?.title),
370
+ !tab?.noremove && (React__default.createElement("div", { className: styles$6.tab_item_button },
371
+ React__default.createElement("button", { className: styles$6.tab_x_button, onClick: () => removeTabKey(key) }, "x")))));
420
372
  })));
421
373
  };
422
374
 
@@ -520,25 +472,32 @@ const NullPage = () => {
520
472
  };
521
473
 
522
474
  const TbFrame = ({ setting, top, bottom, nav, top_banner, hashmode = false, }) => {
523
- const { user, startpage, setStartpage, errMsg, setGlobalpages, setMenupages } = useTbState();
475
+ const { user, errMsg, tabList, setTabList, startTabKey, setStartTabKey } = useTbState();
524
476
  useEffect(() => {
525
- if (setting.startpage) {
526
- setStartpage(setting.startpage);
527
- }
528
- }, [setting.startpage]);
529
- useEffect(() => {
530
- if (setting.globalpages) {
531
- setGlobalpages(setting.globalpages);
532
- }
533
- }, [setting.globalpages]);
534
- useEffect(() => {
535
- if (nav) {
536
- setMenupages(nav);
477
+ if (tabList.length === 0) {
478
+ let p_tabList = [];
479
+ nav.menuSet.forEach((item) => {
480
+ item.menuSetting.forEach((sub) => {
481
+ p_tabList.push(sub.tab);
482
+ sub.children?.forEach((page) => {
483
+ p_tabList.push(page.tab);
484
+ });
485
+ });
486
+ });
487
+ nav?.globalTabs?.forEach((item) => {
488
+ p_tabList.push(item);
489
+ });
490
+ setTabList(p_tabList);
537
491
  }
538
- }, [nav]);
492
+ }, [tabList]);
539
493
  useEffect(() => {
540
494
  if (!errMsg?.isPopup) ;
541
495
  }, [errMsg]);
496
+ useEffect(() => {
497
+ if (!startTabKey && setting?.startTabKey) {
498
+ setStartTabKey(setting?.startTabKey);
499
+ }
500
+ }, [setting.startTabKey]);
542
501
  const route = () => {
543
502
  let route = [];
544
503
  if (setting?.islogin) {
@@ -547,6 +506,12 @@ const TbFrame = ({ setting, top, bottom, nav, top_banner, hashmode = false, }) =
547
506
  element: setting?.loginpage ? setting.loginpage : React__default.createElement(LoginPage, null),
548
507
  });
549
508
  }
509
+ nav.globalTabs?.forEach((item) => {
510
+ route.push({
511
+ path: "/" + item.key,
512
+ element: item.page,
513
+ });
514
+ });
550
515
  nav.menuSet.forEach((item) => {
551
516
  item.menuSetting.forEach((sub) => {
552
517
  route.push({
@@ -561,6 +526,11 @@ const TbFrame = ({ setting, top, bottom, nav, top_banner, hashmode = false, }) =
561
526
  });
562
527
  });
563
528
  });
529
+ // 일치하는 라우트가 없을 경우 메인으로 리다이렉트
530
+ route.push({
531
+ path: "*",
532
+ element: React__default.createElement(Navigate, { to: "/", replace: true }),
533
+ });
564
534
  return route;
565
535
  };
566
536
  const router = useMemo(() => {
@@ -568,7 +538,7 @@ const TbFrame = ({ setting, top, bottom, nav, top_banner, hashmode = false, }) =
568
538
  return createHashRouter([
569
539
  {
570
540
  path: "/",
571
- element: (React__default.createElement(MainLayout, { errMsg: errMsg, startpage: startpage, setting: setting, top_banner: top_banner, nav: nav, user: user, top: top, bottom: bottom })),
541
+ element: (React__default.createElement(MainLayout, { errMsg: errMsg, setting: setting, top_banner: top_banner, nav: nav, user: user, top: top, bottom: bottom })),
572
542
  children: route(),
573
543
  errorElement: React__default.createElement(NullPage, null),
574
544
  },
@@ -578,7 +548,7 @@ const TbFrame = ({ setting, top, bottom, nav, top_banner, hashmode = false, }) =
578
548
  return createBrowserRouter([
579
549
  {
580
550
  path: "/",
581
- element: (React__default.createElement(MainLayout, { errMsg: errMsg, startpage: startpage, setting: setting, top_banner: top_banner, nav: nav, user: user, top: top, bottom: bottom })),
551
+ element: (React__default.createElement(MainLayout, { errMsg: errMsg, setting: setting, top_banner: top_banner, nav: nav, user: user, top: top, bottom: bottom })),
582
552
  children: route(),
583
553
  errorElement: React__default.createElement(NullPage, null),
584
554
  },
@@ -587,13 +557,7 @@ const TbFrame = ({ setting, top, bottom, nav, top_banner, hashmode = false, }) =
587
557
  }, [hashmode, user]);
588
558
  return React__default.createElement(RouterProvider, { router: router });
589
559
  };
590
- const MainLayout = ({ errMsg, startpage, setting, top_banner, nav, user, top, bottom, }) => {
591
- useCallback(() => {
592
- if (startpage)
593
- return setting?.loginpage ? setting.loginpage : React__default.createElement(LoginPage, null);
594
- else
595
- return null;
596
- }, [setting?.loginpage, startpage]);
560
+ const MainLayout = ({ errMsg, setting, top_banner, nav, user, top, bottom, }) => {
597
561
  const TOPBANNER = useCallback(() => {
598
562
  return top_banner ? top_banner : null;
599
563
  }, [top_banner]);