@misael703/ui 1.17.0 → 1.18.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/{chunk-Y6AYAE4O.mjs → chunk-E462CF6P.mjs} +19 -21
- package/dist/chunk-E462CF6P.mjs.map +1 -0
- package/dist/{chunk-7LCZ6ABE.js → chunk-SZWROXKE.js} +19 -21
- package/dist/chunk-SZWROXKE.js.map +1 -0
- package/dist/components/AppShell.d.mts +66 -21
- package/dist/components/AppShell.d.ts +66 -21
- package/dist/components/AppShell.js +3 -3
- package/dist/components/AppShell.mjs +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +4 -4
- package/dist/index.mjs +2 -2
- package/dist/styles.css +1 -1
- package/package.json +1 -1
- package/dist/chunk-7LCZ6ABE.js.map +0 -1
- package/dist/chunk-Y6AYAE4O.mjs.map +0 -1
|
@@ -36,23 +36,18 @@ var NavItemNode = React.memo(function NavItemNode2({
|
|
|
36
36
|
item.children && item.children.length > 0 && /* @__PURE__ */ jsx("ul", { className: "appshell__navchildren", children: item.children.map((c) => /* @__PURE__ */ jsx(NavItemNode2, { item: c, depth: depth + 1, linkAs, onCloseMobile }, c.id)) })
|
|
37
37
|
] });
|
|
38
38
|
});
|
|
39
|
-
function AppShell({
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
theme = "default",
|
|
52
|
-
linkAs,
|
|
53
|
-
headerLayout = "side",
|
|
54
|
-
header
|
|
55
|
-
}) {
|
|
39
|
+
function AppShell(props) {
|
|
40
|
+
const {
|
|
41
|
+
sections,
|
|
42
|
+
footer,
|
|
43
|
+
defaultCollapsed = false,
|
|
44
|
+
collapsed: ctrlCollapsed,
|
|
45
|
+
onCollapsedChange,
|
|
46
|
+
children,
|
|
47
|
+
className,
|
|
48
|
+
theme = "default",
|
|
49
|
+
linkAs
|
|
50
|
+
} = props;
|
|
56
51
|
const [internalCollapsed, setInternalCollapsed] = React.useState(defaultCollapsed);
|
|
57
52
|
const [mobileOpen, setMobileOpen] = React.useState(false);
|
|
58
53
|
const t = useLocale();
|
|
@@ -62,8 +57,10 @@ function AppShell({
|
|
|
62
57
|
onCollapsedChange?.(v);
|
|
63
58
|
};
|
|
64
59
|
const closeMobile = React.useCallback(() => setMobileOpen(false), []);
|
|
65
|
-
if (headerLayout === "top") {
|
|
66
|
-
|
|
60
|
+
if (props.headerLayout === "top") {
|
|
61
|
+
const { header } = props;
|
|
62
|
+
const headerTheme = props.headerTheme ?? theme;
|
|
63
|
+
return /* @__PURE__ */ jsxs("div", { className: cx("appshell", `appshell--${theme}`, "appshell--header-top", `appshell--header-${headerTheme}`, collapsed && "is-collapsed", className), children: [
|
|
67
64
|
/* @__PURE__ */ jsxs("header", { className: "appshell__header", role: "banner", children: [
|
|
68
65
|
/* @__PURE__ */ jsx("div", { className: "appshell__header-left", children: header?.left }),
|
|
69
66
|
/* @__PURE__ */ jsx("div", { className: "appshell__header-center", children: header?.center }),
|
|
@@ -81,6 +78,7 @@ function AppShell({
|
|
|
81
78
|
] })
|
|
82
79
|
] });
|
|
83
80
|
}
|
|
81
|
+
const { brand, brandCollapsed, topbar, user } = props;
|
|
84
82
|
return /* @__PURE__ */ jsxs("div", { className: cx("appshell", `appshell--${theme}`, collapsed && "is-collapsed", mobileOpen && "is-mobile-open", className), children: [
|
|
85
83
|
/* @__PURE__ */ jsxs("aside", { className: "appshell__sidebar", "aria-label": t["appshell.mainNav"], children: [
|
|
86
84
|
/* @__PURE__ */ jsx("div", { className: "appshell__brand", children: collapsed ? brandCollapsed ?? brand : brand }),
|
|
@@ -144,5 +142,5 @@ function PageHeader({ title, description, breadcrumbs, actions, meta, className
|
|
|
144
142
|
}
|
|
145
143
|
|
|
146
144
|
export { AppShell, PageHeader };
|
|
147
|
-
//# sourceMappingURL=chunk-
|
|
148
|
-
//# sourceMappingURL=chunk-
|
|
145
|
+
//# sourceMappingURL=chunk-E462CF6P.mjs.map
|
|
146
|
+
//# sourceMappingURL=chunk-E462CF6P.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/AppShell.tsx"],"names":["NavItemNode"],"mappings":"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","file":"chunk-E462CF6P.mjs","sourcesContent":["'use client';\nimport * as React from 'react';\nimport { cx } from '../utils/cx';\nimport { ChevronLeft, ChevronRight, MenuIcon } from './Icons';\nimport { useLocale } from '../locale/LocaleProvider';\n\n// ---------- AppShell (Sidebar + Topbar + Content) -----------------------\n// Designed to drop into a Next.js app/layout.tsx as a Client Component shell.\n\nexport interface NavItem {\n id: string;\n label: React.ReactNode;\n icon?: React.ReactNode;\n href?: string;\n active?: boolean;\n badge?: React.ReactNode;\n onSelect?: () => void;\n children?: NavItem[];\n}\n\nexport interface NavSection {\n id?: string;\n label?: React.ReactNode;\n items: NavItem[];\n}\n\nexport type AppShellTheme = 'default' | 'brand';\n\nexport type AppShellHeaderLayout = 'side' | 'top';\n\nexport interface AppShellHeader {\n /** Left slot — typically a menu/hamburger trigger or back action. */\n left?: React.ReactNode;\n /** Center slot — typically the brand (Logo). Lands at the true viewport centre. */\n center?: React.ReactNode;\n /** Right slot — notifications, user avatar, utilities. */\n right?: React.ReactNode;\n}\n\n/**\n * Props shared by both layouts. The layout-specific props live in\n * `AppShellSideProps` / `AppShellTopProps`; `AppShellProps` is the\n * discriminated union of the two, keyed on `headerLayout`.\n */\nexport interface AppShellBaseProps {\n sections: NavSection[];\n footer?: React.ReactNode;\n defaultCollapsed?: boolean;\n collapsed?: boolean;\n onCollapsedChange?: (c: boolean) => void;\n children: React.ReactNode;\n className?: string;\n /**\n * Color theme (applies to both layouts):\n * - `default` (light): claro, mejor para apps data-heavy de uso prolongado.\n * - `brand`: superficie azul de marca con texto blanco. Mayor brand recall.\n * En `side` tiñe el sidebar; en `top` tiñe header + sidebar (un solo knob).\n */\n theme?: AppShellTheme;\n /** Render-prop for navigation links so the host app can use Next.js Link, etc. */\n linkAs?: (item: NavItem, content: React.ReactNode, className: string) => React.ReactNode;\n}\n\n/**\n * Sidebar layout (default, `headerLayout=\"side\"` or omitted). The brand\n * block + collapse rail live in the sidebar; the topbar sits over the\n * content with a mobile hamburger. `header` is **not** valid here — that\n * slot belongs to the `top` layout.\n */\nexport interface AppShellSideProps extends AppShellBaseProps {\n headerLayout?: 'side';\n /** Brand node in the sidebar header (expanded state). */\n brand?: React.ReactNode;\n /** Brand node shown when the rail is collapsed. Falls back to `brand`. */\n brandCollapsed?: React.ReactNode;\n /** Content of the topbar over the page (search, etc.). */\n topbar?: React.ReactNode;\n /** User slot at the right of the topbar (avatar/menu). */\n user?: React.ReactNode;\n /** Not valid in the `side` layout — the header slots belong to `top`. */\n header?: never;\n}\n\n/**\n * Top-header layout (`headerLayout=\"top\"`, v1.15.0). Full-width header\n * above the body with three slots (`header.{left,center,right}`); the\n * centre slot lands at the **true viewport centre** (1fr·auto·1fr grid).\n * The sidebar has no brand block and `collapsed` hides it entirely (no\n * 72px rail); the header is **invariant** to the collapse. `theme=\"brand\"`\n * tints both bands. The `side`-only props are **not** valid here — put your\n * chrome in `header`.\n */\nexport interface AppShellTopProps extends AppShellBaseProps {\n headerLayout: 'top';\n /** Slots for the full-width header. Brand usually goes in `center`. */\n header?: AppShellHeader;\n /**\n * Theme of the **header band only**, independent of the sidebar (`theme`).\n * Defaults to `theme`, so `theme=\"brand\"` still tints both bands (no\n * change for existing consumers). Set `theme=\"default\" headerTheme=\"brand\"`\n * for a branded top bar over a neutral, legible sidebar — common in\n * data-heavy admin apps.\n */\n headerTheme?: AppShellTheme;\n /** Not valid in `top` — use `header.center` for the brand. */\n brand?: never;\n /** Not valid in `top` — the sidebar collapses entirely. */\n brandCollapsed?: never;\n /** Not valid in `top` — use the `header` slots. */\n topbar?: never;\n /** Not valid in `top` — use `header.right`. */\n user?: never;\n}\n\n/**\n * Discriminated union keyed on `headerLayout`. TypeScript enforces that\n * `header` is only accepted with `headerLayout=\"top\"` and that\n * `brand`/`brandCollapsed`/`topbar`/`user` are only accepted with the\n * (default) `side` layout — passing the wrong prop for the layout is a\n * compile error instead of being silently ignored at runtime.\n */\nexport type AppShellProps = AppShellSideProps | AppShellTopProps;\n\n// Recursive nav item, memoized so a single item's parent re-render doesn't\n// churn through every other item in the tree. Stability of `linkAs` and\n// `onCloseMobile` is the parent's responsibility (we stabilize\n// `onCloseMobile` via useCallback below; consumers should memoize `linkAs`\n// if they care about avoiding renders, but for typical Next.js Link usage\n// the inline arrow is rarely a hot path).\ninterface NavItemNodeProps {\n item: NavItem;\n depth: number;\n linkAs?: AppShellBaseProps['linkAs'];\n onCloseMobile: () => void;\n}\n\nconst NavItemNode = React.memo(function NavItemNode({\n item, depth, linkAs, onCloseMobile,\n}: NavItemNodeProps) {\n const klass = cx('appshell__navitem', item.active && 'is-active', `appshell__navitem--depth-${depth}`);\n const inner = (\n <>\n {item.icon && <span className=\"appshell__navicon\" aria-hidden=\"true\">{item.icon}</span>}\n <span className=\"appshell__navlabel\">{item.label}</span>\n {item.badge && <span className=\"appshell__navbadge\">{item.badge}</span>}\n </>\n );\n const node = item.href && linkAs\n ? linkAs(item, inner, klass)\n : (\n <a\n href={item.href ?? '#'}\n className={klass}\n aria-current={item.active ? 'page' : undefined}\n onClick={(e) => {\n if (!item.href) e.preventDefault();\n item.onSelect?.();\n onCloseMobile();\n }}\n >\n {inner}\n </a>\n );\n return (\n <li>\n {node}\n {item.children && item.children.length > 0 && (\n <ul className=\"appshell__navchildren\">\n {item.children.map((c) => (\n <NavItemNode key={c.id} item={c} depth={depth + 1} linkAs={linkAs} onCloseMobile={onCloseMobile} />\n ))}\n </ul>\n )}\n </li>\n );\n});\n\nexport function AppShell(props: AppShellProps) {\n const {\n sections, footer, defaultCollapsed = false,\n collapsed: ctrlCollapsed, onCollapsedChange,\n children, className, theme = 'default', linkAs,\n } = props;\n const [internalCollapsed, setInternalCollapsed] = React.useState(defaultCollapsed);\n const [mobileOpen, setMobileOpen] = React.useState(false);\n const t = useLocale();\n const collapsed = ctrlCollapsed ?? internalCollapsed;\n const setCollapsed = (v: boolean) => {\n if (ctrlCollapsed === undefined) setInternalCollapsed(v);\n onCollapsedChange?.(v);\n };\n const closeMobile = React.useCallback(() => setMobileOpen(false), []);\n\n // Top-header variant: full-width header above the body. Topbar is\n // invariant to `collapsed` (only the inner body's columns animate); brand\n // lives in `header.center` at the true viewport centre. Default\n // `headerLayout=\"side\"` falls through to the legacy JSX below\n // (byte-identical for existing consumers). The `props.headerLayout`\n // check narrows the discriminated union, so `header` (top) and\n // `brand`/`topbar`/`user` (side) are each only in scope in their branch.\n if (props.headerLayout === 'top') {\n const { header } = props;\n // Header band themes independently of the sidebar; defaults to `theme`\n // so `theme=\"brand\"` keeps tinting both bands (back-compat).\n const headerTheme = props.headerTheme ?? theme;\n return (\n <div className={cx('appshell', `appshell--${theme}`, 'appshell--header-top', `appshell--header-${headerTheme}`, collapsed && 'is-collapsed', className)}>\n <header className=\"appshell__header\" role=\"banner\">\n <div className=\"appshell__header-left\">{header?.left}</div>\n <div className=\"appshell__header-center\">{header?.center}</div>\n <div className=\"appshell__header-right\">{header?.right}</div>\n </header>\n <div className=\"appshell__body\">\n <aside className=\"appshell__sidebar\" aria-label={t['appshell.mainNav']}>\n <nav className=\"appshell__nav\">\n {sections.map((s, i) => (\n <div key={s.id ?? i} className=\"appshell__navsection\">\n {s.label && <div className=\"appshell__navlabel-section\">{s.label}</div>}\n <ul>{s.items.map((it) => (\n <NavItemNode key={it.id} item={it} depth={0} linkAs={linkAs} onCloseMobile={closeMobile} />\n ))}</ul>\n </div>\n ))}\n </nav>\n {footer != null && <div className=\"appshell__sidebar-foot\">{footer}</div>}\n </aside>\n <main className=\"appshell__content\" role=\"main\">{children}</main>\n </div>\n </div>\n );\n }\n\n const { brand, brandCollapsed, topbar, user } = props;\n return (\n <div className={cx('appshell', `appshell--${theme}`, collapsed && 'is-collapsed', mobileOpen && 'is-mobile-open', className)}>\n <aside className=\"appshell__sidebar\" aria-label={t['appshell.mainNav']}>\n <div className=\"appshell__brand\">\n {collapsed ? (brandCollapsed ?? brand) : brand}\n </div>\n <nav className=\"appshell__nav\">\n {sections.map((s, i) => (\n <div key={s.id ?? i} className=\"appshell__navsection\">\n {s.label && <div className=\"appshell__navlabel-section\">{s.label}</div>}\n <ul>{s.items.map((it) => (\n <NavItemNode key={it.id} item={it} depth={0} linkAs={linkAs} onCloseMobile={closeMobile} />\n ))}</ul>\n </div>\n ))}\n </nav>\n <div className=\"appshell__sidebar-foot\">\n {footer}\n <button\n type=\"button\"\n className=\"appshell__collapse\"\n onClick={() => setCollapsed(!collapsed)}\n aria-expanded={!collapsed}\n aria-label={collapsed ? t['appshell.expandMenu'] : t['appshell.collapseMenu']}\n title={collapsed ? t['appshell.expand'] : t['appshell.collapse']}\n >\n {collapsed ? <ChevronRight size={14} /> : <ChevronLeft size={14} />}\n </button>\n </div>\n </aside>\n\n <div className=\"appshell__main\">\n <header className=\"appshell__topbar\">\n <button\n type=\"button\"\n className=\"appshell__hamburger\"\n aria-label={t['appshell.openMenu']}\n aria-expanded={mobileOpen}\n onClick={() => setMobileOpen((o) => !o)}\n ><MenuIcon size={20} /></button>\n <div className=\"appshell__topbar-content\">{topbar}</div>\n {user && <div className=\"appshell__topbar-user\">{user}</div>}\n </header>\n <main className=\"appshell__content\" role=\"main\">{children}</main>\n </div>\n\n {mobileOpen && (\n <div className=\"appshell__scrim\" onClick={() => setMobileOpen(false)} aria-hidden=\"true\" />\n )}\n </div>\n );\n}\n\n// ---------- PageHeader --------------------------------------------------\nexport interface PageHeaderProps {\n title: React.ReactNode;\n description?: React.ReactNode;\n breadcrumbs?: Array<{ label: React.ReactNode; href?: string }>;\n actions?: React.ReactNode;\n meta?: React.ReactNode;\n className?: string;\n}\n\nexport function PageHeader({ title, description, breadcrumbs, actions, meta, className }: PageHeaderProps) {\n const t = useLocale();\n return (\n <div className={cx('page-header', className)}>\n {breadcrumbs && breadcrumbs.length > 0 && (\n <nav className=\"page-header__crumbs\" aria-label={t['appshell.breadcrumb']}>\n <ol>\n {breadcrumbs.map((c, i) => (\n <li key={i}>\n {c.href ? <a href={c.href}>{c.label}</a> : <span aria-current=\"page\">{c.label}</span>}\n {i < breadcrumbs.length - 1 && <span className=\"page-header__crumb-sep\" aria-hidden=\"true\">/</span>}\n </li>\n ))}\n </ol>\n </nav>\n )}\n <div className=\"page-header__row\">\n <div className=\"page-header__title-wrap\">\n <h1 className=\"page-header__title\">{title}</h1>\n {description && <p className=\"page-header__desc\">{description}</p>}\n </div>\n {actions && <div className=\"page-header__actions\">{actions}</div>}\n </div>\n {meta && <div className=\"page-header__meta\">{meta}</div>}\n </div>\n );\n}\n"]}
|
|
@@ -58,23 +58,18 @@ var NavItemNode = React__namespace.memo(function NavItemNode2({
|
|
|
58
58
|
item.children && item.children.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "appshell__navchildren", children: item.children.map((c) => /* @__PURE__ */ jsxRuntime.jsx(NavItemNode2, { item: c, depth: depth + 1, linkAs, onCloseMobile }, c.id)) })
|
|
59
59
|
] });
|
|
60
60
|
});
|
|
61
|
-
function AppShell({
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
theme = "default",
|
|
74
|
-
linkAs,
|
|
75
|
-
headerLayout = "side",
|
|
76
|
-
header
|
|
77
|
-
}) {
|
|
61
|
+
function AppShell(props) {
|
|
62
|
+
const {
|
|
63
|
+
sections,
|
|
64
|
+
footer,
|
|
65
|
+
defaultCollapsed = false,
|
|
66
|
+
collapsed: ctrlCollapsed,
|
|
67
|
+
onCollapsedChange,
|
|
68
|
+
children,
|
|
69
|
+
className,
|
|
70
|
+
theme = "default",
|
|
71
|
+
linkAs
|
|
72
|
+
} = props;
|
|
78
73
|
const [internalCollapsed, setInternalCollapsed] = React__namespace.useState(defaultCollapsed);
|
|
79
74
|
const [mobileOpen, setMobileOpen] = React__namespace.useState(false);
|
|
80
75
|
const t = chunk4VMQLSHV_js.useLocale();
|
|
@@ -84,8 +79,10 @@ function AppShell({
|
|
|
84
79
|
onCollapsedChange?.(v);
|
|
85
80
|
};
|
|
86
81
|
const closeMobile = React__namespace.useCallback(() => setMobileOpen(false), []);
|
|
87
|
-
if (headerLayout === "top") {
|
|
88
|
-
|
|
82
|
+
if (props.headerLayout === "top") {
|
|
83
|
+
const { header } = props;
|
|
84
|
+
const headerTheme = props.headerTheme ?? theme;
|
|
85
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: chunkPASF6T4H_js.cx("appshell", `appshell--${theme}`, "appshell--header-top", `appshell--header-${headerTheme}`, collapsed && "is-collapsed", className), children: [
|
|
89
86
|
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "appshell__header", role: "banner", children: [
|
|
90
87
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "appshell__header-left", children: header?.left }),
|
|
91
88
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "appshell__header-center", children: header?.center }),
|
|
@@ -103,6 +100,7 @@ function AppShell({
|
|
|
103
100
|
] })
|
|
104
101
|
] });
|
|
105
102
|
}
|
|
103
|
+
const { brand, brandCollapsed, topbar, user } = props;
|
|
106
104
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: chunkPASF6T4H_js.cx("appshell", `appshell--${theme}`, collapsed && "is-collapsed", mobileOpen && "is-mobile-open", className), children: [
|
|
107
105
|
/* @__PURE__ */ jsxRuntime.jsxs("aside", { className: "appshell__sidebar", "aria-label": t["appshell.mainNav"], children: [
|
|
108
106
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "appshell__brand", children: collapsed ? brandCollapsed ?? brand : brand }),
|
|
@@ -167,5 +165,5 @@ function PageHeader({ title, description, breadcrumbs, actions, meta, className
|
|
|
167
165
|
|
|
168
166
|
exports.AppShell = AppShell;
|
|
169
167
|
exports.PageHeader = PageHeader;
|
|
170
|
-
//# sourceMappingURL=chunk-
|
|
171
|
-
//# sourceMappingURL=chunk-
|
|
168
|
+
//# sourceMappingURL=chunk-SZWROXKE.js.map
|
|
169
|
+
//# sourceMappingURL=chunk-SZWROXKE.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/AppShell.tsx"],"names":["React","NavItemNode","cx","jsxs","Fragment","jsx","useLocale","ChevronRight","ChevronLeft","MenuIcon"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwIA,IAAM,WAAA,GAAoBA,gBAAA,CAAA,IAAA,CAAK,SAASC,YAAAA,CAAY;AAAA,EAClD,IAAA;AAAA,EAAM,KAAA;AAAA,EAAO,MAAA;AAAA,EAAQ;AACvB,CAAA,EAAqB;AACnB,EAAA,MAAM,KAAA,GAAQC,oBAAG,mBAAA,EAAqB,IAAA,CAAK,UAAU,WAAA,EAAa,CAAA,yBAAA,EAA4B,KAAK,CAAA,CAAE,CAAA;AACrG,EAAA,MAAM,wBACJC,eAAA,CAAAC,mBAAA,EAAA,EACG,QAAA,EAAA;AAAA,IAAA,IAAA,CAAK,IAAA,mCAAS,MAAA,EAAA,EAAK,SAAA,EAAU,qBAAoB,aAAA,EAAY,MAAA,EAAQ,eAAK,IAAA,EAAK,CAAA;AAAA,oBAChFC,cAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,oBAAA,EAAsB,eAAK,KAAA,EAAM,CAAA;AAAA,IAChD,KAAK,KAAA,oBAASA,cAAA,CAAC,UAAK,SAAA,EAAU,oBAAA,EAAsB,eAAK,KAAA,EAAM;AAAA,GAAA,EAClE,CAAA;AAEF,EAAA,MAAM,IAAA,GAAO,KAAK,IAAA,IAAQ,MAAA,GACtB,OAAO,IAAA,EAAM,KAAA,EAAO,KAAK,CAAA,mBAEzBA,cAAA;AAAA,IAAC,GAAA;AAAA,IAAA;AAAA,MACC,IAAA,EAAM,KAAK,IAAA,IAAQ,GAAA;AAAA,MACnB,SAAA,EAAW,KAAA;AAAA,MACX,cAAA,EAAc,IAAA,CAAK,MAAA,GAAS,MAAA,GAAS,MAAA;AAAA,MACrC,OAAA,EAAS,CAAC,CAAA,KAAM;AACd,QAAA,IAAI,CAAC,IAAA,CAAK,IAAA,EAAM,CAAA,CAAE,cAAA,EAAe;AACjC,QAAA,IAAA,CAAK,QAAA,IAAW;AAChB,QAAA,aAAA,EAAc;AAAA,MAChB,CAAA;AAAA,MAEC,QAAA,EAAA;AAAA;AAAA,GACH;AAEJ,EAAA,uCACG,IAAA,EAAA,EACE,QAAA,EAAA;AAAA,IAAA,IAAA;AAAA,IACA,IAAA,CAAK,QAAA,IAAY,IAAA,CAAK,QAAA,CAAS,MAAA,GAAS,CAAA,oBACvCA,cAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,uBAAA,EACX,QAAA,EAAA,IAAA,CAAK,QAAA,CAAS,GAAA,CAAI,CAAC,CAAA,qBAClBA,cAAA,CAACJ,YAAAA,EAAA,EAAuB,IAAA,EAAM,CAAA,EAAG,KAAA,EAAO,KAAA,GAAQ,CAAA,EAAG,MAAA,EAAgB,aAAA,EAAA,EAAjD,CAAA,CAAE,EAA6E,CAClG,CAAA,EACH;AAAA,GAAA,EAEJ,CAAA;AAEJ,CAAC,CAAA;AAEM,SAAS,SAAS,KAAA,EAAsB;AAC7C,EAAA,MAAM;AAAA,IACJ,QAAA;AAAA,IAAU,MAAA;AAAA,IAAQ,gBAAA,GAAmB,KAAA;AAAA,IACrC,SAAA,EAAW,aAAA;AAAA,IAAe,iBAAA;AAAA,IAC1B,QAAA;AAAA,IAAU,SAAA;AAAA,IAAW,KAAA,GAAQ,SAAA;AAAA,IAAW;AAAA,GAC1C,GAAI,KAAA;AACJ,EAAA,MAAM,CAAC,iBAAA,EAAmB,oBAAoB,CAAA,GAAUD,0BAAS,gBAAgB,CAAA;AACjF,EAAA,MAAM,CAAC,UAAA,EAAY,aAAa,CAAA,GAAUA,0BAAS,KAAK,CAAA;AACxD,EAAA,MAAM,IAAIM,0BAAA,EAAU;AACpB,EAAA,MAAM,YAAY,aAAA,IAAiB,iBAAA;AACnC,EAAA,MAAM,YAAA,GAAe,CAAC,CAAA,KAAe;AACnC,IAAA,IAAI,aAAA,KAAkB,MAAA,EAAW,oBAAA,CAAqB,CAAC,CAAA;AACvD,IAAA,iBAAA,GAAoB,CAAC,CAAA;AAAA,EACvB,CAAA;AACA,EAAA,MAAM,cAAoBN,gBAAA,CAAA,WAAA,CAAY,MAAM,cAAc,KAAK,CAAA,EAAG,EAAE,CAAA;AASpE,EAAA,IAAI,KAAA,CAAM,iBAAiB,KAAA,EAAO;AAChC,IAAA,MAAM,EAAE,QAAO,GAAI,KAAA;AAGnB,IAAA,MAAM,WAAA,GAAc,MAAM,WAAA,IAAe,KAAA;AACzC,IAAA,uBACEG,eAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAWD,mBAAA,CAAG,YAAY,CAAA,UAAA,EAAa,KAAK,CAAA,CAAA,EAAI,sBAAA,EAAwB,oBAAoB,WAAW,CAAA,CAAA,EAAI,SAAA,IAAa,cAAA,EAAgB,SAAS,CAAA,EACpJ,QAAA,EAAA;AAAA,sBAAAC,eAAA,CAAC,QAAA,EAAA,EAAO,SAAA,EAAU,kBAAA,EAAmB,IAAA,EAAK,QAAA,EACxC,QAAA,EAAA;AAAA,wBAAAE,cAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,uBAAA,EAAyB,QAAA,EAAA,MAAA,EAAQ,IAAA,EAAK,CAAA;AAAA,wBACrDA,cAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,yBAAA,EAA2B,kBAAQ,MAAA,EAAO,CAAA;AAAA,wBACzDA,cAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,wBAAA,EAA0B,kBAAQ,KAAA,EAAM;AAAA,OAAA,EACzD,CAAA;AAAA,sBACAF,eAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,gBAAA,EACb,QAAA,EAAA;AAAA,wBAAAA,eAAA,CAAC,WAAM,SAAA,EAAU,mBAAA,EAAoB,YAAA,EAAY,CAAA,CAAE,kBAAkB,CAAA,EACnE,QAAA,EAAA;AAAA,0BAAAE,cAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,eAAA,EACZ,QAAA,EAAA,QAAA,CAAS,GAAA,CAAI,CAAC,CAAA,EAAG,CAAA,qBAChBF,eAAA,CAAC,KAAA,EAAA,EAAoB,SAAA,EAAU,sBAAA,EAC5B,QAAA,EAAA;AAAA,YAAA,CAAA,CAAE,yBAASE,cAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,4BAAA,EAA8B,YAAE,KAAA,EAAM,CAAA;AAAA,2CAChE,IAAA,EAAA,EAAI,QAAA,EAAA,CAAA,CAAE,MAAM,GAAA,CAAI,CAAC,uBAChBA,cAAA,CAAC,WAAA,EAAA,EAAwB,MAAM,EAAA,EAAI,KAAA,EAAO,GAAG,MAAA,EAAgB,aAAA,EAAe,eAA1D,EAAA,CAAG,EAAoE,CAC1F,CAAA,EAAE;AAAA,WAAA,EAAA,EAJK,CAAA,CAAE,EAAA,IAAM,CAKlB,CACD,CAAA,EACH,CAAA;AAAA,UACC,UAAU,IAAA,oBAAQA,cAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,0BAA0B,QAAA,EAAA,MAAA,EAAO;AAAA,SAAA,EACrE,CAAA;AAAA,uCACC,MAAA,EAAA,EAAK,SAAA,EAAU,mBAAA,EAAoB,IAAA,EAAK,QAAQ,QAAA,EAAS;AAAA,OAAA,EAC5D;AAAA,KAAA,EACF,CAAA;AAAA,EAEJ;AAEA,EAAA,MAAM,EAAE,KAAA,EAAO,cAAA,EAAgB,MAAA,EAAQ,MAAK,GAAI,KAAA;AAChD,EAAA,uBACEF,eAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAWD,mBAAA,CAAG,UAAA,EAAY,CAAA,UAAA,EAAa,KAAK,CAAA,CAAA,EAAI,SAAA,IAAa,cAAA,EAAgB,UAAA,IAAc,gBAAA,EAAkB,SAAS,CAAA,EACzH,QAAA,EAAA;AAAA,oBAAAC,eAAA,CAAC,WAAM,SAAA,EAAU,mBAAA,EAAoB,YAAA,EAAY,CAAA,CAAE,kBAAkB,CAAA,EACnE,QAAA,EAAA;AAAA,sBAAAE,cAAA,CAAC,SAAI,SAAA,EAAU,iBAAA,EACZ,QAAA,EAAA,SAAA,GAAa,cAAA,IAAkB,QAAS,KAAA,EAC3C,CAAA;AAAA,sBACAA,cAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,eAAA,EACZ,QAAA,EAAA,QAAA,CAAS,GAAA,CAAI,CAAC,CAAA,EAAG,CAAA,qBAChBF,eAAA,CAAC,KAAA,EAAA,EAAoB,SAAA,EAAU,sBAAA,EAC5B,QAAA,EAAA;AAAA,QAAA,CAAA,CAAE,yBAASE,cAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,4BAAA,EAA8B,YAAE,KAAA,EAAM,CAAA;AAAA,uCAChE,IAAA,EAAA,EAAI,QAAA,EAAA,CAAA,CAAE,MAAM,GAAA,CAAI,CAAC,uBAChBA,cAAA,CAAC,WAAA,EAAA,EAAwB,MAAM,EAAA,EAAI,KAAA,EAAO,GAAG,MAAA,EAAgB,aAAA,EAAe,eAA1D,EAAA,CAAG,EAAoE,CAC1F,CAAA,EAAE;AAAA,OAAA,EAAA,EAJK,CAAA,CAAE,EAAA,IAAM,CAKlB,CACD,CAAA,EACH,CAAA;AAAA,sBACAF,eAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,wBAAA,EACZ,QAAA,EAAA;AAAA,QAAA,MAAA;AAAA,wBACDE,cAAA;AAAA,UAAC,QAAA;AAAA,UAAA;AAAA,YACC,IAAA,EAAK,QAAA;AAAA,YACL,SAAA,EAAU,oBAAA;AAAA,YACV,OAAA,EAAS,MAAM,YAAA,CAAa,CAAC,SAAS,CAAA;AAAA,YACtC,iBAAe,CAAC,SAAA;AAAA,YAChB,cAAY,SAAA,GAAY,CAAA,CAAE,qBAAqB,CAAA,GAAI,EAAE,uBAAuB,CAAA;AAAA,YAC5E,OAAO,SAAA,GAAY,CAAA,CAAE,iBAAiB,CAAA,GAAI,EAAE,mBAAmB,CAAA;AAAA,YAE9D,QAAA,EAAA,SAAA,kCAAaE,6BAAA,EAAA,EAAa,IAAA,EAAM,IAAI,CAAA,mBAAKF,cAAA,CAACG,4BAAA,EAAA,EAAY,IAAA,EAAM,EAAA,EAAI;AAAA;AAAA;AACnE,OAAA,EACF;AAAA,KAAA,EACF,CAAA;AAAA,oBAEAL,eAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,gBAAA,EACb,QAAA,EAAA;AAAA,sBAAAA,eAAA,CAAC,QAAA,EAAA,EAAO,WAAU,kBAAA,EAChB,QAAA,EAAA;AAAA,wBAAAE,cAAA;AAAA,UAAC,QAAA;AAAA,UAAA;AAAA,YACC,IAAA,EAAK,QAAA;AAAA,YACL,SAAA,EAAU,qBAAA;AAAA,YACV,YAAA,EAAY,EAAE,mBAAmB,CAAA;AAAA,YACjC,eAAA,EAAe,UAAA;AAAA,YACf,SAAS,MAAM,aAAA,CAAc,CAAC,CAAA,KAAM,CAAC,CAAC,CAAA;AAAA,YACvC,QAAA,kBAAAA,cAAA,CAACI,yBAAA,EAAA,EAAS,IAAA,EAAM,EAAA,EAAI;AAAA;AAAA,SAAE;AAAA,wBACvBJ,cAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,0BAAA,EAA4B,QAAA,EAAA,MAAA,EAAO,CAAA;AAAA,QACjD,IAAA,oBAAQA,cAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,yBAAyB,QAAA,EAAA,IAAA,EAAK;AAAA,OAAA,EACxD,CAAA;AAAA,qCACC,MAAA,EAAA,EAAK,SAAA,EAAU,mBAAA,EAAoB,IAAA,EAAK,QAAQ,QAAA,EAAS;AAAA,KAAA,EAC5D,CAAA;AAAA,IAEC,UAAA,oBACCA,cAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,iBAAA,EAAkB,OAAA,EAAS,MAAM,aAAA,CAAc,KAAK,CAAA,EAAG,aAAA,EAAY,MAAA,EAAO;AAAA,GAAA,EAE7F,CAAA;AAEJ;AAYO,SAAS,UAAA,CAAW,EAAE,KAAA,EAAO,WAAA,EAAa,aAAa,OAAA,EAAS,IAAA,EAAM,WAAU,EAAoB;AACzG,EAAA,MAAM,IAAIC,0BAAA,EAAU;AACpB,EAAA,uCACG,KAAA,EAAA,EAAI,SAAA,EAAWJ,mBAAA,CAAG,aAAA,EAAe,SAAS,CAAA,EACxC,QAAA,EAAA;AAAA,IAAA,WAAA,IAAe,YAAY,MAAA,GAAS,CAAA,mCAClC,KAAA,EAAA,EAAI,SAAA,EAAU,uBAAsB,YAAA,EAAY,CAAA,CAAE,qBAAqB,CAAA,EACtE,QAAA,kBAAAG,cAAA,CAAC,QACE,QAAA,EAAA,WAAA,CAAY,GAAA,CAAI,CAAC,CAAA,EAAG,CAAA,qCAClB,IAAA,EAAA,EACE,QAAA,EAAA;AAAA,MAAA,CAAA,CAAE,IAAA,mBAAOA,cAAA,CAAC,GAAA,EAAA,EAAE,IAAA,EAAM,EAAE,IAAA,EAAO,QAAA,EAAA,CAAA,CAAE,KAAA,EAAM,CAAA,mBAAOA,cAAA,CAAC,MAAA,EAAA,EAAK,cAAA,EAAa,MAAA,EAAQ,YAAE,KAAA,EAAM,CAAA;AAAA,MAC7E,CAAA,GAAI,WAAA,CAAY,MAAA,GAAS,CAAA,oBAAKA,cAAA,CAAC,UAAK,SAAA,EAAU,wBAAA,EAAyB,aAAA,EAAY,MAAA,EAAO,QAAA,EAAA,GAAA,EAAC;AAAA,KAAA,EAAA,EAFrF,CAGT,CACD,CAAA,EACH,CAAA,EACF,CAAA;AAAA,oBAEFF,eAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,kBAAA,EACb,QAAA,EAAA;AAAA,sBAAAA,eAAA,CAAC,KAAA,EAAA,EAAI,WAAU,yBAAA,EACb,QAAA,EAAA;AAAA,wBAAAE,cAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,oBAAA,EAAsB,QAAA,EAAA,KAAA,EAAM,CAAA;AAAA,QACzC,WAAA,oBAAeA,cAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,qBAAqB,QAAA,EAAA,WAAA,EAAY;AAAA,OAAA,EAChE,CAAA;AAAA,MACC,OAAA,oBAAWA,cAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,wBAAwB,QAAA,EAAA,OAAA,EAAQ;AAAA,KAAA,EAC7D,CAAA;AAAA,IACC,IAAA,oBAAQA,cAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,qBAAqB,QAAA,EAAA,IAAA,EAAK;AAAA,GAAA,EACpD,CAAA;AAEJ","file":"chunk-SZWROXKE.js","sourcesContent":["'use client';\nimport * as React from 'react';\nimport { cx } from '../utils/cx';\nimport { ChevronLeft, ChevronRight, MenuIcon } from './Icons';\nimport { useLocale } from '../locale/LocaleProvider';\n\n// ---------- AppShell (Sidebar + Topbar + Content) -----------------------\n// Designed to drop into a Next.js app/layout.tsx as a Client Component shell.\n\nexport interface NavItem {\n id: string;\n label: React.ReactNode;\n icon?: React.ReactNode;\n href?: string;\n active?: boolean;\n badge?: React.ReactNode;\n onSelect?: () => void;\n children?: NavItem[];\n}\n\nexport interface NavSection {\n id?: string;\n label?: React.ReactNode;\n items: NavItem[];\n}\n\nexport type AppShellTheme = 'default' | 'brand';\n\nexport type AppShellHeaderLayout = 'side' | 'top';\n\nexport interface AppShellHeader {\n /** Left slot — typically a menu/hamburger trigger or back action. */\n left?: React.ReactNode;\n /** Center slot — typically the brand (Logo). Lands at the true viewport centre. */\n center?: React.ReactNode;\n /** Right slot — notifications, user avatar, utilities. */\n right?: React.ReactNode;\n}\n\n/**\n * Props shared by both layouts. The layout-specific props live in\n * `AppShellSideProps` / `AppShellTopProps`; `AppShellProps` is the\n * discriminated union of the two, keyed on `headerLayout`.\n */\nexport interface AppShellBaseProps {\n sections: NavSection[];\n footer?: React.ReactNode;\n defaultCollapsed?: boolean;\n collapsed?: boolean;\n onCollapsedChange?: (c: boolean) => void;\n children: React.ReactNode;\n className?: string;\n /**\n * Color theme (applies to both layouts):\n * - `default` (light): claro, mejor para apps data-heavy de uso prolongado.\n * - `brand`: superficie azul de marca con texto blanco. Mayor brand recall.\n * En `side` tiñe el sidebar; en `top` tiñe header + sidebar (un solo knob).\n */\n theme?: AppShellTheme;\n /** Render-prop for navigation links so the host app can use Next.js Link, etc. */\n linkAs?: (item: NavItem, content: React.ReactNode, className: string) => React.ReactNode;\n}\n\n/**\n * Sidebar layout (default, `headerLayout=\"side\"` or omitted). The brand\n * block + collapse rail live in the sidebar; the topbar sits over the\n * content with a mobile hamburger. `header` is **not** valid here — that\n * slot belongs to the `top` layout.\n */\nexport interface AppShellSideProps extends AppShellBaseProps {\n headerLayout?: 'side';\n /** Brand node in the sidebar header (expanded state). */\n brand?: React.ReactNode;\n /** Brand node shown when the rail is collapsed. Falls back to `brand`. */\n brandCollapsed?: React.ReactNode;\n /** Content of the topbar over the page (search, etc.). */\n topbar?: React.ReactNode;\n /** User slot at the right of the topbar (avatar/menu). */\n user?: React.ReactNode;\n /** Not valid in the `side` layout — the header slots belong to `top`. */\n header?: never;\n}\n\n/**\n * Top-header layout (`headerLayout=\"top\"`, v1.15.0). Full-width header\n * above the body with three slots (`header.{left,center,right}`); the\n * centre slot lands at the **true viewport centre** (1fr·auto·1fr grid).\n * The sidebar has no brand block and `collapsed` hides it entirely (no\n * 72px rail); the header is **invariant** to the collapse. `theme=\"brand\"`\n * tints both bands. The `side`-only props are **not** valid here — put your\n * chrome in `header`.\n */\nexport interface AppShellTopProps extends AppShellBaseProps {\n headerLayout: 'top';\n /** Slots for the full-width header. Brand usually goes in `center`. */\n header?: AppShellHeader;\n /**\n * Theme of the **header band only**, independent of the sidebar (`theme`).\n * Defaults to `theme`, so `theme=\"brand\"` still tints both bands (no\n * change for existing consumers). Set `theme=\"default\" headerTheme=\"brand\"`\n * for a branded top bar over a neutral, legible sidebar — common in\n * data-heavy admin apps.\n */\n headerTheme?: AppShellTheme;\n /** Not valid in `top` — use `header.center` for the brand. */\n brand?: never;\n /** Not valid in `top` — the sidebar collapses entirely. */\n brandCollapsed?: never;\n /** Not valid in `top` — use the `header` slots. */\n topbar?: never;\n /** Not valid in `top` — use `header.right`. */\n user?: never;\n}\n\n/**\n * Discriminated union keyed on `headerLayout`. TypeScript enforces that\n * `header` is only accepted with `headerLayout=\"top\"` and that\n * `brand`/`brandCollapsed`/`topbar`/`user` are only accepted with the\n * (default) `side` layout — passing the wrong prop for the layout is a\n * compile error instead of being silently ignored at runtime.\n */\nexport type AppShellProps = AppShellSideProps | AppShellTopProps;\n\n// Recursive nav item, memoized so a single item's parent re-render doesn't\n// churn through every other item in the tree. Stability of `linkAs` and\n// `onCloseMobile` is the parent's responsibility (we stabilize\n// `onCloseMobile` via useCallback below; consumers should memoize `linkAs`\n// if they care about avoiding renders, but for typical Next.js Link usage\n// the inline arrow is rarely a hot path).\ninterface NavItemNodeProps {\n item: NavItem;\n depth: number;\n linkAs?: AppShellBaseProps['linkAs'];\n onCloseMobile: () => void;\n}\n\nconst NavItemNode = React.memo(function NavItemNode({\n item, depth, linkAs, onCloseMobile,\n}: NavItemNodeProps) {\n const klass = cx('appshell__navitem', item.active && 'is-active', `appshell__navitem--depth-${depth}`);\n const inner = (\n <>\n {item.icon && <span className=\"appshell__navicon\" aria-hidden=\"true\">{item.icon}</span>}\n <span className=\"appshell__navlabel\">{item.label}</span>\n {item.badge && <span className=\"appshell__navbadge\">{item.badge}</span>}\n </>\n );\n const node = item.href && linkAs\n ? linkAs(item, inner, klass)\n : (\n <a\n href={item.href ?? '#'}\n className={klass}\n aria-current={item.active ? 'page' : undefined}\n onClick={(e) => {\n if (!item.href) e.preventDefault();\n item.onSelect?.();\n onCloseMobile();\n }}\n >\n {inner}\n </a>\n );\n return (\n <li>\n {node}\n {item.children && item.children.length > 0 && (\n <ul className=\"appshell__navchildren\">\n {item.children.map((c) => (\n <NavItemNode key={c.id} item={c} depth={depth + 1} linkAs={linkAs} onCloseMobile={onCloseMobile} />\n ))}\n </ul>\n )}\n </li>\n );\n});\n\nexport function AppShell(props: AppShellProps) {\n const {\n sections, footer, defaultCollapsed = false,\n collapsed: ctrlCollapsed, onCollapsedChange,\n children, className, theme = 'default', linkAs,\n } = props;\n const [internalCollapsed, setInternalCollapsed] = React.useState(defaultCollapsed);\n const [mobileOpen, setMobileOpen] = React.useState(false);\n const t = useLocale();\n const collapsed = ctrlCollapsed ?? internalCollapsed;\n const setCollapsed = (v: boolean) => {\n if (ctrlCollapsed === undefined) setInternalCollapsed(v);\n onCollapsedChange?.(v);\n };\n const closeMobile = React.useCallback(() => setMobileOpen(false), []);\n\n // Top-header variant: full-width header above the body. Topbar is\n // invariant to `collapsed` (only the inner body's columns animate); brand\n // lives in `header.center` at the true viewport centre. Default\n // `headerLayout=\"side\"` falls through to the legacy JSX below\n // (byte-identical for existing consumers). The `props.headerLayout`\n // check narrows the discriminated union, so `header` (top) and\n // `brand`/`topbar`/`user` (side) are each only in scope in their branch.\n if (props.headerLayout === 'top') {\n const { header } = props;\n // Header band themes independently of the sidebar; defaults to `theme`\n // so `theme=\"brand\"` keeps tinting both bands (back-compat).\n const headerTheme = props.headerTheme ?? theme;\n return (\n <div className={cx('appshell', `appshell--${theme}`, 'appshell--header-top', `appshell--header-${headerTheme}`, collapsed && 'is-collapsed', className)}>\n <header className=\"appshell__header\" role=\"banner\">\n <div className=\"appshell__header-left\">{header?.left}</div>\n <div className=\"appshell__header-center\">{header?.center}</div>\n <div className=\"appshell__header-right\">{header?.right}</div>\n </header>\n <div className=\"appshell__body\">\n <aside className=\"appshell__sidebar\" aria-label={t['appshell.mainNav']}>\n <nav className=\"appshell__nav\">\n {sections.map((s, i) => (\n <div key={s.id ?? i} className=\"appshell__navsection\">\n {s.label && <div className=\"appshell__navlabel-section\">{s.label}</div>}\n <ul>{s.items.map((it) => (\n <NavItemNode key={it.id} item={it} depth={0} linkAs={linkAs} onCloseMobile={closeMobile} />\n ))}</ul>\n </div>\n ))}\n </nav>\n {footer != null && <div className=\"appshell__sidebar-foot\">{footer}</div>}\n </aside>\n <main className=\"appshell__content\" role=\"main\">{children}</main>\n </div>\n </div>\n );\n }\n\n const { brand, brandCollapsed, topbar, user } = props;\n return (\n <div className={cx('appshell', `appshell--${theme}`, collapsed && 'is-collapsed', mobileOpen && 'is-mobile-open', className)}>\n <aside className=\"appshell__sidebar\" aria-label={t['appshell.mainNav']}>\n <div className=\"appshell__brand\">\n {collapsed ? (brandCollapsed ?? brand) : brand}\n </div>\n <nav className=\"appshell__nav\">\n {sections.map((s, i) => (\n <div key={s.id ?? i} className=\"appshell__navsection\">\n {s.label && <div className=\"appshell__navlabel-section\">{s.label}</div>}\n <ul>{s.items.map((it) => (\n <NavItemNode key={it.id} item={it} depth={0} linkAs={linkAs} onCloseMobile={closeMobile} />\n ))}</ul>\n </div>\n ))}\n </nav>\n <div className=\"appshell__sidebar-foot\">\n {footer}\n <button\n type=\"button\"\n className=\"appshell__collapse\"\n onClick={() => setCollapsed(!collapsed)}\n aria-expanded={!collapsed}\n aria-label={collapsed ? t['appshell.expandMenu'] : t['appshell.collapseMenu']}\n title={collapsed ? t['appshell.expand'] : t['appshell.collapse']}\n >\n {collapsed ? <ChevronRight size={14} /> : <ChevronLeft size={14} />}\n </button>\n </div>\n </aside>\n\n <div className=\"appshell__main\">\n <header className=\"appshell__topbar\">\n <button\n type=\"button\"\n className=\"appshell__hamburger\"\n aria-label={t['appshell.openMenu']}\n aria-expanded={mobileOpen}\n onClick={() => setMobileOpen((o) => !o)}\n ><MenuIcon size={20} /></button>\n <div className=\"appshell__topbar-content\">{topbar}</div>\n {user && <div className=\"appshell__topbar-user\">{user}</div>}\n </header>\n <main className=\"appshell__content\" role=\"main\">{children}</main>\n </div>\n\n {mobileOpen && (\n <div className=\"appshell__scrim\" onClick={() => setMobileOpen(false)} aria-hidden=\"true\" />\n )}\n </div>\n );\n}\n\n// ---------- PageHeader --------------------------------------------------\nexport interface PageHeaderProps {\n title: React.ReactNode;\n description?: React.ReactNode;\n breadcrumbs?: Array<{ label: React.ReactNode; href?: string }>;\n actions?: React.ReactNode;\n meta?: React.ReactNode;\n className?: string;\n}\n\nexport function PageHeader({ title, description, breadcrumbs, actions, meta, className }: PageHeaderProps) {\n const t = useLocale();\n return (\n <div className={cx('page-header', className)}>\n {breadcrumbs && breadcrumbs.length > 0 && (\n <nav className=\"page-header__crumbs\" aria-label={t['appshell.breadcrumb']}>\n <ol>\n {breadcrumbs.map((c, i) => (\n <li key={i}>\n {c.href ? <a href={c.href}>{c.label}</a> : <span aria-current=\"page\">{c.label}</span>}\n {i < breadcrumbs.length - 1 && <span className=\"page-header__crumb-sep\" aria-hidden=\"true\">/</span>}\n </li>\n ))}\n </ol>\n </nav>\n )}\n <div className=\"page-header__row\">\n <div className=\"page-header__title-wrap\">\n <h1 className=\"page-header__title\">{title}</h1>\n {description && <p className=\"page-header__desc\">{description}</p>}\n </div>\n {actions && <div className=\"page-header__actions\">{actions}</div>}\n </div>\n {meta && <div className=\"page-header__meta\">{meta}</div>}\n </div>\n );\n}\n"]}
|
|
@@ -26,42 +26,87 @@ interface AppShellHeader {
|
|
|
26
26
|
/** Right slot — notifications, user avatar, utilities. */
|
|
27
27
|
right?: React.ReactNode;
|
|
28
28
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
/**
|
|
30
|
+
* Props shared by both layouts. The layout-specific props live in
|
|
31
|
+
* `AppShellSideProps` / `AppShellTopProps`; `AppShellProps` is the
|
|
32
|
+
* discriminated union of the two, keyed on `headerLayout`.
|
|
33
|
+
*/
|
|
34
|
+
interface AppShellBaseProps {
|
|
32
35
|
sections: NavSection[];
|
|
33
|
-
topbar?: React.ReactNode;
|
|
34
36
|
footer?: React.ReactNode;
|
|
35
|
-
user?: React.ReactNode;
|
|
36
37
|
defaultCollapsed?: boolean;
|
|
37
38
|
collapsed?: boolean;
|
|
38
39
|
onCollapsedChange?: (c: boolean) => void;
|
|
39
40
|
children: React.ReactNode;
|
|
40
41
|
className?: string;
|
|
41
42
|
/**
|
|
42
|
-
*
|
|
43
|
+
* Color theme (applies to both layouts):
|
|
43
44
|
* - `default` (light): claro, mejor para apps data-heavy de uso prolongado.
|
|
44
|
-
* - `brand`:
|
|
45
|
+
* - `brand`: superficie azul de marca con texto blanco. Mayor brand recall.
|
|
46
|
+
* En `side` tiñe el sidebar; en `top` tiñe header + sidebar (un solo knob).
|
|
45
47
|
*/
|
|
46
48
|
theme?: AppShellTheme;
|
|
47
49
|
/** Render-prop for navigation links so the host app can use Next.js Link, etc. */
|
|
48
50
|
linkAs?: (item: NavItem, content: React.ReactNode, className: string) => React.ReactNode;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Sidebar layout (default, `headerLayout="side"` or omitted). The brand
|
|
54
|
+
* block + collapse rail live in the sidebar; the topbar sits over the
|
|
55
|
+
* content with a mobile hamburger. `header` is **not** valid here — that
|
|
56
|
+
* slot belongs to the `top` layout.
|
|
57
|
+
*/
|
|
58
|
+
interface AppShellSideProps extends AppShellBaseProps {
|
|
59
|
+
headerLayout?: 'side';
|
|
60
|
+
/** Brand node in the sidebar header (expanded state). */
|
|
61
|
+
brand?: React.ReactNode;
|
|
62
|
+
/** Brand node shown when the rail is collapsed. Falls back to `brand`. */
|
|
63
|
+
brandCollapsed?: React.ReactNode;
|
|
64
|
+
/** Content of the topbar over the page (search, etc.). */
|
|
65
|
+
topbar?: React.ReactNode;
|
|
66
|
+
/** User slot at the right of the topbar (avatar/menu). */
|
|
67
|
+
user?: React.ReactNode;
|
|
68
|
+
/** Not valid in the `side` layout — the header slots belong to `top`. */
|
|
69
|
+
header?: never;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Top-header layout (`headerLayout="top"`, v1.15.0). Full-width header
|
|
73
|
+
* above the body with three slots (`header.{left,center,right}`); the
|
|
74
|
+
* centre slot lands at the **true viewport centre** (1fr·auto·1fr grid).
|
|
75
|
+
* The sidebar has no brand block and `collapsed` hides it entirely (no
|
|
76
|
+
* 72px rail); the header is **invariant** to the collapse. `theme="brand"`
|
|
77
|
+
* tints both bands. The `side`-only props are **not** valid here — put your
|
|
78
|
+
* chrome in `header`.
|
|
79
|
+
*/
|
|
80
|
+
interface AppShellTopProps extends AppShellBaseProps {
|
|
81
|
+
headerLayout: 'top';
|
|
82
|
+
/** Slots for the full-width header. Brand usually goes in `center`. */
|
|
83
|
+
header?: AppShellHeader;
|
|
49
84
|
/**
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
* sidebar entirely — no 72px rail. The topbar is **invariant** to the
|
|
56
|
-
* collapse (only the sidebar changes width). `theme="brand"` tints both
|
|
57
|
-
* header and sidebar with the same brand colour (single knob). `brand`,
|
|
58
|
-
* `brandCollapsed` and `topbar` are ignored when `'top'`.
|
|
85
|
+
* Theme of the **header band only**, independent of the sidebar (`theme`).
|
|
86
|
+
* Defaults to `theme`, so `theme="brand"` still tints both bands (no
|
|
87
|
+
* change for existing consumers). Set `theme="default" headerTheme="brand"`
|
|
88
|
+
* for a branded top bar over a neutral, legible sidebar — common in
|
|
89
|
+
* data-heavy admin apps.
|
|
59
90
|
*/
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
|
|
91
|
+
headerTheme?: AppShellTheme;
|
|
92
|
+
/** Not valid in `top` — use `header.center` for the brand. */
|
|
93
|
+
brand?: never;
|
|
94
|
+
/** Not valid in `top` — the sidebar collapses entirely. */
|
|
95
|
+
brandCollapsed?: never;
|
|
96
|
+
/** Not valid in `top` — use the `header` slots. */
|
|
97
|
+
topbar?: never;
|
|
98
|
+
/** Not valid in `top` — use `header.right`. */
|
|
99
|
+
user?: never;
|
|
63
100
|
}
|
|
64
|
-
|
|
101
|
+
/**
|
|
102
|
+
* Discriminated union keyed on `headerLayout`. TypeScript enforces that
|
|
103
|
+
* `header` is only accepted with `headerLayout="top"` and that
|
|
104
|
+
* `brand`/`brandCollapsed`/`topbar`/`user` are only accepted with the
|
|
105
|
+
* (default) `side` layout — passing the wrong prop for the layout is a
|
|
106
|
+
* compile error instead of being silently ignored at runtime.
|
|
107
|
+
*/
|
|
108
|
+
type AppShellProps = AppShellSideProps | AppShellTopProps;
|
|
109
|
+
declare function AppShell(props: AppShellProps): react_jsx_runtime.JSX.Element;
|
|
65
110
|
interface PageHeaderProps {
|
|
66
111
|
title: React.ReactNode;
|
|
67
112
|
description?: React.ReactNode;
|
|
@@ -75,4 +120,4 @@ interface PageHeaderProps {
|
|
|
75
120
|
}
|
|
76
121
|
declare function PageHeader({ title, description, breadcrumbs, actions, meta, className }: PageHeaderProps): react_jsx_runtime.JSX.Element;
|
|
77
122
|
|
|
78
|
-
export { AppShell, type AppShellHeader, type AppShellHeaderLayout, type AppShellProps, type AppShellTheme, type NavItem, type NavSection, PageHeader, type PageHeaderProps };
|
|
123
|
+
export { AppShell, type AppShellBaseProps, type AppShellHeader, type AppShellHeaderLayout, type AppShellProps, type AppShellSideProps, type AppShellTheme, type AppShellTopProps, type NavItem, type NavSection, PageHeader, type PageHeaderProps };
|
|
@@ -26,42 +26,87 @@ interface AppShellHeader {
|
|
|
26
26
|
/** Right slot — notifications, user avatar, utilities. */
|
|
27
27
|
right?: React.ReactNode;
|
|
28
28
|
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
/**
|
|
30
|
+
* Props shared by both layouts. The layout-specific props live in
|
|
31
|
+
* `AppShellSideProps` / `AppShellTopProps`; `AppShellProps` is the
|
|
32
|
+
* discriminated union of the two, keyed on `headerLayout`.
|
|
33
|
+
*/
|
|
34
|
+
interface AppShellBaseProps {
|
|
32
35
|
sections: NavSection[];
|
|
33
|
-
topbar?: React.ReactNode;
|
|
34
36
|
footer?: React.ReactNode;
|
|
35
|
-
user?: React.ReactNode;
|
|
36
37
|
defaultCollapsed?: boolean;
|
|
37
38
|
collapsed?: boolean;
|
|
38
39
|
onCollapsedChange?: (c: boolean) => void;
|
|
39
40
|
children: React.ReactNode;
|
|
40
41
|
className?: string;
|
|
41
42
|
/**
|
|
42
|
-
*
|
|
43
|
+
* Color theme (applies to both layouts):
|
|
43
44
|
* - `default` (light): claro, mejor para apps data-heavy de uso prolongado.
|
|
44
|
-
* - `brand`:
|
|
45
|
+
* - `brand`: superficie azul de marca con texto blanco. Mayor brand recall.
|
|
46
|
+
* En `side` tiñe el sidebar; en `top` tiñe header + sidebar (un solo knob).
|
|
45
47
|
*/
|
|
46
48
|
theme?: AppShellTheme;
|
|
47
49
|
/** Render-prop for navigation links so the host app can use Next.js Link, etc. */
|
|
48
50
|
linkAs?: (item: NavItem, content: React.ReactNode, className: string) => React.ReactNode;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Sidebar layout (default, `headerLayout="side"` or omitted). The brand
|
|
54
|
+
* block + collapse rail live in the sidebar; the topbar sits over the
|
|
55
|
+
* content with a mobile hamburger. `header` is **not** valid here — that
|
|
56
|
+
* slot belongs to the `top` layout.
|
|
57
|
+
*/
|
|
58
|
+
interface AppShellSideProps extends AppShellBaseProps {
|
|
59
|
+
headerLayout?: 'side';
|
|
60
|
+
/** Brand node in the sidebar header (expanded state). */
|
|
61
|
+
brand?: React.ReactNode;
|
|
62
|
+
/** Brand node shown when the rail is collapsed. Falls back to `brand`. */
|
|
63
|
+
brandCollapsed?: React.ReactNode;
|
|
64
|
+
/** Content of the topbar over the page (search, etc.). */
|
|
65
|
+
topbar?: React.ReactNode;
|
|
66
|
+
/** User slot at the right of the topbar (avatar/menu). */
|
|
67
|
+
user?: React.ReactNode;
|
|
68
|
+
/** Not valid in the `side` layout — the header slots belong to `top`. */
|
|
69
|
+
header?: never;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Top-header layout (`headerLayout="top"`, v1.15.0). Full-width header
|
|
73
|
+
* above the body with three slots (`header.{left,center,right}`); the
|
|
74
|
+
* centre slot lands at the **true viewport centre** (1fr·auto·1fr grid).
|
|
75
|
+
* The sidebar has no brand block and `collapsed` hides it entirely (no
|
|
76
|
+
* 72px rail); the header is **invariant** to the collapse. `theme="brand"`
|
|
77
|
+
* tints both bands. The `side`-only props are **not** valid here — put your
|
|
78
|
+
* chrome in `header`.
|
|
79
|
+
*/
|
|
80
|
+
interface AppShellTopProps extends AppShellBaseProps {
|
|
81
|
+
headerLayout: 'top';
|
|
82
|
+
/** Slots for the full-width header. Brand usually goes in `center`. */
|
|
83
|
+
header?: AppShellHeader;
|
|
49
84
|
/**
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
* sidebar entirely — no 72px rail. The topbar is **invariant** to the
|
|
56
|
-
* collapse (only the sidebar changes width). `theme="brand"` tints both
|
|
57
|
-
* header and sidebar with the same brand colour (single knob). `brand`,
|
|
58
|
-
* `brandCollapsed` and `topbar` are ignored when `'top'`.
|
|
85
|
+
* Theme of the **header band only**, independent of the sidebar (`theme`).
|
|
86
|
+
* Defaults to `theme`, so `theme="brand"` still tints both bands (no
|
|
87
|
+
* change for existing consumers). Set `theme="default" headerTheme="brand"`
|
|
88
|
+
* for a branded top bar over a neutral, legible sidebar — common in
|
|
89
|
+
* data-heavy admin apps.
|
|
59
90
|
*/
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
|
|
91
|
+
headerTheme?: AppShellTheme;
|
|
92
|
+
/** Not valid in `top` — use `header.center` for the brand. */
|
|
93
|
+
brand?: never;
|
|
94
|
+
/** Not valid in `top` — the sidebar collapses entirely. */
|
|
95
|
+
brandCollapsed?: never;
|
|
96
|
+
/** Not valid in `top` — use the `header` slots. */
|
|
97
|
+
topbar?: never;
|
|
98
|
+
/** Not valid in `top` — use `header.right`. */
|
|
99
|
+
user?: never;
|
|
63
100
|
}
|
|
64
|
-
|
|
101
|
+
/**
|
|
102
|
+
* Discriminated union keyed on `headerLayout`. TypeScript enforces that
|
|
103
|
+
* `header` is only accepted with `headerLayout="top"` and that
|
|
104
|
+
* `brand`/`brandCollapsed`/`topbar`/`user` are only accepted with the
|
|
105
|
+
* (default) `side` layout — passing the wrong prop for the layout is a
|
|
106
|
+
* compile error instead of being silently ignored at runtime.
|
|
107
|
+
*/
|
|
108
|
+
type AppShellProps = AppShellSideProps | AppShellTopProps;
|
|
109
|
+
declare function AppShell(props: AppShellProps): react_jsx_runtime.JSX.Element;
|
|
65
110
|
interface PageHeaderProps {
|
|
66
111
|
title: React.ReactNode;
|
|
67
112
|
description?: React.ReactNode;
|
|
@@ -75,4 +120,4 @@ interface PageHeaderProps {
|
|
|
75
120
|
}
|
|
76
121
|
declare function PageHeader({ title, description, breadcrumbs, actions, meta, className }: PageHeaderProps): react_jsx_runtime.JSX.Element;
|
|
77
122
|
|
|
78
|
-
export { AppShell, type AppShellHeader, type AppShellHeaderLayout, type AppShellProps, type AppShellTheme, type NavItem, type NavSection, PageHeader, type PageHeaderProps };
|
|
123
|
+
export { AppShell, type AppShellBaseProps, type AppShellHeader, type AppShellHeaderLayout, type AppShellProps, type AppShellSideProps, type AppShellTheme, type AppShellTopProps, type NavItem, type NavSection, PageHeader, type PageHeaderProps };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var
|
|
4
|
+
var chunkSZWROXKE_js = require('../chunk-SZWROXKE.js');
|
|
5
5
|
require('../chunk-4VMQLSHV.js');
|
|
6
6
|
require('../chunk-RQOTH7I7.js');
|
|
7
7
|
require('../chunk-PASF6T4H.js');
|
|
@@ -10,11 +10,11 @@ require('../chunk-PASF6T4H.js');
|
|
|
10
10
|
|
|
11
11
|
Object.defineProperty(exports, "AppShell", {
|
|
12
12
|
enumerable: true,
|
|
13
|
-
get: function () { return
|
|
13
|
+
get: function () { return chunkSZWROXKE_js.AppShell; }
|
|
14
14
|
});
|
|
15
15
|
Object.defineProperty(exports, "PageHeader", {
|
|
16
16
|
enumerable: true,
|
|
17
|
-
get: function () { return
|
|
17
|
+
get: function () { return chunkSZWROXKE_js.PageHeader; }
|
|
18
18
|
});
|
|
19
19
|
//# sourceMappingURL=AppShell.js.map
|
|
20
20
|
//# sourceMappingURL=AppShell.js.map
|
package/dist/index.d.mts
CHANGED
|
@@ -15,7 +15,7 @@ export { Accordion, AccordionItem, AccordionProps, BreadcrumbItem, Breadcrumbs,
|
|
|
15
15
|
export { CheckboxGroup, CheckboxGroupProps, MoneyInput, MoneyInputProps, OptionItem, PhoneInput, PhoneInputProps, Progress, ProgressCircle, ProgressCircleProps, ProgressProps, RadioGroup, RadioGroupProps, Slider, SliderProps, TagInput, TagInputProps, TimePicker, TimePickerProps } from './components/InputsExtra.mjs';
|
|
16
16
|
export { Avatar, AvatarGroup, AvatarGroupProps, AvatarProps, Menu, MenuItemProps, MenuProps, Stat, StatProps } from './components/Display2.mjs';
|
|
17
17
|
export { CommandItem, CommandPalette, CommandPaletteProps, DateRange, DateRangePicker, DateRangePickerProps, MultiCombobox, MultiComboboxOption, MultiComboboxProps, UseCommandPaletteOptions, useCommandPalette } from './components/AdvancedPickers.mjs';
|
|
18
|
-
export { AppShell, AppShellHeader, AppShellHeaderLayout, AppShellProps, AppShellTheme, NavItem, NavSection, PageHeader, PageHeaderProps } from './components/AppShell.mjs';
|
|
18
|
+
export { AppShell, AppShellBaseProps, AppShellHeader, AppShellHeaderLayout, AppShellProps, AppShellSideProps, AppShellTheme, AppShellTopProps, NavItem, NavSection, PageHeader, PageHeaderProps } from './components/AppShell.mjs';
|
|
19
19
|
export { AreaChart, AreaChartProps, BarChart, BarChartProps, BaseChartProps, DonutChart, DonutChartProps, LineChart, LineChartProps, RechartsLike, Sparkline, SparklineProps } from './components/Charts.mjs';
|
|
20
20
|
export { AlertCircle, AlertTriangle, AlignCenter, AlignLeft, AlignRight, ArrowDown, ArrowLeft, ArrowRight, ArrowUp, Bell, Bold, Building, CalendarIcon, Check, CheckCircle, ChevronDown, ChevronLeft, ChevronRight, ChevronUp, Clock, Copy, CreditCard, Download, Edit, ExternalLink, Eye, EyeOff, FileText, Filter, Folder, Globe, Heart, Home, IconProps, Info, Italic, Link, Loader, Lock, LogOut, Mail, MapPin, MenuIcon, Minus, Moon, MoreHorizontal, MoreVertical, Package, Phone, Plus, RefreshCw, Search, Settings, ShoppingCart, Star, Sun, Tag, Tool, Trash, Truck, Underline, Unlock, Upload, User, Users, Wrench, X } from './components/Icons.mjs';
|
|
21
21
|
export { Logo, LogoBg, LogoFormat, LogoProps, LogoVariant } from './components/Logo.mjs';
|
package/dist/index.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ export { Accordion, AccordionItem, AccordionProps, BreadcrumbItem, Breadcrumbs,
|
|
|
15
15
|
export { CheckboxGroup, CheckboxGroupProps, MoneyInput, MoneyInputProps, OptionItem, PhoneInput, PhoneInputProps, Progress, ProgressCircle, ProgressCircleProps, ProgressProps, RadioGroup, RadioGroupProps, Slider, SliderProps, TagInput, TagInputProps, TimePicker, TimePickerProps } from './components/InputsExtra.js';
|
|
16
16
|
export { Avatar, AvatarGroup, AvatarGroupProps, AvatarProps, Menu, MenuItemProps, MenuProps, Stat, StatProps } from './components/Display2.js';
|
|
17
17
|
export { CommandItem, CommandPalette, CommandPaletteProps, DateRange, DateRangePicker, DateRangePickerProps, MultiCombobox, MultiComboboxOption, MultiComboboxProps, UseCommandPaletteOptions, useCommandPalette } from './components/AdvancedPickers.js';
|
|
18
|
-
export { AppShell, AppShellHeader, AppShellHeaderLayout, AppShellProps, AppShellTheme, NavItem, NavSection, PageHeader, PageHeaderProps } from './components/AppShell.js';
|
|
18
|
+
export { AppShell, AppShellBaseProps, AppShellHeader, AppShellHeaderLayout, AppShellProps, AppShellSideProps, AppShellTheme, AppShellTopProps, NavItem, NavSection, PageHeader, PageHeaderProps } from './components/AppShell.js';
|
|
19
19
|
export { AreaChart, AreaChartProps, BarChart, BarChartProps, BaseChartProps, DonutChart, DonutChartProps, LineChart, LineChartProps, RechartsLike, Sparkline, SparklineProps } from './components/Charts.js';
|
|
20
20
|
export { AlertCircle, AlertTriangle, AlignCenter, AlignLeft, AlignRight, ArrowDown, ArrowLeft, ArrowRight, ArrowUp, Bell, Bold, Building, CalendarIcon, Check, CheckCircle, ChevronDown, ChevronLeft, ChevronRight, ChevronUp, Clock, Copy, CreditCard, Download, Edit, ExternalLink, Eye, EyeOff, FileText, Filter, Folder, Globe, Heart, Home, IconProps, Info, Italic, Link, Loader, Lock, LogOut, Mail, MapPin, MenuIcon, Minus, Moon, MoreHorizontal, MoreVertical, Package, Phone, Plus, RefreshCw, Search, Settings, ShoppingCart, Star, Sun, Tag, Tool, Trash, Truck, Underline, Unlock, Upload, User, Users, Wrench, X } from './components/Icons.js';
|
|
21
21
|
export { Logo, LogoBg, LogoFormat, LogoProps, LogoVariant } from './components/Logo.js';
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
+
require('./chunk-4REALDR3.js');
|
|
4
5
|
require('./chunk-427NHGTX.js');
|
|
5
6
|
require('./chunk-2LTV7VB5.js');
|
|
6
|
-
require('./chunk-4REALDR3.js');
|
|
7
7
|
var chunkJT2SFHBH_js = require('./chunk-JT2SFHBH.js');
|
|
8
8
|
var chunkDGBVPXGW_js = require('./chunk-DGBVPXGW.js');
|
|
9
9
|
var chunkVDBGWTIG_js = require('./chunk-VDBGWTIG.js');
|
|
@@ -41,7 +41,7 @@ var chunkXMLBKK7X_js = require('./chunk-XMLBKK7X.js');
|
|
|
41
41
|
var chunk7I5LFBQR_js = require('./chunk-7I5LFBQR.js');
|
|
42
42
|
var chunkWAGWB35Q_js = require('./chunk-WAGWB35Q.js');
|
|
43
43
|
var chunk3PXYCXDW_js = require('./chunk-3PXYCXDW.js');
|
|
44
|
-
var
|
|
44
|
+
var chunkSZWROXKE_js = require('./chunk-SZWROXKE.js');
|
|
45
45
|
var chunk4VMQLSHV_js = require('./chunk-4VMQLSHV.js');
|
|
46
46
|
var chunkAJ22SXI2_js = require('./chunk-AJ22SXI2.js');
|
|
47
47
|
var chunkEUB4PHPI_js = require('./chunk-EUB4PHPI.js');
|
|
@@ -667,11 +667,11 @@ Object.defineProperty(exports, "resetBrand", {
|
|
|
667
667
|
});
|
|
668
668
|
Object.defineProperty(exports, "AppShell", {
|
|
669
669
|
enumerable: true,
|
|
670
|
-
get: function () { return
|
|
670
|
+
get: function () { return chunkSZWROXKE_js.AppShell; }
|
|
671
671
|
});
|
|
672
672
|
Object.defineProperty(exports, "PageHeader", {
|
|
673
673
|
enumerable: true,
|
|
674
|
-
get: function () { return
|
|
674
|
+
get: function () { return chunkSZWROXKE_js.PageHeader; }
|
|
675
675
|
});
|
|
676
676
|
Object.defineProperty(exports, "LocaleProvider", {
|
|
677
677
|
enumerable: true,
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
|
+
import './chunk-CHVTPN3K.mjs';
|
|
2
3
|
import './chunk-BVQRDAR7.mjs';
|
|
3
4
|
import './chunk-XTHC46M2.mjs';
|
|
4
|
-
import './chunk-CHVTPN3K.mjs';
|
|
5
5
|
export { PermissionMatrix } from './chunk-LVLJ75ND.mjs';
|
|
6
6
|
export { Combobox, DatePicker, FileUpload, MonthPicker, YearPicker } from './chunk-YNU45Y5T.mjs';
|
|
7
7
|
export { Popover } from './chunk-FA6526ME.mjs';
|
|
@@ -39,7 +39,7 @@ export { useDismiss } from './chunk-6P2TKRTL.mjs';
|
|
|
39
39
|
export { usePopoverPosition } from './chunk-PRML6VEF.mjs';
|
|
40
40
|
export { Portal } from './chunk-FKBQYQQD.mjs';
|
|
41
41
|
export { BRAND_DEFAULTS, configureBrand, getBrand, resetBrand } from './chunk-5GEWIK4T.mjs';
|
|
42
|
-
export { AppShell, PageHeader } from './chunk-
|
|
42
|
+
export { AppShell, PageHeader } from './chunk-E462CF6P.mjs';
|
|
43
43
|
export { LocaleProvider, esMessages, useLocale } from './chunk-PQV7HHCJ.mjs';
|
|
44
44
|
export { Button, ButtonGroup } from './chunk-NAL457NQ.mjs';
|
|
45
45
|
export { AspectRatio, ScrollArea, Separator, Slot, Slottable } from './chunk-IEPKSPBX.mjs';
|