@pnkx-lib/ui 1.9.410 → 1.9.412

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 (50) hide show
  1. package/dist/style.css +2 -2
  2. package/es/chunks/BellIcon-Bv07EhTB.js +45 -0
  3. package/es/chunks/{bundle-mjs-BBFHkixS.js → bundle-mjs-BME7zF0Z.js} +1 -1
  4. package/es/chunks/{index.esm-o4O8pXMN.js → index.esm-AaUjBMaK.js} +39 -21
  5. package/es/chunks/{layout-C0dbwkpb.js → layout-2jUdRxjk.js} +11 -5
  6. package/es/fields/CascaderField.js +1 -1
  7. package/es/fields/Checkbox.js +1 -1
  8. package/es/fields/DatePicker.js +26 -5
  9. package/es/fields/DateRangePicker.js +1 -1
  10. package/es/fields/Input.js +1 -1
  11. package/es/fields/InputRangePicker.js +1 -1
  12. package/es/fields/PnkxField.js +1 -1
  13. package/es/fields/Select.js +1 -1
  14. package/es/fields/SliderRanger.js +1 -1
  15. package/es/fields/SliderSingle.js +1 -1
  16. package/es/fields/Switch.js +1 -1
  17. package/es/fields/Textarea.js +1 -1
  18. package/es/fields/TimePicker.js +1 -1
  19. package/es/fields/TimeRangePicker.js +1 -1
  20. package/es/fields/TinyMCE.js +35 -16
  21. package/es/ui/Button.js +1 -1
  22. package/es/ui/Cascader.js +1 -1
  23. package/es/ui/CategoryStatus.js +1 -1
  24. package/es/ui/Container.js +1 -1
  25. package/es/ui/Label.js +1 -1
  26. package/es/ui/Layout.js +1 -1
  27. package/es/ui/Modal.js +1 -1
  28. package/es/ui/SearchFilterForm.js +1 -1
  29. package/es/ui/SelectSingleTable.js +1 -1
  30. package/es/ui/SelectTable.js +1 -1
  31. package/es/ui/Sidebar.js +2 -2
  32. package/es/ui/SidebarV2.js +6 -48
  33. package/es/ui/SidebarV3/index.js +490 -0
  34. package/es/ui/UploadComponent.js +1 -1
  35. package/es/ui/UploadImage.js +1 -1
  36. package/es/ui/index.js +1 -1
  37. package/package.json +2 -2
  38. package/types/components/ui/SidebarV3/ContentArea.d.ts +8 -0
  39. package/types/components/ui/SidebarV3/Example.d.ts +2 -0
  40. package/types/components/ui/SidebarV3/Header.d.ts +12 -0
  41. package/types/components/ui/SidebarV3/MainSidebar.d.ts +12 -0
  42. package/types/components/ui/SidebarV3/SearchHeader.d.ts +11 -0
  43. package/types/components/ui/SidebarV3/SidebarV3.d.ts +3 -0
  44. package/types/components/ui/SidebarV3/SubMenu.d.ts +13 -0
  45. package/types/components/ui/SidebarV3/UserInfoSection.d.ts +6 -0
  46. package/types/components/ui/SidebarV3/hooks.d.ts +9 -0
  47. package/types/components/ui/SidebarV3/index.d.ts +3 -0
  48. package/types/components/ui/SidebarV3/types.d.ts +25 -0
  49. package/types/components/ui/SidebarV3/utils.d.ts +2 -0
  50. package/types/ui/SidebarV3/index.d.ts +2 -0
@@ -0,0 +1,490 @@
1
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
+ import { useMemo, useState } from 'react';
3
+ import { useLocation, Link, useNavigate } from 'react-router';
4
+ import { S as SearchIcon, V as VietNamIcon, D as DownOutlinedIcon, l as logoHeaderText, R as RefIcon, u as useDebounce } from '../../chunks/logo-header-DG8abRGF.js';
5
+ import { Flex, AutoComplete, Divider, Dropdown } from 'antd';
6
+ import { Layout } from '../Layout.js';
7
+ import { Input } from '../../fields/Input.js';
8
+ import { t as twMerge } from '../../chunks/bundle-mjs-BME7zF0Z.js';
9
+ import { F as ForwardRef, R as RefIcon$2 } from '../../chunks/BellIcon-Bv07EhTB.js';
10
+ import { R as RefIcon$1 } from '../../chunks/DownOutlined-CkHKgaSi.js';
11
+
12
+ const useMenuFilter = (menu) => {
13
+ const sidebarMenu = useMemo(
14
+ () => menu?.filter((route) => route?.isShow)?.flatMap((route) => route?.children)?.filter(Boolean),
15
+ [menu]
16
+ );
17
+ return { sidebarMenu };
18
+ };
19
+ const usePathUtils = () => {
20
+ const normalizePath = (path) => {
21
+ return path.trim().replace(/^\/+|\/+$/g, "").replace(/\/{2,}/g, "/").toLowerCase();
22
+ };
23
+ const comparePaths = (a, b) => {
24
+ return normalizePath(a) === normalizePath(b);
25
+ };
26
+ return { normalizePath, comparePaths };
27
+ };
28
+ const classNames = (...classes) => {
29
+ return classes.filter(Boolean).join(" ");
30
+ };
31
+
32
+ const Title = (props) => /* @__PURE__ */ jsx(Flex, { align: "center", justify: "space-between", children: props.title });
33
+ const renderItem = (title, path) => ({
34
+ value: title,
35
+ label: /* @__PURE__ */ jsx(Flex, { align: "center", justify: "space-between", children: title }),
36
+ path
37
+ });
38
+ const getDataOption = (menu, searchValue) => {
39
+ return menu.reduce((acc, itemMenu) => {
40
+ const groupName = itemMenu.name;
41
+ (itemMenu.children ?? []).forEach((itemChildren) => {
42
+ (itemChildren.children ?? []).forEach(
43
+ (itemSub) => {
44
+ if (!searchValue || itemSub.name.toLowerCase().includes(searchValue.toLowerCase())) {
45
+ let group = acc.find((g) => g.label.props.title === groupName);
46
+ if (!group) {
47
+ group = {
48
+ label: /* @__PURE__ */ jsx(Title, { title: groupName }),
49
+ options: []
50
+ };
51
+ acc.push(group);
52
+ }
53
+ const path = `${itemChildren.path}/${itemSub.path}`;
54
+ group.options.push(renderItem(itemSub.name, path));
55
+ }
56
+ }
57
+ );
58
+ });
59
+ return acc;
60
+ }, []);
61
+ };
62
+
63
+ const SearchHeader = ({
64
+ dataOption,
65
+ valueSearch,
66
+ onSearchChange,
67
+ onSelect
68
+ }) => {
69
+ return /* @__PURE__ */ jsx("div", { className: "flex items-end", children: /* @__PURE__ */ jsx(
70
+ AutoComplete,
71
+ {
72
+ classNames: {
73
+ popup: { root: "certain-category-search-dropdown" }
74
+ },
75
+ popupMatchSelectWidth: 500,
76
+ style: { width: 500 },
77
+ options: dataOption ?? [],
78
+ onSelect,
79
+ onChange: onSearchChange,
80
+ value: valueSearch,
81
+ children: /* @__PURE__ */ jsx(
82
+ Input,
83
+ {
84
+ className: "!placeholder:bg-[#E7F0FF] !bg-[#E7F0FF] !border !border-[#BDE3FF]",
85
+ placeholder: "Tìm kiếm theo chức năng,module của hệ thống",
86
+ iconStartInput: /* @__PURE__ */ jsx("div", { className: "w-5 h-5", children: /* @__PURE__ */ jsx(SearchIcon, { className: "w-5 text-[#116DFF]" }) })
87
+ }
88
+ )
89
+ }
90
+ ) });
91
+ };
92
+
93
+ const userInfo = {
94
+ name: "admin",
95
+ avatar: "http://10.1.15.154:9000/image/logo-phenikaa-mec.webp"
96
+ };
97
+ const items = [
98
+ { key: "1", label: "Hồ sơ" },
99
+ { key: "4", label: "Cài đặt" },
100
+ { key: "2", label: "Đăng xuất" }
101
+ ];
102
+ const UserInfoSection = ({
103
+ hoverOpenMenu
104
+ }) => {
105
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
106
+ /* @__PURE__ */ jsx("div", { className: "flex items-center", children: /* @__PURE__ */ jsx("li", { className: "list-none cursor-pointer group flex items-center", children: /* @__PURE__ */ jsxs(
107
+ "div",
108
+ {
109
+ className: twMerge(
110
+ hoverOpenMenu ? "" : "justify-center",
111
+ "text-black flex items-center rounded-md gap-2"
112
+ ),
113
+ children: [
114
+ /* @__PURE__ */ jsx(Divider, { type: "vertical" }),
115
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-center gap-4 items-center", children: [
116
+ /* @__PURE__ */ jsx(VietNamIcon, { className: "w-6 h-6" }),
117
+ /* @__PURE__ */ jsx(ForwardRef, { className: "w-6 h-6" })
118
+ ] })
119
+ ]
120
+ }
121
+ ) }) }),
122
+ /* @__PURE__ */ jsx("div", { className: "flex items-center z-[9999]", children: /* @__PURE__ */ jsx("a", { onClick: (e) => e.preventDefault(), children: /* @__PURE__ */ jsx("li", { className: "list-none cursor-pointer group flex items-center", children: /* @__PURE__ */ jsxs(
123
+ "div",
124
+ {
125
+ className: twMerge(
126
+ hoverOpenMenu ? "" : "justify-center",
127
+ "text-black flex items-center rounded-md gap-2"
128
+ ),
129
+ children: [
130
+ /* @__PURE__ */ jsx(Divider, { type: "vertical" }),
131
+ /* @__PURE__ */ jsx("div", { className: "flex justify-center w-[30px] h-[30px] rounded-full", children: /* @__PURE__ */ jsx("img", { src: userInfo?.avatar, alt: "default_avatar" }) }),
132
+ /* @__PURE__ */ jsx("p", { children: userInfo?.name }),
133
+ /* @__PURE__ */ jsx(Dropdown, { menu: { items }, children: /* @__PURE__ */ jsx(DownOutlinedIcon, { className: "w-6 h-6" }) })
134
+ ]
135
+ }
136
+ ) }) }) })
137
+ ] });
138
+ };
139
+
140
+ const Header = ({
141
+ dataOption,
142
+ valueSearch,
143
+ onSearchChange,
144
+ onSelect,
145
+ hoverOpenMenu
146
+ }) => {
147
+ return /* @__PURE__ */ jsx(
148
+ Layout.Header,
149
+ {
150
+ style: {
151
+ backgroundColor: "#FFFFFF",
152
+ display: "flex",
153
+ width: "100%",
154
+ borderBottom: "1px solid white",
155
+ boxShadow: "0 1px 2px rgba(0, 0, 0, 0.15)",
156
+ height: "56px",
157
+ position: "fixed",
158
+ zIndex: 2e3
159
+ },
160
+ children: /* @__PURE__ */ jsxs("div", { className: "w-full flex items-center justify-between", children: [
161
+ /* @__PURE__ */ jsx("div", { className: "flex items-center ml-[-2rem]", children: /* @__PURE__ */ jsx("img", { src: logoHeaderText, alt: "logo", width: 200 }) }),
162
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4", children: [
163
+ /* @__PURE__ */ jsx(
164
+ SearchHeader,
165
+ {
166
+ dataOption,
167
+ valueSearch,
168
+ onSearchChange,
169
+ onSelect
170
+ }
171
+ ),
172
+ /* @__PURE__ */ jsx(UserInfoSection, { hoverOpenMenu })
173
+ ] })
174
+ ] })
175
+ }
176
+ );
177
+ };
178
+
179
+ const MainSidebar = ({
180
+ sidebarMenu,
181
+ hoverOpenMenu,
182
+ activeModule,
183
+ onMouseEnter,
184
+ onMouseLeave,
185
+ onNavigateModule
186
+ }) => {
187
+ return /* @__PURE__ */ jsx(
188
+ "div",
189
+ {
190
+ className: twMerge(
191
+ "fixed inset-y-0 flex h-screen flex-col transition-all duration-300 ease-in-out z-[999]",
192
+ hoverOpenMenu ? "w-[225px]" : "w-[62px]"
193
+ ),
194
+ onMouseLeave,
195
+ onMouseEnter,
196
+ children: /* @__PURE__ */ jsx("div", { className: "flex grow flex-col mt-14 gap-y-5 bg-[#001523] px-6 pb-4 relative", children: /* @__PURE__ */ jsx("nav", { className: "flex flex-1 flex-col mt-4", children: /* @__PURE__ */ jsx("ul", { role: "list", className: "-mx-3 space-y-1", children: sidebarMenu.map((item) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(
197
+ "a",
198
+ {
199
+ onClick: () => {
200
+ onNavigateModule(item);
201
+ },
202
+ className: classNames(
203
+ item.path === activeModule ? "bg-[#007BE5] text-white" : "text-gray-400 hover:text-white hover:bg-[#007BE5]",
204
+ "group flex items-center gap-x-3 rounded-md px-1.5 py-2 text-sm font-semibold"
205
+ ),
206
+ children: [
207
+ item.icon,
208
+ /* @__PURE__ */ jsx(
209
+ "span",
210
+ {
211
+ className: twMerge(
212
+ "whitespace-nowrap overflow-hidden transition-opacity duration-200",
213
+ hoverOpenMenu && "opacity-100"
214
+ ),
215
+ children: item.name
216
+ }
217
+ )
218
+ ]
219
+ }
220
+ ) }, item.name)) }) }) })
221
+ }
222
+ );
223
+ };
224
+
225
+ const SubMenu = ({
226
+ sidebarMenu,
227
+ showSubmenu,
228
+ hoverOpenMenu,
229
+ activeModule,
230
+ openDropdownMenu,
231
+ onCloseSubmenu,
232
+ onClickDropdownMenu
233
+ }) => {
234
+ const location = useLocation();
235
+ const pathName = location.pathname;
236
+ const { comparePaths } = usePathUtils();
237
+ if (!showSubmenu || sidebarMenu.length === 0) {
238
+ return null;
239
+ }
240
+ return /* @__PURE__ */ jsxs(
241
+ "div",
242
+ {
243
+ className: twMerge(
244
+ "fixed w-[217px] pt-15 left-[62px] h-full bg-[#FFFFFF] z-[50] flex flex-col",
245
+ hoverOpenMenu && "opacity-0"
246
+ ),
247
+ onMouseLeave: () => onCloseSubmenu,
248
+ children: [
249
+ sidebarMenu.map((moduleMenu) => {
250
+ const isActiveMainMenu = activeModule === moduleMenu.path;
251
+ if (!isActiveMainMenu) return null;
252
+ return /* @__PURE__ */ jsxs("div", { children: [
253
+ /* @__PURE__ */ jsx("span", { className: "block px-4 h-[42px] shadow-[0px_4px_6px_0px_#0006241f] py-2 text-[16px] font-semibold text-[#1F1F1F]", children: moduleMenu.name }),
254
+ /* @__PURE__ */ jsx("ul", { className: "mt-4", children: moduleMenu.children?.map((subMenu) => {
255
+ const pathActive = comparePaths(pathName, subMenu.path);
256
+ const isDropdown = subMenu.isShow;
257
+ const activeMenu = pathName.startsWith(subMenu.path);
258
+ return /* @__PURE__ */ jsxs("li", { children: [
259
+ /* @__PURE__ */ jsxs(
260
+ "div",
261
+ {
262
+ onClick: () => onClickDropdownMenu(isDropdown, subMenu),
263
+ className: twMerge(
264
+ "px-4 py-2 mt-1 items-center gap-2 cursor-pointer flex text-sm hover:bg-[#E5F4FF] hover:text-[#007BE5]",
265
+ pathActive && !isDropdown ? "!text-[#007BE5] !bg-[#E5F4FF]" : isDropdown && (pathActive || activeMenu) ? "!text-[#007BE5]" : "text-[#1F1F1F]"
266
+ ),
267
+ children: [
268
+ subMenu.icon,
269
+ subMenu.name,
270
+ isDropdown && openDropdownMenu === subMenu.path ? /* @__PURE__ */ jsx(RefIcon, { className: "w-4 h-4 ml-auto" }) : isDropdown && /* @__PURE__ */ jsx(RefIcon$1, { className: "w-4 h-4 ml-auto" })
271
+ ]
272
+ }
273
+ ),
274
+ isDropdown && openDropdownMenu === subMenu.path && subMenu.children?.map((dropdownItem) => {
275
+ const pathActiveDropdown = comparePaths(
276
+ pathName,
277
+ subMenu.path
278
+ );
279
+ const path = `${subMenu.path}/${dropdownItem.path}`;
280
+ return /* @__PURE__ */ jsxs(
281
+ Link,
282
+ {
283
+ to: path,
284
+ className: twMerge(
285
+ "px-4 py-2 mt-1 items-center gap-2 flex text-sm hover:bg-[#E5F4FF] hover:text-[#007BE5]",
286
+ pathActiveDropdown || activeMenu ? "!text-[#007BE5] !bg-[#E5F4FF]" : "text-[#1F1F1F]"
287
+ ),
288
+ children: [
289
+ dropdownItem.icon,
290
+ dropdownItem.name
291
+ ]
292
+ },
293
+ dropdownItem.path
294
+ );
295
+ })
296
+ ] }, subMenu.path);
297
+ }) })
298
+ ] }, moduleMenu.path);
299
+ }),
300
+ /* @__PURE__ */ jsxs(
301
+ "div",
302
+ {
303
+ className: "mt-auto select-none px-4 py-2 shadow-[0px_0px_12px_0px_#0006241f] flex space-x-2 cursor-pointer",
304
+ onClick: onCloseSubmenu,
305
+ children: [
306
+ /* @__PURE__ */ jsx(RefIcon$2, {}),
307
+ /* @__PURE__ */ jsx("span", { className: "text-[#131313]", children: "Thu gọn menu" })
308
+ ]
309
+ }
310
+ )
311
+ ]
312
+ }
313
+ );
314
+ };
315
+
316
+ const ContentArea = ({
317
+ children,
318
+ hoverOpenMenu,
319
+ showSubmenu
320
+ }) => {
321
+ const getContentMargin = () => {
322
+ if (hoverOpenMenu) return "ml-[225px]";
323
+ if (showSubmenu) return "ml-[279px]";
324
+ return "ml-[62px]";
325
+ };
326
+ return /* @__PURE__ */ jsx(
327
+ "div",
328
+ {
329
+ className: twMerge(
330
+ "transition-all duration-300 ease-in-out pt-14 h-screen",
331
+ getContentMargin()
332
+ ),
333
+ children
334
+ }
335
+ );
336
+ };
337
+
338
+ const SidebarV3 = ({ menu, children }) => {
339
+ const [hoverOpenMenu, setHoverOpenMenu] = useState(false);
340
+ const [valueSearch, setValueSearch] = useState("");
341
+ const searchSidebar = useDebounce(valueSearch, 300);
342
+ const [showSubmenu, setShowSubmenu] = useState(false);
343
+ const [activeModule, setActiveModule] = useState("");
344
+ const [openDropdownMenu, setOpenDropdownMenu] = useState(null);
345
+ const navigate = useNavigate();
346
+ const { sidebarMenu } = useMenuFilter(menu);
347
+ const dataOption = useMemo(
348
+ () => getDataOption(sidebarMenu, searchSidebar),
349
+ [sidebarMenu, searchSidebar]
350
+ );
351
+ const handleSelect = (_value, path) => {
352
+ navigate(path.path);
353
+ };
354
+ const handleClickDropdownMenu = (isDropdown, item) => {
355
+ if (isDropdown) {
356
+ setOpenDropdownMenu((prev) => prev === item.path ? null : item.path);
357
+ return;
358
+ }
359
+ navigate(item.path);
360
+ };
361
+ const handleNavigateModule = (item) => {
362
+ setShowSubmenu(true);
363
+ setHoverOpenMenu(false);
364
+ setActiveModule(item.path);
365
+ };
366
+ const handleCloseSubmenu = () => {
367
+ setShowSubmenu(false);
368
+ };
369
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
370
+ /* @__PURE__ */ jsx(
371
+ Header,
372
+ {
373
+ dataOption,
374
+ valueSearch,
375
+ onSearchChange: setValueSearch,
376
+ onSelect: handleSelect,
377
+ hoverOpenMenu
378
+ }
379
+ ),
380
+ /* @__PURE__ */ jsx(
381
+ MainSidebar,
382
+ {
383
+ sidebarMenu,
384
+ hoverOpenMenu,
385
+ activeModule,
386
+ onMouseEnter: () => setHoverOpenMenu(true),
387
+ onMouseLeave: () => setHoverOpenMenu(false),
388
+ onNavigateModule: handleNavigateModule
389
+ }
390
+ ),
391
+ /* @__PURE__ */ jsx(
392
+ SubMenu,
393
+ {
394
+ sidebarMenu,
395
+ showSubmenu,
396
+ hoverOpenMenu,
397
+ activeModule,
398
+ openDropdownMenu,
399
+ onCloseSubmenu: handleCloseSubmenu,
400
+ onClickDropdownMenu: handleClickDropdownMenu
401
+ }
402
+ ),
403
+ /* @__PURE__ */ jsx(ContentArea, { hoverOpenMenu, showSubmenu, children })
404
+ ] });
405
+ };
406
+
407
+ const DashboardIcon = () => /* @__PURE__ */ jsx("span", { children: "📊" });
408
+ const UsersIcon = () => /* @__PURE__ */ jsx("span", { children: "👥" });
409
+ const SettingsIcon = () => /* @__PURE__ */ jsx("span", { children: "⚙️" });
410
+ const exampleMenu = [
411
+ {
412
+ name: "Dashboard",
413
+ path: "/dashboard",
414
+ isShow: true,
415
+ icon: /* @__PURE__ */ jsx(DashboardIcon, {}),
416
+ children: [
417
+ {
418
+ name: "Analytics",
419
+ path: "/dashboard/analytics",
420
+ isShow: true,
421
+ icon: /* @__PURE__ */ jsx(DashboardIcon, {}),
422
+ children: [
423
+ { name: "Reports", path: "reports" },
424
+ { name: "Charts", path: "charts" }
425
+ ]
426
+ },
427
+ {
428
+ name: "Overview",
429
+ path: "/dashboard/overview",
430
+ isShow: false,
431
+ // Dropdown menu
432
+ icon: /* @__PURE__ */ jsx(DashboardIcon, {}),
433
+ children: [
434
+ { name: "Summary", path: "summary" },
435
+ { name: "Details", path: "details" }
436
+ ]
437
+ }
438
+ ]
439
+ },
440
+ {
441
+ name: "Users",
442
+ path: "/users",
443
+ isShow: true,
444
+ icon: /* @__PURE__ */ jsx(UsersIcon, {}),
445
+ children: [
446
+ {
447
+ name: "Management",
448
+ path: "/users/management",
449
+ isShow: true,
450
+ icon: /* @__PURE__ */ jsx(UsersIcon, {}),
451
+ children: [
452
+ { name: "List", path: "list" },
453
+ { name: "Roles", path: "roles" }
454
+ ]
455
+ }
456
+ ]
457
+ },
458
+ {
459
+ name: "Settings",
460
+ path: "/settings",
461
+ isShow: true,
462
+ icon: /* @__PURE__ */ jsx(SettingsIcon, {}),
463
+ children: [
464
+ {
465
+ name: "General",
466
+ path: "/settings/general",
467
+ isShow: true,
468
+ icon: /* @__PURE__ */ jsx(SettingsIcon, {})
469
+ }
470
+ ]
471
+ }
472
+ ];
473
+ const ExampleContent = () => /* @__PURE__ */ jsxs("div", { className: "p-6", children: [
474
+ /* @__PURE__ */ jsx("h1", { className: "text-2xl font-bold mb-4", children: "Main Content Area" }),
475
+ /* @__PURE__ */ jsx("p", { className: "text-gray-600", children: "Đây là nội dung chính của ứng dụng. Sidebar sẽ tự động điều chỉnh margin của content area này dựa trên trạng thái hiển thị." }),
476
+ /* @__PURE__ */ jsxs("div", { className: "mt-6 p-4 bg-gray-100 rounded", children: [
477
+ /* @__PURE__ */ jsx("h2", { className: "font-semibold", children: "Features:" }),
478
+ /* @__PURE__ */ jsxs("ul", { className: "mt-2 space-y-1", children: [
479
+ /* @__PURE__ */ jsx("li", { children: "• Hover sidebar để mở rộng" }),
480
+ /* @__PURE__ */ jsx("li", { children: "• Click module để hiển thị submenu" }),
481
+ /* @__PURE__ */ jsx("li", { children: "• Sử dụng search để tìm nhanh chức năng" }),
482
+ /* @__PURE__ */ jsx("li", { children: '• Click "Thu gọn menu" để đóng submenu' })
483
+ ] })
484
+ ] })
485
+ ] });
486
+ const SidebarV3Example = () => {
487
+ return /* @__PURE__ */ jsx(SidebarV3, { menu: exampleMenu, children: /* @__PURE__ */ jsx(ExampleContent, {}) });
488
+ };
489
+
490
+ export { SidebarV3, SidebarV3Example };
@@ -1,7 +1,7 @@
1
1
  import { jsxs, jsx } from 'react/jsx-runtime';
2
2
  import { Upload, Image, Tooltip } from 'antd';
3
3
  import { Spin } from './Spin.js';
4
- import { t as twMerge } from '../chunks/bundle-mjs-BBFHkixS.js';
4
+ import { t as twMerge } from '../chunks/bundle-mjs-BME7zF0Z.js';
5
5
  import { Label } from './Label.js';
6
6
  import { R as RefIcon } from '../chunks/CloseOutlined-D9hb-IcI.js';
7
7
 
@@ -1,5 +1,5 @@
1
1
  import { jsx } from 'react/jsx-runtime';
2
- import { C as Controller } from '../chunks/index.esm-o4O8pXMN.js';
2
+ import { C as Controller } from '../chunks/index.esm-AaUjBMaK.js';
3
3
  import { UploadComponent } from './UploadComponent.js';
4
4
 
5
5
  const UploadImage = ({
package/es/ui/index.js CHANGED
@@ -59,7 +59,7 @@ import { CATEGORY_LIST_ENUM } from './CategoryStatus.js';
59
59
  export { CategoryStatus, badgeStatusCategoryConfig } from './CategoryStatus.js';
60
60
  import { useToggle } from '@pnkx-lib/core';
61
61
  import { isEmpty, isBoolean } from 'lodash';
62
- import { t as twMerge } from '../chunks/bundle-mjs-BBFHkixS.js';
62
+ import { t as twMerge } from '../chunks/bundle-mjs-BME7zF0Z.js';
63
63
  export { BreadcrumbHeading } from './BreadcrumbHeading.js';
64
64
  export { Card } from './Card.js';
65
65
  export { ConfigProvider } from './ConfigProvider.js';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pnkx-lib/ui",
3
3
  "private": false,
4
- "version": "1.9.410",
4
+ "version": "1.9.412",
5
5
  "type": "module",
6
6
  "main": "./es/index.js",
7
7
  "module": "./es/index.js",
@@ -117,7 +117,7 @@
117
117
  ]
118
118
  },
119
119
  "peerDependencies": {
120
- "@pnkx-lib/core": "^1.1.77",
120
+ "@pnkx-lib/core": "^1.1.107",
121
121
  "@tailwindcss/vite": "^4.0.17",
122
122
  "antd": "^5.24.4",
123
123
  "react": "^18.3.1",
@@ -0,0 +1,8 @@
1
+ import { default as React } from 'react';
2
+ interface ContentAreaProps {
3
+ children: React.ReactNode;
4
+ hoverOpenMenu: boolean;
5
+ showSubmenu: boolean;
6
+ }
7
+ export declare const ContentArea: React.FC<ContentAreaProps>;
8
+ export {};
@@ -0,0 +1,2 @@
1
+ import { default as React } from 'react';
2
+ export declare const SidebarV3Example: React.FC;
@@ -0,0 +1,12 @@
1
+ import { default as React } from 'react';
2
+ interface HeaderProps {
3
+ dataOption: any[];
4
+ valueSearch: string;
5
+ onSearchChange: (value: string) => void;
6
+ onSelect: (value: string, option: {
7
+ path: string;
8
+ }) => void;
9
+ hoverOpenMenu: boolean;
10
+ }
11
+ export declare const Header: React.FC<HeaderProps>;
12
+ export {};
@@ -0,0 +1,12 @@
1
+ import { default as React } from 'react';
2
+ import { MenuTypeV3 } from './types';
3
+ interface MainSidebarProps {
4
+ sidebarMenu: MenuTypeV3[];
5
+ hoverOpenMenu: boolean;
6
+ activeModule: string;
7
+ onMouseEnter: () => void;
8
+ onMouseLeave: () => void;
9
+ onNavigateModule: (item: MenuTypeV3) => void;
10
+ }
11
+ export declare const MainSidebar: React.FC<MainSidebarProps>;
12
+ export {};
@@ -0,0 +1,11 @@
1
+ import { default as React } from 'react';
2
+ interface SearchHeaderProps {
3
+ dataOption: any[];
4
+ valueSearch: string;
5
+ onSearchChange: (value: string) => void;
6
+ onSelect: (value: string, option: {
7
+ path: string;
8
+ }) => void;
9
+ }
10
+ export declare const SearchHeader: React.FC<SearchHeaderProps>;
11
+ export {};
@@ -0,0 +1,3 @@
1
+ import { default as React } from 'react';
2
+ import { SidebarV3Props } from './types';
3
+ export declare const SidebarV3: React.FC<SidebarV3Props>;
@@ -0,0 +1,13 @@
1
+ import { default as React } from 'react';
2
+ import { MenuTypeV3 } from './types';
3
+ interface SubMenuProps {
4
+ sidebarMenu: MenuTypeV3[];
5
+ showSubmenu: boolean;
6
+ hoverOpenMenu: boolean;
7
+ activeModule: string;
8
+ openDropdownMenu: string | null;
9
+ onCloseSubmenu: () => void;
10
+ onClickDropdownMenu: (isDropdown: boolean | undefined, item: MenuTypeV3) => void;
11
+ }
12
+ export declare const SubMenu: React.FC<SubMenuProps>;
13
+ export {};
@@ -0,0 +1,6 @@
1
+ import { default as React } from 'react';
2
+ interface UserInfoSectionProps {
3
+ hoverOpenMenu: boolean;
4
+ }
5
+ export declare const UserInfoSection: React.FC<UserInfoSectionProps>;
6
+ export {};
@@ -0,0 +1,9 @@
1
+ import { MenuTypeV3 } from './types';
2
+ export declare const useMenuFilter: (menu: MenuTypeV3[]) => {
3
+ sidebarMenu: MenuTypeV3[];
4
+ };
5
+ export declare const usePathUtils: () => {
6
+ normalizePath: (path: string) => string;
7
+ comparePaths: (a: string, b: string) => boolean;
8
+ };
9
+ export declare const classNames: (...classes: unknown[]) => string;
@@ -0,0 +1,3 @@
1
+ export { SidebarV3 } from './SidebarV3';
2
+ export type { MenuTypeV3, SidebarV3Props, SidebarState } from './types';
3
+ export { SidebarV3Example } from './Example';
@@ -0,0 +1,25 @@
1
+ import { ReactNode } from 'react';
2
+ export type MenuTypeV3 = {
3
+ name: string;
4
+ path: string;
5
+ isShow?: boolean;
6
+ isPrivateRoute?: boolean;
7
+ icon?: ReactNode;
8
+ code?: string;
9
+ isShowLabel?: boolean;
10
+ isModule?: boolean;
11
+ component?: React.LazyExoticComponent<React.MemoExoticComponent<any>> | React.ExoticComponent<any> | ReactNode | React.FC;
12
+ componentProps?: Record<string, any>;
13
+ children?: MenuTypeV3[];
14
+ };
15
+ export interface SidebarV3Props {
16
+ menu: MenuTypeV3[];
17
+ children: React.ReactNode;
18
+ }
19
+ export interface SidebarState {
20
+ hoverOpenMenu: boolean;
21
+ valueSearch: string;
22
+ showSubmenu: boolean;
23
+ activeModule: string;
24
+ openDropdownMenu: string | null;
25
+ }
@@ -0,0 +1,2 @@
1
+ import { MenuTypeV3 } from './types';
2
+ export declare const getDataOption: (menu: MenuTypeV3[], searchValue: string) => any;
@@ -0,0 +1,2 @@
1
+ export * from '../../components/ui/SidebarV3/index'
2
+ export {}