@rqdhw3n/react-admin-layout 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,804 @@
1
+ import { jsx as n, Fragment as A, jsxs as o } from "react/jsx-runtime";
2
+ import { createContext as V, useState as w, useEffect as M, useCallback as L, useMemo as U, useContext as Z, useRef as T } from "react";
3
+ import { useLocation as I, NavLink as ee } from "react-router-dom";
4
+ import { ChevronDown as H, X as te, Home as ne, ChevronRight as ae, Search as re, Bell as ie, Sun as le, Moon as se, Settings as de, User as oe, LogOut as ce, Menu as me, PanelLeftOpen as J, PanelLeftClose as G } from "lucide-react";
5
+ function ue(e) {
6
+ if (typeof window > "u") return {};
7
+ try {
8
+ const t = localStorage.getItem(e);
9
+ return t ? JSON.parse(t) : {};
10
+ } catch {
11
+ return {};
12
+ }
13
+ }
14
+ function be(e, t) {
15
+ if (!(typeof window > "u"))
16
+ try {
17
+ localStorage.setItem(e, JSON.stringify(t));
18
+ } catch {
19
+ }
20
+ }
21
+ const Q = V(null);
22
+ function he({
23
+ children: e,
24
+ storageKey: t = "rqdhw3n-admin-layout",
25
+ defaultCollapsed: a = !1,
26
+ permissions: r = {},
27
+ initialBreadcrumbs: s = [],
28
+ initialActivePath: l = "/",
29
+ initialDarkMode: i
30
+ }) {
31
+ const d = ue(t), [c, b] = w(
32
+ d.sidebarCollapsed ?? a
33
+ ), [f, v] = w(!1), [h, m] = w(
34
+ d.darkMode ?? i ?? !1
35
+ ), [p, N] = w(s), [C, x] = w(l);
36
+ M(() => {
37
+ be(t, { sidebarCollapsed: c, darkMode: h });
38
+ }, [t, c, h]), M(() => {
39
+ const y = document.documentElement;
40
+ h ? y.classList.add("dark") : y.classList.remove("dark");
41
+ }, [h]);
42
+ const S = L(() => b((y) => !y), []), g = L(() => v((y) => !y), []), P = L(() => m((y) => !y), []), B = U(
43
+ () => ({
44
+ sidebarCollapsed: c,
45
+ mobileOpen: f,
46
+ darkMode: h,
47
+ toggleSidebar: S,
48
+ setSidebarCollapsed: b,
49
+ toggleMobile: g,
50
+ setMobileOpen: v,
51
+ toggleDarkMode: P,
52
+ setDarkMode: m,
53
+ permissions: r,
54
+ breadcrumbs: p,
55
+ setBreadcrumbs: N,
56
+ activePath: C,
57
+ setActivePath: x
58
+ }),
59
+ [
60
+ c,
61
+ f,
62
+ h,
63
+ S,
64
+ g,
65
+ P,
66
+ r,
67
+ p,
68
+ C
69
+ ]
70
+ );
71
+ return /* @__PURE__ */ n(Q.Provider, { value: B, children: e });
72
+ }
73
+ function k() {
74
+ const e = Z(Q);
75
+ if (!e)
76
+ throw new Error("useLayoutContext must be used within LayoutProvider / AdminLayout");
77
+ return e;
78
+ }
79
+ function O() {
80
+ const {
81
+ sidebarCollapsed: e,
82
+ mobileOpen: t,
83
+ toggleSidebar: a,
84
+ setSidebarCollapsed: r,
85
+ toggleMobile: s,
86
+ setMobileOpen: l
87
+ } = k();
88
+ return {
89
+ collapsed: e,
90
+ mobileOpen: t,
91
+ toggle: a,
92
+ setCollapsed: r,
93
+ toggleMobile: s,
94
+ setMobileOpen: l,
95
+ closeMobile: () => l(!1)
96
+ };
97
+ }
98
+ function E(e) {
99
+ const t = e.split("/").filter(Boolean);
100
+ return t.length ? t.map((a, r) => {
101
+ const s = "/" + t.slice(0, r + 1).join("/");
102
+ return { label: a.replace(/-/g, " ").replace(/\b\w/g, (i) => i.toUpperCase()), path: r < t.length - 1 ? s : void 0 };
103
+ }) : [{ label: "Home", path: "/" }];
104
+ }
105
+ function W(e) {
106
+ var t, a, r = "";
107
+ if (typeof e == "string" || typeof e == "number") r += e;
108
+ else if (typeof e == "object") if (Array.isArray(e)) {
109
+ var s = e.length;
110
+ for (t = 0; t < s; t++) e[t] && (a = W(e[t])) && (r && (r += " "), r += a);
111
+ } else for (a in e) e[a] && (r && (r += " "), r += a);
112
+ return r;
113
+ }
114
+ function fe() {
115
+ for (var e, t, a = 0, r = "", s = arguments.length; a < s; a++) (e = arguments[a]) && (t = W(e)) && (r && (r += " "), r += t);
116
+ return r;
117
+ }
118
+ function u(...e) {
119
+ return fe(e);
120
+ }
121
+ function pe({ children: e }) {
122
+ const { pathname: t } = I(), { setActivePath: a, setBreadcrumbs: r, breadcrumbs: s } = k();
123
+ return M(() => {
124
+ a(t), s.length || r(E(t));
125
+ }, [t, a, r, s.length]), /* @__PURE__ */ n(A, { children: e });
126
+ }
127
+ function xe({ children: e, className: t }) {
128
+ return /* @__PURE__ */ n(
129
+ "footer",
130
+ {
131
+ className: u(
132
+ "mt-auto border-t border-admin-border bg-admin-surface px-6 py-4 text-sm text-admin-muted",
133
+ t
134
+ ),
135
+ children: e ?? /* @__PURE__ */ o("p", { className: "text-center", children: [
136
+ "© ",
137
+ (/* @__PURE__ */ new Date()).getFullYear(),
138
+ " Admin Layout · Built with @rqdhw3n/react-admin-layout"
139
+ ] })
140
+ }
141
+ );
142
+ }
143
+ function ge(e) {
144
+ const t = e.indexOf(".");
145
+ return t === -1 ? { resource: e, action: "view" } : {
146
+ resource: e.slice(0, t),
147
+ action: e.slice(t + 1)
148
+ };
149
+ }
150
+ function ve(e, t) {
151
+ if (!t) return !0;
152
+ const { resource: a, action: r } = ge(t), s = e[a];
153
+ return s != null && s.length ? s.includes(r) || s.includes("*") : !1;
154
+ }
155
+ function D(e, t) {
156
+ return e.filter((a) => ve(t, a.permission)).map((a) => ({
157
+ ...a,
158
+ children: a.children ? D(a.children, t) : void 0
159
+ })).filter((a) => {
160
+ var r;
161
+ return !((r = a.children) != null && r.length) || a.children.length > 0 || a.path;
162
+ });
163
+ }
164
+ function X({ label: e, children: t, collapsed: a, className: r }) {
165
+ return /* @__PURE__ */ o("div", { className: u("mb-4", r), children: [
166
+ e && !a && /* @__PURE__ */ n("p", { className: "mb-2 px-3 text-[11px] font-semibold uppercase tracking-wider text-admin-muted", children: e }),
167
+ /* @__PURE__ */ n("ul", { className: "space-y-0.5", children: t })
168
+ ] });
169
+ }
170
+ function z(e, t) {
171
+ return e ? t === e || t.startsWith(`${e}/`) : !1;
172
+ }
173
+ function R({
174
+ item: e,
175
+ collapsed: t = !1,
176
+ depth: a = 0,
177
+ activePath: r = "/",
178
+ onNavigate: s,
179
+ LinkComponent: l,
180
+ onItemClick: i
181
+ }) {
182
+ var x, S;
183
+ const d = !!((x = e.children) != null && x.length), c = e.path ? z(e.path, r) : !1, b = (S = e.children) == null ? void 0 : S.some((g) => g.path && z(g.path, r)), [f, v] = w(c || b), h = e.icon, m = u(
184
+ "group flex w-full items-center gap-3 rounded-lg px-3 py-2.5 text-sm font-medium transition-all duration-200",
185
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-admin-primary",
186
+ c || b ? "bg-admin-primary text-white shadow-sm" : "text-admin-muted hover:bg-admin-bg hover:text-admin-text",
187
+ e.disabled && "pointer-events-none opacity-50",
188
+ a > 0 && "text-[13px] py-2"
189
+ ), p = /* @__PURE__ */ o(A, { children: [
190
+ h && /* @__PURE__ */ n(
191
+ h,
192
+ {
193
+ className: u("h-[18px] w-[18px] shrink-0", c || b ? "text-white" : ""),
194
+ "aria-hidden": !0
195
+ }
196
+ ),
197
+ !t && /* @__PURE__ */ o(A, { children: [
198
+ /* @__PURE__ */ n("span", { className: "flex-1 truncate text-left", children: e.label }),
199
+ e.badge != null && /* @__PURE__ */ n(
200
+ "span",
201
+ {
202
+ className: u(
203
+ "rounded-full px-2 py-0.5 text-[11px] font-semibold",
204
+ c ? "bg-white/20 text-white" : "bg-admin-primary/10 text-admin-primary"
205
+ ),
206
+ children: e.badge
207
+ }
208
+ ),
209
+ d && /* @__PURE__ */ n(
210
+ H,
211
+ {
212
+ className: u("h-4 w-4 shrink-0 transition-transform", f && "rotate-180"),
213
+ "aria-hidden": !0
214
+ }
215
+ )
216
+ ] })
217
+ ] }), N = () => {
218
+ if (d) {
219
+ v((g) => !g);
220
+ return;
221
+ }
222
+ e.path && (s == null || s(e.path), i == null || i());
223
+ }, C = e.path && !d && l ? /* @__PURE__ */ n(
224
+ l,
225
+ {
226
+ to: e.path,
227
+ className: m,
228
+ onClick: () => {
229
+ i == null || i();
230
+ },
231
+ children: p
232
+ }
233
+ ) : /* @__PURE__ */ n("button", { type: "button", className: m, onClick: N, disabled: e.disabled, children: p });
234
+ return /* @__PURE__ */ o("li", { children: [
235
+ C,
236
+ d && f && !t && /* @__PURE__ */ n("ul", { className: "mt-1 space-y-0.5 border-l border-admin-border ml-5 pl-2", children: e.children.map((g) => /* @__PURE__ */ n(
237
+ R,
238
+ {
239
+ item: g,
240
+ collapsed: t,
241
+ depth: a + 1,
242
+ activePath: r,
243
+ onNavigate: s,
244
+ LinkComponent: l,
245
+ onItemClick: i
246
+ },
247
+ g.label + (g.path ?? "")
248
+ )) })
249
+ ] });
250
+ }
251
+ function ye({
252
+ items: e,
253
+ appName: t = "Admin",
254
+ appLogo: a,
255
+ onNavigate: r,
256
+ activePath: s,
257
+ LinkComponent: l
258
+ }) {
259
+ const { mobileOpen: i, closeMobile: d } = O(), { permissions: c, activePath: b } = k(), f = s ?? b, v = D(e, c);
260
+ if (M(() => {
261
+ if (!i) return;
262
+ const m = (p) => {
263
+ p.key === "Escape" && d();
264
+ };
265
+ return document.addEventListener("keydown", m), document.body.style.overflow = "hidden", () => {
266
+ document.removeEventListener("keydown", m), document.body.style.overflow = "";
267
+ };
268
+ }, [i, d]), !i) return null;
269
+ const h = (m) => {
270
+ r == null || r(m), d();
271
+ };
272
+ return /* @__PURE__ */ o("div", { className: "fixed inset-0 z-50 lg:hidden", role: "dialog", "aria-modal": "true", children: [
273
+ /* @__PURE__ */ n(
274
+ "button",
275
+ {
276
+ type: "button",
277
+ className: "absolute inset-0 bg-slate-900/50 backdrop-blur-sm animate-fade-in",
278
+ "aria-label": "Close menu",
279
+ onClick: d
280
+ }
281
+ ),
282
+ /* @__PURE__ */ o(
283
+ "aside",
284
+ {
285
+ className: u(
286
+ "absolute left-0 top-0 flex h-full w-[min(280px,85vw)] flex-col",
287
+ "border-r border-admin-border bg-admin-surface shadow-admin-lg animate-slide-in"
288
+ ),
289
+ children: [
290
+ /* @__PURE__ */ o("div", { className: "flex h-16 items-center justify-between border-b border-admin-border px-4", children: [
291
+ /* @__PURE__ */ o("div", { className: "flex items-center gap-3", children: [
292
+ a ?? /* @__PURE__ */ n("div", { className: "flex h-9 w-9 items-center justify-center rounded-xl bg-admin-primary text-sm font-bold text-white", children: t.charAt(0) }),
293
+ /* @__PURE__ */ n("span", { className: "font-semibold text-admin-text", children: t })
294
+ ] }),
295
+ /* @__PURE__ */ n(
296
+ "button",
297
+ {
298
+ type: "button",
299
+ onClick: d,
300
+ className: "rounded-lg p-2 text-admin-muted hover:bg-admin-bg",
301
+ "aria-label": "Close sidebar",
302
+ children: /* @__PURE__ */ n(te, { className: "h-5 w-5" })
303
+ }
304
+ )
305
+ ] }),
306
+ /* @__PURE__ */ n("nav", { className: "flex-1 overflow-y-auto p-3", children: /* @__PURE__ */ n(X, { children: v.map((m) => /* @__PURE__ */ n(
307
+ R,
308
+ {
309
+ item: m,
310
+ activePath: f,
311
+ onNavigate: h,
312
+ LinkComponent: l,
313
+ onItemClick: d
314
+ },
315
+ m.label + (m.path ?? "")
316
+ )) }) })
317
+ ]
318
+ }
319
+ )
320
+ ] });
321
+ }
322
+ function we({
323
+ items: e,
324
+ className: t,
325
+ LinkComponent: a,
326
+ onNavigate: r
327
+ }) {
328
+ if (!e.length) return null;
329
+ const s = (l, i) => {
330
+ const d = u(
331
+ "text-sm transition-colors",
332
+ i ? "font-medium text-admin-text" : "text-admin-muted hover:text-admin-text"
333
+ );
334
+ return !l.path || i ? /* @__PURE__ */ n("span", { className: d, children: l.label }) : a ? /* @__PURE__ */ n(a, { to: l.path, className: d, children: l.label }) : /* @__PURE__ */ n("button", { type: "button", className: d, onClick: () => r == null ? void 0 : r(l.path), children: l.label });
335
+ };
336
+ return /* @__PURE__ */ o("nav", { "aria-label": "Breadcrumb", className: u("flex items-center gap-1.5", t), children: [
337
+ /* @__PURE__ */ n(ne, { className: "h-4 w-4 text-admin-muted shrink-0", "aria-hidden": !0 }),
338
+ e.map((l, i) => {
339
+ const d = i === e.length - 1;
340
+ return /* @__PURE__ */ o("span", { className: "flex items-center gap-1.5", children: [
341
+ /* @__PURE__ */ n(ae, { className: "h-3.5 w-3.5 text-admin-muted", "aria-hidden": !0 }),
342
+ s(l, d)
343
+ ] }, `${l.label}-${i}`);
344
+ })
345
+ ] });
346
+ }
347
+ function Ne({
348
+ placeholder: e = "Search...",
349
+ onSearch: t,
350
+ className: a
351
+ }) {
352
+ const [r, s] = w("");
353
+ return /* @__PURE__ */ o("form", { onSubmit: (i) => {
354
+ i.preventDefault(), t == null || t(r.trim());
355
+ }, className: u("relative w-full max-w-md", a), children: [
356
+ /* @__PURE__ */ n(
357
+ re,
358
+ {
359
+ className: "pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-admin-muted",
360
+ "aria-hidden": !0
361
+ }
362
+ ),
363
+ /* @__PURE__ */ n(
364
+ "input",
365
+ {
366
+ type: "search",
367
+ value: r,
368
+ onChange: (i) => s(i.target.value),
369
+ placeholder: e,
370
+ className: u(
371
+ "h-10 w-full rounded-xl border border-admin-border bg-admin-bg pl-10 pr-4 text-sm text-admin-text",
372
+ "placeholder:text-admin-muted focus:border-admin-primary focus:outline-none focus:ring-2 focus:ring-admin-primary/20"
373
+ ),
374
+ "aria-label": "Search"
375
+ }
376
+ )
377
+ ] });
378
+ }
379
+ function ke({ notifications: e = [], className: t }) {
380
+ const [a, r] = w(!1), s = T(null), l = e.filter((i) => !i.read).length;
381
+ return M(() => {
382
+ const i = (d) => {
383
+ s.current && !s.current.contains(d.target) && r(!1);
384
+ };
385
+ return document.addEventListener("mousedown", i), () => document.removeEventListener("mousedown", i);
386
+ }, []), /* @__PURE__ */ o("div", { ref: s, className: u("relative", t), children: [
387
+ /* @__PURE__ */ o(
388
+ "button",
389
+ {
390
+ type: "button",
391
+ onClick: () => r((i) => !i),
392
+ className: u(
393
+ "relative inline-flex h-9 w-9 items-center justify-center rounded-lg border border-admin-border",
394
+ "bg-admin-surface text-admin-muted transition-colors hover:bg-admin-bg hover:text-admin-text",
395
+ "focus-visible:ring-2 focus-visible:ring-admin-primary"
396
+ ),
397
+ "aria-label": `Notifications${l ? `, ${l} unread` : ""}`,
398
+ "aria-expanded": a,
399
+ children: [
400
+ /* @__PURE__ */ n(ie, { className: "h-4 w-4", "aria-hidden": !0 }),
401
+ l > 0 && /* @__PURE__ */ n("span", { className: "absolute -right-0.5 -top-0.5 flex h-4 min-w-4 items-center justify-center rounded-full bg-red-500 px-1 text-[10px] font-bold text-white", children: l > 9 ? "9+" : l })
402
+ ]
403
+ }
404
+ ),
405
+ a && /* @__PURE__ */ o("div", { className: "absolute right-0 top-full z-50 mt-2 w-80 rounded-xl border border-admin-border bg-admin-surface shadow-admin-lg animate-fade-in", children: [
406
+ /* @__PURE__ */ n("div", { className: "border-b border-admin-border px-4 py-3", children: /* @__PURE__ */ n("p", { className: "text-sm font-semibold text-admin-text", children: "Notifications" }) }),
407
+ /* @__PURE__ */ n("ul", { className: "max-h-72 overflow-y-auto p-2", children: e.length === 0 ? /* @__PURE__ */ n("li", { className: "px-3 py-6 text-center text-sm text-admin-muted", children: "No notifications" }) : e.map((i) => /* @__PURE__ */ o(
408
+ "li",
409
+ {
410
+ className: u(
411
+ "rounded-lg px-3 py-2.5 transition-colors hover:bg-admin-bg",
412
+ !i.read && "bg-admin-primary/5"
413
+ ),
414
+ children: [
415
+ /* @__PURE__ */ n("p", { className: "text-sm font-medium text-admin-text", children: i.title }),
416
+ i.description && /* @__PURE__ */ n("p", { className: "mt-0.5 text-xs text-admin-muted line-clamp-2", children: i.description }),
417
+ i.time && /* @__PURE__ */ n("p", { className: "mt-1 text-[11px] text-admin-muted", children: i.time })
418
+ ]
419
+ },
420
+ i.id
421
+ )) })
422
+ ] })
423
+ ] });
424
+ }
425
+ function Ce() {
426
+ const { darkMode: e, toggleDarkMode: t, setDarkMode: a } = k();
427
+ return {
428
+ isDark: e,
429
+ toggle: t,
430
+ setDarkMode: a
431
+ };
432
+ }
433
+ function Se({ className: e }) {
434
+ const { isDark: t, toggle: a } = Ce();
435
+ return /* @__PURE__ */ n(
436
+ "button",
437
+ {
438
+ type: "button",
439
+ onClick: a,
440
+ className: u(
441
+ "inline-flex h-9 w-9 items-center justify-center rounded-lg border border-admin-border",
442
+ "bg-admin-surface text-admin-muted transition-colors hover:bg-admin-bg hover:text-admin-text",
443
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-admin-primary focus-visible:ring-offset-2",
444
+ e
445
+ ),
446
+ "aria-label": t ? "Switch to light mode" : "Switch to dark mode",
447
+ children: t ? /* @__PURE__ */ n(le, { className: "h-4 w-4", "aria-hidden": !0 }) : /* @__PURE__ */ n(se, { className: "h-4 w-4", "aria-hidden": !0 })
448
+ }
449
+ );
450
+ }
451
+ function Me({ user: e, onLogout: t, onSettings: a, className: r }) {
452
+ const [s, l] = w(!1), i = T(null);
453
+ M(() => {
454
+ const c = (b) => {
455
+ i.current && !i.current.contains(b.target) && l(!1);
456
+ };
457
+ return document.addEventListener("mousedown", c), () => document.removeEventListener("mousedown", c);
458
+ }, []);
459
+ const d = e.name.split(" ").map((c) => c[0]).join("").slice(0, 2).toUpperCase();
460
+ return /* @__PURE__ */ o("div", { ref: i, className: u("relative", r), children: [
461
+ /* @__PURE__ */ o(
462
+ "button",
463
+ {
464
+ type: "button",
465
+ onClick: () => l((c) => !c),
466
+ className: u(
467
+ "flex items-center gap-2 rounded-xl border border-admin-border bg-admin-surface px-2 py-1.5",
468
+ "transition-colors hover:bg-admin-bg focus-visible:ring-2 focus-visible:ring-admin-primary"
469
+ ),
470
+ "aria-expanded": s,
471
+ "aria-haspopup": "menu",
472
+ children: [
473
+ e.avatar ? /* @__PURE__ */ n("img", { src: e.avatar, alt: "", className: "h-8 w-8 rounded-lg object-cover" }) : /* @__PURE__ */ n("div", { className: "flex h-8 w-8 items-center justify-center rounded-lg bg-admin-primary text-xs font-semibold text-white", children: d }),
474
+ /* @__PURE__ */ o("div", { className: "hidden text-left sm:block", children: [
475
+ /* @__PURE__ */ n("p", { className: "text-sm font-medium text-admin-text leading-tight", children: e.name }),
476
+ /* @__PURE__ */ n("p", { className: "text-xs text-admin-muted leading-tight", children: e.email })
477
+ ] }),
478
+ /* @__PURE__ */ n(H, { className: "hidden h-4 w-4 text-admin-muted sm:block", "aria-hidden": !0 })
479
+ ]
480
+ }
481
+ ),
482
+ s && /* @__PURE__ */ o(
483
+ "div",
484
+ {
485
+ role: "menu",
486
+ className: "absolute right-0 top-full z-50 mt-2 w-56 rounded-xl border border-admin-border bg-admin-surface p-1.5 shadow-admin-lg animate-fade-in",
487
+ children: [
488
+ /* @__PURE__ */ o(
489
+ "button",
490
+ {
491
+ type: "button",
492
+ role: "menuitem",
493
+ className: "flex w-full items-center gap-2 rounded-lg px-3 py-2 text-sm text-admin-text hover:bg-admin-bg",
494
+ onClick: () => {
495
+ a == null || a(), l(!1);
496
+ },
497
+ children: [
498
+ /* @__PURE__ */ n(de, { className: "h-4 w-4 text-admin-muted" }),
499
+ "Settings"
500
+ ]
501
+ }
502
+ ),
503
+ /* @__PURE__ */ o(
504
+ "button",
505
+ {
506
+ type: "button",
507
+ role: "menuitem",
508
+ className: "flex w-full items-center gap-2 rounded-lg px-3 py-2 text-sm text-admin-text hover:bg-admin-bg",
509
+ children: [
510
+ /* @__PURE__ */ n(oe, { className: "h-4 w-4 text-admin-muted" }),
511
+ "Profile"
512
+ ]
513
+ }
514
+ ),
515
+ /* @__PURE__ */ n("hr", { className: "my-1 border-admin-border" }),
516
+ /* @__PURE__ */ o(
517
+ "button",
518
+ {
519
+ type: "button",
520
+ role: "menuitem",
521
+ className: "flex w-full items-center gap-2 rounded-lg px-3 py-2 text-sm text-red-600 hover:bg-red-50 dark:hover:bg-red-950/30",
522
+ onClick: () => {
523
+ t == null || t(), l(!1);
524
+ },
525
+ children: [
526
+ /* @__PURE__ */ n(ce, { className: "h-4 w-4" }),
527
+ "Log out"
528
+ ]
529
+ }
530
+ )
531
+ ]
532
+ }
533
+ )
534
+ ] });
535
+ }
536
+ function Pe({
537
+ user: e,
538
+ notifications: t = [],
539
+ onSearch: a,
540
+ searchPlaceholder: r = "Search...",
541
+ showSearch: s = !0,
542
+ className: l,
543
+ breadcrumbs: i = [],
544
+ onMenuClick: d,
545
+ sidebarCollapsed: c,
546
+ onToggleSidebar: b
547
+ }) {
548
+ return /* @__PURE__ */ o(
549
+ "header",
550
+ {
551
+ className: u(
552
+ "sticky top-0 z-40 flex h-16 shrink-0 items-center gap-4 border-b border-admin-border",
553
+ "admin-glass bg-admin-surface px-4 lg:px-6",
554
+ l
555
+ ),
556
+ children: [
557
+ /* @__PURE__ */ n(
558
+ "button",
559
+ {
560
+ type: "button",
561
+ className: "rounded-lg p-2 text-admin-muted hover:bg-admin-bg lg:hidden",
562
+ onClick: d,
563
+ "aria-label": "Open menu",
564
+ children: /* @__PURE__ */ n(me, { className: "h-5 w-5" })
565
+ }
566
+ ),
567
+ /* @__PURE__ */ n(
568
+ "button",
569
+ {
570
+ type: "button",
571
+ className: "hidden rounded-lg p-2 text-admin-muted hover:bg-admin-bg lg:inline-flex",
572
+ onClick: b,
573
+ "aria-label": c ? "Expand sidebar" : "Collapse sidebar",
574
+ children: c ? /* @__PURE__ */ n(J, { className: "h-5 w-5" }) : /* @__PURE__ */ n(G, { className: "h-5 w-5" })
575
+ }
576
+ ),
577
+ /* @__PURE__ */ n("div", { className: "hidden min-w-0 flex-1 md:block", children: /* @__PURE__ */ n(we, { items: i }) }),
578
+ /* @__PURE__ */ o("div", { className: "flex flex-1 items-center justify-end gap-2 sm:gap-3", children: [
579
+ s && /* @__PURE__ */ n("div", { className: "hidden flex-1 sm:flex sm:max-w-md", children: /* @__PURE__ */ n(Ne, { placeholder: r, onSearch: a }) }),
580
+ /* @__PURE__ */ n(Se, {}),
581
+ /* @__PURE__ */ n(ke, { notifications: t }),
582
+ e && /* @__PURE__ */ n(Me, { user: e })
583
+ ] })
584
+ ]
585
+ }
586
+ );
587
+ }
588
+ function Le({
589
+ items: e,
590
+ collapsed: t,
591
+ appName: a = "Admin",
592
+ appLogo: r,
593
+ className: s,
594
+ onNavigate: l,
595
+ activePath: i,
596
+ LinkComponent: d
597
+ }) {
598
+ const { collapsed: c, toggle: b, closeMobile: f } = O(), { permissions: v, activePath: h } = k(), m = t ?? c, p = i ?? h, N = D(e, v), C = (x) => {
599
+ l == null || l(x), f();
600
+ };
601
+ return /* @__PURE__ */ o(
602
+ "aside",
603
+ {
604
+ className: u(
605
+ "hidden lg:flex flex-col border-r border-admin-border bg-admin-surface transition-all duration-300 ease-in-out",
606
+ m ? "w-[var(--admin-sidebar-collapsed)]" : "w-[var(--admin-sidebar-width)]",
607
+ s
608
+ ),
609
+ "aria-label": "Sidebar navigation",
610
+ children: [
611
+ /* @__PURE__ */ o(
612
+ "div",
613
+ {
614
+ className: u(
615
+ "flex h-16 items-center border-b border-admin-border px-4",
616
+ m ? "justify-center" : "justify-between gap-2"
617
+ ),
618
+ children: [
619
+ /* @__PURE__ */ o("div", { className: u("flex items-center gap-3 min-w-0", m && "justify-center"), children: [
620
+ r ?? /* @__PURE__ */ n("div", { className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-xl bg-admin-primary text-sm font-bold text-white shadow-admin", children: a.charAt(0) }),
621
+ !m && /* @__PURE__ */ n("span", { className: "truncate text-base font-semibold text-admin-text", children: a })
622
+ ] }),
623
+ !m && /* @__PURE__ */ n(
624
+ "button",
625
+ {
626
+ type: "button",
627
+ onClick: b,
628
+ className: "rounded-lg p-2 text-admin-muted hover:bg-admin-bg hover:text-admin-text focus-visible:ring-2 focus-visible:ring-admin-primary",
629
+ "aria-label": "Collapse sidebar",
630
+ children: /* @__PURE__ */ n(G, { className: "h-4 w-4" })
631
+ }
632
+ )
633
+ ]
634
+ }
635
+ ),
636
+ m && /* @__PURE__ */ n("div", { className: "flex justify-center py-2 border-b border-admin-border", children: /* @__PURE__ */ n(
637
+ "button",
638
+ {
639
+ type: "button",
640
+ onClick: b,
641
+ className: "rounded-lg p-2 text-admin-muted hover:bg-admin-bg",
642
+ "aria-label": "Expand sidebar",
643
+ children: /* @__PURE__ */ n(J, { className: "h-4 w-4" })
644
+ }
645
+ ) }),
646
+ /* @__PURE__ */ n("nav", { className: "flex-1 overflow-y-auto p-3", children: /* @__PURE__ */ n(X, { collapsed: m, children: N.map((x) => /* @__PURE__ */ n(
647
+ R,
648
+ {
649
+ item: x,
650
+ collapsed: m,
651
+ activePath: p,
652
+ onNavigate: C,
653
+ LinkComponent: d
654
+ },
655
+ x.label + (x.path ?? "")
656
+ )) }) })
657
+ ]
658
+ }
659
+ );
660
+ }
661
+ function F({
662
+ children: e,
663
+ sidebarItems: t,
664
+ appName: a = "Admin",
665
+ appLogo: r,
666
+ user: s,
667
+ notifications: l = [],
668
+ footer: i,
669
+ showFooter: d = !0,
670
+ showSearch: c = !0,
671
+ searchPlaceholder: b,
672
+ onSearch: f,
673
+ breadcrumbs: v,
674
+ contentClassName: h,
675
+ activePath: m,
676
+ onNavigate: p,
677
+ LinkComponent: N,
678
+ enableRouter: C = !1
679
+ }) {
680
+ const {
681
+ sidebarCollapsed: x,
682
+ toggleSidebar: S,
683
+ toggleMobile: g,
684
+ breadcrumbs: P,
685
+ setBreadcrumbs: B,
686
+ activePath: y,
687
+ setActivePath: Y
688
+ } = k(), { closeMobile: _ } = O(), $ = m ?? y, K = v ?? P, q = (j) => {
689
+ Y(j), v || B(E(j)), p == null || p(j), _();
690
+ };
691
+ return /* @__PURE__ */ o("div", { className: "admin-layout-root min-h-screen bg-admin-bg text-admin-text", children: [
692
+ /* @__PURE__ */ n(
693
+ Le,
694
+ {
695
+ items: t,
696
+ appName: a,
697
+ appLogo: r,
698
+ activePath: $,
699
+ onNavigate: q,
700
+ LinkComponent: N
701
+ }
702
+ ),
703
+ /* @__PURE__ */ n(
704
+ ye,
705
+ {
706
+ items: t,
707
+ appName: a,
708
+ appLogo: r,
709
+ activePath: $,
710
+ onNavigate: q,
711
+ LinkComponent: N
712
+ }
713
+ ),
714
+ /* @__PURE__ */ o("div", { className: u("flex min-h-screen flex-col transition-all duration-300", x ? "lg:pl-[var(--admin-sidebar-collapsed)]" : "lg:pl-[var(--admin-sidebar-width)]"), children: [
715
+ /* @__PURE__ */ n(
716
+ Pe,
717
+ {
718
+ user: s,
719
+ notifications: l,
720
+ onSearch: f,
721
+ searchPlaceholder: b,
722
+ showSearch: c,
723
+ breadcrumbs: K,
724
+ onMenuClick: g,
725
+ sidebarCollapsed: x,
726
+ onToggleSidebar: S
727
+ }
728
+ ),
729
+ /* @__PURE__ */ n("main", { className: u("flex-1 p-4 lg:p-6", h), children: e }),
730
+ d && /* @__PURE__ */ n(xe, { children: i })
731
+ ] })
732
+ ] });
733
+ }
734
+ function De(e) {
735
+ const {
736
+ storageKey: t = "rqdhw3n-admin-layout",
737
+ defaultCollapsed: a = !1,
738
+ initialDarkMode: r = !1,
739
+ permissions: s = {},
740
+ breadcrumbs: l = [],
741
+ activePath: i = "/",
742
+ enableRouter: d = !1,
743
+ children: c,
744
+ ...b
745
+ } = e, f = U(
746
+ () => l.length ? l : E(i),
747
+ [l, i]
748
+ );
749
+ return /* @__PURE__ */ n(
750
+ he,
751
+ {
752
+ storageKey: t,
753
+ defaultCollapsed: a,
754
+ permissions: s,
755
+ initialBreadcrumbs: f,
756
+ initialActivePath: i,
757
+ initialDarkMode: r,
758
+ children: d ? /* @__PURE__ */ n(pe, { children: /* @__PURE__ */ n(F, { ...b, enableRouter: d, children: c }) }) : /* @__PURE__ */ n(F, { ...b, enableRouter: d, children: c })
759
+ }
760
+ );
761
+ }
762
+ function Re({ to: e, className: t, children: a, onClick: r }) {
763
+ return /* @__PURE__ */ n(ee, { to: e, className: t, onClick: r, children: a });
764
+ }
765
+ function $e() {
766
+ return k();
767
+ }
768
+ function qe() {
769
+ const { breadcrumbs: e, setBreadcrumbs: t } = k(), a = L(
770
+ (r) => t(r),
771
+ [t]
772
+ );
773
+ return {
774
+ items: e,
775
+ setBreadcrumbs: a
776
+ };
777
+ }
778
+ export {
779
+ De as AdminLayout,
780
+ pe as AdminLayoutRouterSync,
781
+ we as Breadcrumbs,
782
+ xe as Footer,
783
+ he as LayoutProvider,
784
+ ye as MobileSidebar,
785
+ Pe as Navbar,
786
+ Ne as NavbarSearch,
787
+ ke as NotificationMenu,
788
+ Re as RouterLink,
789
+ Le as Sidebar,
790
+ X as SidebarGroup,
791
+ R as SidebarItem,
792
+ Se as ThemeToggle,
793
+ Me as UserMenu,
794
+ u as cn,
795
+ D as filterSidebarByPermissions,
796
+ E as generateBreadcrumbsFromPath,
797
+ ve as hasPermission,
798
+ qe as useBreadcrumbs,
799
+ Ce as useDarkMode,
800
+ k as useLayoutContext,
801
+ $e as useLayoutState,
802
+ O as useSidebar
803
+ };
804
+ //# sourceMappingURL=index.js.map