@countermeasure-platform/web-components 1.3.3-dev.33.1 → 1.3.4-dev.35.1

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 (64) hide show
  1. package/README.md +31 -0
  2. package/dist/component-D5sRm1fq.js +389 -0
  3. package/dist/component-D5sRm1fq.js.map +1 -0
  4. package/dist/components/index.js +27 -27
  5. package/dist/icons/index.d.ts +12 -0
  6. package/dist/icons/index.d.ts.map +1 -1
  7. package/dist/icons/index.js +12 -0
  8. package/dist/icons/index.js.map +1 -1
  9. package/dist/index.d.ts +1 -1
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +127 -126
  12. package/dist/layout/app-shell.d.ts +50 -3
  13. package/dist/layout/app-shell.d.ts.map +1 -1
  14. package/dist/layout/app-shell.js +142 -13
  15. package/dist/layout/app-shell.js.map +1 -1
  16. package/dist/layout/core-app-chrome.d.ts +81 -0
  17. package/dist/layout/core-app-chrome.d.ts.map +1 -0
  18. package/dist/layout/core-app-chrome.js +349 -0
  19. package/dist/layout/core-app-chrome.js.map +1 -0
  20. package/dist/layout/index.d.ts +4 -2
  21. package/dist/layout/index.d.ts.map +1 -1
  22. package/dist/layout/index.js +88 -87
  23. package/dist/layout/index.js.map +1 -1
  24. package/dist/react/primitives/badge.d.ts +1 -1
  25. package/dist/react/primitives/button.d.ts +2 -2
  26. package/dist/react/primitives/copy-button.d.ts +1 -1
  27. package/dist/react/primitives/stat-card.d.ts +1 -1
  28. package/dist/react/primitives/toggle.d.ts +1 -1
  29. package/dist/react/sidebar.d.ts +4 -4
  30. package/dist/react/sidebar.d.ts.map +1 -1
  31. package/dist/react/sidebar.js +18 -16
  32. package/dist/react/sidebar.js.map +1 -1
  33. package/dist/sidebar/component.d.ts +24 -2
  34. package/dist/sidebar/component.d.ts.map +1 -1
  35. package/dist/sidebar/enhance.d.ts +8 -0
  36. package/dist/sidebar/enhance.d.ts.map +1 -1
  37. package/dist/sidebar/index.d.ts +3 -0
  38. package/dist/sidebar/index.d.ts.map +1 -1
  39. package/dist/sidebar/index.js +81 -28
  40. package/dist/sidebar/index.js.map +1 -1
  41. package/dist/sidebar/types.d.ts +126 -4
  42. package/dist/sidebar/types.d.ts.map +1 -1
  43. package/dist/styles/layout.css +252 -0
  44. package/dist/styles/sidebar.css +313 -5
  45. package/package.json +6 -1
  46. package/src/icons/icons.test.ts +9 -0
  47. package/src/icons/index.ts +12 -0
  48. package/src/index.ts +11 -0
  49. package/src/layout/app-shell.test.ts +204 -0
  50. package/src/layout/app-shell.ts +362 -3
  51. package/src/layout/core-app-chrome.test.ts +507 -0
  52. package/src/layout/core-app-chrome.ts +662 -0
  53. package/src/layout/index.ts +36 -2
  54. package/src/react/sidebar.test.tsx +104 -3
  55. package/src/react/sidebar.tsx +26 -4
  56. package/src/sidebar/component.test.ts +395 -1
  57. package/src/sidebar/component.ts +661 -86
  58. package/src/sidebar/enhance.ts +118 -0
  59. package/src/sidebar/index.ts +144 -0
  60. package/src/sidebar/types.ts +143 -4
  61. package/src/styles/layout.css +252 -0
  62. package/src/styles/sidebar.css +313 -5
  63. package/dist/component-Bxhxf21c.js +0 -167
  64. package/dist/component-Bxhxf21c.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"sidebar.js","names":[],"sources":["../../src/react/sidebar.tsx"],"sourcesContent":["/**\n * Sidebar React wrapper — Lane A imperative wrap over src/sidebar/component.ts\n *\n * Import from the dedicated subpath:\n * import { Sidebar } from '@countermeasure-platform/web-components/react/sidebar'\n *\n * The wrapper renders a host div then mounts `SidebarComponent` into it on\n * mount. Prop changes to `activeItemId` and controlled `open` are synced via\n * the class's public API.\n */\n\nimport * as React from 'react'\nimport { cn } from './primitives/utils'\nimport { SidebarComponent } from '../sidebar/component'\nimport type {\n SidebarComponentConfig,\n SidebarNavItem,\n SidebarSection,\n SidebarUser,\n SidebarFooterAction,\n} from '../sidebar/types'\n\nexport interface SidebarProps extends Omit<\n SidebarComponentConfig,\n 'container' | 'onNavigate' | 'onCollapse'\n> {\n /** Currently active nav item ID. Synced via `setActive` on changes. */\n activeItemId?: string\n /** Called when the user clicks a nav item. */\n onNavigate?: (item: SidebarNavItem) => void\n /** Called when the sidebar is collapsed/expanded. */\n onCollapse?: (collapsed: boolean) => void\n className?: string\n}\n\nexport type { SidebarNavItem, SidebarSection, SidebarUser, SidebarFooterAction }\n\nexport interface SidebarCollapseButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n collapsed?: boolean\n edge?: boolean\n visible?: boolean\n label?: string\n}\n\nconst Sidebar = (props: SidebarProps) => {\n const { activeItemId, onNavigate, onCollapse, className, open, ...config } = props\n const containerRef = React.useRef<HTMLDivElement>(null)\n const sidebarRef = React.useRef<SidebarComponent | null>(null)\n const onNavigateRef = React.useRef(onNavigate)\n const onCollapseRef = React.useRef(onCollapse)\n onNavigateRef.current = onNavigate\n onCollapseRef.current = onCollapse\n\n // Construct once on mount — SSR-safe\n React.useEffect(() => {\n if (typeof document === 'undefined' || !containerRef.current) return\n const sidebarConfig: SidebarComponentConfig = {\n ...config,\n container: containerRef.current,\n onNavigate: (item: SidebarNavItem) => {\n onNavigateRef.current?.(item)\n },\n onCollapse: (collapsed: boolean) => {\n onCollapseRef.current?.(collapsed)\n },\n }\n if (open !== undefined) {\n sidebarConfig.open = open\n }\n sidebarRef.current = new SidebarComponent(sidebarConfig)\n return () => {\n sidebarRef.current?.destroy()\n sidebarRef.current = null\n }\n }, [])\n\n // Sync mobile open state to the component default when the prop is removed.\n React.useEffect(() => {\n if (!sidebarRef.current) return\n sidebarRef.current.setOpen(open === true)\n }, [open])\n\n // Sync active item when prop changes\n React.useEffect(() => {\n if (!sidebarRef.current || activeItemId === undefined) return\n sidebarRef.current.setActive(activeItemId)\n }, [activeItemId])\n\n return <div ref={containerRef} data-slot=\"sidebar\" className={cn(className)} />\n}\n\nSidebar.displayName = 'Sidebar'\n\nconst collapseDefaultLabel = (collapsed: boolean): string =>\n collapsed ? 'Expand sidebar' : 'Collapse sidebar'\n\nconst collapseIconPath = (collapsed: boolean): string =>\n collapsed ? 'm9 18 6-6-6-6' : 'm15 18-6-6 6-6'\n\nconst CollapseChevron = ({ collapsed }: { collapsed: boolean }) => (\n <svg\n aria-hidden=\"true\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d={collapseIconPath(collapsed)} />\n </svg>\n)\n\nconst SidebarCollapseButton = (componentProps: SidebarCollapseButtonProps) => {\n const {\n collapsed = false,\n edge = false,\n visible = false,\n label,\n className,\n type = 'button',\n children,\n ...props\n } = componentProps\n const resolvedLabel = label ?? collapseDefaultLabel(collapsed)\n\n return (\n <button\n type={type}\n className={cn('sidebar__collapse-btn', edge && 'sidebar__collapse-btn--edge', className)}\n aria-label={resolvedLabel}\n aria-expanded={!collapsed}\n title={resolvedLabel}\n data-collapsed={collapsed ? 'true' : 'false'}\n data-visible={visible ? 'true' : undefined}\n {...props}\n >\n {children ?? <CollapseChevron collapsed={collapsed} />}\n </button>\n )\n}\n\nSidebarCollapseButton.displayName = 'SidebarCollapseButton'\n\nexport { Sidebar, SidebarCollapseButton }\n"],"mappings":";;;;;AA4CA,IAAM,KAAW,MAAwB;CACvC,IAAM,EAAE,iBAAc,eAAY,eAAY,cAAW,SAAM,GAAG,MAAW,GACvE,IAAe,EAAM,OAAuB,IAAI,GAChD,IAAa,EAAM,OAAgC,IAAI,GACvD,IAAgB,EAAM,OAAO,CAAU,GACvC,IAAgB,EAAM,OAAO,CAAU;CAuC7C,OAtCA,EAAc,UAAU,GACxB,EAAc,UAAU,GAGxB,EAAM,gBAAgB;EACpB,IAAI,OAAO,WAAa,OAAe,CAAC,EAAa,SAAS;EAC9D,IAAM,IAAwC;GAC5C,GAAG;GACH,WAAW,EAAa;GACxB,aAAa,MAAyB;IACpC,EAAc,UAAU,CAAI;GAC9B;GACA,aAAa,MAAuB;IAClC,EAAc,UAAU,CAAS;GACnC;EACF;EAKA,OAJI,MAAS,KAAA,MACX,EAAc,OAAO,IAEvB,EAAW,UAAU,IAAI,EAAiB,CAAa,SAC1C;GAEX,AADA,EAAW,SAAS,QAAQ,GAC5B,EAAW,UAAU;EACvB;CACF,GAAG,CAAC,CAAC,GAGL,EAAM,gBAAgB;EACf,EAAW,WAChB,EAAW,QAAQ,QAAQ,MAAS,EAAI;CAC1C,GAAG,CAAC,CAAI,CAAC,GAGT,EAAM,gBAAgB;EAChB,CAAC,EAAW,WAAW,MAAiB,KAAA,KAC5C,EAAW,QAAQ,UAAU,CAAY;CAC3C,GAAG,CAAC,CAAY,CAAC,GAEV,kBAAC,OAAD;EAAK,KAAK;EAAc,aAAU;EAAU,WAAW,EAAG,CAAS;CAAI,CAAA;AAChF;AAEA,EAAQ,cAAc;AAEtB,IAAM,KAAwB,MAC5B,IAAY,mBAAmB,oBAE3B,KAAoB,MACxB,IAAY,kBAAkB,kBAE1B,KAAmB,EAAE,mBACzB,kBAAC,OAAD;CACE,eAAY;CACZ,SAAQ;CACR,MAAK;CACL,QAAO;CACP,aAAY;CACZ,eAAc;CACd,gBAAe;WAEf,kBAAC,QAAD,EAAM,GAAG,EAAiB,CAAS,EAAI,CAAA;AACpC,CAAA,GAGD,KAAyB,MAA+C;CAC5E,IAAM,EACJ,eAAY,IACZ,UAAO,IACP,aAAU,IACV,UACA,cACA,UAAO,UACP,aACA,GAAG,MACD,GACE,IAAgB,KAAS,EAAqB,CAAS;CAE7D,OACE,kBAAC,UAAD;EACQ;EACN,WAAW,EAAG,yBAAyB,KAAQ,+BAA+B,CAAS;EACvF,cAAY;EACZ,iBAAe,CAAC;EAChB,OAAO;EACP,kBAAgB,IAAY,SAAS;EACrC,gBAAc,IAAU,SAAS,KAAA;EACjC,GAAI;YAEH,KAAY,kBAAC,GAAD,EAA4B,aAAY,CAAA;CAC/C,CAAA;AAEZ;AAEA,EAAsB,cAAc"}
1
+ {"version":3,"file":"sidebar.js","names":[],"sources":["../../src/react/sidebar.tsx"],"sourcesContent":["/**\n * Sidebar React wrapper — Lane A imperative wrap over src/sidebar/component.ts\n *\n * Import from the dedicated subpath:\n * import { Sidebar } from '@countermeasure-platform/web-components/react/sidebar'\n *\n * The wrapper renders a host div then mounts `SidebarComponent` into it on\n * mount. Prop changes to `activeItemId`, `pathname`, and controlled `open`\n * are synced via the class's public API.\n */\n\nimport * as React from 'react'\nimport { cn } from './primitives/utils'\nimport { SidebarComponent } from '../sidebar/component'\nimport type {\n SidebarComponentConfig,\n SidebarBadgeConfig,\n SidebarBadgeTone,\n SidebarNavItem,\n SidebarScopeConfig,\n SidebarScopeOption,\n SidebarSection,\n SidebarUser,\n SidebarFooterAction,\n} from '../sidebar/types'\n\nexport interface SidebarProps extends Omit<\n SidebarComponentConfig,\n 'container' | 'onNavigate' | 'onCollapse'\n> {\n /** Currently active nav item ID. Synced via `setActive` on changes. */\n activeItemId?: string\n /** Called when the user clicks a nav item. */\n onNavigate?: (item: SidebarNavItem) => void\n /** Called when the sidebar is collapsed/expanded. */\n onCollapse?: (collapsed: boolean) => void\n className?: string\n}\n\nexport type {\n SidebarBadgeConfig,\n SidebarBadgeTone,\n SidebarFooterAction,\n SidebarNavItem,\n SidebarScopeConfig,\n SidebarScopeOption,\n SidebarSection,\n SidebarUser,\n}\n\nexport interface SidebarCollapseButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n collapsed?: boolean\n edge?: boolean\n visible?: boolean\n label?: string\n}\n\nconst Sidebar = (props: SidebarProps) => {\n const { activeItemId, pathname, onNavigate, onCollapse, className, open, ...config } = props\n const containerRef = React.useRef<HTMLDivElement>(null)\n const sidebarRef = React.useRef<SidebarComponent | null>(null)\n const onNavigateRef = React.useRef(onNavigate)\n const onCollapseRef = React.useRef(onCollapse)\n onNavigateRef.current = onNavigate\n onCollapseRef.current = onCollapse\n\n // Construct once on mount — SSR-safe\n React.useEffect(() => {\n if (typeof document === 'undefined' || !containerRef.current) return\n const sidebarConfig: SidebarComponentConfig = {\n ...config,\n container: containerRef.current,\n onNavigate: (item: SidebarNavItem) => {\n onNavigateRef.current?.(item)\n },\n onCollapse: (collapsed: boolean) => {\n onCollapseRef.current?.(collapsed)\n },\n }\n if (open !== undefined) {\n sidebarConfig.open = open\n }\n if (pathname !== undefined) {\n sidebarConfig.pathname = pathname\n }\n sidebarRef.current = new SidebarComponent(sidebarConfig)\n return () => {\n sidebarRef.current?.destroy()\n sidebarRef.current = null\n }\n }, [])\n\n // Sync mobile open state to the component default when the prop is removed.\n React.useEffect(() => {\n if (!sidebarRef.current) return\n sidebarRef.current.setOpen(open === true)\n }, [open])\n\n // Sync active item when prop changes\n React.useEffect(() => {\n if (!sidebarRef.current || activeItemId === undefined) return\n sidebarRef.current.setActive(activeItemId)\n }, [activeItemId])\n\n // Sync route-derived active state when no explicit active item controls it.\n React.useEffect(() => {\n if (!sidebarRef.current || activeItemId !== undefined) return\n sidebarRef.current.setPathname(pathname)\n }, [activeItemId, pathname])\n\n return <div ref={containerRef} data-slot=\"sidebar\" className={cn(className)} />\n}\n\nSidebar.displayName = 'Sidebar'\n\nconst collapseDefaultLabel = (collapsed: boolean): string =>\n collapsed ? 'Expand sidebar' : 'Collapse sidebar'\n\nconst collapseIconPath = (collapsed: boolean): string =>\n collapsed ? 'm9 18 6-6-6-6' : 'm15 18-6-6 6-6'\n\nconst CollapseChevron = ({ collapsed }: { collapsed: boolean }) => (\n <svg\n aria-hidden=\"true\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d={collapseIconPath(collapsed)} />\n </svg>\n)\n\nconst SidebarCollapseButton = (componentProps: SidebarCollapseButtonProps) => {\n const {\n collapsed = false,\n edge = false,\n visible = false,\n label,\n className,\n type = 'button',\n children,\n ...props\n } = componentProps\n const resolvedLabel = label ?? collapseDefaultLabel(collapsed)\n\n return (\n <button\n type={type}\n className={cn('sidebar__collapse-btn', edge && 'sidebar__collapse-btn--edge', className)}\n aria-label={resolvedLabel}\n aria-expanded={!collapsed}\n title={resolvedLabel}\n data-collapsed={collapsed ? 'true' : 'false'}\n data-visible={visible ? 'true' : undefined}\n {...props}\n >\n {children ?? <CollapseChevron collapsed={collapsed} />}\n </button>\n )\n}\n\nSidebarCollapseButton.displayName = 'SidebarCollapseButton'\n\nexport { Sidebar, SidebarCollapseButton }\n"],"mappings":";;;;;AAyDA,IAAM,KAAW,MAAwB;CACvC,IAAM,EAAE,iBAAc,aAAU,eAAY,eAAY,cAAW,SAAM,GAAG,MAAW,GACjF,IAAe,EAAM,OAAuB,IAAI,GAChD,IAAa,EAAM,OAAgC,IAAI,GACvD,IAAgB,EAAM,OAAO,CAAU,GACvC,IAAgB,EAAM,OAAO,CAAU;CAgD7C,OA/CA,EAAc,UAAU,GACxB,EAAc,UAAU,GAGxB,EAAM,gBAAgB;EACpB,IAAI,OAAO,WAAa,OAAe,CAAC,EAAa,SAAS;EAC9D,IAAM,IAAwC;GAC5C,GAAG;GACH,WAAW,EAAa;GACxB,aAAa,MAAyB;IACpC,EAAc,UAAU,CAAI;GAC9B;GACA,aAAa,MAAuB;IAClC,EAAc,UAAU,CAAS;GACnC;EACF;EAQA,OAPI,MAAS,KAAA,MACX,EAAc,OAAO,IAEnB,MAAa,KAAA,MACf,EAAc,WAAW,IAE3B,EAAW,UAAU,IAAI,EAAiB,CAAa,SAC1C;GAEX,AADA,EAAW,SAAS,QAAQ,GAC5B,EAAW,UAAU;EACvB;CACF,GAAG,CAAC,CAAC,GAGL,EAAM,gBAAgB;EACf,EAAW,WAChB,EAAW,QAAQ,QAAQ,MAAS,EAAI;CAC1C,GAAG,CAAC,CAAI,CAAC,GAGT,EAAM,gBAAgB;EAChB,CAAC,EAAW,WAAW,MAAiB,KAAA,KAC5C,EAAW,QAAQ,UAAU,CAAY;CAC3C,GAAG,CAAC,CAAY,CAAC,GAGjB,EAAM,gBAAgB;EAChB,CAAC,EAAW,WAAW,MAAiB,KAAA,KAC5C,EAAW,QAAQ,YAAY,CAAQ;CACzC,GAAG,CAAC,GAAc,CAAQ,CAAC,GAEpB,kBAAC,OAAD;EAAK,KAAK;EAAc,aAAU;EAAU,WAAW,EAAG,CAAS;CAAI,CAAA;AAChF;AAEA,EAAQ,cAAc;AAEtB,IAAM,KAAwB,MAC5B,IAAY,mBAAmB,oBAE3B,KAAoB,MACxB,IAAY,kBAAkB,kBAE1B,KAAmB,EAAE,mBACzB,kBAAC,OAAD;CACE,eAAY;CACZ,SAAQ;CACR,MAAK;CACL,QAAO;CACP,aAAY;CACZ,eAAc;CACd,gBAAe;WAEf,kBAAC,QAAD,EAAM,GAAG,EAAiB,CAAS,EAAI,CAAA;AACpC,CAAA,GAGD,KAAyB,MAA+C;CAC5E,IAAM,EACJ,eAAY,IACZ,UAAO,IACP,aAAU,IACV,UACA,cACA,UAAO,UACP,aACA,GAAG,MACD,GACE,IAAgB,KAAS,EAAqB,CAAS;CAE7D,OACE,kBAAC,UAAD;EACQ;EACN,WAAW,EAAG,yBAAyB,KAAQ,+BAA+B,CAAS;EACvF,cAAY;EACZ,iBAAe,CAAC;EAChB,OAAO;EACP,kBAAgB,IAAY,SAAS;EACrC,gBAAc,IAAU,SAAS,KAAA;EACjC,GAAI;YAEH,KAAY,kBAAC,GAAD,EAA4B,aAAY,CAAA;CAC/C,CAAA;AAEZ;AAEA,EAAsB,cAAc"}
@@ -1,20 +1,31 @@
1
- import { SidebarComponentConfig } from './types';
1
+ import { SidebarBadgeTone, SidebarComponentConfig } from './types';
2
2
  export declare class SidebarComponent {
3
3
  private readonly container;
4
4
  private readonly aside;
5
5
  private readonly config;
6
6
  private readonly iconSet;
7
+ private readonly variant;
8
+ private readonly cleanupFns;
7
9
  private collapseButton;
10
+ private backdrop;
8
11
  constructor(config: SidebarComponentConfig);
9
12
  private render;
10
13
  private buildSection;
14
+ private buildItem;
11
15
  private renderHeader;
16
+ private renderScope;
12
17
  private renderCollapseButton;
13
18
  private renderFooter;
19
+ private renderBackdrop;
20
+ private setupBehavior;
21
+ private setupKeyboardNavigation;
22
+ private setupMobileToggles;
14
23
  /** Mark a nav item as active, removing active state from all others. */
15
24
  setActive(itemId: string): void;
25
+ /** Recompute active route state from a supplied pathname or the current location. */
26
+ setPathname(pathname: string | undefined): void;
16
27
  /** Update the badge count for a nav item (empty string when count is 0). */
17
- updateBadge(itemId: string, count: number): void;
28
+ updateBadge(itemId: string, count: number, tone?: SidebarBadgeTone): void;
18
29
  /** Toggle the sidebar between collapsed and expanded states. */
19
30
  toggleCollapse(): void;
20
31
  /** Collapse the sidebar. */
@@ -25,6 +36,17 @@ export declare class SidebarComponent {
25
36
  setOpen(open: boolean): void;
26
37
  /** Remove the sidebar from the DOM. */
27
38
  destroy(): void;
39
+ private applyBadge;
40
+ private setCollapsed;
41
+ private isCollapsed;
42
+ private isOpen;
43
+ private getMobileBreakpoint;
44
+ private resolveInitialCollapsed;
45
+ private persistCollapsed;
46
+ private getCurrentPathname;
47
+ private isItemActive;
48
+ private syncActiveRouteState;
49
+ private closeScopeMenus;
28
50
  private updateCollapseButton;
29
51
  }
30
52
  //# sourceMappingURL=component.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../../src/sidebar/component.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAMH,OAAO,EAAE,KAAK,sBAAsB,EAAuB,MAAM,SAAS,CAAA;AAmC1E,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAa;IACvC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAa;IACnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwB;IAC/C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,cAAc,CAAiC;gBAE3C,MAAM,EAAE,sBAAsB;IAkB1C,OAAO,CAAC,MAAM;IAkBd,OAAO,CAAC,YAAY;IAuGpB,OAAO,CAAC,YAAY;IAiDpB,OAAO,CAAC,oBAAoB;IAgC5B,OAAO,CAAC,YAAY;IA2DpB,wEAAwE;IACxE,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAW/B,4EAA4E;IAC5E,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAShD,gEAAgE;IAChE,cAAc,IAAI,IAAI;IAQtB,4BAA4B;IAC5B,QAAQ,IAAI,IAAI;IAShB,0BAA0B;IAC1B,MAAM,IAAI,IAAI;IASd,sEAAsE;IACtE,OAAO,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;IAI5B,uCAAuC;IACvC,OAAO,IAAI,IAAI;IAIf,OAAO,CAAC,oBAAoB;CAe7B"}
1
+ {"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../../src/sidebar/component.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,sBAAsB,EAG5B,MAAM,SAAS,CAAA;AA4HhB,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAa;IACvC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAa;IACnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwB;IAC/C,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAQ;IAChC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAqB;IAChD,OAAO,CAAC,cAAc,CAAiC;IACvD,OAAO,CAAC,QAAQ,CAA2B;gBAE/B,MAAM,EAAE,sBAAsB;IA6B1C,OAAO,CAAC,MAAM;IA4Bd,OAAO,CAAC,YAAY;IAoEpB,OAAO,CAAC,SAAS;IA6EjB,OAAO,CAAC,YAAY;IAiDpB,OAAO,CAAC,WAAW;IAgHnB,OAAO,CAAC,oBAAoB;IAgC5B,OAAO,CAAC,YAAY;IAuGpB,OAAO,CAAC,cAAc;IActB,OAAO,CAAC,aAAa;IA4BrB,OAAO,CAAC,uBAAuB;IA2B/B,OAAO,CAAC,kBAAkB;IAmB1B,wEAAwE;IACxE,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAgB/B,qFAAqF;IACrF,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAU/C,4EAA4E;IAC5E,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,gBAAgB,GAAG,IAAI;IAmBzE,gEAAgE;IAChE,cAAc,IAAI,IAAI;IAItB,4BAA4B;IAC5B,QAAQ,IAAI,IAAI;IAIhB,0BAA0B;IAC1B,MAAM,IAAI,IAAI;IAId,sEAAsE;IACtE,OAAO,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;IAU5B,uCAAuC;IACvC,OAAO,IAAI,IAAI;IAQf,OAAO,CAAC,UAAU;IA0BlB,OAAO,CAAC,YAAY;IAWpB,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,MAAM;IAId,OAAO,CAAC,mBAAmB;IAI3B,OAAO,CAAC,uBAAuB;IAc/B,OAAO,CAAC,gBAAgB;IAYxB,OAAO,CAAC,kBAAkB;IAY1B,OAAO,CAAC,YAAY;IAwCpB,OAAO,CAAC,oBAAoB;IAsB5B,OAAO,CAAC,eAAe;IASvB,OAAO,CAAC,oBAAoB;CAe7B"}
@@ -21,6 +21,12 @@ export interface EnhanceOptions {
21
21
  skeletonTimeoutMs?: number;
22
22
  /** CSS class for collapsed state (default: 'sidebar--collapsed') */
23
23
  collapsedClass?: string;
24
+ /** Variants that should opt into product sidebar visuals. */
25
+ productVariants?: string[];
26
+ /** Derive the active nav item from window.location on enhancement. */
27
+ activeFromLocation?: boolean;
28
+ /** Close an open mobile sidebar after clicking a route link. */
29
+ closeOnNavigate?: boolean;
24
30
  }
25
31
  export declare class Sidebar {
26
32
  readonly element: HTMLElement;
@@ -30,6 +36,8 @@ export declare class Sidebar {
30
36
  private skeletonTimer;
31
37
  constructor(element: HTMLElement, options?: EnhanceOptions);
32
38
  private init;
39
+ private setupProductChrome;
40
+ private setupRouteState;
33
41
  /**
34
42
  * Collapse/expand toggle with localStorage persistence.
35
43
  */
@@ -1 +1 @@
1
- {"version":3,"file":"enhance.d.ts","sourceRoot":"","sources":["../../src/sidebar/enhance.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,MAAM,WAAW,cAAc;IAC7B,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,kEAAkE;IAClE,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,8EAA8E;IAC9E,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,oEAAoE;IACpE,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAWD,qBAAa,OAAO;IAClB,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAA;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA0B;IAClD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAQ;IAChC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAqB;IAChD,OAAO,CAAC,aAAa,CAA6C;gBAEtD,OAAO,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,cAAc;IAO1D,OAAO,CAAC,IAAI;IAMZ;;OAEG;IACH,OAAO,CAAC,aAAa;IAkFrB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IA6BxB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IA4B5B;;OAEG;IACH,qBAAqB,IAAI,IAAI;IAO7B;;OAEG;IACH,OAAO,IAAI,IAAI;CAQhB;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,WAAW,EAAE,WAAW,SAA0B,GAAG,IAAI,CAexF;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,GAAG,IAAI,CAalF;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,OAAO,CAAC,EAAE,cAAc,GAAG,MAAM,IAAI,CAgB/D"}
1
+ {"version":3,"file":"enhance.d.ts","sourceRoot":"","sources":["../../src/sidebar/enhance.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,MAAM,WAAW,cAAc;IAC7B,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,kEAAkE;IAClE,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,8EAA8E;IAC9E,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,oEAAoE;IACpE,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,6DAA6D;IAC7D,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;IAC1B,sEAAsE;IACtE,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,gEAAgE;IAChE,eAAe,CAAC,EAAE,OAAO,CAAA;CAC1B;AAqCD,qBAAa,OAAO;IAClB,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAA;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA0B;IAClD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAQ;IAChC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAqB;IAChD,OAAO,CAAC,aAAa,CAA6C;gBAEtD,OAAO,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,cAAc;IAO1D,OAAO,CAAC,IAAI;IAQZ,OAAO,CAAC,kBAAkB;IAmB1B,OAAO,CAAC,eAAe;IA2CvB;;OAEG;IACH,OAAO,CAAC,aAAa;IAwGrB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IA6BxB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IA4B5B;;OAEG;IACH,qBAAqB,IAAI,IAAI;IAO7B;;OAEG;IACH,OAAO,IAAI,IAAI;CAQhB;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,WAAW,EAAE,WAAW,SAA0B,GAAG,IAAI,CAexF;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,GAAG,IAAI,CAalF;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,OAAO,CAAC,EAAE,cAAc,GAAG,MAAM,IAAI,CAgB/D"}
@@ -16,6 +16,9 @@ export interface SidebarConfig {
16
16
  storageKey?: string;
17
17
  mobileBreakpoint?: number;
18
18
  collapsedClass?: string;
19
+ productVariants?: string[];
20
+ activeFromLocation?: boolean;
21
+ closeOnNavigate?: boolean;
19
22
  }
20
23
  export interface LegacySidebarConfig {
21
24
  sidebar: string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sidebar/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAC9C,YAAY,EACV,sBAAsB,EACtB,kBAAkB,EAClB,cAAc,EACd,cAAc,EACd,WAAW,EACX,mBAAmB,GACpB,MAAM,SAAS,CAAA;AAEhB,MAAM,WAAW,aAAa;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,YAAY,EAAE,MAAM,CAAA;IACpB,QAAQ,EAAE,MAAM,CAAA;IAChB,cAAc,EAAE,MAAM,CAAA;CACvB;AAUD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAE5D;AAED;;GAEG;AACH,wBAAgB,QAAQ,IAAI,OAAO,CAElC;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAGnD;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,GAAG,IAAI,CAE/D;AAkID;;GAEG;AACH,eAAO,MAAM,oBAAoB,EAAE,mBAAmB,EA6BrD,CAAA;AAED;;GAEG;AACH,wBAAgB,WAAW,CACzB,MAAM,CAAC,EAAE,aAAa,EACtB,aAAa,GAAE,mBAAmB,EAAyB,GAC1D,IAAI,CAUN"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/sidebar/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAC9C,YAAY,EACV,sBAAsB,EACtB,kBAAkB,EAClB,cAAc,EACd,cAAc,EACd,WAAW,EACX,mBAAmB,GACpB,MAAM,SAAS,CAAA;AAEhB,MAAM,WAAW,aAAa;IAC5B,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,eAAe,CAAC,EAAE,MAAM,EAAE,CAAA;IAC1B,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,eAAe,CAAC,EAAE,OAAO,CAAA;CAC1B;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,MAAM,CAAA;IACd,YAAY,EAAE,MAAM,CAAA;IACpB,QAAQ,EAAE,MAAM,CAAA;IAChB,cAAc,EAAE,MAAM,CAAA;CACvB;AAcD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAE5D;AAED;;GAEG;AACH,wBAAgB,QAAQ,IAAI,OAAO,CAElC;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAGnD;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,OAAO,GAAG,IAAI,CAE/D;AA2QD;;GAEG;AACH,eAAO,MAAM,oBAAoB,EAAE,mBAAmB,EA6BrD,CAAA;AAED;;GAEG;AACH,wBAAgB,WAAW,CACzB,MAAM,CAAC,EAAE,aAAa,EACtB,aAAa,GAAE,mBAAmB,EAAyB,GAC1D,IAAI,CAUN"}
@@ -1,61 +1,114 @@
1
- import { t as e } from "../component-Bxhxf21c.js";
1
+ import { t as e } from "../component-D5sRm1fq.js";
2
2
  //#region src/sidebar/index.ts
3
3
  var t = {
4
4
  storageKey: "sidebar-collapsed",
5
5
  mobileBreakpoint: 900,
6
- collapsedClass: "sidebar--collapsed"
7
- }, n = { ...t };
8
- function r(e) {
6
+ collapsedClass: "sidebar--collapsed",
7
+ productVariants: [
8
+ "app",
9
+ "cm",
10
+ "threat-library"
11
+ ],
12
+ activeFromLocation: !0,
13
+ closeOnNavigate: !0
14
+ }, n = { ...t }, r = "data-sidebar-initialized";
15
+ function i(e) {
9
16
  n = {
10
17
  ...t,
11
18
  ...e
12
19
  };
13
20
  }
14
- function i() {
21
+ function a() {
15
22
  return window.innerWidth <= n.mobileBreakpoint;
16
23
  }
17
- function a(e) {
24
+ function o(e) {
18
25
  return localStorage.getItem(`${n.storageKey}-${e}`) === "true";
19
26
  }
20
- function o(e, t) {
27
+ function s(e, t) {
21
28
  localStorage.setItem(`${n.storageKey}-${e}`, String(t));
22
29
  }
23
- function s(e, t) {
30
+ function c(e, t) {
24
31
  e.setAttribute("data-open", "false"), t && t.setAttribute("data-visible", "false");
25
32
  }
26
- function c(e, t) {
33
+ function l(e, t) {
27
34
  let n = e.getAttribute("data-open") === "true";
28
35
  e.setAttribute("data-open", String(!n)), t && t.setAttribute("data-visible", String(!n));
29
36
  }
30
- function l({ sidebar: e, toggle: t, mobileToggles: n, backdrop: r, collapsedClass: l, key: u }) {
31
- !i() && a(u) && e.classList.add(l), t && t.addEventListener("click", () => {
32
- o(u, e.classList.toggle(l));
33
- }), n.forEach((t) => {
37
+ function u(e) {
38
+ return e === "/" ? e : e.replace(/\/+$/, "");
39
+ }
40
+ function d(e, t) {
41
+ try {
42
+ let n = u(new URL(t, window.location.href).pathname), r = u(e);
43
+ return n === "/" ? r === "/" : r === n || r.startsWith(`${n}/`);
44
+ } catch {
45
+ return !1;
46
+ }
47
+ }
48
+ function f(e) {
49
+ let t = Array.from(e.querySelectorAll("a.sidebar__item[href], a.sidebar__nav-link[href], a[data-nav-item][href]")), n = null, r = -1;
50
+ for (let e of t) {
51
+ let t = e.getAttribute("href");
52
+ if (!(t === null || !d(window.location.pathname, t))) try {
53
+ let i = u(new URL(t, window.location.href).pathname);
54
+ i.length > r && (n = e, r = i.length);
55
+ } catch {}
56
+ }
57
+ return n;
58
+ }
59
+ function p(e) {
60
+ if (n.activeFromLocation !== !0 || typeof window > "u") return;
61
+ let t = f(e);
62
+ t !== null && (e.querySelectorAll(".sidebar__item--active").forEach((e) => {
63
+ e.classList.remove("sidebar__item--active"), e.removeAttribute("aria-current");
64
+ }), t.classList.add("sidebar__item--active"), t.setAttribute("aria-current", "page"));
65
+ }
66
+ function m(e, t) {
67
+ (e.hasAttribute("data-sidebar-product") || e.classList.contains("sidebar--cm") || n.productVariants.includes(t)) && e.classList.add("sidebar--product"), e.querySelectorAll(".sidebar__item, .sidebar__nav-link").forEach((e) => {
68
+ e.hasAttribute("data-nav-item") || e.setAttribute("data-nav-item", "");
69
+ }), p(e);
70
+ }
71
+ function h(e) {
72
+ e.addEventListener("keydown", (t) => {
73
+ if (t.key !== "ArrowDown" && t.key !== "ArrowUp") return;
74
+ let n = Array.from(e.querySelectorAll("[data-nav-item]:not([aria-disabled=\"true\"])")).filter((e) => !e.hidden && e.offsetParent !== null);
75
+ if (n.length === 0) return;
76
+ let r = n.indexOf(document.activeElement);
77
+ r !== -1 && (t.preventDefault(), n[t.key === "ArrowDown" ? (r + 1) % n.length : (r - 1 + n.length) % n.length]?.focus());
78
+ });
79
+ }
80
+ function g({ sidebar: e, toggle: t, mobileToggles: i, backdrop: u, collapsedClass: d, key: f }) {
81
+ !a() && o(f) && e.classList.add(d), t && t.addEventListener("click", () => {
82
+ s(f, e.classList.toggle(d));
83
+ }), i.forEach((t) => {
34
84
  t.addEventListener("click", () => {
35
- c(e, r);
85
+ l(e, u);
36
86
  });
37
- }), r && r.addEventListener("click", () => {
38
- s(e, r);
87
+ }), u && u.addEventListener("click", () => {
88
+ c(e, u);
89
+ }), n.closeOnNavigate === !0 && e.addEventListener("click", (t) => {
90
+ let n = t.target;
91
+ (n instanceof Element ? n.closest("a.sidebar__item[href], a.sidebar__nav-link[href], a[data-nav-item][href]") : null) !== null && e.getAttribute("data-open") === "true" && c(e, u);
39
92
  }), window.addEventListener("resize", () => {
40
- i() && s(e, r);
93
+ a() && c(e, u);
41
94
  }), document.addEventListener("keydown", (t) => {
42
- t.key === "Escape" && e.getAttribute("data-open") === "true" && s(e, r);
43
- });
95
+ t.key === "Escape" && e.getAttribute("data-open") === "true" && c(e, u);
96
+ }), h(e), e.setAttribute(r, "true");
44
97
  }
45
- function u(e) {
98
+ function _(e) {
46
99
  let t = e.getAttribute("data-sidebar");
47
- t === null || t === "" || l({
100
+ t === null || t === "" || (m(e, t), e.getAttribute(r) !== "true" && g({
48
101
  sidebar: e,
49
102
  toggle: e.querySelector("[data-sidebar-toggle]"),
50
103
  mobileToggles: Array.from(document.querySelectorAll("[data-sidebar-mobile-toggle]")),
51
104
  backdrop: document.querySelector(`[data-sidebar-backdrop="${t}"]`),
52
105
  collapsedClass: n.collapsedClass,
53
106
  key: t
54
- });
107
+ }));
55
108
  }
56
- function d(e) {
109
+ function v(e) {
57
110
  let t = document.querySelector(e.sidebar);
58
- t && (t.hasAttribute("data-sidebar") || l({
111
+ t && (t.hasAttribute("data-sidebar") || g({
59
112
  sidebar: t,
60
113
  toggle: document.querySelector(e.toggle),
61
114
  mobileToggles: Array.from(document.querySelectorAll(e.mobileToggle)),
@@ -64,7 +117,7 @@ function d(e) {
64
117
  key: e.sidebar.replace(/[^a-z]/g, "")
65
118
  }));
66
119
  }
67
- var f = [
120
+ var y = [
68
121
  {
69
122
  sidebar: ".page__sidebar",
70
123
  toggle: "[data-page-sidebar-toggle]",
@@ -94,10 +147,10 @@ var f = [
94
147
  collapsedClass: "storage-sidebar--collapsed"
95
148
  }
96
149
  ];
97
- function p(e, t = f) {
98
- e && r(e), document.querySelectorAll("[data-sidebar]").forEach(u), t.forEach(d);
150
+ function b(e, t = y) {
151
+ e && i(e), document.querySelectorAll("[data-sidebar]").forEach(_), t.forEach(v);
99
152
  }
100
153
  //#endregion
101
- export { e as SidebarComponent, r as configureSidebar, f as defaultLegacyConfigs, a as getStoredState, p as initSidebar, i as isMobile, o as saveState };
154
+ export { e as SidebarComponent, i as configureSidebar, y as defaultLegacyConfigs, o as getStoredState, b as initSidebar, a as isMobile, s as saveState };
102
155
 
103
156
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/sidebar/index.ts"],"sourcesContent":["/**\n * Sidebar Module\n *\n * Unified sidebar toggle functionality for CounterMeasure applications.\n * Handles collapsible sidebar for desktop and mobile with localStorage persistence.\n *\n * Usage:\n * - Add data-sidebar=\"{variant}\" to your sidebar element (e.g., data-sidebar=\"admin\")\n * - Add data-sidebar-toggle to the toggle button\n * - Add data-sidebar-mobile-toggle to the mobile toggle button\n * - Add data-sidebar-backdrop=\"{variant}\" to the backdrop element\n */\n\n// Re-export programmatic sidebar component\nexport { SidebarComponent } from './component'\nexport type {\n SidebarComponentConfig,\n SidebarBrandConfig,\n SidebarNavItem,\n SidebarSection,\n SidebarUser,\n SidebarFooterAction,\n} from './types'\n\nexport interface SidebarConfig {\n storageKey?: string\n mobileBreakpoint?: number\n collapsedClass?: string\n}\n\nexport interface LegacySidebarConfig {\n sidebar: string\n toggle: string\n mobileToggle: string\n backdrop: string\n collapsedClass: string\n}\n\nconst DEFAULT_CONFIG: Required<SidebarConfig> = {\n storageKey: 'sidebar-collapsed',\n mobileBreakpoint: 900,\n collapsedClass: 'sidebar--collapsed',\n}\n\nlet currentConfig: Required<SidebarConfig> = { ...DEFAULT_CONFIG }\n\n/**\n * Configure sidebar settings.\n */\nexport function configureSidebar(config: SidebarConfig): void {\n currentConfig = { ...DEFAULT_CONFIG, ...config }\n}\n\n/**\n * Check if we're on mobile viewport.\n */\nexport function isMobile(): boolean {\n return window.innerWidth <= currentConfig.mobileBreakpoint\n}\n\n/**\n * Get stored collapsed state for a sidebar.\n */\nexport function getStoredState(key: string): boolean {\n const stored = localStorage.getItem(`${currentConfig.storageKey}-${key}`)\n return stored === 'true'\n}\n\n/**\n * Save collapsed state for a sidebar.\n */\nexport function saveState(key: string, collapsed: boolean): void {\n localStorage.setItem(`${currentConfig.storageKey}-${key}`, String(collapsed))\n}\n\n/**\n * Close a sidebar (mobile).\n */\nfunction closeSidebar(sidebar: HTMLElement, backdrop: HTMLElement | null): void {\n sidebar.setAttribute('data-open', 'false')\n if (backdrop) {\n backdrop.setAttribute('data-visible', 'false')\n }\n}\n\n/**\n * Toggle sidebar open state (mobile).\n */\nfunction toggleSidebarOpen(sidebar: HTMLElement, backdrop: HTMLElement | null): void {\n const isOpen = sidebar.getAttribute('data-open') === 'true'\n sidebar.setAttribute('data-open', String(!isOpen))\n if (backdrop) {\n backdrop.setAttribute('data-visible', String(!isOpen))\n }\n}\n\ninterface SidebarHandlerParams {\n sidebar: HTMLElement\n toggle: HTMLButtonElement | null\n mobileToggles: HTMLButtonElement[]\n backdrop: HTMLElement | null\n collapsedClass: string\n key: string\n}\n\n/**\n * Attach all sidebar event handlers (shared between unified and legacy init).\n */\nfunction attachSidebarHandlers({\n sidebar,\n toggle,\n mobileToggles,\n backdrop,\n collapsedClass,\n key,\n}: SidebarHandlerParams): void {\n // Apply stored collapsed state on desktop\n if (!isMobile() && getStoredState(key)) {\n sidebar.classList.add(collapsedClass)\n }\n\n // Desktop toggle handler\n if (toggle) {\n toggle.addEventListener('click', () => {\n const isCollapsed = sidebar.classList.toggle(collapsedClass)\n saveState(key, isCollapsed)\n })\n }\n\n // Mobile toggle handler\n mobileToggles.forEach(mobileToggle => {\n mobileToggle.addEventListener('click', () => {\n toggleSidebarOpen(sidebar, backdrop)\n })\n })\n\n // Backdrop click handler\n if (backdrop) {\n backdrop.addEventListener('click', () => {\n closeSidebar(sidebar, backdrop)\n })\n }\n\n // Handle window resize\n window.addEventListener('resize', () => {\n if (isMobile()) {\n closeSidebar(sidebar, backdrop)\n }\n })\n\n // Close sidebar on escape key\n document.addEventListener('keydown', e => {\n if (e.key === 'Escape' && sidebar.getAttribute('data-open') === 'true') {\n closeSidebar(sidebar, backdrop)\n }\n })\n}\n\n/**\n * Initialize a single sidebar using the unified data-sidebar attribute.\n */\nfunction initUnifiedSidebar(sidebar: HTMLElement): void {\n const variant = sidebar.getAttribute('data-sidebar')\n if (variant === null || variant === '') {\n return\n }\n\n attachSidebarHandlers({\n sidebar,\n toggle: sidebar.querySelector<HTMLButtonElement>('[data-sidebar-toggle]'),\n mobileToggles: Array.from(\n document.querySelectorAll<HTMLButtonElement>('[data-sidebar-mobile-toggle]')\n ),\n backdrop: document.querySelector<HTMLElement>(`[data-sidebar-backdrop=\"${variant}\"]`),\n collapsedClass: currentConfig.collapsedClass,\n key: variant,\n })\n}\n\n/**\n * Initialize a legacy sidebar (backwards compatibility).\n */\nfunction initLegacySidebar(config: LegacySidebarConfig): void {\n const sidebar = document.querySelector<HTMLElement>(config.sidebar)\n if (!sidebar) {\n return\n }\n\n // Skip if this sidebar uses the new unified approach\n if (sidebar.hasAttribute('data-sidebar')) {\n return\n }\n\n attachSidebarHandlers({\n sidebar,\n toggle: document.querySelector<HTMLButtonElement>(config.toggle),\n mobileToggles: Array.from(document.querySelectorAll<HTMLButtonElement>(config.mobileToggle)),\n backdrop: document.querySelector<HTMLElement>(config.backdrop),\n collapsedClass: config.collapsedClass,\n key: config.sidebar.replace(/[^a-z]/g, ''),\n })\n}\n\n/**\n * Default legacy sidebar configurations for CounterMeasure apps.\n */\nexport const defaultLegacyConfigs: LegacySidebarConfig[] = [\n {\n sidebar: '.page__sidebar',\n toggle: '[data-page-sidebar-toggle]',\n mobileToggle: '[data-page-mobile-toggle]',\n backdrop: '.sidebar-backdrop',\n collapsedClass: 'page__sidebar--collapsed',\n },\n {\n sidebar: '.chat-sidebar',\n toggle: '[data-chat-sidebar-toggle]',\n mobileToggle: '.chat-header__menu-toggle',\n backdrop: '.chat-sidebar-backdrop',\n collapsedClass: 'chat-sidebar--collapsed',\n },\n {\n sidebar: '.files-sidebar',\n toggle: '[data-files-sidebar-toggle]',\n mobileToggle: '[data-files-mobile-toggle]',\n backdrop: '.files-sidebar-backdrop',\n collapsedClass: 'files-sidebar--collapsed',\n },\n {\n sidebar: '.storage-sidebar',\n toggle: '[data-storage-sidebar-toggle]',\n mobileToggle: '[data-storage-mobile-toggle]',\n backdrop: '.storage-sidebar-backdrop',\n collapsedClass: 'storage-sidebar--collapsed',\n },\n]\n\n/**\n * Initialize all sidebars (both new unified and legacy).\n */\nexport function initSidebar(\n config?: SidebarConfig,\n legacyConfigs: LegacySidebarConfig[] = defaultLegacyConfigs\n): void {\n if (config) {\n configureSidebar(config)\n }\n\n // Initialize new unified sidebars\n document.querySelectorAll<HTMLElement>('[data-sidebar]').forEach(initUnifiedSidebar)\n\n // Initialize legacy sidebars for backwards compatibility\n legacyConfigs.forEach(initLegacySidebar)\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/sidebar/index.ts"],"sourcesContent":["/**\n * Sidebar Module\n *\n * Unified sidebar toggle functionality for CounterMeasure applications.\n * Handles collapsible sidebar for desktop and mobile with localStorage persistence.\n *\n * Usage:\n * - Add data-sidebar=\"{variant}\" to your sidebar element (e.g., data-sidebar=\"admin\")\n * - Add data-sidebar-toggle to the toggle button\n * - Add data-sidebar-mobile-toggle to the mobile toggle button\n * - Add data-sidebar-backdrop=\"{variant}\" to the backdrop element\n */\n\n// Re-export programmatic sidebar component\nexport { SidebarComponent } from './component'\nexport type {\n SidebarComponentConfig,\n SidebarBrandConfig,\n SidebarNavItem,\n SidebarSection,\n SidebarUser,\n SidebarFooterAction,\n} from './types'\n\nexport interface SidebarConfig {\n storageKey?: string\n mobileBreakpoint?: number\n collapsedClass?: string\n productVariants?: string[]\n activeFromLocation?: boolean\n closeOnNavigate?: boolean\n}\n\nexport interface LegacySidebarConfig {\n sidebar: string\n toggle: string\n mobileToggle: string\n backdrop: string\n collapsedClass: string\n}\n\nconst DEFAULT_CONFIG: Required<SidebarConfig> = {\n storageKey: 'sidebar-collapsed',\n mobileBreakpoint: 900,\n collapsedClass: 'sidebar--collapsed',\n productVariants: ['app', 'cm', 'threat-library'],\n activeFromLocation: true,\n closeOnNavigate: true,\n}\n\nlet currentConfig: Required<SidebarConfig> = { ...DEFAULT_CONFIG }\nconst INITIALIZED_ATTR = 'data-sidebar-initialized'\n\n/**\n * Configure sidebar settings.\n */\nexport function configureSidebar(config: SidebarConfig): void {\n currentConfig = { ...DEFAULT_CONFIG, ...config }\n}\n\n/**\n * Check if we're on mobile viewport.\n */\nexport function isMobile(): boolean {\n return window.innerWidth <= currentConfig.mobileBreakpoint\n}\n\n/**\n * Get stored collapsed state for a sidebar.\n */\nexport function getStoredState(key: string): boolean {\n const stored = localStorage.getItem(`${currentConfig.storageKey}-${key}`)\n return stored === 'true'\n}\n\n/**\n * Save collapsed state for a sidebar.\n */\nexport function saveState(key: string, collapsed: boolean): void {\n localStorage.setItem(`${currentConfig.storageKey}-${key}`, String(collapsed))\n}\n\n/**\n * Close a sidebar (mobile).\n */\nfunction closeSidebar(sidebar: HTMLElement, backdrop: HTMLElement | null): void {\n sidebar.setAttribute('data-open', 'false')\n if (backdrop) {\n backdrop.setAttribute('data-visible', 'false')\n }\n}\n\n/**\n * Toggle sidebar open state (mobile).\n */\nfunction toggleSidebarOpen(sidebar: HTMLElement, backdrop: HTMLElement | null): void {\n const isOpen = sidebar.getAttribute('data-open') === 'true'\n sidebar.setAttribute('data-open', String(!isOpen))\n if (backdrop) {\n backdrop.setAttribute('data-visible', String(!isOpen))\n }\n}\n\ninterface SidebarHandlerParams {\n sidebar: HTMLElement\n toggle: HTMLButtonElement | null\n mobileToggles: HTMLButtonElement[]\n backdrop: HTMLElement | null\n collapsedClass: string\n key: string\n}\n\nfunction normalizePathname(pathname: string): string {\n if (pathname === '/') {\n return pathname\n }\n\n return pathname.replace(/\\/+$/, '')\n}\n\nfunction routeMatches(pathname: string, href: string): boolean {\n try {\n const hrefPathname = normalizePathname(new URL(href, window.location.href).pathname)\n const currentPathname = normalizePathname(pathname)\n\n if (hrefPathname === '/') {\n return currentPathname === '/'\n }\n\n return currentPathname === hrefPathname || currentPathname.startsWith(`${hrefPathname}/`)\n } catch {\n return false\n }\n}\n\nfunction resolveActiveRouteItem(sidebar: HTMLElement): HTMLElement | null {\n const items = Array.from(\n sidebar.querySelectorAll<HTMLElement>(\n 'a.sidebar__item[href], a.sidebar__nav-link[href], a[data-nav-item][href]'\n )\n )\n\n let active: HTMLElement | null = null\n let activeLength = -1\n\n for (const item of items) {\n const href = item.getAttribute('href')\n if (href === null || !routeMatches(window.location.pathname, href)) {\n continue\n }\n\n try {\n const pathname = normalizePathname(new URL(href, window.location.href).pathname)\n if (pathname.length > activeLength) {\n active = item\n activeLength = pathname.length\n }\n } catch {\n // Ignore malformed href values; they cannot represent the current route.\n }\n }\n\n return active\n}\n\nfunction syncRouteActiveState(sidebar: HTMLElement): void {\n if (currentConfig.activeFromLocation !== true || typeof window === 'undefined') {\n return\n }\n\n const active = resolveActiveRouteItem(sidebar)\n if (active === null) {\n return\n }\n\n sidebar.querySelectorAll<HTMLElement>('.sidebar__item--active').forEach(item => {\n item.classList.remove('sidebar__item--active')\n item.removeAttribute('aria-current')\n })\n active.classList.add('sidebar__item--active')\n active.setAttribute('aria-current', 'page')\n}\n\nfunction prepareUnifiedSidebar(sidebar: HTMLElement, variant: string): void {\n const shouldUseProductStyle =\n sidebar.hasAttribute('data-sidebar-product') ||\n sidebar.classList.contains('sidebar--cm') ||\n currentConfig.productVariants.includes(variant)\n\n if (shouldUseProductStyle) {\n sidebar.classList.add('sidebar--product')\n }\n\n sidebar.querySelectorAll<HTMLElement>('.sidebar__item, .sidebar__nav-link').forEach(item => {\n if (!item.hasAttribute('data-nav-item')) {\n item.setAttribute('data-nav-item', '')\n }\n })\n\n syncRouteActiveState(sidebar)\n}\n\nfunction setupKeyboardNavigation(sidebar: HTMLElement): void {\n sidebar.addEventListener('keydown', event => {\n if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp') return\n\n const items = Array.from(\n sidebar.querySelectorAll<HTMLElement>('[data-nav-item]:not([aria-disabled=\"true\"])')\n ).filter(item => !item.hidden && item.offsetParent !== null)\n\n if (items.length === 0) return\n\n const currentIndex = items.indexOf(document.activeElement as HTMLElement)\n if (currentIndex === -1) return\n\n event.preventDefault()\n const nextIndex =\n event.key === 'ArrowDown'\n ? (currentIndex + 1) % items.length\n : (currentIndex - 1 + items.length) % items.length\n\n items[nextIndex]?.focus()\n })\n}\n\n/**\n * Attach all sidebar event handlers (shared between unified and legacy init).\n */\nfunction attachSidebarHandlers({\n sidebar,\n toggle,\n mobileToggles,\n backdrop,\n collapsedClass,\n key,\n}: SidebarHandlerParams): void {\n // Apply stored collapsed state on desktop\n if (!isMobile() && getStoredState(key)) {\n sidebar.classList.add(collapsedClass)\n }\n\n // Desktop toggle handler\n if (toggle) {\n toggle.addEventListener('click', () => {\n const isCollapsed = sidebar.classList.toggle(collapsedClass)\n saveState(key, isCollapsed)\n })\n }\n\n // Mobile toggle handler\n mobileToggles.forEach(mobileToggle => {\n mobileToggle.addEventListener('click', () => {\n toggleSidebarOpen(sidebar, backdrop)\n })\n })\n\n // Backdrop click handler\n if (backdrop) {\n backdrop.addEventListener('click', () => {\n closeSidebar(sidebar, backdrop)\n })\n }\n\n if (currentConfig.closeOnNavigate === true) {\n sidebar.addEventListener('click', event => {\n const target = event.target\n const navItem =\n target instanceof Element\n ? target.closest<HTMLElement>(\n 'a.sidebar__item[href], a.sidebar__nav-link[href], a[data-nav-item][href]'\n )\n : null\n if (navItem !== null && sidebar.getAttribute('data-open') === 'true') {\n closeSidebar(sidebar, backdrop)\n }\n })\n }\n\n // Handle window resize\n window.addEventListener('resize', () => {\n if (isMobile()) {\n closeSidebar(sidebar, backdrop)\n }\n })\n\n // Close sidebar on escape key\n document.addEventListener('keydown', e => {\n if (e.key === 'Escape' && sidebar.getAttribute('data-open') === 'true') {\n closeSidebar(sidebar, backdrop)\n }\n })\n\n setupKeyboardNavigation(sidebar)\n sidebar.setAttribute(INITIALIZED_ATTR, 'true')\n}\n\n/**\n * Initialize a single sidebar using the unified data-sidebar attribute.\n */\nfunction initUnifiedSidebar(sidebar: HTMLElement): void {\n const variant = sidebar.getAttribute('data-sidebar')\n if (variant === null || variant === '') {\n return\n }\n\n prepareUnifiedSidebar(sidebar, variant)\n\n if (sidebar.getAttribute(INITIALIZED_ATTR) === 'true') {\n return\n }\n\n attachSidebarHandlers({\n sidebar,\n toggle: sidebar.querySelector<HTMLButtonElement>('[data-sidebar-toggle]'),\n mobileToggles: Array.from(\n document.querySelectorAll<HTMLButtonElement>('[data-sidebar-mobile-toggle]')\n ),\n backdrop: document.querySelector<HTMLElement>(`[data-sidebar-backdrop=\"${variant}\"]`),\n collapsedClass: currentConfig.collapsedClass,\n key: variant,\n })\n}\n\n/**\n * Initialize a legacy sidebar (backwards compatibility).\n */\nfunction initLegacySidebar(config: LegacySidebarConfig): void {\n const sidebar = document.querySelector<HTMLElement>(config.sidebar)\n if (!sidebar) {\n return\n }\n\n // Skip if this sidebar uses the new unified approach\n if (sidebar.hasAttribute('data-sidebar')) {\n return\n }\n\n attachSidebarHandlers({\n sidebar,\n toggle: document.querySelector<HTMLButtonElement>(config.toggle),\n mobileToggles: Array.from(document.querySelectorAll<HTMLButtonElement>(config.mobileToggle)),\n backdrop: document.querySelector<HTMLElement>(config.backdrop),\n collapsedClass: config.collapsedClass,\n key: config.sidebar.replace(/[^a-z]/g, ''),\n })\n}\n\n/**\n * Default legacy sidebar configurations for CounterMeasure apps.\n */\nexport const defaultLegacyConfigs: LegacySidebarConfig[] = [\n {\n sidebar: '.page__sidebar',\n toggle: '[data-page-sidebar-toggle]',\n mobileToggle: '[data-page-mobile-toggle]',\n backdrop: '.sidebar-backdrop',\n collapsedClass: 'page__sidebar--collapsed',\n },\n {\n sidebar: '.chat-sidebar',\n toggle: '[data-chat-sidebar-toggle]',\n mobileToggle: '.chat-header__menu-toggle',\n backdrop: '.chat-sidebar-backdrop',\n collapsedClass: 'chat-sidebar--collapsed',\n },\n {\n sidebar: '.files-sidebar',\n toggle: '[data-files-sidebar-toggle]',\n mobileToggle: '[data-files-mobile-toggle]',\n backdrop: '.files-sidebar-backdrop',\n collapsedClass: 'files-sidebar--collapsed',\n },\n {\n sidebar: '.storage-sidebar',\n toggle: '[data-storage-sidebar-toggle]',\n mobileToggle: '[data-storage-mobile-toggle]',\n backdrop: '.storage-sidebar-backdrop',\n collapsedClass: 'storage-sidebar--collapsed',\n },\n]\n\n/**\n * Initialize all sidebars (both new unified and legacy).\n */\nexport function initSidebar(\n config?: SidebarConfig,\n legacyConfigs: LegacySidebarConfig[] = defaultLegacyConfigs\n): void {\n if (config) {\n configureSidebar(config)\n }\n\n // Initialize new unified sidebars\n document.querySelectorAll<HTMLElement>('[data-sidebar]').forEach(initUnifiedSidebar)\n\n // Initialize legacy sidebars for backwards compatibility\n legacyConfigs.forEach(initLegacySidebar)\n}\n"],"mappings":"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"}
@@ -1,21 +1,68 @@
1
1
  import { BrandSize } from '../components/brand';
2
2
  import { IconSet } from '../icons/index';
3
+ export type SidebarBadgeTone = 'default' | 'primary' | 'amber' | 'cyan' | 'rose' | 'warning' | 'error';
4
+ export type SidebarActiveMatcher = 'exact' | 'prefix' | string | RegExp | ((pathname: string, item: SidebarNavItem) => boolean);
5
+ export interface SidebarBadgeConfig {
6
+ /** Visible badge text. Use short labels such as "9", "99+", or "Soon". */
7
+ label: string;
8
+ /** Optional accessible title used in collapsed tooltips and native titles. */
9
+ title?: string;
10
+ /**
11
+ * Visual tone for the badge.
12
+ * @default 'primary'
13
+ */
14
+ tone?: SidebarBadgeTone;
15
+ /**
16
+ * Keep the collapsed rail dot visible even when label is empty.
17
+ * @default false
18
+ */
19
+ dot?: boolean;
20
+ }
3
21
  export interface SidebarNavItem {
4
22
  /** Stable identifier used for selection and badge updates. */
5
23
  id: string;
6
24
  /** Visible label rendered alongside the icon. */
7
25
  label: string;
26
+ /** Optional navigation target. When omitted, the item renders as a button. */
27
+ href?: string;
28
+ /** Optional target for link navigation. */
29
+ target?: string;
30
+ /** Optional rel for external links. */
31
+ rel?: string;
32
+ /** Accessible label override. */
33
+ ariaLabel?: string;
8
34
  /** Icon name resolved through the active icon set. */
9
35
  icon?: string;
10
- /** Numeric badge displayed at the trailing edge of the row. */
11
- badge?: number;
36
+ /** Numeric or rich badge displayed at the trailing edge of the row. */
37
+ badge?: number | SidebarBadgeConfig;
12
38
  /**
13
39
  * Visual tone for the badge.
14
40
  * @default 'primary'
15
41
  */
16
- badgeTone?: 'default' | 'primary' | 'amber' | 'cyan' | 'rose' | 'warning' | 'error';
42
+ badgeTone?: SidebarBadgeTone;
43
+ /** Static pill label such as "Admin" or "Soon". */
44
+ tag?: string;
45
+ /** Tooltip/title shown when the sidebar is collapsed. */
46
+ tooltip?: string;
47
+ /**
48
+ * Whether this item is the current page. If omitted, active state can be
49
+ * derived from `activeItemId`, `href`, or `activeMatch`.
50
+ */
51
+ active?: boolean;
52
+ /** Route matching rule used against the current configured/browser pathname. */
53
+ activeMatch?: SidebarActiveMatcher;
54
+ /**
55
+ * Treat href matching as exact instead of prefix matching.
56
+ * @default false
57
+ */
58
+ end?: boolean;
59
+ /**
60
+ * Render the item as unavailable while preserving its position.
61
+ * @default false
62
+ */
63
+ disabled?: boolean;
17
64
  /** Called when the item is activated. */
18
- onClick?: () => void;
65
+ onClick?: (event: MouseEvent) => void;
19
66
  }
20
67
  export interface SidebarSection {
21
68
  /** Stable section identifier. */
@@ -42,6 +89,18 @@ export interface SidebarSection {
42
89
  export interface SidebarUser {
43
90
  /** Display name shown in the footer. */
44
91
  name: string;
92
+ /** Secondary user metadata such as email or role. */
93
+ detail?: string;
94
+ /** Avatar image URL. */
95
+ avatarUrl?: string;
96
+ /** Initials fallback when no avatar URL is provided. */
97
+ initials?: string;
98
+ /** Presence dot tone shown on the avatar. */
99
+ presence?: 'online' | 'away' | 'busy' | 'dnd' | 'offline';
100
+ /** Accessible label for the user trigger. */
101
+ label?: string;
102
+ /** Called when the user surface is activated. */
103
+ onClick?: () => void;
45
104
  }
46
105
  export interface SidebarFooterAction {
47
106
  /** Stable identifier for the action. */
@@ -78,6 +137,26 @@ export interface SidebarBrandConfig {
78
137
  */
79
138
  decorative?: boolean;
80
139
  }
140
+ export interface SidebarScopeOption {
141
+ id: string;
142
+ label: string;
143
+ status?: 'active' | 'suspended' | 'archived' | 'warning' | 'error' | 'neutral';
144
+ disabled?: boolean;
145
+ }
146
+ export interface SidebarScopeConfig {
147
+ /** Label shown above/inside the selector. */
148
+ label?: string;
149
+ /** Icon name resolved through the active icon set. */
150
+ icon?: string;
151
+ /** Current selected option id. */
152
+ value?: string;
153
+ /** Fallback label when `value` does not match an option. */
154
+ placeholder?: string;
155
+ /** Options rendered in the selector menu. */
156
+ options: SidebarScopeOption[];
157
+ /** Called when the selected option changes. */
158
+ onChange?: (option: SidebarScopeOption) => void;
159
+ }
81
160
  export interface SidebarComponentConfig {
82
161
  /** Container element (or selector) the sidebar is mounted into. */
83
162
  container: HTMLElement | string;
@@ -87,6 +166,12 @@ export interface SidebarComponentConfig {
87
166
  sections: SidebarSection[];
88
167
  /** Optional brand header rendered above the navigation. */
89
168
  brand?: SidebarBrandConfig;
169
+ /** Optional scope/tenant selector rendered below the brand. */
170
+ scope?: SidebarScopeConfig;
171
+ /** Optional element inserted between the header/scope area and navigation. */
172
+ beforeNav?: HTMLElement | HTMLElement[];
173
+ /** Optional element inserted after navigation and before footer. */
174
+ afterNav?: HTMLElement | HTMLElement[];
90
175
  /**
91
176
  * Render the shared edge-docked collapse control.
92
177
  * @default false
@@ -113,6 +198,41 @@ export interface SidebarComponentConfig {
113
198
  * @default false
114
199
  */
115
200
  collapsed?: boolean;
201
+ /**
202
+ * Current active nav item ID. Applied during initial render and when React
203
+ * wrappers call `setActive`.
204
+ */
205
+ activeItemId?: string;
206
+ /**
207
+ * Current route path used to derive active link state. When omitted, browser
208
+ * consumers fall back to `window.location.pathname`.
209
+ */
210
+ pathname?: string;
211
+ /**
212
+ * Persist collapsed state under this localStorage key.
213
+ * When omitted, collapsed state remains in memory only.
214
+ */
215
+ storageKey?: string;
216
+ /**
217
+ * Persist collapsed state when `storageKey` is supplied.
218
+ * @default true
219
+ */
220
+ persistCollapsed?: boolean;
221
+ /**
222
+ * Viewport width below which the sidebar behaves as a mobile drawer.
223
+ * @default 900
224
+ */
225
+ mobileBreakpoint?: number;
226
+ /**
227
+ * Render and control a mobile backdrop alongside the sidebar.
228
+ * @default false
229
+ */
230
+ mobileBackdrop?: boolean;
231
+ /**
232
+ * Close the mobile drawer after a nav item activates.
233
+ * @default true
234
+ */
235
+ closeOnNavigate?: boolean;
116
236
  /**
117
237
  * Controlled mobile open state. Reflected to `data-open` for the mobile
118
238
  * sidebar visibility contract.
@@ -123,5 +243,7 @@ export interface SidebarComponentConfig {
123
243
  onNavigate?: (item: SidebarNavItem) => void;
124
244
  /** Called when the sidebar's collapsed state changes. */
125
245
  onCollapse?: (collapsed: boolean) => void;
246
+ /** Called when the mobile open state changes. */
247
+ onOpenChange?: (open: boolean) => void;
126
248
  }
127
249
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/sidebar/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,gBAAgB,CAAA;AAE7C,MAAM,WAAW,cAAc;IAC7B,8DAA8D;IAC9D,EAAE,EAAE,MAAM,CAAA;IACV,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAA;IACb,sDAAsD;IACtD,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,+DAA+D;IAC/D,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;OAGG;IACH,SAAS,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,CAAA;IACnF,yCAAyC;IACzC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,iCAAiC;IACjC,EAAE,EAAE,MAAM,CAAA;IACV,gCAAgC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,8CAA8C;IAC9C,KAAK,EAAE,cAAc,EAAE,CAAA;IACvB;;;;;OAKG;IACH,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB;;;OAGG;IACH,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,sDAAsD;IACtD,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,WAAW;IAC1B,wCAAwC;IACxC,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,mBAAmB;IAClC,wCAAwC;IACxC,EAAE,EAAE,MAAM,CAAA;IACV,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAA;IACZ,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAA;IACb;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,2CAA2C;IAC3C,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,uBAAuB;IACvB,QAAQ,CAAC,EAAE,SAAS,GAAG,MAAM,CAAA;IAC7B;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,kDAAkD;IAClD,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,kDAAkD;IAClD,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB;AAED,MAAM,WAAW,sBAAsB;IACrC,mEAAmE;IACnE,SAAS,EAAE,WAAW,GAAG,MAAM,CAAA;IAC/B,yEAAyE;IACzE,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,uCAAuC;IACvC,QAAQ,EAAE,cAAc,EAAE,CAAA;IAC1B,2DAA2D;IAC3D,KAAK,CAAC,EAAE,kBAAkB,CAAA;IAC1B;;;OAGG;IACH,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAA;IAC/B,oDAAoD;IACpD,IAAI,CAAC,EAAE,WAAW,CAAA;IAClB,+DAA+D;IAC/D,aAAa,CAAC,EAAE,mBAAmB,EAAE,CAAA;IACrC;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB;;;;OAIG;IACH,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,2CAA2C;IAC3C,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAA;IAC3C,yDAAyD;IACzD,UAAU,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAA;CAC1C"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/sidebar/types.ts"],"names":[],"mappings":"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"}