@countermeasure-platform/web-components 1.3.5 → 1.3.6-dev.37.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 (82) hide show
  1. package/dist/{component-D5sRm1fq.js → component-D_asjmrt.js} +5 -3
  2. package/dist/component-D_asjmrt.js.map +1 -0
  3. package/dist/components/brand/index.d.ts.map +1 -1
  4. package/dist/components/brand/index.js +11 -5
  5. package/dist/components/brand/index.js.map +1 -1
  6. package/dist/components/brand/types.d.ts +2 -0
  7. package/dist/components/brand/types.d.ts.map +1 -1
  8. package/dist/icons/index.d.ts +7 -2
  9. package/dist/icons/index.d.ts.map +1 -1
  10. package/dist/icons/index.js +7 -2
  11. package/dist/icons/index.js.map +1 -1
  12. package/dist/icons/lucide.d.ts +3 -0
  13. package/dist/icons/lucide.d.ts.map +1 -1
  14. package/dist/icons/lucide.js +3 -0
  15. package/dist/icons/lucide.js.map +1 -1
  16. package/dist/index.d.ts +1 -1
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +126 -125
  19. package/dist/layout/app-shell.d.ts +7 -0
  20. package/dist/layout/app-shell.d.ts.map +1 -1
  21. package/dist/layout/app-shell.js +24 -6
  22. package/dist/layout/app-shell.js.map +1 -1
  23. package/dist/layout/core-app-chrome.d.ts.map +1 -1
  24. package/dist/layout/core-app-chrome.js +8 -5
  25. package/dist/layout/core-app-chrome.js.map +1 -1
  26. package/dist/layout/core-app-library-dashboard.d.ts +72 -0
  27. package/dist/layout/core-app-library-dashboard.d.ts.map +1 -0
  28. package/dist/layout/core-app-library-dashboard.js +160 -0
  29. package/dist/layout/core-app-library-dashboard.js.map +1 -0
  30. package/dist/layout/index.d.ts +2 -0
  31. package/dist/layout/index.d.ts.map +1 -1
  32. package/dist/layout/index.js +38 -37
  33. package/dist/layout/index.js.map +1 -1
  34. package/dist/react/brand/index.d.ts +3 -1
  35. package/dist/react/brand/index.d.ts.map +1 -1
  36. package/dist/react/brand.js +19 -13
  37. package/dist/react/brand.js.map +1 -1
  38. package/dist/react/layout/core-app-library-dashboard.d.ts +13 -0
  39. package/dist/react/layout/core-app-library-dashboard.d.ts.map +1 -0
  40. package/dist/react/layout/core-app-library-dashboard.js +27 -0
  41. package/dist/react/layout/core-app-library-dashboard.js.map +1 -0
  42. package/dist/react/layout/index.d.ts +1 -0
  43. package/dist/react/layout/index.d.ts.map +1 -1
  44. package/dist/react/layout/index.js +3 -2
  45. package/dist/react/primitives/alert.d.ts +1 -1
  46. package/dist/react/primitives/toast.d.ts +1 -1
  47. package/dist/react/sidebar.js +1 -1
  48. package/dist/react.js +97 -96
  49. package/dist/sidebar/component.d.ts.map +1 -1
  50. package/dist/sidebar/index.js +1 -1
  51. package/dist/sidebar/types.d.ts +7 -0
  52. package/dist/sidebar/types.d.ts.map +1 -1
  53. package/dist/styles/components/brand.css +22 -0
  54. package/dist/styles/layout.css +577 -0
  55. package/dist/styles/sidebar.css +26 -0
  56. package/package.json +11 -1
  57. package/src/components/brand/index.ts +22 -4
  58. package/src/components/brand/types.ts +2 -0
  59. package/src/icons/icons.test.ts +1 -1
  60. package/src/icons/index.ts +7 -2
  61. package/src/icons/lucide.ts +4 -0
  62. package/src/index.ts +2 -0
  63. package/src/layout/app-shell.test.ts +76 -0
  64. package/src/layout/app-shell.ts +38 -7
  65. package/src/layout/core-app-chrome.test.ts +17 -5
  66. package/src/layout/core-app-chrome.ts +8 -3
  67. package/src/layout/core-app-library-dashboard.test.ts +397 -0
  68. package/src/layout/core-app-library-dashboard.ts +519 -0
  69. package/src/layout/index.ts +18 -0
  70. package/src/react/brand/index.test.tsx +10 -0
  71. package/src/react/brand/index.tsx +25 -4
  72. package/src/react/layout/core-app-chrome.test.tsx +2 -2
  73. package/src/react/layout/core-app-library-dashboard.test.tsx +42 -0
  74. package/src/react/layout/core-app-library-dashboard.tsx +56 -0
  75. package/src/react/layout/index.ts +6 -0
  76. package/src/sidebar/component.test.ts +21 -1
  77. package/src/sidebar/component.ts +14 -8
  78. package/src/sidebar/types.ts +7 -0
  79. package/src/styles/components/brand.css +22 -0
  80. package/src/styles/layout.css +577 -0
  81. package/src/styles/sidebar.css +26 -0
  82. package/dist/component-D5sRm1fq.js.map +0 -1
@@ -2,34 +2,35 @@ import { n as e } from "../sanitize-uWpY18N9.js";
2
2
  import { t } from "../navigation-DihI8dfX.js";
3
3
  import { AppShell as n, TopMenuBar as r, createAppShell as i, createProductShell as a, createTopMenuBar as o } from "./app-shell.js";
4
4
  import { CORE_APP_ROUTE_LABELS as s, createCoreAppChromePreset as c, createCoreAppSidebarConfig as l, createCoreAppSidebarSections as u, createCoreAppTopbarActions as d, createCoreAppTopbarConfig as f, getCoreAppRouteLabel as p, mountCoreAppChrome as m, mountCoreAppChromeFromDom as h } from "./core-app-chrome.js";
5
- import { PageHeader as g, createPageHeader as _ } from "./page-header.js";
5
+ import { mountCoreAppLibraryDashboard as g, mountCoreAppLibraryDashboardFromDom as _ } from "./core-app-library-dashboard.js";
6
+ import { PageHeader as v, createPageHeader as y } from "./page-header.js";
6
7
  //#region src/layout/index.ts
7
- var v = () => {
8
+ var b = () => {
8
9
  if (typeof window > "u") return null;
9
10
  try {
10
11
  return window.localStorage;
11
12
  } catch {
12
13
  return console.warn("Unable to access localStorage"), null;
13
14
  }
14
- }, y = (e) => {
15
+ }, x = (e) => {
15
16
  try {
16
17
  return new URL(e, window.location.href).origin === window.location.origin;
17
18
  } catch {
18
19
  return !1;
19
20
  }
20
- }, b = {
21
+ }, S = {
21
22
  storageKey: "cmm-sidebar-state",
22
23
  desktopBreakpoint: "(min-width: 1024px)",
23
24
  collapsedClass: "cmm-shell--sidebar-collapsed",
24
25
  openClass: "cmm-shell--sidebar-open"
25
26
  };
26
- function x(e = {}) {
27
+ function C(e = {}) {
27
28
  let t = {
28
- ...b,
29
+ ...S,
29
30
  ...e
30
31
  }, n = document.querySelector("[data-shell-layout]"), r = document.querySelector("[data-shell-sidebar]");
31
32
  if (!n || !r) return () => {};
32
- let i = v(), a = window.matchMedia(t.desktopBreakpoint), o = Array.from(document.querySelectorAll("[data-sidebar-toggle]")), s = Array.from(document.querySelectorAll("[data-sidebar-dismiss]")), c = r.id || "shell-sidebar";
33
+ let i = b(), a = window.matchMedia(t.desktopBreakpoint), o = Array.from(document.querySelectorAll("[data-sidebar-toggle]")), s = Array.from(document.querySelectorAll("[data-sidebar-dismiss]")), c = r.id || "shell-sidebar";
33
34
  r.id = c;
34
35
  let l = () => i?.getItem(t.storageKey) === "collapsed", u = () => {
35
36
  let e = a.matches ? !n.classList.contains(t.collapsedClass) : n.classList.contains(t.openClass);
@@ -61,7 +62,7 @@ function x(e = {}) {
61
62
  }), document.removeEventListener("keydown", g), a.removeEventListener("change", p);
62
63
  };
63
64
  }
64
- function S(e = {}) {
65
+ function w(e = {}) {
65
66
  let t = e.triggerSelector ?? "[data-user-trigger]", n = e.dropdownSelector ?? "[data-user-dropdown]", r = document.querySelector("[data-user-menu]"), i = document.querySelector(t), a = document.querySelector(n);
66
67
  if (!r || !i || !a) return () => {};
67
68
  let o = (e) => {
@@ -84,17 +85,17 @@ function S(e = {}) {
84
85
  i.removeEventListener("click", c), document.removeEventListener("click", l), document.removeEventListener("keydown", u), a.removeEventListener("keydown", f), i.removeEventListener("keydown", p);
85
86
  };
86
87
  }
87
- var C = (e) => e.dataset.collapsibleOpen === "true" || !e.classList.contains("hidden"), w = "cmm-collapsible--hidden", T = (e, t) => {
88
- e.classList.toggle("hidden", !t), e.classList.toggle(w, !t), e.dataset.collapsibleOpen = t.toString(), e.setAttribute("aria-hidden", t ? "false" : "true");
89
- }, E = (e, t) => {
88
+ var T = (e) => e.dataset.collapsibleOpen === "true" || !e.classList.contains("hidden"), E = "cmm-collapsible--hidden", D = (e, t) => {
89
+ e.classList.toggle("hidden", !t), e.classList.toggle(E, !t), e.dataset.collapsibleOpen = t.toString(), e.setAttribute("aria-hidden", t ? "false" : "true");
90
+ }, O = (e, t) => {
90
91
  document.querySelectorAll(`[data-toggle-target='${e}']`).forEach((e) => {
91
92
  e.setAttribute("aria-expanded", t.toString());
92
93
  });
93
94
  };
94
- function D(e = {}) {
95
+ function k(e = {}) {
95
96
  let { scrollIntoView: t = !0, scrollBehavior: n = "smooth", hiddenClass: r = "cmm-collapsible--hidden" } = e;
96
- w = r, document.querySelectorAll("[data-collapsible]").forEach((e) => {
97
- T(e, e.dataset.collapsibleOpen === "true" || !e.classList.contains("hidden"));
97
+ E = r, document.querySelectorAll("[data-collapsible]").forEach((e) => {
98
+ D(e, e.dataset.collapsibleOpen === "true" || !e.classList.contains("hidden"));
98
99
  });
99
100
  let i = [];
100
101
  document.querySelectorAll("[data-toggle-target]").forEach((e) => {
@@ -103,11 +104,11 @@ function D(e = {}) {
103
104
  let a = document.querySelector(r);
104
105
  if (!a) return;
105
106
  let o = a.id || r.replace(/^#/, "");
106
- e.setAttribute("aria-controls", o), e.setAttribute("aria-expanded", C(a).toString());
107
+ e.setAttribute("aria-controls", o), e.setAttribute("aria-expanded", T(a).toString());
107
108
  let s = (e) => {
108
109
  e.preventDefault();
109
- let i = !C(a);
110
- T(a, i), E(r, i), i && t && a.scrollIntoView({
110
+ let i = !T(a);
111
+ D(a, i), O(r, i), i && t && a.scrollIntoView({
111
112
  behavior: n,
112
113
  block: "start"
113
114
  });
@@ -122,7 +123,7 @@ function D(e = {}) {
122
123
  let n = document.querySelector(t);
123
124
  if (!n) return;
124
125
  let r = (e) => {
125
- e.preventDefault(), T(n, !1), E(t, !1);
126
+ e.preventDefault(), D(n, !1), O(t, !1);
126
127
  };
127
128
  e.addEventListener("click", r), i.push({
128
129
  element: e,
@@ -132,7 +133,7 @@ function D(e = {}) {
132
133
  let a = window.location.hash;
133
134
  if (a) {
134
135
  let e = document.querySelector(a);
135
- e?.dataset.collapsible !== void 0 && (T(e, !0), E(a, !0));
136
+ e?.dataset.collapsible !== void 0 && (D(e, !0), O(a, !0));
136
137
  }
137
138
  return () => {
138
139
  i.forEach(({ element: e, handler: t }) => {
@@ -140,12 +141,12 @@ function D(e = {}) {
140
141
  });
141
142
  };
142
143
  }
143
- var O = "\n <div class=\"cmm-sheet__loading\">\n <div class=\"cmm-spinner\"></div>\n </div>\n", k = "\n <div class=\"cmm-sheet__error\">\n <p>Failed to load content. Please try the full page.</p>\n </div>\n";
144
- function A(t, n) {
144
+ var A = "\n <div class=\"cmm-sheet__loading\">\n <div class=\"cmm-spinner\"></div>\n </div>\n", j = "\n <div class=\"cmm-sheet__error\">\n <p>Failed to load content. Please try the full page.</p>\n </div>\n";
145
+ function M(t, n) {
145
146
  t.replaceChildren(e(n, { allowSvg: !0 }));
146
147
  }
147
- function j(e = {}) {
148
- let { openClass: n = "cmm-sheet--open", hiddenClass: r = "cmm-sheet--hidden", backdropVisibleClass: i = "cmm-sheet__backdrop--visible", backdropHiddenClass: a = "cmm-sheet__backdrop--hidden", spinnerHtml: o = O, errorHtml: s = k, allowCrossOriginFetch: c = !1 } = e, l = /* @__PURE__ */ new Map();
148
+ function N(e = {}) {
149
+ let { openClass: n = "cmm-sheet--open", hiddenClass: r = "cmm-sheet--hidden", backdropVisibleClass: i = "cmm-sheet__backdrop--visible", backdropHiddenClass: a = "cmm-sheet__backdrop--hidden", spinnerHtml: o = A, errorHtml: s = j, allowCrossOriginFetch: c = !1 } = e, l = /* @__PURE__ */ new Map();
149
150
  if (document.querySelectorAll("[data-sheet]").forEach((e) => {
150
151
  let t = e.dataset.sheet;
151
152
  if (!t) return;
@@ -167,19 +168,19 @@ function j(e = {}) {
167
168
  }, p = async (e, n) => {
168
169
  u && u.key !== e.key && f(u), u = e, d(e, !0);
169
170
  let r = n?.dataset.sheetUrl ?? e.sheet.dataset.sheetUrl, i = n?.dataset.sheetFocus ?? e.focusSelector, a = n?.dataset.sheetFullpage ?? e.sheet.dataset.sheetFullpage, l = n?.dataset.sheetExpand ?? e.sheet.dataset.sheetExpand;
170
- if (e.fullPageLink && a && (e.fullPageLink.href = a), e.expandLink && l && (e.expandLink.href = l), !r || !c && !y(r)) {
171
- A(e.content, s);
171
+ if (e.fullPageLink && a && (e.fullPageLink.href = a), e.expandLink && l && (e.expandLink.href = l), !r || !c && !x(r)) {
172
+ M(e.content, s);
172
173
  return;
173
174
  }
174
- A(e.content, o);
175
+ M(e.content, o);
175
176
  try {
176
177
  let n = await fetch(r);
177
178
  if (n.ok) {
178
179
  let t = await n.text();
179
- A(e.content, t), i && e.content.querySelector(i)?.focus();
180
- } else a ? t(a) : A(e.content, s);
180
+ M(e.content, t), i && e.content.querySelector(i)?.focus();
181
+ } else a ? t(a) : M(e.content, s);
181
182
  } catch {
182
- a ? t(a) : A(e.content, s);
183
+ a ? t(a) : M(e.content, s);
183
184
  }
184
185
  }, m = [];
185
186
  l.forEach((e) => {
@@ -226,7 +227,7 @@ function j(e = {}) {
226
227
  }), document.removeEventListener("keydown", h);
227
228
  };
228
229
  }
229
- function M() {
230
+ function P() {
230
231
  let e = document.querySelector("[data-nav-list]");
231
232
  if (!e) return () => {};
232
233
  let t = () => Array.from(e.querySelectorAll("[data-nav-item]")), n = (e) => {
@@ -237,13 +238,13 @@ function M() {
237
238
  e.removeEventListener("keydown", n);
238
239
  };
239
240
  }
240
- function N(e = {}) {
241
+ function F(e = {}) {
241
242
  let t = [
242
- x(e.sidebar),
243
- S(e.userMenu),
244
- D(e.collapsibles),
245
- j(e.sheets),
246
- M()
243
+ C(e.sidebar),
244
+ w(e.userMenu),
245
+ k(e.collapsibles),
246
+ N(e.sheets),
247
+ P()
247
248
  ];
248
249
  return () => {
249
250
  t.forEach((e) => {
@@ -252,6 +253,6 @@ function N(e = {}) {
252
253
  };
253
254
  }
254
255
  //#endregion
255
- export { n as AppShell, s as CORE_APP_ROUTE_LABELS, g as PageHeader, r as TopMenuBar, i as createAppShell, c as createCoreAppChromePreset, l as createCoreAppSidebarConfig, u as createCoreAppSidebarSections, d as createCoreAppTopbarActions, f as createCoreAppTopbarConfig, _ as createPageHeader, a as createProductShell, o as createTopMenuBar, p as getCoreAppRouteLabel, N as initLayout, m as mountCoreAppChrome, h as mountCoreAppChromeFromDom, D as setupCollapsibles, M as setupNavKeyboard, j as setupSheets, x as setupSidebar, S as setupUserMenu };
256
+ export { n as AppShell, s as CORE_APP_ROUTE_LABELS, v as PageHeader, r as TopMenuBar, i as createAppShell, c as createCoreAppChromePreset, l as createCoreAppSidebarConfig, u as createCoreAppSidebarSections, d as createCoreAppTopbarActions, f as createCoreAppTopbarConfig, y as createPageHeader, a as createProductShell, o as createTopMenuBar, p as getCoreAppRouteLabel, F as initLayout, m as mountCoreAppChrome, h as mountCoreAppChromeFromDom, g as mountCoreAppLibraryDashboard, _ as mountCoreAppLibraryDashboardFromDom, k as setupCollapsibles, P as setupNavKeyboard, N as setupSheets, C as setupSidebar, w as setupUserMenu };
256
257
 
257
258
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../src/layout/index.ts"],"sourcesContent":["/**\n * Layout Components\n * @countermeasure/web-components\n *\n * Shared layout utilities for sidebar, user menu, collapsibles, and sheets.\n */\n\nimport { createSafeMarkupFragment } from '../utils/sanitize'\nimport { navigateDocumentTo } from '../utils/navigation'\nexport {\n AppShell,\n TopMenuBar,\n createAppShell,\n createProductShell,\n createTopMenuBar,\n} from './app-shell'\nexport type {\n AppShellConfig,\n TopMenuBarAction,\n TopMenuBarActionInput,\n TopMenuBarBreadcrumb,\n TopMenuBarConfig,\n TopMenuBarUser,\n} from './app-shell'\nexport {\n CORE_APP_ROUTE_LABELS,\n createCoreAppChromePreset,\n createCoreAppSidebarConfig,\n createCoreAppSidebarSections,\n createCoreAppTopbarActions,\n createCoreAppTopbarConfig,\n getCoreAppRouteLabel,\n mountCoreAppChrome,\n mountCoreAppChromeFromDom,\n} from './core-app-chrome'\nexport type {\n CoreAppChromePreset,\n CoreAppChromeDomMountOptions,\n CoreAppChromeMount,\n CoreAppChromeMountOptions,\n CoreAppChromePresetOptions,\n CoreAppRouteLabel,\n CoreAppSidebarPresetOptions,\n CoreAppTopbarPresetOptions,\n} from './core-app-chrome'\nexport { PageHeader, createPageHeader } from './page-header'\nexport type { PageHeaderConfig, PageHeaderMetadata } from './page-header'\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\nexport interface SidebarConfig {\n storageKey?: string\n desktopBreakpoint?: string\n collapsedClass?: string\n openClass?: string\n}\n\nexport interface UserMenuConfig {\n triggerSelector?: string\n dropdownSelector?: string\n dropdownItemSelector?: string\n}\n\nexport interface CollapsibleConfig {\n scrollIntoView?: boolean\n scrollBehavior?: ScrollBehavior\n hiddenClass?: string\n}\n\nexport interface SheetConfig {\n key: string\n sheet: HTMLElement\n backdrop: HTMLElement\n content: HTMLElement\n fullPageLink?: HTMLAnchorElement | null | undefined\n expandLink?: HTMLAnchorElement | null | undefined\n focusSelector?: string | undefined\n}\n\nexport interface SheetSetupConfig {\n openClass?: string\n hiddenClass?: string\n backdropVisibleClass?: string\n backdropHiddenClass?: string\n spinnerHtml?: string\n errorHtml?: string\n /** Allow fetching sheet content from non-same-origin URLs. Default: false. */\n allowCrossOriginFetch?: boolean\n}\n\n// ============================================================================\n// STORAGE HELPERS\n// ============================================================================\n\nconst resolveStorage = (): Storage | null => {\n if (typeof window === 'undefined') {\n return null\n }\n try {\n return window.localStorage\n } catch {\n console.warn('Unable to access localStorage')\n return null\n }\n}\n\nconst isSameOriginUrl = (url: string): boolean => {\n try {\n return new URL(url, window.location.href).origin === window.location.origin\n } catch {\n return false\n }\n}\n\n// ============================================================================\n// SIDEBAR\n// ============================================================================\n\nconst DEFAULT_SIDEBAR_CONFIG: Required<SidebarConfig> = {\n storageKey: 'cmm-sidebar-state',\n desktopBreakpoint: '(min-width: 1024px)',\n collapsedClass: 'cmm-shell--sidebar-collapsed',\n openClass: 'cmm-shell--sidebar-open',\n}\n\n/**\n * Setup responsive sidebar with collapse/expand functionality.\n */\nexport function setupSidebar(config: SidebarConfig = {}): () => void {\n const options = { ...DEFAULT_SIDEBAR_CONFIG, ...config }\n const layout = document.querySelector<HTMLElement>('[data-shell-layout]')\n const sidebar = document.querySelector<HTMLElement>('[data-shell-sidebar]')\n\n if (!layout || !sidebar) {\n return () => {\n /* noop */\n }\n }\n\n const storage = resolveStorage()\n const mediaQuery = window.matchMedia(options.desktopBreakpoint)\n const toggles = Array.from(document.querySelectorAll<HTMLElement>('[data-sidebar-toggle]'))\n const dismissors = Array.from(document.querySelectorAll<HTMLElement>('[data-sidebar-dismiss]'))\n\n const sidebarId = sidebar.id || 'shell-sidebar'\n sidebar.id = sidebarId\n\n const readStoredCollapsed = () => storage?.getItem(options.storageKey) === 'collapsed'\n\n const syncToggleAria = () => {\n const expanded = mediaQuery.matches\n ? !layout.classList.contains(options.collapsedClass)\n : layout.classList.contains(options.openClass)\n\n toggles.forEach(toggle => {\n toggle.setAttribute('aria-expanded', expanded.toString())\n toggle.setAttribute('aria-controls', sidebarId)\n })\n }\n\n const applyCollapsed = (collapsed: boolean, persist = true) => {\n layout.classList.toggle(options.collapsedClass, collapsed)\n if (persist && mediaQuery.matches) {\n storage?.setItem(options.storageKey, collapsed ? 'collapsed' : 'expanded')\n }\n syncToggleAria()\n }\n\n const setOpen = (open: boolean) => {\n layout.classList.toggle(options.openClass, open)\n syncToggleAria()\n }\n\n const syncForViewport = () => {\n if (mediaQuery.matches) {\n setOpen(false)\n applyCollapsed(readStoredCollapsed(), false)\n } else {\n setOpen(false)\n applyCollapsed(false, false)\n }\n }\n\n const handleToggleClick = () => {\n if (mediaQuery.matches) {\n const collapsed = layout.classList.contains(options.collapsedClass)\n applyCollapsed(!collapsed)\n } else {\n const open = layout.classList.contains(options.openClass)\n setOpen(!open)\n }\n }\n\n const handleDismissClick = () => {\n setOpen(false)\n }\n\n const handleKeydown = (event: KeyboardEvent) => {\n if (event.key === 'Escape' && !mediaQuery.matches) {\n setOpen(false)\n }\n }\n\n // Attach listeners\n toggles.forEach(toggle => {\n toggle.addEventListener('click', handleToggleClick)\n })\n dismissors.forEach(dismiss => {\n dismiss.addEventListener('click', handleDismissClick)\n })\n document.addEventListener('keydown', handleKeydown)\n mediaQuery.addEventListener('change', syncForViewport)\n\n // Initialize\n syncForViewport()\n\n // Return cleanup function\n return () => {\n toggles.forEach(toggle => {\n toggle.removeEventListener('click', handleToggleClick)\n })\n dismissors.forEach(dismiss => {\n dismiss.removeEventListener('click', handleDismissClick)\n })\n document.removeEventListener('keydown', handleKeydown)\n mediaQuery.removeEventListener('change', syncForViewport)\n }\n}\n\n// ============================================================================\n// USER MENU\n// ============================================================================\n\n/**\n * Setup user menu dropdown with keyboard navigation.\n */\nexport function setupUserMenu(config: UserMenuConfig = {}): () => void {\n const triggerSelector = config.triggerSelector ?? '[data-user-trigger]'\n const dropdownSelector = config.dropdownSelector ?? '[data-user-dropdown]'\n\n const userMenu = document.querySelector<HTMLElement>('[data-user-menu]')\n const trigger = document.querySelector<HTMLButtonElement>(triggerSelector)\n const dropdown = document.querySelector<HTMLElement>(dropdownSelector)\n\n if (!userMenu || !trigger || !dropdown) {\n return () => {\n /* noop */\n }\n }\n\n const setExpanded = (expanded: boolean) => {\n trigger.setAttribute('aria-expanded', expanded.toString())\n userMenu.setAttribute('aria-expanded', expanded.toString())\n }\n\n const isExpanded = () => trigger.getAttribute('aria-expanded') === 'true'\n\n const handleTriggerClick = (event: Event) => {\n event.stopPropagation()\n setExpanded(!isExpanded())\n }\n\n const handleDocumentClick = (event: Event) => {\n if (!userMenu.contains(event.target as Node)) {\n setExpanded(false)\n }\n }\n\n const handleKeydown = (event: KeyboardEvent) => {\n if (event.key === 'Escape' && isExpanded()) {\n setExpanded(false)\n trigger.focus()\n }\n }\n\n const dropdownItemSelector = config.dropdownItemSelector ?? '.cmm-user-menu__dropdown-item'\n\n const handleDropdownKeydown = (event: KeyboardEvent) => {\n const items = Array.from(dropdown.querySelectorAll<HTMLAnchorElement>(dropdownItemSelector))\n const currentIndex = items.indexOf(document.activeElement as HTMLAnchorElement)\n\n if (event.key === 'ArrowDown') {\n event.preventDefault()\n const nextIndex = currentIndex < items.length - 1 ? currentIndex + 1 : 0\n items[nextIndex]?.focus()\n } else if (event.key === 'ArrowUp') {\n event.preventDefault()\n const prevIndex = currentIndex > 0 ? currentIndex - 1 : items.length - 1\n items[prevIndex]?.focus()\n } else if (event.key === 'Tab' && !event.shiftKey && currentIndex === items.length - 1) {\n setExpanded(false)\n } else if (event.key === 'Tab' && event.shiftKey && currentIndex === 0) {\n setExpanded(false)\n }\n }\n\n const handleTriggerKeydown = (event: KeyboardEvent) => {\n if (\n (event.key === 'Enter' || event.key === ' ' || event.key === 'ArrowDown') &&\n !isExpanded()\n ) {\n event.preventDefault()\n setExpanded(true)\n setTimeout(() => {\n const firstItem = dropdown.querySelector<HTMLAnchorElement>(dropdownItemSelector)\n firstItem?.focus()\n }, 50)\n }\n }\n\n // Attach listeners\n trigger.addEventListener('click', handleTriggerClick)\n document.addEventListener('click', handleDocumentClick)\n document.addEventListener('keydown', handleKeydown)\n dropdown.addEventListener('keydown', handleDropdownKeydown)\n trigger.addEventListener('keydown', handleTriggerKeydown)\n\n // Return cleanup function\n return () => {\n trigger.removeEventListener('click', handleTriggerClick)\n document.removeEventListener('click', handleDocumentClick)\n document.removeEventListener('keydown', handleKeydown)\n dropdown.removeEventListener('keydown', handleDropdownKeydown)\n trigger.removeEventListener('keydown', handleTriggerKeydown)\n }\n}\n\n// ============================================================================\n// COLLAPSIBLES\n// ============================================================================\n\nconst isCollapsibleExpanded = (section: HTMLElement) =>\n section.dataset.collapsibleOpen === 'true' || !section.classList.contains('hidden')\n\nlet collapsibleHiddenClass = 'cmm-collapsible--hidden'\n\nconst updateCollapsibleState = (section: HTMLElement, expanded: boolean) => {\n section.classList.toggle('hidden', !expanded)\n section.classList.toggle(collapsibleHiddenClass, !expanded)\n section.dataset.collapsibleOpen = expanded.toString()\n section.setAttribute('aria-hidden', expanded ? 'false' : 'true')\n}\n\nconst syncCollapsibleToggles = (selector: string, expanded: boolean) => {\n document.querySelectorAll<HTMLElement>(`[data-toggle-target='${selector}']`).forEach(toggle => {\n toggle.setAttribute('aria-expanded', expanded.toString())\n })\n}\n\n/**\n * Setup collapsible sections with toggle buttons.\n */\nexport function setupCollapsibles(config: CollapsibleConfig = {}): () => void {\n const {\n scrollIntoView = true,\n scrollBehavior = 'smooth',\n hiddenClass = 'cmm-collapsible--hidden',\n } = config\n collapsibleHiddenClass = hiddenClass\n\n // Initialize all collapsible sections\n document.querySelectorAll<HTMLElement>('[data-collapsible]').forEach(section => {\n const expanded =\n section.dataset.collapsibleOpen === 'true' || !section.classList.contains('hidden')\n updateCollapsibleState(section, expanded)\n })\n\n const handlers: { element: HTMLElement; handler: (e: Event) => void }[] = []\n\n // Setup toggle triggers\n document.querySelectorAll<HTMLElement>('[data-toggle-target]').forEach(toggle => {\n const selector = toggle.dataset.toggleTarget\n if (!selector) {\n return\n }\n\n const target = document.querySelector<HTMLElement>(selector)\n if (!target) {\n return\n }\n\n const ariaTarget = target.id || selector.replace(/^#/, '')\n toggle.setAttribute('aria-controls', ariaTarget)\n toggle.setAttribute('aria-expanded', isCollapsibleExpanded(target).toString())\n\n const handler = (event: Event) => {\n event.preventDefault()\n const expanded = !isCollapsibleExpanded(target)\n updateCollapsibleState(target, expanded)\n syncCollapsibleToggles(selector, expanded)\n\n if (expanded && scrollIntoView) {\n target.scrollIntoView({ behavior: scrollBehavior, block: 'start' })\n }\n }\n\n toggle.addEventListener('click', handler)\n handlers.push({ element: toggle, handler })\n })\n\n // Setup collapse triggers (close only)\n document.querySelectorAll<HTMLElement>('[data-collapse-target]').forEach(toggle => {\n const selector = toggle.dataset.collapseTarget\n if (!selector) {\n return\n }\n\n const target = document.querySelector<HTMLElement>(selector)\n if (!target) {\n return\n }\n\n const handler = (event: Event) => {\n event.preventDefault()\n updateCollapsibleState(target, false)\n syncCollapsibleToggles(selector, false)\n }\n\n toggle.addEventListener('click', handler)\n handlers.push({ element: toggle, handler })\n })\n\n // Handle URL hash for deep linking\n const hash = window.location.hash\n if (hash) {\n const target = document.querySelector<HTMLElement>(hash)\n if (target?.dataset.collapsible !== undefined) {\n updateCollapsibleState(target, true)\n syncCollapsibleToggles(hash, true)\n }\n }\n\n // Return cleanup function\n return () => {\n handlers.forEach(({ element, handler }) => {\n element.removeEventListener('click', handler)\n })\n }\n}\n\n// ============================================================================\n// SHEETS / SIDE PANELS\n// ============================================================================\n\nconst SHEET_SPINNER_HTML = `\n <div class=\"cmm-sheet__loading\">\n <div class=\"cmm-spinner\"></div>\n </div>\n`\n\nconst SHEET_ERROR_HTML = `\n <div class=\"cmm-sheet__error\">\n <p>Failed to load content. Please try the full page.</p>\n </div>\n`\n\nfunction replaceSheetMarkup(element: HTMLElement, markup: string): void {\n element.replaceChildren(createSafeMarkupFragment(markup, { allowSvg: true }))\n}\n\n/**\n * Setup side sheet/drawer components.\n */\nexport function setupSheets(setupConfig: SheetSetupConfig = {}): () => void {\n const {\n openClass = 'cmm-sheet--open',\n hiddenClass = 'cmm-sheet--hidden',\n backdropVisibleClass = 'cmm-sheet__backdrop--visible',\n backdropHiddenClass = 'cmm-sheet__backdrop--hidden',\n spinnerHtml: spinnerMarkup = SHEET_SPINNER_HTML,\n errorHtml: errorMarkup = SHEET_ERROR_HTML,\n allowCrossOriginFetch = false,\n } = setupConfig\n\n const sheetMap = new Map<string, SheetConfig>()\n\n document.querySelectorAll<HTMLElement>('[data-sheet]').forEach(sheet => {\n const key = sheet.dataset.sheet\n if (!key) {\n return\n }\n\n const backdrop = document.querySelector<HTMLElement>(`[data-sheet-backdrop='${key}']`)\n const content = sheet.querySelector<HTMLElement>('[data-sheet-content]')\n if (!backdrop || !content) {\n return\n }\n\n sheetMap.set(key, {\n key,\n sheet,\n backdrop,\n content,\n fullPageLink: sheet.querySelector<HTMLAnchorElement>('[data-sheet-fullpage]'),\n expandLink: sheet.querySelector<HTMLAnchorElement>('[data-sheet-expand]'),\n focusSelector: sheet.dataset.sheetFocus,\n })\n })\n\n if (sheetMap.size === 0) {\n return () => {\n /* noop */\n }\n }\n\n let activeSheet: SheetConfig | null = null\n\n const setOpenState = (config: SheetConfig, open: boolean) => {\n config.sheet.classList.toggle(openClass, open)\n config.sheet.classList.toggle(hiddenClass, !open)\n config.backdrop.classList.toggle(backdropVisibleClass, open)\n config.backdrop.classList.toggle(backdropHiddenClass, !open)\n config.sheet.setAttribute('aria-hidden', open ? 'false' : 'true')\n }\n\n const closeSheet = (config: SheetConfig) => {\n if (activeSheet?.key === config.key) {\n activeSheet = null\n }\n setOpenState(config, false)\n }\n\n const openSheet = async (config: SheetConfig, trigger?: HTMLElement) => {\n if (activeSheet && activeSheet.key !== config.key) {\n closeSheet(activeSheet)\n }\n\n activeSheet = config\n setOpenState(config, true)\n\n const url = trigger?.dataset.sheetUrl ?? config.sheet.dataset.sheetUrl\n const focusSelector = trigger?.dataset.sheetFocus ?? config.focusSelector\n const fullPageHref = trigger?.dataset.sheetFullpage ?? config.sheet.dataset.sheetFullpage\n const expandHref = trigger?.dataset.sheetExpand ?? config.sheet.dataset.sheetExpand\n\n if (config.fullPageLink && fullPageHref) {\n config.fullPageLink.href = fullPageHref\n }\n\n if (config.expandLink && expandHref) {\n config.expandLink.href = expandHref\n }\n\n if (!url || (!allowCrossOriginFetch && !isSameOriginUrl(url))) {\n replaceSheetMarkup(config.content, errorMarkup)\n return\n }\n\n replaceSheetMarkup(config.content, spinnerMarkup)\n\n try {\n const response = await fetch(url)\n if (response.ok) {\n const markup = await response.text()\n replaceSheetMarkup(config.content, markup)\n if (focusSelector) {\n const focusTarget = config.content.querySelector<HTMLElement>(focusSelector)\n focusTarget?.focus()\n }\n } else if (fullPageHref) {\n navigateDocumentTo(fullPageHref)\n } else {\n replaceSheetMarkup(config.content, errorMarkup)\n }\n } catch {\n if (fullPageHref) {\n navigateDocumentTo(fullPageHref)\n } else {\n replaceSheetMarkup(config.content, errorMarkup)\n }\n }\n }\n\n const handlers: { element: HTMLElement; event: string; handler: (e: Event) => void }[] = []\n\n sheetMap.forEach(config => {\n const closeHandler = (event: Event) => {\n const target = event.target as HTMLElement\n if (target.closest('[data-sheet-close]')) {\n event.preventDefault()\n closeSheet(config)\n }\n }\n\n const backdropHandler = () => {\n closeSheet(config)\n }\n\n const expandHandler = () => {\n closeSheet(config)\n }\n\n config.sheet.addEventListener('click', closeHandler)\n config.backdrop.addEventListener('click', backdropHandler)\n handlers.push({ element: config.sheet, event: 'click', handler: closeHandler })\n handlers.push({ element: config.backdrop, event: 'click', handler: backdropHandler })\n\n if (config.expandLink) {\n config.expandLink.addEventListener('click', expandHandler)\n handlers.push({ element: config.expandLink, event: 'click', handler: expandHandler })\n }\n })\n\n // Setup triggers\n document.querySelectorAll<HTMLElement>('[data-sheet-trigger]').forEach(trigger => {\n const key = trigger.dataset.sheetTrigger\n if (!key) {\n return\n }\n\n const config = sheetMap.get(key)\n if (!config) {\n return\n }\n\n const handler = (event: Event) => {\n event.preventDefault()\n void openSheet(config, trigger)\n }\n\n trigger.addEventListener('click', handler)\n handlers.push({ element: trigger, event: 'click', handler })\n })\n\n // Escape key handler\n const escapeHandler = (event: KeyboardEvent) => {\n if (event.key === 'Escape' && activeSheet) {\n closeSheet(activeSheet)\n }\n }\n\n document.addEventListener('keydown', escapeHandler)\n\n // Return cleanup function\n return () => {\n handlers.forEach(({ element, event, handler }) => {\n element.removeEventListener(event, handler)\n })\n document.removeEventListener('keydown', escapeHandler)\n }\n}\n\n// ============================================================================\n// NAVIGATION KEYBOARD SUPPORT\n// ============================================================================\n\n/**\n * Setup keyboard navigation for sidebar nav items.\n */\nexport function setupNavKeyboard(): () => void {\n const navList = document.querySelector<HTMLElement>('[data-nav-list]')\n if (!navList) {\n return () => {\n /* noop */\n }\n }\n\n const getNavItems = () =>\n Array.from(navList.querySelectorAll<HTMLAnchorElement>('[data-nav-item]'))\n\n const handler = (event: KeyboardEvent) => {\n const items = getNavItems()\n const currentIndex = items.indexOf(document.activeElement as HTMLAnchorElement)\n\n if (event.key === 'ArrowDown') {\n event.preventDefault()\n const nextIndex = currentIndex < items.length - 1 ? currentIndex + 1 : 0\n items[nextIndex]?.focus()\n } else if (event.key === 'ArrowUp') {\n event.preventDefault()\n const prevIndex = currentIndex > 0 ? currentIndex - 1 : items.length - 1\n items[prevIndex]?.focus()\n } else if (event.key === 'Home') {\n event.preventDefault()\n items[0]?.focus()\n } else if (event.key === 'End') {\n event.preventDefault()\n items[items.length - 1]?.focus()\n }\n }\n\n navList.addEventListener('keydown', handler)\n\n return () => {\n navList.removeEventListener('keydown', handler)\n }\n}\n\n// ============================================================================\n// BOOTSTRAP\n// ============================================================================\n\n/**\n * Initialize all layout components.\n */\nexport function initLayout(\n config: {\n sidebar?: SidebarConfig\n userMenu?: UserMenuConfig\n collapsibles?: CollapsibleConfig\n sheets?: SheetSetupConfig\n } = {}\n): () => void {\n const cleanups = [\n setupSidebar(config.sidebar),\n setupUserMenu(config.userMenu),\n setupCollapsibles(config.collapsibles),\n setupSheets(config.sheets),\n setupNavKeyboard(),\n ]\n\n return () => {\n cleanups.forEach(cleanup => {\n cleanup()\n })\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/layout/index.ts"],"sourcesContent":["/**\n * Layout Components\n * @countermeasure/web-components\n *\n * Shared layout utilities for sidebar, user menu, collapsibles, and sheets.\n */\n\nimport { createSafeMarkupFragment } from '../utils/sanitize'\nimport { navigateDocumentTo } from '../utils/navigation'\nexport {\n AppShell,\n TopMenuBar,\n createAppShell,\n createProductShell,\n createTopMenuBar,\n} from './app-shell'\nexport type {\n AppShellConfig,\n TopMenuBarAction,\n TopMenuBarActionInput,\n TopMenuBarBreadcrumb,\n TopMenuBarConfig,\n TopMenuBarUser,\n} from './app-shell'\nexport {\n CORE_APP_ROUTE_LABELS,\n createCoreAppChromePreset,\n createCoreAppSidebarConfig,\n createCoreAppSidebarSections,\n createCoreAppTopbarActions,\n createCoreAppTopbarConfig,\n getCoreAppRouteLabel,\n mountCoreAppChrome,\n mountCoreAppChromeFromDom,\n} from './core-app-chrome'\nexport type {\n CoreAppChromePreset,\n CoreAppChromeDomMountOptions,\n CoreAppChromeMount,\n CoreAppChromeMountOptions,\n CoreAppChromePresetOptions,\n CoreAppRouteLabel,\n CoreAppSidebarPresetOptions,\n CoreAppTopbarPresetOptions,\n} from './core-app-chrome'\nexport {\n mountCoreAppLibraryDashboard,\n mountCoreAppLibraryDashboardFromDom,\n} from './core-app-library-dashboard'\nexport type {\n CoreAppLibraryConnector,\n CoreAppLibraryConnectorStatus,\n CoreAppLibraryDashboardData,\n CoreAppLibraryDashboardDomMountOptions,\n CoreAppLibraryDashboardError,\n CoreAppLibraryDashboardMount,\n CoreAppLibraryDashboardMountOptions,\n CoreAppLibraryFreshnessBucket,\n CoreAppLibraryMetric,\n CoreAppLibraryMetricTone,\n CoreAppLibraryPipelineSummary,\n CoreAppLibraryTacticDepth,\n} from './core-app-library-dashboard'\nexport { PageHeader, createPageHeader } from './page-header'\nexport type { PageHeaderConfig, PageHeaderMetadata } from './page-header'\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\nexport interface SidebarConfig {\n storageKey?: string\n desktopBreakpoint?: string\n collapsedClass?: string\n openClass?: string\n}\n\nexport interface UserMenuConfig {\n triggerSelector?: string\n dropdownSelector?: string\n dropdownItemSelector?: string\n}\n\nexport interface CollapsibleConfig {\n scrollIntoView?: boolean\n scrollBehavior?: ScrollBehavior\n hiddenClass?: string\n}\n\nexport interface SheetConfig {\n key: string\n sheet: HTMLElement\n backdrop: HTMLElement\n content: HTMLElement\n fullPageLink?: HTMLAnchorElement | null | undefined\n expandLink?: HTMLAnchorElement | null | undefined\n focusSelector?: string | undefined\n}\n\nexport interface SheetSetupConfig {\n openClass?: string\n hiddenClass?: string\n backdropVisibleClass?: string\n backdropHiddenClass?: string\n spinnerHtml?: string\n errorHtml?: string\n /** Allow fetching sheet content from non-same-origin URLs. Default: false. */\n allowCrossOriginFetch?: boolean\n}\n\n// ============================================================================\n// STORAGE HELPERS\n// ============================================================================\n\nconst resolveStorage = (): Storage | null => {\n if (typeof window === 'undefined') {\n return null\n }\n try {\n return window.localStorage\n } catch {\n console.warn('Unable to access localStorage')\n return null\n }\n}\n\nconst isSameOriginUrl = (url: string): boolean => {\n try {\n return new URL(url, window.location.href).origin === window.location.origin\n } catch {\n return false\n }\n}\n\n// ============================================================================\n// SIDEBAR\n// ============================================================================\n\nconst DEFAULT_SIDEBAR_CONFIG: Required<SidebarConfig> = {\n storageKey: 'cmm-sidebar-state',\n desktopBreakpoint: '(min-width: 1024px)',\n collapsedClass: 'cmm-shell--sidebar-collapsed',\n openClass: 'cmm-shell--sidebar-open',\n}\n\n/**\n * Setup responsive sidebar with collapse/expand functionality.\n */\nexport function setupSidebar(config: SidebarConfig = {}): () => void {\n const options = { ...DEFAULT_SIDEBAR_CONFIG, ...config }\n const layout = document.querySelector<HTMLElement>('[data-shell-layout]')\n const sidebar = document.querySelector<HTMLElement>('[data-shell-sidebar]')\n\n if (!layout || !sidebar) {\n return () => {\n /* noop */\n }\n }\n\n const storage = resolveStorage()\n const mediaQuery = window.matchMedia(options.desktopBreakpoint)\n const toggles = Array.from(document.querySelectorAll<HTMLElement>('[data-sidebar-toggle]'))\n const dismissors = Array.from(document.querySelectorAll<HTMLElement>('[data-sidebar-dismiss]'))\n\n const sidebarId = sidebar.id || 'shell-sidebar'\n sidebar.id = sidebarId\n\n const readStoredCollapsed = () => storage?.getItem(options.storageKey) === 'collapsed'\n\n const syncToggleAria = () => {\n const expanded = mediaQuery.matches\n ? !layout.classList.contains(options.collapsedClass)\n : layout.classList.contains(options.openClass)\n\n toggles.forEach(toggle => {\n toggle.setAttribute('aria-expanded', expanded.toString())\n toggle.setAttribute('aria-controls', sidebarId)\n })\n }\n\n const applyCollapsed = (collapsed: boolean, persist = true) => {\n layout.classList.toggle(options.collapsedClass, collapsed)\n if (persist && mediaQuery.matches) {\n storage?.setItem(options.storageKey, collapsed ? 'collapsed' : 'expanded')\n }\n syncToggleAria()\n }\n\n const setOpen = (open: boolean) => {\n layout.classList.toggle(options.openClass, open)\n syncToggleAria()\n }\n\n const syncForViewport = () => {\n if (mediaQuery.matches) {\n setOpen(false)\n applyCollapsed(readStoredCollapsed(), false)\n } else {\n setOpen(false)\n applyCollapsed(false, false)\n }\n }\n\n const handleToggleClick = () => {\n if (mediaQuery.matches) {\n const collapsed = layout.classList.contains(options.collapsedClass)\n applyCollapsed(!collapsed)\n } else {\n const open = layout.classList.contains(options.openClass)\n setOpen(!open)\n }\n }\n\n const handleDismissClick = () => {\n setOpen(false)\n }\n\n const handleKeydown = (event: KeyboardEvent) => {\n if (event.key === 'Escape' && !mediaQuery.matches) {\n setOpen(false)\n }\n }\n\n // Attach listeners\n toggles.forEach(toggle => {\n toggle.addEventListener('click', handleToggleClick)\n })\n dismissors.forEach(dismiss => {\n dismiss.addEventListener('click', handleDismissClick)\n })\n document.addEventListener('keydown', handleKeydown)\n mediaQuery.addEventListener('change', syncForViewport)\n\n // Initialize\n syncForViewport()\n\n // Return cleanup function\n return () => {\n toggles.forEach(toggle => {\n toggle.removeEventListener('click', handleToggleClick)\n })\n dismissors.forEach(dismiss => {\n dismiss.removeEventListener('click', handleDismissClick)\n })\n document.removeEventListener('keydown', handleKeydown)\n mediaQuery.removeEventListener('change', syncForViewport)\n }\n}\n\n// ============================================================================\n// USER MENU\n// ============================================================================\n\n/**\n * Setup user menu dropdown with keyboard navigation.\n */\nexport function setupUserMenu(config: UserMenuConfig = {}): () => void {\n const triggerSelector = config.triggerSelector ?? '[data-user-trigger]'\n const dropdownSelector = config.dropdownSelector ?? '[data-user-dropdown]'\n\n const userMenu = document.querySelector<HTMLElement>('[data-user-menu]')\n const trigger = document.querySelector<HTMLButtonElement>(triggerSelector)\n const dropdown = document.querySelector<HTMLElement>(dropdownSelector)\n\n if (!userMenu || !trigger || !dropdown) {\n return () => {\n /* noop */\n }\n }\n\n const setExpanded = (expanded: boolean) => {\n trigger.setAttribute('aria-expanded', expanded.toString())\n userMenu.setAttribute('aria-expanded', expanded.toString())\n }\n\n const isExpanded = () => trigger.getAttribute('aria-expanded') === 'true'\n\n const handleTriggerClick = (event: Event) => {\n event.stopPropagation()\n setExpanded(!isExpanded())\n }\n\n const handleDocumentClick = (event: Event) => {\n if (!userMenu.contains(event.target as Node)) {\n setExpanded(false)\n }\n }\n\n const handleKeydown = (event: KeyboardEvent) => {\n if (event.key === 'Escape' && isExpanded()) {\n setExpanded(false)\n trigger.focus()\n }\n }\n\n const dropdownItemSelector = config.dropdownItemSelector ?? '.cmm-user-menu__dropdown-item'\n\n const handleDropdownKeydown = (event: KeyboardEvent) => {\n const items = Array.from(dropdown.querySelectorAll<HTMLAnchorElement>(dropdownItemSelector))\n const currentIndex = items.indexOf(document.activeElement as HTMLAnchorElement)\n\n if (event.key === 'ArrowDown') {\n event.preventDefault()\n const nextIndex = currentIndex < items.length - 1 ? currentIndex + 1 : 0\n items[nextIndex]?.focus()\n } else if (event.key === 'ArrowUp') {\n event.preventDefault()\n const prevIndex = currentIndex > 0 ? currentIndex - 1 : items.length - 1\n items[prevIndex]?.focus()\n } else if (event.key === 'Tab' && !event.shiftKey && currentIndex === items.length - 1) {\n setExpanded(false)\n } else if (event.key === 'Tab' && event.shiftKey && currentIndex === 0) {\n setExpanded(false)\n }\n }\n\n const handleTriggerKeydown = (event: KeyboardEvent) => {\n if (\n (event.key === 'Enter' || event.key === ' ' || event.key === 'ArrowDown') &&\n !isExpanded()\n ) {\n event.preventDefault()\n setExpanded(true)\n setTimeout(() => {\n const firstItem = dropdown.querySelector<HTMLAnchorElement>(dropdownItemSelector)\n firstItem?.focus()\n }, 50)\n }\n }\n\n // Attach listeners\n trigger.addEventListener('click', handleTriggerClick)\n document.addEventListener('click', handleDocumentClick)\n document.addEventListener('keydown', handleKeydown)\n dropdown.addEventListener('keydown', handleDropdownKeydown)\n trigger.addEventListener('keydown', handleTriggerKeydown)\n\n // Return cleanup function\n return () => {\n trigger.removeEventListener('click', handleTriggerClick)\n document.removeEventListener('click', handleDocumentClick)\n document.removeEventListener('keydown', handleKeydown)\n dropdown.removeEventListener('keydown', handleDropdownKeydown)\n trigger.removeEventListener('keydown', handleTriggerKeydown)\n }\n}\n\n// ============================================================================\n// COLLAPSIBLES\n// ============================================================================\n\nconst isCollapsibleExpanded = (section: HTMLElement) =>\n section.dataset.collapsibleOpen === 'true' || !section.classList.contains('hidden')\n\nlet collapsibleHiddenClass = 'cmm-collapsible--hidden'\n\nconst updateCollapsibleState = (section: HTMLElement, expanded: boolean) => {\n section.classList.toggle('hidden', !expanded)\n section.classList.toggle(collapsibleHiddenClass, !expanded)\n section.dataset.collapsibleOpen = expanded.toString()\n section.setAttribute('aria-hidden', expanded ? 'false' : 'true')\n}\n\nconst syncCollapsibleToggles = (selector: string, expanded: boolean) => {\n document.querySelectorAll<HTMLElement>(`[data-toggle-target='${selector}']`).forEach(toggle => {\n toggle.setAttribute('aria-expanded', expanded.toString())\n })\n}\n\n/**\n * Setup collapsible sections with toggle buttons.\n */\nexport function setupCollapsibles(config: CollapsibleConfig = {}): () => void {\n const {\n scrollIntoView = true,\n scrollBehavior = 'smooth',\n hiddenClass = 'cmm-collapsible--hidden',\n } = config\n collapsibleHiddenClass = hiddenClass\n\n // Initialize all collapsible sections\n document.querySelectorAll<HTMLElement>('[data-collapsible]').forEach(section => {\n const expanded =\n section.dataset.collapsibleOpen === 'true' || !section.classList.contains('hidden')\n updateCollapsibleState(section, expanded)\n })\n\n const handlers: { element: HTMLElement; handler: (e: Event) => void }[] = []\n\n // Setup toggle triggers\n document.querySelectorAll<HTMLElement>('[data-toggle-target]').forEach(toggle => {\n const selector = toggle.dataset.toggleTarget\n if (!selector) {\n return\n }\n\n const target = document.querySelector<HTMLElement>(selector)\n if (!target) {\n return\n }\n\n const ariaTarget = target.id || selector.replace(/^#/, '')\n toggle.setAttribute('aria-controls', ariaTarget)\n toggle.setAttribute('aria-expanded', isCollapsibleExpanded(target).toString())\n\n const handler = (event: Event) => {\n event.preventDefault()\n const expanded = !isCollapsibleExpanded(target)\n updateCollapsibleState(target, expanded)\n syncCollapsibleToggles(selector, expanded)\n\n if (expanded && scrollIntoView) {\n target.scrollIntoView({ behavior: scrollBehavior, block: 'start' })\n }\n }\n\n toggle.addEventListener('click', handler)\n handlers.push({ element: toggle, handler })\n })\n\n // Setup collapse triggers (close only)\n document.querySelectorAll<HTMLElement>('[data-collapse-target]').forEach(toggle => {\n const selector = toggle.dataset.collapseTarget\n if (!selector) {\n return\n }\n\n const target = document.querySelector<HTMLElement>(selector)\n if (!target) {\n return\n }\n\n const handler = (event: Event) => {\n event.preventDefault()\n updateCollapsibleState(target, false)\n syncCollapsibleToggles(selector, false)\n }\n\n toggle.addEventListener('click', handler)\n handlers.push({ element: toggle, handler })\n })\n\n // Handle URL hash for deep linking\n const hash = window.location.hash\n if (hash) {\n const target = document.querySelector<HTMLElement>(hash)\n if (target?.dataset.collapsible !== undefined) {\n updateCollapsibleState(target, true)\n syncCollapsibleToggles(hash, true)\n }\n }\n\n // Return cleanup function\n return () => {\n handlers.forEach(({ element, handler }) => {\n element.removeEventListener('click', handler)\n })\n }\n}\n\n// ============================================================================\n// SHEETS / SIDE PANELS\n// ============================================================================\n\nconst SHEET_SPINNER_HTML = `\n <div class=\"cmm-sheet__loading\">\n <div class=\"cmm-spinner\"></div>\n </div>\n`\n\nconst SHEET_ERROR_HTML = `\n <div class=\"cmm-sheet__error\">\n <p>Failed to load content. Please try the full page.</p>\n </div>\n`\n\nfunction replaceSheetMarkup(element: HTMLElement, markup: string): void {\n element.replaceChildren(createSafeMarkupFragment(markup, { allowSvg: true }))\n}\n\n/**\n * Setup side sheet/drawer components.\n */\nexport function setupSheets(setupConfig: SheetSetupConfig = {}): () => void {\n const {\n openClass = 'cmm-sheet--open',\n hiddenClass = 'cmm-sheet--hidden',\n backdropVisibleClass = 'cmm-sheet__backdrop--visible',\n backdropHiddenClass = 'cmm-sheet__backdrop--hidden',\n spinnerHtml: spinnerMarkup = SHEET_SPINNER_HTML,\n errorHtml: errorMarkup = SHEET_ERROR_HTML,\n allowCrossOriginFetch = false,\n } = setupConfig\n\n const sheetMap = new Map<string, SheetConfig>()\n\n document.querySelectorAll<HTMLElement>('[data-sheet]').forEach(sheet => {\n const key = sheet.dataset.sheet\n if (!key) {\n return\n }\n\n const backdrop = document.querySelector<HTMLElement>(`[data-sheet-backdrop='${key}']`)\n const content = sheet.querySelector<HTMLElement>('[data-sheet-content]')\n if (!backdrop || !content) {\n return\n }\n\n sheetMap.set(key, {\n key,\n sheet,\n backdrop,\n content,\n fullPageLink: sheet.querySelector<HTMLAnchorElement>('[data-sheet-fullpage]'),\n expandLink: sheet.querySelector<HTMLAnchorElement>('[data-sheet-expand]'),\n focusSelector: sheet.dataset.sheetFocus,\n })\n })\n\n if (sheetMap.size === 0) {\n return () => {\n /* noop */\n }\n }\n\n let activeSheet: SheetConfig | null = null\n\n const setOpenState = (config: SheetConfig, open: boolean) => {\n config.sheet.classList.toggle(openClass, open)\n config.sheet.classList.toggle(hiddenClass, !open)\n config.backdrop.classList.toggle(backdropVisibleClass, open)\n config.backdrop.classList.toggle(backdropHiddenClass, !open)\n config.sheet.setAttribute('aria-hidden', open ? 'false' : 'true')\n }\n\n const closeSheet = (config: SheetConfig) => {\n if (activeSheet?.key === config.key) {\n activeSheet = null\n }\n setOpenState(config, false)\n }\n\n const openSheet = async (config: SheetConfig, trigger?: HTMLElement) => {\n if (activeSheet && activeSheet.key !== config.key) {\n closeSheet(activeSheet)\n }\n\n activeSheet = config\n setOpenState(config, true)\n\n const url = trigger?.dataset.sheetUrl ?? config.sheet.dataset.sheetUrl\n const focusSelector = trigger?.dataset.sheetFocus ?? config.focusSelector\n const fullPageHref = trigger?.dataset.sheetFullpage ?? config.sheet.dataset.sheetFullpage\n const expandHref = trigger?.dataset.sheetExpand ?? config.sheet.dataset.sheetExpand\n\n if (config.fullPageLink && fullPageHref) {\n config.fullPageLink.href = fullPageHref\n }\n\n if (config.expandLink && expandHref) {\n config.expandLink.href = expandHref\n }\n\n if (!url || (!allowCrossOriginFetch && !isSameOriginUrl(url))) {\n replaceSheetMarkup(config.content, errorMarkup)\n return\n }\n\n replaceSheetMarkup(config.content, spinnerMarkup)\n\n try {\n const response = await fetch(url)\n if (response.ok) {\n const markup = await response.text()\n replaceSheetMarkup(config.content, markup)\n if (focusSelector) {\n const focusTarget = config.content.querySelector<HTMLElement>(focusSelector)\n focusTarget?.focus()\n }\n } else if (fullPageHref) {\n navigateDocumentTo(fullPageHref)\n } else {\n replaceSheetMarkup(config.content, errorMarkup)\n }\n } catch {\n if (fullPageHref) {\n navigateDocumentTo(fullPageHref)\n } else {\n replaceSheetMarkup(config.content, errorMarkup)\n }\n }\n }\n\n const handlers: { element: HTMLElement; event: string; handler: (e: Event) => void }[] = []\n\n sheetMap.forEach(config => {\n const closeHandler = (event: Event) => {\n const target = event.target as HTMLElement\n if (target.closest('[data-sheet-close]')) {\n event.preventDefault()\n closeSheet(config)\n }\n }\n\n const backdropHandler = () => {\n closeSheet(config)\n }\n\n const expandHandler = () => {\n closeSheet(config)\n }\n\n config.sheet.addEventListener('click', closeHandler)\n config.backdrop.addEventListener('click', backdropHandler)\n handlers.push({ element: config.sheet, event: 'click', handler: closeHandler })\n handlers.push({ element: config.backdrop, event: 'click', handler: backdropHandler })\n\n if (config.expandLink) {\n config.expandLink.addEventListener('click', expandHandler)\n handlers.push({ element: config.expandLink, event: 'click', handler: expandHandler })\n }\n })\n\n // Setup triggers\n document.querySelectorAll<HTMLElement>('[data-sheet-trigger]').forEach(trigger => {\n const key = trigger.dataset.sheetTrigger\n if (!key) {\n return\n }\n\n const config = sheetMap.get(key)\n if (!config) {\n return\n }\n\n const handler = (event: Event) => {\n event.preventDefault()\n void openSheet(config, trigger)\n }\n\n trigger.addEventListener('click', handler)\n handlers.push({ element: trigger, event: 'click', handler })\n })\n\n // Escape key handler\n const escapeHandler = (event: KeyboardEvent) => {\n if (event.key === 'Escape' && activeSheet) {\n closeSheet(activeSheet)\n }\n }\n\n document.addEventListener('keydown', escapeHandler)\n\n // Return cleanup function\n return () => {\n handlers.forEach(({ element, event, handler }) => {\n element.removeEventListener(event, handler)\n })\n document.removeEventListener('keydown', escapeHandler)\n }\n}\n\n// ============================================================================\n// NAVIGATION KEYBOARD SUPPORT\n// ============================================================================\n\n/**\n * Setup keyboard navigation for sidebar nav items.\n */\nexport function setupNavKeyboard(): () => void {\n const navList = document.querySelector<HTMLElement>('[data-nav-list]')\n if (!navList) {\n return () => {\n /* noop */\n }\n }\n\n const getNavItems = () =>\n Array.from(navList.querySelectorAll<HTMLAnchorElement>('[data-nav-item]'))\n\n const handler = (event: KeyboardEvent) => {\n const items = getNavItems()\n const currentIndex = items.indexOf(document.activeElement as HTMLAnchorElement)\n\n if (event.key === 'ArrowDown') {\n event.preventDefault()\n const nextIndex = currentIndex < items.length - 1 ? currentIndex + 1 : 0\n items[nextIndex]?.focus()\n } else if (event.key === 'ArrowUp') {\n event.preventDefault()\n const prevIndex = currentIndex > 0 ? currentIndex - 1 : items.length - 1\n items[prevIndex]?.focus()\n } else if (event.key === 'Home') {\n event.preventDefault()\n items[0]?.focus()\n } else if (event.key === 'End') {\n event.preventDefault()\n items[items.length - 1]?.focus()\n }\n }\n\n navList.addEventListener('keydown', handler)\n\n return () => {\n navList.removeEventListener('keydown', handler)\n }\n}\n\n// ============================================================================\n// BOOTSTRAP\n// ============================================================================\n\n/**\n * Initialize all layout components.\n */\nexport function initLayout(\n config: {\n sidebar?: SidebarConfig\n userMenu?: UserMenuConfig\n collapsibles?: CollapsibleConfig\n sheets?: SheetSetupConfig\n } = {}\n): () => void {\n const cleanups = [\n setupSidebar(config.sidebar),\n setupUserMenu(config.userMenu),\n setupCollapsibles(config.collapsibles),\n setupSheets(config.sheets),\n setupNavKeyboard(),\n ]\n\n return () => {\n cleanups.forEach(cleanup => {\n cleanup()\n })\n }\n}\n"],"mappings":"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"}
@@ -23,10 +23,12 @@ export declare function Wordmark({ className, size, variant, subtitle, label, de
23
23
  export interface BrandLockupProps extends React.HTMLAttributes<HTMLSpanElement> {
24
24
  markSize?: BrandSize | number;
25
25
  label?: string;
26
+ subtitle?: string;
27
+ wordmarkCase?: BrandLockupConfig['wordmarkCase'];
26
28
  decorative?: boolean;
27
29
  showWordmark?: boolean;
28
30
  }
29
- export declare function BrandLockup({ className, markSize, label, decorative, showWordmark, ...props }: BrandLockupProps): import("react/jsx-runtime").JSX.Element;
31
+ export declare function BrandLockup({ className, markSize, label, subtitle, wordmarkCase, decorative, showWordmark, ...props }: BrandLockupProps): import("react/jsx-runtime").JSX.Element;
30
32
  export interface ConnectorLogoProps extends React.HTMLAttributes<HTMLSpanElement> {
31
33
  name: string;
32
34
  src?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/react/brand/index.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAKL,KAAK,SAAS,EACd,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACrB,MAAM,wBAAwB,CAAA;AAG/B,MAAM,WAAW,YAAa,SAAQ,KAAK,CAAC,aAAa,CAAC,aAAa,CAAC;IACtE,IAAI,CAAC,EAAE,SAAS,GAAG,MAAM,CAAA;IACzB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB;AAED,wBAAgB,OAAO,CAAC,EACtB,SAAS,EACT,IAAS,EACT,KAAgC,EAChC,UAAiB,EACjB,GAAG,KAAK,EACT,EAAE,YAAY,2CA6Cd;AAED,MAAM,WAAW,aAAc,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IACzE,IAAI,CAAC,EAAE,SAAS,GAAG,MAAM,CAAA;IACzB,OAAO,CAAC,EAAE,eAAe,CAAA;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB;AAED,wBAAgB,QAAQ,CAAC,EACvB,SAAS,EACT,IAAS,EACT,OAAgB,EAChB,QAAQ,EACR,KAAwB,EACxB,UAAkB,EAClB,GAAG,KAAK,EACT,EAAE,aAAa,2CAgEf;AAED,MAAM,WAAW,gBAAiB,SAAQ,KAAK,CAAC,cAAc,CAAC,eAAe,CAAC;IAC7E,QAAQ,CAAC,EAAE,SAAS,GAAG,MAAM,CAAA;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,YAAY,CAAC,EAAE,OAAO,CAAA;CACvB;AAED,wBAAgB,WAAW,CAAC,EAC1B,SAAS,EACT,QAAa,EACb,KAAwB,EACxB,UAAkB,EAClB,YAAmB,EACnB,GAAG,KAAK,EACT,EAAE,gBAAgB,2CAgBlB;AAED,MAAM,WAAW,kBAAmB,SAAQ,KAAK,CAAC,cAAc,CAAC,eAAe,CAAC;IAC/E,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,iBAAiB,CAAA;IACxB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB;AAED,wBAAgB,aAAa,CAAC,EAC5B,SAAS,EACT,IAAI,EACJ,GAAG,EACH,IAAS,EACT,KAAK,EACL,UAAkB,EAClB,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,kBAAkB,2CA6BpB;AAED,MAAM,MAAM,uBAAuB,GAAG,YAAY,CAAA;AAClD,MAAM,MAAM,uBAAuB,GAAG,YAAY,CAAA;AAClD,MAAM,MAAM,2BAA2B,GAAG,aAAa,CAAA;AACvD,MAAM,MAAM,2BAA2B,GAAG,aAAa,CAAA;AACvD,MAAM,MAAM,8BAA8B,GAAG,gBAAgB,CAAA;AAC7D,MAAM,MAAM,8BAA8B,GAAG,gBAAgB,CAAA;AAC7D,YAAY,EAAE,iBAAiB,EAAE,CAAA;AAEjC,eAAO,MAAM,kBAAkB,gBAAU,CAAA;AACzC,eAAO,MAAM,kBAAkB,gBAAU,CAAA;AACzC,eAAO,MAAM,sBAAsB,iBAAW,CAAA;AAC9C,eAAO,MAAM,sBAAsB,iBAAW,CAAA;AAC9C,eAAO,MAAM,yBAAyB,oBAAc,CAAA;AACpD,eAAO,MAAM,yBAAyB,oBAAc,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/react/brand/index.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,EAKL,KAAK,SAAS,EACd,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACrB,MAAM,wBAAwB,CAAA;AAG/B,MAAM,WAAW,YAAa,SAAQ,KAAK,CAAC,aAAa,CAAC,aAAa,CAAC;IACtE,IAAI,CAAC,EAAE,SAAS,GAAG,MAAM,CAAA;IACzB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB;AAED,wBAAgB,OAAO,CAAC,EACtB,SAAS,EACT,IAAS,EACT,KAAgC,EAChC,UAAiB,EACjB,GAAG,KAAK,EACT,EAAE,YAAY,2CA6Cd;AAED,MAAM,WAAW,aAAc,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IACzE,IAAI,CAAC,EAAE,SAAS,GAAG,MAAM,CAAA;IACzB,OAAO,CAAC,EAAE,eAAe,CAAA;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB;AAED,wBAAgB,QAAQ,CAAC,EACvB,SAAS,EACT,IAAS,EACT,OAAgB,EAChB,QAAQ,EACR,KAAwB,EACxB,UAAkB,EAClB,GAAG,KAAK,EACT,EAAE,aAAa,2CAgEf;AAED,MAAM,WAAW,gBAAiB,SAAQ,KAAK,CAAC,cAAc,CAAC,eAAe,CAAC;IAC7E,QAAQ,CAAC,EAAE,SAAS,GAAG,MAAM,CAAA;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,YAAY,CAAC,EAAE,iBAAiB,CAAC,cAAc,CAAC,CAAA;IAChD,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,YAAY,CAAC,EAAE,OAAO,CAAA;CACvB;AAED,wBAAgB,WAAW,CAAC,EAC1B,SAAS,EACT,QAAa,EACb,KAAwB,EACxB,QAAQ,EACR,YAA0B,EAC1B,UAAkB,EAClB,YAAmB,EACnB,GAAG,KAAK,EACT,EAAE,gBAAgB,2CAiClB;AAED,MAAM,WAAW,kBAAmB,SAAQ,KAAK,CAAC,cAAc,CAAC,eAAe,CAAC;IAC/E,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,iBAAiB,CAAA;IACxB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB;AAED,wBAAgB,aAAa,CAAC,EAC5B,SAAS,EACT,IAAI,EACJ,GAAG,EACH,IAAS,EACT,KAAK,EACL,UAAkB,EAClB,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,kBAAkB,2CA6BpB;AAED,MAAM,MAAM,uBAAuB,GAAG,YAAY,CAAA;AAClD,MAAM,MAAM,uBAAuB,GAAG,YAAY,CAAA;AAClD,MAAM,MAAM,2BAA2B,GAAG,aAAa,CAAA;AACvD,MAAM,MAAM,2BAA2B,GAAG,aAAa,CAAA;AACvD,MAAM,MAAM,8BAA8B,GAAG,gBAAgB,CAAA;AAC7D,MAAM,MAAM,8BAA8B,GAAG,gBAAgB,CAAA;AAC7D,YAAY,EAAE,iBAAiB,EAAE,CAAA;AAEjC,eAAO,MAAM,kBAAkB,gBAAU,CAAA;AACzC,eAAO,MAAM,kBAAkB,gBAAU,CAAA;AACzC,eAAO,MAAM,sBAAsB,iBAAW,CAAA;AAC9C,eAAO,MAAM,sBAAsB,iBAAW,CAAA;AAC9C,eAAO,MAAM,yBAAyB,oBAAc,CAAA;AACpD,eAAO,MAAM,yBAAyB,oBAAc,CAAA"}
@@ -110,27 +110,33 @@ function c({ className: e, size: t = 32, variant: n = "auto", subtitle: r, label
110
110
  })]
111
111
  });
112
112
  }
113
- function l({ className: e, markSize: t = 22, label: n = "CounterMeasure", decorative: r = !1, showWordmark: c = !0, ...l }) {
114
- let u = r ? { "aria-hidden": !0 } : {
113
+ function l({ className: e, markSize: t = 22, label: n = "CounterMeasure", subtitle: r, wordmarkCase: c = "uppercase", decorative: l = !1, showWordmark: u = !0, ...d }) {
114
+ let f = l ? { "aria-hidden": !0 } : {
115
115
  role: "img",
116
116
  "aria-label": n
117
117
  };
118
118
  return /* @__PURE__ */ o("span", {
119
- className: i("cmm-brand-lockup", e),
120
- ...u,
121
- ...l,
119
+ className: i("cmm-brand-lockup", c === "title" && "cmm-brand-lockup--title", e),
120
+ ...f,
121
+ ...d,
122
122
  children: [/* @__PURE__ */ a(s, {
123
123
  size: t,
124
124
  decorative: !0
125
- }), c ? /* @__PURE__ */ o("span", {
126
- className: "cmm-brand-lockup__wordmark",
125
+ }), u ? /* @__PURE__ */ o("span", {
126
+ className: "cmm-brand-lockup__copy",
127
127
  "aria-hidden": "true",
128
- children: [/* @__PURE__ */ a("span", {
129
- className: "cmm-brand-lockup__counter",
130
- children: "COUNTER"
131
- }), /* @__PURE__ */ a("span", {
132
- className: "cmm-brand-lockup__measure",
133
- children: "MEASURE"
128
+ children: [/* @__PURE__ */ o("span", {
129
+ className: "cmm-brand-lockup__wordmark",
130
+ children: [/* @__PURE__ */ a("span", {
131
+ className: "cmm-brand-lockup__counter",
132
+ children: c === "title" ? "Counter" : "COUNTER"
133
+ }), /* @__PURE__ */ a("span", {
134
+ className: "cmm-brand-lockup__measure",
135
+ children: c === "title" ? "Measure" : "MEASURE"
136
+ })]
137
+ }), r === void 0 ? null : /* @__PURE__ */ a("span", {
138
+ className: "cmm-brand-lockup__subtitle",
139
+ children: r
134
140
  })]
135
141
  }) : null]
136
142
  });
@@ -1 +1 @@
1
- {"version":3,"file":"brand.js","names":[],"sources":["../../src/react/brand/index.tsx"],"sourcesContent":["/**\n * CounterMeasure brand wrappers.\n *\n * React wrappers render the same semantic SVGs and CSS classes as the vanilla\n * brand helpers in `src/components/brand`.\n */\n\nimport * as React from 'react'\n\nimport {\n getBrandSizeClass,\n getConnectorLogoInitial,\n getConnectorLogoSizeClass,\n getConnectorLogoTone,\n type BrandSize,\n type BrandLockupConfig,\n type ConnectorLogoSize,\n type WordmarkVariant,\n} from '../../components/brand'\nimport { cn } from '../primitives/utils'\n\nexport interface DiamondProps extends React.SVGAttributes<SVGSVGElement> {\n size?: BrandSize | number\n label?: string\n decorative?: boolean\n}\n\nexport function Diamond({\n className,\n size = 24,\n label = 'CounterMeasure diamond',\n decorative = true,\n ...props\n}: DiamondProps) {\n const sizeClass = getBrandSizeClass('cmm-diamond', size)\n const accessibilityProps = decorative\n ? { 'aria-hidden': true }\n : { role: 'img', 'aria-label': label }\n\n return (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 46.64 46.64\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className={cn('cmm-diamond', sizeClass, className)}\n {...accessibilityProps}\n {...props}\n >\n <rect\n x=\"2.62\"\n y=\"16.42\"\n width=\"13.8\"\n height=\"13.8\"\n rx=\"0.57\"\n transform=\"translate(-13.7 13.56) rotate(-45)\"\n className=\"cmm-diamond__foreground\"\n />\n <rect\n x=\"16.42\"\n y=\"30.22\"\n width=\"13.8\"\n height=\"13.8\"\n rx=\"0.57\"\n transform=\"translate(-19.42 27.36) rotate(-45)\"\n className=\"cmm-diamond__slate\"\n />\n <rect\n x=\"16.42\"\n y=\"2.62\"\n width=\"13.8\"\n height=\"13.8\"\n rx=\"0.57\"\n transform=\"translate(0.1 19.28) rotate(-45)\"\n className=\"cmm-diamond__orange\"\n />\n </svg>\n )\n}\n\nexport interface WordmarkProps extends React.HTMLAttributes<HTMLDivElement> {\n size?: BrandSize | number\n variant?: WordmarkVariant\n subtitle?: string\n label?: string\n decorative?: boolean\n}\n\nexport function Wordmark({\n className,\n size = 32,\n variant = 'auto',\n subtitle,\n label = 'CounterMeasure',\n decorative = false,\n ...props\n}: WordmarkProps) {\n const width = Math.round(size * (220 / 32) * 100) / 100\n const accessibilityProps = decorative\n ? { 'aria-hidden': true }\n : { role: 'img', 'aria-label': label }\n\n return (\n <div\n className={cn('cmm-wordmark', `cmm-wordmark--${variant}`, className)}\n {...accessibilityProps}\n {...props}\n >\n <svg\n width={width}\n height={size}\n viewBox=\"0 0 220 32\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"cmm-wordmark__svg\"\n aria-hidden=\"true\"\n >\n <g transform=\"translate(0,3)\">\n <rect\n x=\"1.78\"\n y=\"11.16\"\n width=\"9.4\"\n height=\"9.4\"\n rx=\"0.4\"\n transform=\"translate(-9.32 9.22) rotate(-45)\"\n className=\"cmm-wordmark__foreground\"\n />\n <rect\n x=\"11.16\"\n y=\"20.54\"\n width=\"9.4\"\n height=\"9.4\"\n rx=\"0.4\"\n transform=\"translate(-13.21 18.6) rotate(-45)\"\n className=\"cmm-wordmark__slate\"\n />\n <rect\n x=\"11.16\"\n y=\"1.78\"\n width=\"9.4\"\n height=\"9.4\"\n rx=\"0.4\"\n transform=\"translate(0.07 13.11) rotate(-45)\"\n className=\"cmm-wordmark__orange\"\n />\n </g>\n <text\n x=\"42\"\n y=\"22\"\n className=\"cmm-wordmark__text\"\n fontFamily=\"Outfit, sans-serif\"\n fontSize=\"18\"\n fontWeight=\"600\"\n letterSpacing=\"-0.01em\"\n >\n CounterMeasure\n </text>\n </svg>\n {subtitle !== undefined ? <span className=\"cmm-wordmark__subtitle\">{subtitle}</span> : null}\n </div>\n )\n}\n\nexport interface BrandLockupProps extends React.HTMLAttributes<HTMLSpanElement> {\n markSize?: BrandSize | number\n label?: string\n decorative?: boolean\n showWordmark?: boolean\n}\n\nexport function BrandLockup({\n className,\n markSize = 22,\n label = 'CounterMeasure',\n decorative = false,\n showWordmark = true,\n ...props\n}: BrandLockupProps) {\n const accessibilityProps = decorative\n ? { 'aria-hidden': true }\n : { role: 'img', 'aria-label': label }\n\n return (\n <span className={cn('cmm-brand-lockup', className)} {...accessibilityProps} {...props}>\n <Diamond size={markSize} decorative />\n {showWordmark ? (\n <span className=\"cmm-brand-lockup__wordmark\" aria-hidden=\"true\">\n <span className=\"cmm-brand-lockup__counter\">COUNTER</span>\n <span className=\"cmm-brand-lockup__measure\">MEASURE</span>\n </span>\n ) : null}\n </span>\n )\n}\n\nexport interface ConnectorLogoProps extends React.HTMLAttributes<HTMLSpanElement> {\n name: string\n src?: string\n size?: ConnectorLogoSize\n label?: string\n decorative?: boolean\n}\n\nexport function ConnectorLogo({\n className,\n name,\n src,\n size = 32,\n label,\n decorative = false,\n children,\n ...props\n}: ConnectorLogoProps) {\n const hasAsset = src !== undefined || children !== undefined\n const accessibilityProps = decorative\n ? { 'aria-hidden': true }\n : { role: 'img', 'aria-label': label ?? `${name} connector` }\n\n return (\n <span\n className={cn(\n 'cmm-connector-logo',\n getConnectorLogoSizeClass(size),\n `cmm-connector-logo--vendor-${getConnectorLogoTone(name)}`,\n hasAsset && 'cmm-connector-logo--asset',\n className\n )}\n {...accessibilityProps}\n {...props}\n >\n {src !== undefined ? (\n <img className=\"cmm-connector-logo__asset\" src={src} alt=\"\" aria-hidden=\"true\" />\n ) : children !== undefined ? (\n <span className=\"cmm-connector-logo__asset\" aria-hidden=\"true\">\n {children}\n </span>\n ) : (\n getConnectorLogoInitial(name)\n )}\n </span>\n )\n}\n\nexport type CountermeasureLogoProps = DiamondProps\nexport type CounterMeasureLogoProps = DiamondProps\nexport type CountermeasureWordmarkProps = WordmarkProps\nexport type CounterMeasureWordmarkProps = WordmarkProps\nexport type CountermeasureBrandLockupProps = BrandLockupProps\nexport type CounterMeasureBrandLockupProps = BrandLockupProps\nexport type { BrandLockupConfig }\n\nexport const CountermeasureLogo = Diamond\nexport const CounterMeasureLogo = Diamond\nexport const CountermeasureWordmark = Wordmark\nexport const CounterMeasureWordmark = Wordmark\nexport const CountermeasureBrandLockup = BrandLockup\nexport const CounterMeasureBrandLockup = BrandLockup\n"],"mappings":";;;;;AA2BA,SAAgB,EAAQ,EACtB,cACA,UAAO,IACP,WAAQ,0BACR,gBAAa,IACb,GAAG,KACY;CACf,IAAM,IAAY,EAAkB,eAAe,CAAI,GACjD,IAAqB,IACvB,EAAE,eAAe,GAAK,IACtB;EAAE,MAAM;EAAO,cAAc;CAAM;CAEvC,OACE,kBAAC,OAAD;EACE,OAAO;EACP,QAAQ;EACR,SAAQ;EACR,OAAM;EACN,WAAW,EAAG,eAAe,GAAW,CAAS;EACjD,GAAI;EACJ,GAAI;YAPN;GASE,kBAAC,QAAD;IACE,GAAE;IACF,GAAE;IACF,OAAM;IACN,QAAO;IACP,IAAG;IACH,WAAU;IACV,WAAU;GACX,CAAA;GACD,kBAAC,QAAD;IACE,GAAE;IACF,GAAE;IACF,OAAM;IACN,QAAO;IACP,IAAG;IACH,WAAU;IACV,WAAU;GACX,CAAA;GACD,kBAAC,QAAD;IACE,GAAE;IACF,GAAE;IACF,OAAM;IACN,QAAO;IACP,IAAG;IACH,WAAU;IACV,WAAU;GACX,CAAA;EACE;;AAET;AAUA,SAAgB,EAAS,EACvB,cACA,UAAO,IACP,aAAU,QACV,aACA,WAAQ,kBACR,gBAAa,IACb,GAAG,KACa;CAChB,IAAM,IAAQ,KAAK,MAAc,MAAM,KAAd,IAAoB,GAAG,IAAI,KAC9C,IAAqB,IACvB,EAAE,eAAe,GAAK,IACtB;EAAE,MAAM;EAAO,cAAc;CAAM;CAEvC,OACE,kBAAC,OAAD;EACE,WAAW,EAAG,gBAAgB,iBAAiB,KAAW,CAAS;EACnE,GAAI;EACJ,GAAI;YAHN,CAKE,kBAAC,OAAD;GACS;GACP,QAAQ;GACR,SAAQ;GACR,OAAM;GACN,WAAU;GACV,eAAY;aANd,CAQE,kBAAC,KAAD;IAAG,WAAU;cAAb;KACE,kBAAC,QAAD;MACE,GAAE;MACF,GAAE;MACF,OAAM;MACN,QAAO;MACP,IAAG;MACH,WAAU;MACV,WAAU;KACX,CAAA;KACD,kBAAC,QAAD;MACE,GAAE;MACF,GAAE;MACF,OAAM;MACN,QAAO;MACP,IAAG;MACH,WAAU;MACV,WAAU;KACX,CAAA;KACD,kBAAC,QAAD;MACE,GAAE;MACF,GAAE;MACF,OAAM;MACN,QAAO;MACP,IAAG;MACH,WAAU;MACV,WAAU;KACX,CAAA;IACA;OACH,kBAAC,QAAD;IACE,GAAE;IACF,GAAE;IACF,WAAU;IACV,YAAW;IACX,UAAS;IACT,YAAW;IACX,eAAc;cACf;GAEK,CAAA,CACH;MACJ,MAAa,KAAA,IAAyE,OAA7D,kBAAC,QAAD;GAAM,WAAU;aAA0B;EAAe,CAAA,CAChF;;AAET;AASA,SAAgB,EAAY,EAC1B,cACA,cAAW,IACX,WAAQ,kBACR,gBAAa,IACb,kBAAe,IACf,GAAG,KACgB;CACnB,IAAM,IAAqB,IACvB,EAAE,eAAe,GAAK,IACtB;EAAE,MAAM;EAAO,cAAc;CAAM;CAEvC,OACE,kBAAC,QAAD;EAAM,WAAW,EAAG,oBAAoB,CAAS;EAAG,GAAI;EAAoB,GAAI;YAAhF,CACE,kBAAC,GAAD;GAAS,MAAM;GAAU,YAAA;EAAY,CAAA,GACpC,IACC,kBAAC,QAAD;GAAM,WAAU;GAA6B,eAAY;aAAzD,CACE,kBAAC,QAAD;IAAM,WAAU;cAA4B;GAAa,CAAA,GACzD,kBAAC,QAAD;IAAM,WAAU;cAA4B;GAAa,CAAA,CACrD;OACJ,IACA;;AAEV;AAUA,SAAgB,EAAc,EAC5B,cACA,SACA,QACA,UAAO,IACP,UACA,gBAAa,IACb,aACA,GAAG,KACkB;CACrB,IAAM,IAAW,MAAQ,KAAA,KAAa,MAAa,KAAA,GAC7C,IAAqB,IACvB,EAAE,eAAe,GAAK,IACtB;EAAE,MAAM;EAAO,cAAc,KAAS,GAAG,EAAK;CAAY;CAE9D,OACE,kBAAC,QAAD;EACE,WAAW,EACT,sBACA,EAA0B,CAAI,GAC9B,8BAA8B,EAAqB,CAAI,KACvD,KAAY,6BACZ,CACF;EACA,GAAI;EACJ,GAAI;YAEH,MAAQ,KAAA,IAEL,MAAa,KAAA,IAKf,EAAwB,CAAI,IAJ5B,kBAAC,QAAD;GAAM,WAAU;GAA4B,eAAY;GACrD;EACG,CAAA,IAJN,kBAAC,OAAD;GAAK,WAAU;GAAiC;GAAK,KAAI;GAAG,eAAY;EAAQ,CAAA;CAQ9E,CAAA;AAEV;AAUA,IAAa,IAAqB,GACrB,IAAqB,GACrB,IAAyB,GACzB,IAAyB,GACzB,IAA4B,GAC5B,IAA4B"}
1
+ {"version":3,"file":"brand.js","names":[],"sources":["../../src/react/brand/index.tsx"],"sourcesContent":["/**\n * CounterMeasure brand wrappers.\n *\n * React wrappers render the same semantic SVGs and CSS classes as the vanilla\n * brand helpers in `src/components/brand`.\n */\n\nimport * as React from 'react'\n\nimport {\n getBrandSizeClass,\n getConnectorLogoInitial,\n getConnectorLogoSizeClass,\n getConnectorLogoTone,\n type BrandSize,\n type BrandLockupConfig,\n type ConnectorLogoSize,\n type WordmarkVariant,\n} from '../../components/brand'\nimport { cn } from '../primitives/utils'\n\nexport interface DiamondProps extends React.SVGAttributes<SVGSVGElement> {\n size?: BrandSize | number\n label?: string\n decorative?: boolean\n}\n\nexport function Diamond({\n className,\n size = 24,\n label = 'CounterMeasure diamond',\n decorative = true,\n ...props\n}: DiamondProps) {\n const sizeClass = getBrandSizeClass('cmm-diamond', size)\n const accessibilityProps = decorative\n ? { 'aria-hidden': true }\n : { role: 'img', 'aria-label': label }\n\n return (\n <svg\n width={size}\n height={size}\n viewBox=\"0 0 46.64 46.64\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className={cn('cmm-diamond', sizeClass, className)}\n {...accessibilityProps}\n {...props}\n >\n <rect\n x=\"2.62\"\n y=\"16.42\"\n width=\"13.8\"\n height=\"13.8\"\n rx=\"0.57\"\n transform=\"translate(-13.7 13.56) rotate(-45)\"\n className=\"cmm-diamond__foreground\"\n />\n <rect\n x=\"16.42\"\n y=\"30.22\"\n width=\"13.8\"\n height=\"13.8\"\n rx=\"0.57\"\n transform=\"translate(-19.42 27.36) rotate(-45)\"\n className=\"cmm-diamond__slate\"\n />\n <rect\n x=\"16.42\"\n y=\"2.62\"\n width=\"13.8\"\n height=\"13.8\"\n rx=\"0.57\"\n transform=\"translate(0.1 19.28) rotate(-45)\"\n className=\"cmm-diamond__orange\"\n />\n </svg>\n )\n}\n\nexport interface WordmarkProps extends React.HTMLAttributes<HTMLDivElement> {\n size?: BrandSize | number\n variant?: WordmarkVariant\n subtitle?: string\n label?: string\n decorative?: boolean\n}\n\nexport function Wordmark({\n className,\n size = 32,\n variant = 'auto',\n subtitle,\n label = 'CounterMeasure',\n decorative = false,\n ...props\n}: WordmarkProps) {\n const width = Math.round(size * (220 / 32) * 100) / 100\n const accessibilityProps = decorative\n ? { 'aria-hidden': true }\n : { role: 'img', 'aria-label': label }\n\n return (\n <div\n className={cn('cmm-wordmark', `cmm-wordmark--${variant}`, className)}\n {...accessibilityProps}\n {...props}\n >\n <svg\n width={width}\n height={size}\n viewBox=\"0 0 220 32\"\n xmlns=\"http://www.w3.org/2000/svg\"\n className=\"cmm-wordmark__svg\"\n aria-hidden=\"true\"\n >\n <g transform=\"translate(0,3)\">\n <rect\n x=\"1.78\"\n y=\"11.16\"\n width=\"9.4\"\n height=\"9.4\"\n rx=\"0.4\"\n transform=\"translate(-9.32 9.22) rotate(-45)\"\n className=\"cmm-wordmark__foreground\"\n />\n <rect\n x=\"11.16\"\n y=\"20.54\"\n width=\"9.4\"\n height=\"9.4\"\n rx=\"0.4\"\n transform=\"translate(-13.21 18.6) rotate(-45)\"\n className=\"cmm-wordmark__slate\"\n />\n <rect\n x=\"11.16\"\n y=\"1.78\"\n width=\"9.4\"\n height=\"9.4\"\n rx=\"0.4\"\n transform=\"translate(0.07 13.11) rotate(-45)\"\n className=\"cmm-wordmark__orange\"\n />\n </g>\n <text\n x=\"42\"\n y=\"22\"\n className=\"cmm-wordmark__text\"\n fontFamily=\"Outfit, sans-serif\"\n fontSize=\"18\"\n fontWeight=\"600\"\n letterSpacing=\"-0.01em\"\n >\n CounterMeasure\n </text>\n </svg>\n {subtitle !== undefined ? <span className=\"cmm-wordmark__subtitle\">{subtitle}</span> : null}\n </div>\n )\n}\n\nexport interface BrandLockupProps extends React.HTMLAttributes<HTMLSpanElement> {\n markSize?: BrandSize | number\n label?: string\n subtitle?: string\n wordmarkCase?: BrandLockupConfig['wordmarkCase']\n decorative?: boolean\n showWordmark?: boolean\n}\n\nexport function BrandLockup({\n className,\n markSize = 22,\n label = 'CounterMeasure',\n subtitle,\n wordmarkCase = 'uppercase',\n decorative = false,\n showWordmark = true,\n ...props\n}: BrandLockupProps) {\n const accessibilityProps = decorative\n ? { 'aria-hidden': true }\n : { role: 'img', 'aria-label': label }\n\n return (\n <span\n className={cn(\n 'cmm-brand-lockup',\n wordmarkCase === 'title' && 'cmm-brand-lockup--title',\n className\n )}\n {...accessibilityProps}\n {...props}\n >\n <Diamond size={markSize} decorative />\n {showWordmark ? (\n <span className=\"cmm-brand-lockup__copy\" aria-hidden=\"true\">\n <span className=\"cmm-brand-lockup__wordmark\">\n <span className=\"cmm-brand-lockup__counter\">\n {wordmarkCase === 'title' ? 'Counter' : 'COUNTER'}\n </span>\n <span className=\"cmm-brand-lockup__measure\">\n {wordmarkCase === 'title' ? 'Measure' : 'MEASURE'}\n </span>\n </span>\n {subtitle !== undefined ? (\n <span className=\"cmm-brand-lockup__subtitle\">{subtitle}</span>\n ) : null}\n </span>\n ) : null}\n </span>\n )\n}\n\nexport interface ConnectorLogoProps extends React.HTMLAttributes<HTMLSpanElement> {\n name: string\n src?: string\n size?: ConnectorLogoSize\n label?: string\n decorative?: boolean\n}\n\nexport function ConnectorLogo({\n className,\n name,\n src,\n size = 32,\n label,\n decorative = false,\n children,\n ...props\n}: ConnectorLogoProps) {\n const hasAsset = src !== undefined || children !== undefined\n const accessibilityProps = decorative\n ? { 'aria-hidden': true }\n : { role: 'img', 'aria-label': label ?? `${name} connector` }\n\n return (\n <span\n className={cn(\n 'cmm-connector-logo',\n getConnectorLogoSizeClass(size),\n `cmm-connector-logo--vendor-${getConnectorLogoTone(name)}`,\n hasAsset && 'cmm-connector-logo--asset',\n className\n )}\n {...accessibilityProps}\n {...props}\n >\n {src !== undefined ? (\n <img className=\"cmm-connector-logo__asset\" src={src} alt=\"\" aria-hidden=\"true\" />\n ) : children !== undefined ? (\n <span className=\"cmm-connector-logo__asset\" aria-hidden=\"true\">\n {children}\n </span>\n ) : (\n getConnectorLogoInitial(name)\n )}\n </span>\n )\n}\n\nexport type CountermeasureLogoProps = DiamondProps\nexport type CounterMeasureLogoProps = DiamondProps\nexport type CountermeasureWordmarkProps = WordmarkProps\nexport type CounterMeasureWordmarkProps = WordmarkProps\nexport type CountermeasureBrandLockupProps = BrandLockupProps\nexport type CounterMeasureBrandLockupProps = BrandLockupProps\nexport type { BrandLockupConfig }\n\nexport const CountermeasureLogo = Diamond\nexport const CounterMeasureLogo = Diamond\nexport const CountermeasureWordmark = Wordmark\nexport const CounterMeasureWordmark = Wordmark\nexport const CountermeasureBrandLockup = BrandLockup\nexport const CounterMeasureBrandLockup = BrandLockup\n"],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import { CoreAppLibraryDashboardData, CoreAppLibraryDashboardMount } from '../../layout/core-app-library-dashboard';
2
+ export interface CoreAppLibraryDashboardProps {
3
+ data?: CoreAppLibraryDashboardData;
4
+ className?: string;
5
+ dashboardClassName?: string;
6
+ }
7
+ export type { CoreAppLibraryDashboardData, CoreAppLibraryDashboardMount };
8
+ declare function CoreAppLibraryDashboard({ data, className, dashboardClassName, }: CoreAppLibraryDashboardProps): import("react/jsx-runtime").JSX.Element;
9
+ declare namespace CoreAppLibraryDashboard {
10
+ var displayName: string;
11
+ }
12
+ export { CoreAppLibraryDashboard };
13
+ //# sourceMappingURL=core-app-library-dashboard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"core-app-library-dashboard.d.ts","sourceRoot":"","sources":["../../../src/react/layout/core-app-library-dashboard.tsx"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,2BAA2B,EAChC,KAAK,4BAA4B,EAElC,MAAM,yCAAyC,CAAA;AAGhD,MAAM,WAAW,4BAA4B;IAC3C,IAAI,CAAC,EAAE,2BAA2B,CAAA;IAClC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAC5B;AAED,YAAY,EAAE,2BAA2B,EAAE,4BAA4B,EAAE,CAAA;AAEzE,iBAAS,uBAAuB,CAAC,EAC/B,IAAI,EACJ,SAAS,EACT,kBAAkB,GACnB,EAAE,4BAA4B,2CA6B9B;kBAjCQ,uBAAuB;;;AAqChC,OAAO,EAAE,uBAAuB,EAAE,CAAA"}
@@ -0,0 +1,27 @@
1
+ import { mountCoreAppLibraryDashboard as e } from "../../layout/core-app-library-dashboard.js";
2
+ import { t } from "../../utils-BC9GT6Pr.js";
3
+ import * as n from "react";
4
+ import { jsx as r } from "react/jsx-runtime";
5
+ //#region src/react/layout/core-app-library-dashboard.tsx
6
+ function i({ data: i, className: a, dashboardClassName: o }) {
7
+ let s = n.useRef(null), c = n.useRef(null), l = n.useRef(i);
8
+ return l.current = i, n.useEffect(() => {
9
+ let t = s.current;
10
+ if (t === null) return;
11
+ let n = { container: t };
12
+ return l.current !== void 0 && (n.data = l.current), o !== void 0 && (n.className = o), c.current = e(n), () => {
13
+ c.current?.destroy(), c.current = null;
14
+ };
15
+ }, [o]), n.useEffect(() => {
16
+ c.current?.update(i ?? {});
17
+ }, [i]), /* @__PURE__ */ r("div", {
18
+ ref: s,
19
+ "data-slot": "core-app-library-dashboard",
20
+ className: t(a)
21
+ });
22
+ }
23
+ i.displayName = "CoreAppLibraryDashboard";
24
+ //#endregion
25
+ export { i as CoreAppLibraryDashboard };
26
+
27
+ //# sourceMappingURL=core-app-library-dashboard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"core-app-library-dashboard.js","names":[],"sources":["../../../src/react/layout/core-app-library-dashboard.tsx"],"sourcesContent":["import * as React from 'react'\n\nimport {\n mountCoreAppLibraryDashboard,\n type CoreAppLibraryDashboardData,\n type CoreAppLibraryDashboardMount,\n type CoreAppLibraryDashboardMountOptions,\n} from '../../layout/core-app-library-dashboard'\nimport { cn } from '../primitives/utils'\n\nexport interface CoreAppLibraryDashboardProps {\n data?: CoreAppLibraryDashboardData\n className?: string\n dashboardClassName?: string\n}\n\nexport type { CoreAppLibraryDashboardData, CoreAppLibraryDashboardMount }\n\nfunction CoreAppLibraryDashboard({\n data,\n className,\n dashboardClassName,\n}: CoreAppLibraryDashboardProps) {\n const containerRef = React.useRef<HTMLDivElement>(null)\n const mountRef = React.useRef<CoreAppLibraryDashboardMount | null>(null)\n const latestDataRef = React.useRef<CoreAppLibraryDashboardData | undefined>(data)\n latestDataRef.current = data\n\n React.useEffect(() => {\n const container = containerRef.current\n if (container === null) {\n return\n }\n\n const mountOptions: CoreAppLibraryDashboardMountOptions = { container }\n if (latestDataRef.current !== undefined) mountOptions.data = latestDataRef.current\n if (dashboardClassName !== undefined) mountOptions.className = dashboardClassName\n\n mountRef.current = mountCoreAppLibraryDashboard(mountOptions)\n\n return () => {\n mountRef.current?.destroy()\n mountRef.current = null\n }\n }, [dashboardClassName])\n\n React.useEffect(() => {\n mountRef.current?.update(data ?? {})\n }, [data])\n\n return <div ref={containerRef} data-slot=\"core-app-library-dashboard\" className={cn(className)} />\n}\n\nCoreAppLibraryDashboard.displayName = 'CoreAppLibraryDashboard'\n\nexport { CoreAppLibraryDashboard }\n"],"mappings":";;;;;AAkBA,SAAS,EAAwB,EAC/B,SACA,cACA,yBAC+B;CAC/B,IAAM,IAAe,EAAM,OAAuB,IAAI,GAChD,IAAW,EAAM,OAA4C,IAAI,GACjE,IAAgB,EAAM,OAAgD,CAAI;CAyBhF,OAxBA,EAAc,UAAU,GAExB,EAAM,gBAAgB;EACpB,IAAM,IAAY,EAAa;EAC/B,IAAI,MAAc,MAChB;EAGF,IAAM,IAAoD,EAAE,aAAU;EAMtE,OALI,EAAc,YAAY,KAAA,MAAW,EAAa,OAAO,EAAc,UACvE,MAAuB,KAAA,MAAW,EAAa,YAAY,IAE/D,EAAS,UAAU,EAA6B,CAAY,SAE/C;GAEX,AADA,EAAS,SAAS,QAAQ,GAC1B,EAAS,UAAU;EACrB;CACF,GAAG,CAAC,CAAkB,CAAC,GAEvB,EAAM,gBAAgB;EACpB,EAAS,SAAS,OAAO,KAAQ,CAAC,CAAC;CACrC,GAAG,CAAC,CAAI,CAAC,GAEF,kBAAC,OAAD;EAAK,KAAK;EAAc,aAAU;EAA6B,WAAW,EAAG,CAAS;CAAI,CAAA;AACnG;AAEA,EAAwB,cAAc"}
@@ -1,6 +1,7 @@
1
1
  export { AppShell, type AppShellProps } from './app-shell';
2
2
  export { BrowserLayout, type BrowserLayoutProps } from './browser-layout';
3
3
  export { CoreAppChrome, type CoreAppChromeMount, type CoreAppChromeProps, type CoreAppSidebarPresetOptions, type CoreAppTopbarPresetOptions, } from './core-app-chrome';
4
+ export { CoreAppLibraryDashboard, type CoreAppLibraryDashboardData, type CoreAppLibraryDashboardMount, type CoreAppLibraryDashboardProps, } from './core-app-library-dashboard';
4
5
  export { DetailHeader, type DetailHeaderProps } from './detail-header';
5
6
  export { PageHeader, type PageHeaderProps } from './page-header';
6
7
  export { SubNav, type SubNavItem, type SubNavProps } from './sub-nav';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/react/layout/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAA;AAC1D,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AACzE,OAAO,EACL,aAAa,EACb,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,2BAA2B,EAChC,KAAK,0BAA0B,GAChC,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AACtE,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,eAAe,CAAA;AAChE,OAAO,EAAE,MAAM,EAAE,KAAK,UAAU,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAA;AACrE,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,cAAc,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/react/layout/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAA;AAC1D,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AACzE,OAAO,EACL,aAAa,EACb,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,2BAA2B,EAChC,KAAK,0BAA0B,GAChC,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EACL,uBAAuB,EACvB,KAAK,2BAA2B,EAChC,KAAK,4BAA4B,EACjC,KAAK,4BAA4B,GAClC,MAAM,8BAA8B,CAAA;AACrC,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AACtE,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,eAAe,CAAA;AAChE,OAAO,EAAE,MAAM,EAAE,KAAK,UAAU,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAA;AACrE,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,cAAc,CAAA"}
@@ -1,5 +1,6 @@
1
1
  import { AppShell as e } from "./app-shell.js";
2
2
  import { i as t, n, r, t as i } from "../../layout-64M2la9A.js";
3
3
  import { CoreAppChrome as a } from "./core-app-chrome.js";
4
- import { PageHeader as o } from "./page-header.js";
5
- export { e as AppShell, t as BrowserLayout, a as CoreAppChrome, r as DetailHeader, i as PageFrame, o as PageHeader, n as SubNav };
4
+ import { CoreAppLibraryDashboard as o } from "./core-app-library-dashboard.js";
5
+ import { PageHeader as s } from "./page-header.js";
6
+ export { e as AppShell, t as BrowserLayout, a as CoreAppChrome, o as CoreAppLibraryDashboard, r as DetailHeader, i as PageFrame, s as PageHeader, n as SubNav };
@@ -1,7 +1,7 @@
1
1
  import { VariantProps } from 'class-variance-authority';
2
2
  import * as React from 'react';
3
3
  declare const alertVariants: (props?: ({
4
- variant?: "error" | "warning" | "info" | "success" | null | undefined;
4
+ variant?: "error" | "warning" | "success" | "info" | null | undefined;
5
5
  } & import('class-variance-authority/types').ClassProp) | undefined) => string;
6
6
  /**
7
7
  * Variants emitted by the alert today. The `AlertProps['variant']` shape
@@ -12,7 +12,7 @@ export interface ToastData {
12
12
  persistent?: boolean;
13
13
  }
14
14
  declare const toastVariants: (props?: ({
15
- level?: "error" | "warning" | "info" | "success" | null | undefined;
15
+ level?: "error" | "warning" | "success" | "info" | null | undefined;
16
16
  } & import('class-variance-authority/types').ClassProp) | undefined) => string;
17
17
  interface ToastContextValue {
18
18
  toasts: ToastData[];
@@ -1,4 +1,4 @@
1
- import { t as e } from "../component-D5sRm1fq.js";
1
+ import { t as e } from "../component-D_asjmrt.js";
2
2
  import { t } from "../utils-BC9GT6Pr.js";
3
3
  import * as n from "react";
4
4
  import { jsx as r } from "react/jsx-runtime";